;; Machine description for TI C6X. ;; Copyright (C) 2010-2021 Free Software Foundation, Inc. ;; Contributed by Andrew Jenner andrew@codesourcery.com ;; Contributed by Bernd Schmidt bernds@codesourcery.com ;; Contributed by CodeSourcery. ;; ;; 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/.

;; Register names

(define_constants [(REG_A0 0) (REG_A1 1) (REG_A2 2) (REG_A3 3) (REG_A4 4) (REG_A5 5) (REG_A6 6) (REG_A7 7) (REG_A8 8) (REG_A9 9) (REG_A10 10) (REG_A11 11) (REG_A12 12) (REG_A13 13) (REG_A14 14) (REG_A15 15) (REG_A16 16) (REG_A17 17) (REG_A18 18) (REG_A19 19) (REG_A20 20) (REG_A21 21) (REG_A22 22) (REG_A23 23) (REG_A24 24) (REG_A25 25) (REG_A26 26) (REG_A27 27) (REG_A28 28) (REG_A29 29) (REG_A30 30) (REG_A31 31) (REG_B0 32) (REG_B1 33) (REG_B2 34) (REG_B3 35) (REG_B4 36) (REG_B5 37) (REG_B6 38) (REG_B7 39) (REG_B8 40) (REG_B9 41) (REG_B10 42) (REG_B11 43) (REG_B12 44) (REG_B13 45) (REG_B14 46) (REG_SP 47) (REG_B15 47) (REG_B16 48) (REG_B17 49) (REG_B18 50) (REG_B19 51) (REG_B20 52) (REG_B21 53) (REG_B22 54) (REG_B23 55) (REG_B24 56) (REG_B25 57) (REG_B26 58) (REG_B27 59) (REG_B28 60) (REG_B29 61) (REG_B30 62) (REG_B31 63) (REG_FRAME 64) (REG_ARGP 65) (REG_ILC 66)])

(define_c_enum “unspec” [ UNSPEC_NOP UNSPEC_RCP UNSPEC_MISALIGNED_ACCESS UNSPEC_ADDKPC UNSPEC_SETUP_DSBT UNSPEC_LOAD_GOT UNSPEC_LOAD_SDATA UNSPEC_BITREV UNSPEC_GOTOFF UNSPEC_MVILC UNSPEC_REAL_JUMP UNSPEC_REAL_LOAD UNSPEC_REAL_MULT UNSPEC_JUMP_SHADOW UNSPEC_LOAD_SHADOW UNSPEC_MULT_SHADOW UNSPEC_EPILOGUE_BARRIER UNSPEC_ATOMIC UNSPEC_CLR UNSPEC_EXT UNSPEC_EXTU UNSPEC_SUBC UNSPEC_AVG ])

(define_c_enum “unspecv” [ UNSPECV_BLOCKAGE UNSPECV_SPLOOP UNSPECV_SPKERNEL UNSPECV_EH_RETURN UNSPECV_CAS ])

;; ------------------------------------------------------------------------- ;; Instruction attributes ;; -------------------------------------------------------------------------

(define_attr “cpu” “c62x,c64x,c64xp,c67x,c67xp,c674x” (const (symbol_ref “(enum attr_cpu)c6x_arch”)))

;; Define a type for each insn which is used in the scheduling description. ;; These correspond to the types defined in chapter 4 of the C674x manual. (define_attr “type” “unknown,single,mpy2,store,storen,mpy4,load,loadn,branch,call,callp,dp2,fp4, intdp,cmpdp,adddp,mpy,mpyi,mpyid,mpydp,mpyspdp,mpysp2dp,spkernel,sploop, mvilc,blockage,shadow,load_shadow,mult_shadow,atomic” (const_string “single”))

;; The register file used by an instruction‘s destination register. ;; The function destreg_file computes this; instructions can override the ;; attribute if they aren’t a single_set. (define_attr “dest_regfile” “unknown,any,a,b” (cond [(eq_attr “type” “single,load,mpy2,mpy4,dp2,fp4,intdp,cmpdp,adddp,mpy,mpyi,mpyid,mpydp,mpyspdp,mpysp2dp”) (cond [(match_operand 0 “a_register” "") (const_string “a”) (match_operand 0 “b_register” "") (const_string “b”)] (const_string “unknown”)) (eq_attr “type” “store”) (cond [(match_operand 1 “a_register” "") (const_string “a”) (match_operand 1 “b_register” "") (const_string “b”)] (const_string “unknown”))] (const_string “unknown”)))

(define_attr “addr_regfile” “unknown,a,b” (const_string “unknown”))

(define_attr “cross” “n,y” (const_string “n”))

;; This describes the relationship between operands and register files. ;; For example, “sxs” means that operands 0 and 2 determine the side of ;; the machine, and operand 1 can optionally use the cross path. “dt” and ;; “td” are used to describe loads and stores. ;; Used for register renaming in loops for improving modulo scheduling. (define_attr “op_pattern” “unknown,dt,td,sx,sxs,ssx” (cond [(eq_attr “type” “load”) (const_string “td”) (eq_attr “type” “store”) (const_string “dt”)] (const_string “unknown”)))

(define_attr “has_shadow” “n,y” (const_string “n”))

;; The number of cycles the instruction takes to finish. Any cycles above ;; the first are delay slots. (define_attr “cycles” "" (cond [(eq_attr “type” “branch,call”) (const_int 6) (eq_attr “type” “load,loadn”) (const_int 5) (eq_attr “type” “dp2”) (const_int 2) (eq_attr “type” “mpy2”) (const_int 2) (eq_attr “type” “mpy4”) (const_int 4) (eq_attr “type” “fp4”) (const_int 4) (eq_attr “type” “mvilc”) (const_int 4) (eq_attr “type” “cmpdp”) (const_int 2) (eq_attr “type” “intdp”) (const_int 5) (eq_attr “type” “adddp”) (const_int 7) (eq_attr “type” “mpydp”) (const_int 10) (eq_attr “type” “mpyi”) (const_int 9) (eq_attr “type” “mpyid”) (const_int 10) (eq_attr “type” “mpyspdp”) (const_int 7) (eq_attr “type” “mpysp2dp”) (const_int 5)] (const_int 1)))

;; The number of cycles during which the instruction reserves functional ;; units. (define_attr “reserve_cycles” "" (cond [(eq_attr “type” “cmpdp”) (const_int 2) (eq_attr “type” “adddp”) (const_int 2) (eq_attr “type” “mpydp”) (const_int 4) (eq_attr “type” “mpyi”) (const_int 4) (eq_attr “type” “mpyid”) (const_int 4) (eq_attr “type” “mpyspdp”) (const_int 2)] (const_int 1)))

(define_attr “predicable” “no,yes” (const_string “yes”))

(define_attr “enabled” “no,yes” (const_string “yes”))

;; Specify which units can be used by a given instruction. Normally, ;; dest_regfile is used to select between the two halves of the machine. ;; D_ADDR is for load/store instructions; they use the D unit and use ;; addr_regfile to choose between D1 and D2.

(define_attr “units62” “unknown,d,d_addr,l,m,s,dl,ds,dls,ls” (const_string “unknown”))

(define_attr “units64” “unknown,d,d_addr,l,m,s,dl,ds,dls,ls” (const_string “unknown”))

(define_attr “units64p” “unknown,d,d_addr,l,m,s,dl,ds,dls,ls” (attr “units64”))

(define_attr “units67” “unknown,d,d_addr,l,m,s,dl,ds,dls,ls” (attr “units62”))

(define_attr “units67p” “unknown,d,d_addr,l,m,s,dl,ds,dls,ls” (attr “units67”))

(define_attr “units674” “unknown,d,d_addr,l,m,s,dl,ds,dls,ls” (attr “units64”))

(define_attr “units” “unknown,d,d_addr,l,m,s,dl,ds,dls,ls” (cond [(eq_attr “cpu” “c62x”) (attr “units62”) (eq_attr “cpu” “c67x”) (attr “units67”) (eq_attr “cpu” “c67xp”) (attr “units67p”) (eq_attr “cpu” “c64x”) (attr “units64”) (eq_attr “cpu” “c64xp”) (attr “units64p”) (eq_attr “cpu” “c674x”) (attr “units674”) ] (const_string “unknown”)))

(define_automaton “c6x_1,c6x_2,c6x_m1,c6x_m2,c6x_t1,c6x_t2,c6x_branch”) (automata_option “no-comb-vect”) (automata_option “ndfa”) (automata_option “collapse-ndfa”)

(define_query_cpu_unit “d1,l1,s1” “c6x_1”) (define_cpu_unit “x1” “c6x_1”) (define_cpu_unit “l1w,s1w” “c6x_1”) (define_query_cpu_unit “m1” “c6x_m1”) (define_cpu_unit “m1w” “c6x_m1”) (define_cpu_unit “t1” “c6x_t1”) (define_query_cpu_unit “d2,l2,s2” “c6x_2”) (define_cpu_unit “x2” “c6x_2”) (define_cpu_unit “l2w,s2w” “c6x_2”) (define_query_cpu_unit “m2” “c6x_m2”) (define_cpu_unit “m2w” “c6x_m2”) (define_cpu_unit “t2” “c6x_t2”) ;; A special set of units used to identify specific reservations, rather than ;; just units. (define_query_cpu_unit “fps1,fpl1,adddps1,adddpl1” “c6x_1”) (define_query_cpu_unit “fps2,fpl2,adddps2,adddpl2” “c6x_2”)

;; There can be up to two branches in one cycle (on the .s1 and .s2 ;; units), but some instructions must not be scheduled in parallel ;; with a branch. We model this by reserving either br0 or br1 for a ;; normal branch, and both of them for an insn such as callp. ;; Another constraint is that two branches may only execute in parallel ;; if one uses an offset, and the other a register. We can distinguish ;; these by the dest_regfile attribute; it is “any” iff the branch uses ;; an offset. br0 is reserved for these, while br1 is reserved for ;; branches using a register. (define_cpu_unit “br0,br1” “c6x_branch”)

(include “c6x-sched.md”)

;; Some reservations which aren't generated from c6x-sched.md.in

(define_insn_reservation “branch_s1any” 6 (and (eq_attr “type” “branch”) (and (eq_attr “cross” “n”) (and (eq_attr “units” “s”) (eq_attr “dest_regfile” “any”)))) “s1+s1w+br0”)

;; For calls, we also reserve the units needed in the following cycles ;; to load the return address. There are two options; using addkpc or ;; mvkh/mvkl. The code in c6x_reorg knows whether to use one of these ;; or whether to use callp. The actual insns are emitted only after ;; the final scheduling pass is complete. ;; We always reserve S2 for PC-relative call insns, since that allows ;; us to turn them into callp insns later on. (define_insn_reservation “call_addkpc_s1any” 6 (and (eq_attr “type” “call”) (and (ne (symbol_ref “TARGET_INSNS_64”) (const_int 0)) (and (eq_attr “cross” “n”) (and (eq_attr “units” “s”) (eq_attr “dest_regfile” “any”))))) “s2+s2w+br0,s2+s2w+br0+br1”)

(define_insn_reservation “call_mvk_s1any” 6 (and (eq_attr “type” “call”) (and (eq (symbol_ref “TARGET_INSNS_64”) (const_int 0)) (and (eq_attr “cross” “n”) (and (eq_attr “units” “s”) (eq_attr “dest_regfile” “any”))))) “s2+s2w+br0,s2+s2w,s2+s2w”)

(define_reservation “all” “s1+s2+d1+d2+l1+l2+m1+m2”)

(define_insn_reservation “callp_s1” 1 (and (eq_attr “type” “callp”) (eq_attr “dest_regfile” “a”)) “s1+s1w,all*5”)

(define_insn_reservation “callp_s2” 1 (and (eq_attr “type” “callp”) (eq_attr “dest_regfile” “b”)) “s2+s2w,all*5”)

;; Constraints

(include “constraints.md”)

;; Predicates

(include “predicates.md”)

;; General predication pattern.

(define_cond_exec [(match_operator 0 “eqne_operator” [(match_operand 1 “predicate_register” “AB”) (const_int 0)])] "" "")

;; ------------------------------------------------------------------------- ;; NOP instruction ;; -------------------------------------------------------------------------

(define_insn “nop” [(const_int 0)] "" “nop”)

(define_insn “nop_count” [(unspec [(match_operand 0 “const_int_operand” “n”)] UNSPEC_NOP)] "" “%|%.\tnop\t%0”)

;; ------------------------------------------------------------------------- ;; Move instructions ;; -------------------------------------------------------------------------

(define_mode_iterator QIHIM [QI HI]) (define_mode_iterator SIDIM [SI DI]) (define_mode_iterator SIDIVM [SI DI V2HI V4QI]) (define_mode_iterator VEC4M [V2HI V4QI]) (define_mode_iterator VEC8M [V2SI V4HI V8QI]) (define_mode_iterator SISFVM [SI SF V2HI V4QI]) (define_mode_iterator DIDFM [DI DF]) (define_mode_iterator DIDFVM [DI DF V2SI V4HI V8QI]) (define_mode_iterator SFDFM [SF DF]) (define_mode_iterator M32 [QI HI SI SF V2HI V4QI])

;; The C6X LO_SUM and HIGH are backwards - HIGH sets the low bits, and ;; LO_SUM adds in the high bits. Fortunately these are opaque operations ;; so this does not matter. (define_insn “movsi_lo_sum” [(set (match_operand:SI 0 “register_operand” “=ab”) (lo_sum:SI (match_operand:SI 1 “register_operand” “0”) (match_operand:SI 2 “const_int_or_symbolic_operand” “i”)))] “reload_completed” “%|%.\tmvkh\t%$\t%2, %0” [(set_attr “units” “s”)])

(define_insn “movsi_high” [(set (match_operand:SI 0 “register_operand” “=ab”) (high:SI (match_operand:SI 1 “const_int_or_symbolic_operand” “i”)))] “reload_completed” “%|%.\tmvkl\t%$\t%1, %0” [(set_attr “units” “s”)])

(define_insn “movsi_gotoff_lo_sum” [(set (match_operand:SI 0 “register_operand” “=ab”) (lo_sum:SI (match_operand:SI 1 “register_operand” “0”) (unspec:SI [(match_operand:SI 2 “symbolic_operand” “S2”)] UNSPEC_GOTOFF)))] “flag_pic == 2” “%|%.\tmvkh\t%$\t$dpr_got%2, %0” [(set_attr “units” “s”)])

(define_insn “movsi_gotoff_high” [(set (match_operand:SI 0 “register_operand” “=ab”) (high:SI (unspec:SI [(match_operand:SI 1 “symbolic_operand” “S2”)] UNSPEC_GOTOFF)))] “flag_pic == 2” “%|%.\tmvkl\t%$\t$dpr_got%1, %0” [(set_attr “units” “s”)])

;; Normally we‘d represent this as a normal load insn, but we can’t currently ;; represent the addressing mode. (define_insn “load_got_gotoff” [(set (match_operand:SI 0 “register_operand” “=a,b”) (unspec:SI [(match_operand:SI 1 “register_operand” “Z,Z”) (match_operand:SI 2 “register_operand” “b,b”)] UNSPEC_GOTOFF))] “flag_pic == 2” “%|%.\tldw\t%$\t*+%1[%2], %0” [(set_attr “type” “load”) (set_attr “units” “d_addr”) (set_attr “op_pattern” “unknown”) (set_attr “dest_regfile” “a,b”) (set_attr “addr_regfile” “b”)])

(define_insn “*movstricthi_high” [(set (match_operand:SI 0 “register_operand” “+ab”) (ior:SI (and:SI (match_dup 0) (const_int 65535)) (ashift:SI (match_operand:SI 1 “const_int_operand” “IuB”) (const_int 16))))] “reload_completed” “%|%.\tmvklh\t%$\t%1, %0” [(set_attr “units” “s”)])

;; Break up SImode loads of immediate operands.

(define_split [(set (match_operand:SI 0 “register_operand” "") (match_operand:SI 1 “const_int_operand” ""))] “reload_completed && !satisfies_constraint_IsB (operands[1])” [(set (match_dup 0) (match_dup 2)) (set (match_dup 0) (ior:SI (and:SI (match_dup 0) (const_int 65535)) (ashift:SI (match_dup 3) (const_int 16))))] { HOST_WIDE_INT val = INTVAL (operands[1]); operands[2] = GEN_INT (trunc_int_for_mode (val, HImode)); operands[3] = GEN_INT ((val >> 16) & 65535); })

(define_split [(set (match_operand:VEC4M 0 “register_operand” "") (match_operand:VEC4M 1 “const_vector_operand” ""))] “reload_completed” [(set (match_dup 2) (match_dup 3))] { unsigned HOST_WIDE_INT mask, val; machine_mode inner_mode = GET_MODE_INNER (mode); int i;

val = 0; mask = GET_MODE_MASK (inner_mode); if (TARGET_BIG_ENDIAN) { for (i = 0; i < GET_MODE_NUNITS (mode); i++) { val <<= GET_MODE_BITSIZE (inner_mode); val |= INTVAL (CONST_VECTOR_ELT (operands[1], i)) & mask; } } else { i = GET_MODE_NUNITS (mode); while (i-- > 0) { val <<= GET_MODE_BITSIZE (inner_mode); val |= INTVAL (CONST_VECTOR_ELT (operands[1], i)) & mask; } } operands[2] = gen_rtx_REG (SImode, REGNO (operands[0])); operands[3] = GEN_INT (trunc_int_for_mode (val, SImode)); })

(define_split [(set (match_operand:VEC8M 0 “register_operand” "") (match_operand:VEC8M 1 “const_vector_operand” ""))] “reload_completed” [(set (match_dup 2) (match_dup 3)) (set (match_dup 4) (match_dup 5))] { unsigned HOST_WIDE_INT mask; unsigned HOST_WIDE_INT val[2]; rtx lo_half, hi_half; machine_mode inner_mode = GET_MODE_INNER (mode); int i, j;

split_di (operands, 1, &lo_half, &hi_half);

val[0] = val[1] = 0; mask = GET_MODE_MASK (inner_mode); if (TARGET_BIG_ENDIAN) { for (i = 0, j = 1; i < GET_MODE_NUNITS (mode); i++) { if (i * 2 == GET_MODE_NUNITS (mode)) j--; val[j] <<= GET_MODE_BITSIZE (inner_mode); val[j] |= INTVAL (CONST_VECTOR_ELT (operands[1], i)) & mask; } } else { i = GET_MODE_NUNITS (mode); j = 1; while (i-- > 0) { val[j] <<= GET_MODE_BITSIZE (inner_mode); val[j] |= INTVAL (CONST_VECTOR_ELT (operands[1], i)) & mask; if (i * 2 == GET_MODE_NUNITS (mode)) j--; } } operands[2] = lo_half; operands[3] = GEN_INT (trunc_int_for_mode (val[0], SImode)); operands[4] = hi_half; operands[5] = GEN_INT (trunc_int_for_mode (val[1], SImode)); })

(define_split [(set (match_operand:SF 0 “register_operand” "") (match_operand:SF 1 “immediate_operand” ""))] “reload_completed” [(set (match_dup 2) (match_dup 3)) (set (match_dup 2) (ior:SI (and:SI (match_dup 2) (const_int 65535)) (ashift:SI (match_dup 4) (const_int 16))))] { long values;

gcc_assert (GET_CODE (operands[1]) == CONST_DOUBLE);

REAL_VALUE_TO_TARGET_SINGLE (*CONST_DOUBLE_REAL_VALUE (operands[1]), values);

operands[2] = gen_rtx_REG (SImode, true_regnum (operands[0])); operands[3] = GEN_INT (trunc_int_for_mode (values, HImode)); if (values >= -32768 && values < 32768) { emit_move_insn (operands[2], operands[3]); DONE; } operands[4] = GEN_INT ((values >> 16) & 65535); })

(define_split [(set (match_operand:SI 0 “register_operand” "") (match_operand:SI 1 “symbolic_operand” ""))] “reload_completed && (!TARGET_INSNS_64PLUS || !sdata_symbolic_operand (operands[1], SImode))” [(set (match_dup 0) (high:SI (match_dup 1))) (set (match_dup 0) (lo_sum:SI (match_dup 0) (match_dup 1)))] "")

;; Normally, we represent the load of an sdata address as a normal ;; move of a SYMBOL_REF. In DSBT mode, B14 is not constant, so we ;; should show the dependency. (define_insn “load_sdata_pic” [(set (match_operand:SI 0 “register_operand” “=a,b”) (plus:SI (match_operand:SI 1 “pic_register_operand” “Z,Z”) (unspec:SI [(match_operand:SI 2 “sdata_symbolic_operand” “S0,S0”)] UNSPEC_LOAD_SDATA)))] “flag_pic” “@ %|%.\tadda%D2\t%$\t%1, %2, %0 %|%.\tadda%D2\t%$\t%1, %2, %0” [(set_attr “units” “d”) (set_attr “cross” “y,n”) (set_attr “op_pattern” “unknown”) (set_attr “predicable” “no”)])

;; Move instruction patterns

(define_mode_attr LDST_SUFFIX [(QI “b”) (HI “h”) (SI “w”) (SF “w”) (V2HI “w”) (V4QI “w”) (DI “dw”) (V2SI “dw”) (V4HI “dw”) (V8QI “dw”)])

(define_insn “mov_insn” [(set (match_operand:QIHIM 0 “nonimmediate_operand” “=a,b, a, b, ab, ab,a,?a, b,?b, Q, R, R, Q”) (match_operand:QIHIM 1 “general_operand” “a,b,?b,?a,Is5,IsB,Q, R, R, Q, a,?a, b,?b”))] “GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) == REG” “@ %|%.\tmv\t%$\t%1, %0 %|%.\tmv\t%$\t%1, %0 %|%.\tmv\t%$\t%1, %0 %|%.\tmv\t%$\t%1, %0 %|%.\tmvk\t%$\t%1, %0 %|%.\tmvk\t%$\t%1, %0 %|%.\tld<LDST_SUFFIX>\t%$\t%1, %0 %|%.\tld<LDST_SUFFIX>\t%$\t%1, %0 %|%.\tld<LDST_SUFFIX>\t%$\t%1, %0 %|%.\tld<LDST_SUFFIX>\t%$\t%1, %0 %|%.\tst<LDST_SUFFIX>\t%$\t%1, %0 %|%.\tst<LDST_SUFFIX>\t%$\t%1, %0 %|%.\tst<LDST_SUFFIX>\t%$\t%1, %0 %|%.\tst<LDST_SUFFIX>\t%$\t%1, %0” [(set_attr “type” “,,,,,,load,load,load,load,store,store,store,store”) (set_attr “units62” “dls,dls,ls,ls,s,s,d_addr,d_addr,d_addr,d_addr,d_addr,d_addr,d_addr,d_addr”) (set_attr “units64” “dls,dls,ls,ls,dl,s,d_addr,d_addr,d_addr,d_addr,d_addr,d_addr,d_addr,d_addr”) (set_attr “op_pattern” “sx,sx,sx,sx,,,,,,,,,,”) (set_attr “addr_regfile” “,,,,,,a,b,b,a,a,b,b,a”) (set_attr “dest_regfile” “,,,,,,a,a,b,b,a,a,b,b”) (set_attr “cross” “n,n,y,y,n,n,n,y,n,y,n,y,n,y”)])

(define_insn “mov_insn” [(set (match_operand:SISFVM 0 “nonimmediate_operand” “=a,b, a, b, ab, ab,a,b,ab,a,?a, b,?b, Q, R, R, Q”) (match_operand:SISFVM 1 “general_operand” “a,b,?b,?a,Is5,IsB,S0,S0,Si,Q, R, R, Q, a,?a, b,?b”))] “(GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) == REG || (GET_CODE (operands[1]) == SUBREG && REG_P (SUBREG_REG (operands[1]))))” "@ %|%.\tmv\t%$\t%1, %0 %|%.\tmv\t%$\t%1, %0 %|%.\tmv\t%$\t%1, %0 %|%.\tmv\t%$\t%1, %0 %|%.\tmvk\t%$\t%1, %0 %|%.\tmvk\t%$\t%1, %0 %|%.\tadda%D1\t%$\tB14, %1, %0 %|%.\tadda%D1\t%$\tB14, %1, %0

%|%.\tldw\t%$\t%1, %0 %|%.\tldw\t%$\t%1, %0 %|%.\tldw\t%$\t%1, %0 %|%.\tldw\t%$\t%1, %0 %|%.\tstw\t%$\t%1, %0 %|%.\tstw\t%$\t%1, %0 %|%.\tstw\t%$\t%1, %0 %|%.\tstw\t%$\t%1, %0" [(set_attr “type” “,,,,,,,,*,load,load,load,load,store,store,store,store”) (set_attr “units62” “dls,dls,ls,ls,s,s,d,d,*,d_addr,d_addr,d_addr,d_addr,d_addr,d_addr,d_addr,d_addr”) (set_attr “units64” “dls,dls,ls,ls,dl,s,d,d,*,d_addr,d_addr,d_addr,d_addr,d_addr,d_addr,d_addr,d_addr”) (set_attr “op_pattern” “sx,sx,sx,sx,,,,,,,,,,,,,*”) (set_attr “addr_regfile” “,,,,,,,,*,a,b,b,a,a,b,b,a”) (set_attr “dest_regfile” “,,,,,,,,*,a,a,b,b,a,a,b,b”) (set_attr “cross” “n,n,y,y,n,n,y,n,*,n,y,n,y,n,y,n,y”) (set_attr “predicable” “yes,yes,yes,yes,yes,yes,no,no,yes,yes,yes,yes,yes,yes,yes,yes,yes”)])

(define_insn “*mov_insn” [(set (match_operand:DIDFVM 0 “nonimmediate_operand” “=a,b, a, b,ab,a,?a, b,?b, Q, R, R, Q”) (match_operand:DIDFVM 1 “general_operand” “a,b,?b,?a,iF,Q, R, R, Q, a,?a, b,?b”))] “(!MEM_P (operands[0]) || REG_P (operands[1]) || (GET_CODE (operands[1]) == SUBREG && REG_P (SUBREG_REG (operands[1]))))” { if (MEM_P (operands[1]) && TARGET_LDDW) return “%|%.\tlddw\t%$\t%1, %0”; if (MEM_P (operands[0]) && TARGET_STDW) return “%|%.\tstdw\t%$\t%1, %0”; if (TARGET_INSNS_64PLUS && REG_P (operands[0]) && REG_P (operands[1]) && A_REGNO_P (REGNO (operands[0])) == A_REGNO_P (REGNO (operands[1]))) return “%|%.\tdmv\t%$\t%P1, %p1, %0”; return “#”; } [(set_attr “units” “s,s,,,*,d_addr,d_addr,d_addr,d_addr,d_addr,d_addr,d_addr,d_addr”) (set_attr “addr_regfile” “,,,,*,a,b,b,a,a,b,b,a”) (set_attr “dest_regfile” “,,,,*,a,a,b,b,a,a,b,b”) (set_attr “type” “,,,,*,load,load,load,load,store,store,store,store”) (set_attr “cross” “n,n,y,y,*,n,y,n,y,n,y,n,y”)])

(define_split [(set (match_operand:DIDFVM 0 “nonimmediate_operand” "") (match_operand:DIDFVM 1 “general_operand” ""))] “reload_completed && !((MEM_P (operands[0]) && TARGET_STDW) || (MEM_P (operands[1]) && TARGET_LDDW)) && !const_vector_operand (operands[1], mode) && !(TARGET_INSNS_64PLUS && REG_P (operands[0]) && REG_P (operands[1]) && A_REGNO_P (REGNO (operands[0])) == A_REGNO_P (REGNO (operands[1])))” [(set (match_dup 2) (match_dup 3)) (set (match_dup 4) (match_dup 5))] { rtx lo_half[2], hi_half[2]; split_di (operands, 2, lo_half, hi_half);

/* We can‘t have overlap for a register-register move, but if memory is involved, we have to make sure we don’t clobber the address. */ if (reg_overlap_mentioned_p (lo_half[0], hi_half[1])) { operands[2] = hi_half[0]; operands[3] = hi_half[1]; operands[4] = lo_half[0]; operands[5] = lo_half[1]; } else { operands[2] = lo_half[0]; operands[3] = lo_half[1]; operands[4] = hi_half[0]; operands[5] = hi_half[1]; } })

(define_insn “real_load” [(unspec [(match_operand 0 “const_int_operand” “JA,JA,JB,JB”) (match_operand:M32 1 “memory_operand” “Q,R,R,Q”)] UNSPEC_REAL_LOAD)] "" “%|%.\tld<LDST_SUFFIX>\t%$\t%1, %k0” [(set_attr “type” “load”) (set_attr “units” “d_addr”) (set_attr “addr_regfile” “a,b,b,a”) (set_attr “dest_regfile” “a,a,b,b”) (set_attr “cross” “n,y,n,y”)])

(define_insn “real_load” [(unspec [(match_operand 0 “const_int_operand” “JA,JA,JB,JB”) (match_operand:DIDFVM 1 “memory_operand” “Q,R,R,Q”)] UNSPEC_REAL_LOAD)] “TARGET_LDDW” “%|%.\tlddw\t%$\t%1, %K0” [(set_attr “type” “load”) (set_attr “units” “d_addr”) (set_attr “addr_regfile” “a,b,b,a”) (set_attr “dest_regfile” “a,a,b,b”) (set_attr “cross” “n,y,n,y”)])

(define_insn “load_shadow” [(set (match_operand 0 “register_operand” “=ab”) (unspec [(pc)] UNSPEC_LOAD_SHADOW))] "" “;; load to %0 occurs” [(set_attr “type” “load_shadow”)])

(define_insn “mult_shadow” [(set (match_operand 0 “register_operand” “=ab”) (unspec [(pc)] UNSPEC_MULT_SHADOW))] "" “;; multiplication occurs and stores to %0” [(set_attr “type” “mult_shadow”)])

(define_mode_iterator MOV [QI HI SI SF DI DF V2HI V4QI V2SI V4HI V8QI])

(define_expand “mov” [(set (match_operand:MOV 0 “nonimmediate_operand” "") (match_operand:MOV 1 “general_operand” ""))] "" { if (expand_move (operands, mode)) DONE; })

(define_expand “movmisalign” [(set (match_operand:SIDIVM 0 “nonimmediate_operand” "") (unspec:SIDIVM [(match_operand:SIDIVM 1 “nonimmediate_operand” "")] UNSPEC_MISALIGNED_ACCESS))] “TARGET_INSNS_64” { if (MEM_P (operands[0])) { emit_insn (gen_movmisalign_store (operands[0], operands[1])); DONE; } })

(define_insn_and_split “movmisalign_store” [(set (match_operand:SIDIVM 0 “memory_operand” “=W,Q,T,Q,T”) (unspec:SIDIVM [(match_operand:SIDIVM 1 “register_operand” “r,a,b,b,a”)] UNSPEC_MISALIGNED_ACCESS)) (clobber (match_scratch:SI 2 “=r,X,X,X,X”))] “TARGET_INSNS_64” "@

%|%.\tstn<LDST_SUFFIX>\t%$\t%1, %0 %|%.\tstn<LDST_SUFFIX>\t%$\t%1, %0 %|%.\tstn<LDST_SUFFIX>\t%$\t%1, %0 %|%.\tstn<LDST_SUFFIX>\t%$\t%1, %0" “&& reload_completed && satisfies_constraint_W (operands[0])” [(parallel [(set (match_dup 3) (unspec:SIDIVM [(match_dup 1)] UNSPEC_MISALIGNED_ACCESS)) (clobber (match_dup 4))])] { rtx addr = XEXP (operands[0], 0); rtx tmpreg = operands[2];

if (GET_CODE (addr) == PLUS && XEXP (addr, 0) == stack_pointer_rtx && GET_CODE (XEXP (addr, 1)) == CONST_INT) { unsigned HOST_WIDE_INT val = INTVAL (XEXP (addr, 1)); val &= GET_MODE_SIZE (mode) - 1; if (val == 0) { emit_move_insn (operands[0], operands[1]); DONE; } } operands[3] = change_address (operands[0], mode, tmpreg); emit_move_insn (tmpreg, addr); operands[4] = gen_rtx_SCRATCH (SImode); } [(set_attr “type” “storen”) (set_attr “units” “d_addr”) (set_attr “addr_regfile” “*,a,b,a,b”) (set_attr “dest_regfile” “*,a,b,b,a”) (set_attr “cross” “*,n,n,y,y”)])

(define_insn_and_split “movmisalign_load” [(set (match_operand:SIDIVM 0 “register_operand” “=ab,a,b,b,a”) (unspec:SIDIVM [(match_operand:SIDIVM 1 “memory_operand” “W,Q,T,Q,T”)] UNSPEC_MISALIGNED_ACCESS))] “TARGET_INSNS_64” "@

%|%.\tldn<LDST_SUFFIX>\t%$\t%1, %0 %|%.\tldn<LDST_SUFFIX>\t%$\t%1, %0 %|%.\tldn<LDST_SUFFIX>\t%$\t%1, %0 %|%.\tldn<LDST_SUFFIX>\t%$\t%1, %0" “&& reload_completed && satisfies_constraint_W (operands[1])” [(set (match_dup 0) (unspec:SIDIVM [(match_dup 2)] UNSPEC_MISALIGNED_ACCESS))] { rtx addr = XEXP (operands[1], 0); rtx tmpreg = (GET_MODE (operands[0]) == SImode ? operands[0] : operand_subword_force (operands[0], 0, DImode));

if (GET_CODE (addr) == PLUS && XEXP (addr, 0) == stack_pointer_rtx && GET_CODE (XEXP (addr, 1)) == CONST_INT) { unsigned HOST_WIDE_INT val = INTVAL (XEXP (addr, 1)); val &= GET_MODE_SIZE (mode) - 1; if (val == 0) { emit_move_insn (operands[0], operands[1]); DONE; } } operands[2] = change_address (operands[1], mode, tmpreg); emit_move_insn (tmpreg, addr); } [(set_attr “type” “loadn”) (set_attr “units” “d_addr”) (set_attr “addr_regfile” “*,a,b,a,b”) (set_attr “dest_regfile” “*,a,b,b,a”) (set_attr “cross” “*,n,n,y,y”)])

;;

;; ------------------------------------------------------------------------- ;; Extensions/extractions ;; -------------------------------------------------------------------------

(define_code_iterator any_extract [zero_extract sign_extract]) (define_code_iterator any_ext [zero_extend sign_extend])

(define_code_attr ext_name [(zero_extend “zero_extend”) (sign_extend “sign_extend”)])

(define_code_attr u [(zero_extend “u”) (sign_extend "")])

(define_code_attr z [(zero_extract “z”) (sign_extract "")]) (define_code_attr zu [(zero_extract “u”) (sign_extract "")])

(define_mode_attr ext_shift [(QI “24”) (HI “16”)])

(define_insn “<ext_name>si2” [(set (match_operand:SI 0 “register_operand” “=a,b,a,?a, b,?b”) (any_ext:SI (match_operand:QIHIM 1 “nonimmediate_operand” “a,b,Q, R, R, Q”)))] "" “@ %|%.\text\t%$\t%1, <ext_shift>, <ext_shift>, %0 %|%.\text\t%$\t%1, <ext_shift>, <ext_shift>, %0 %|%.\tld<LDST_SUFFIX>\t%$\t%1, %0 %|%.\tld<LDST_SUFFIX>\t%$\t%1, %0 %|%.\tld<LDST_SUFFIX>\t%$\t%1, %0 %|%.\tld<LDST_SUFFIX>\t%$\t%1, %0” [(set_attr “type” “,,load,load,load,load”) (set_attr “units” “s,s,d_addr,d_addr,d_addr,d_addr”) (set_attr “addr_regfile” “,,a,b,b,a”) (set_attr “dest_regfile” “,,a,a,b,b”) (set_attr “cross” “n,n,n,y,n,y”)])

(define_insn “*extv_const” [(set (match_operand:SI 0 “nonimmediate_operand” “=a,b”) (any_extract:SI (match_operand:SI 1 “register_operand” “a,b”) (match_operand:SI 2 “const_int_operand” “n,n”) (match_operand:SI 3 “const_int_operand” “n,n”)))] “INTVAL (operands[3]) >= 0 && INTVAL (operands[2]) + INTVAL (operands[3]) <= 32” { int pos = INTVAL (operands[3]); int len = INTVAL (operands[2]); rtx xop[4]; xop[0] = operands[0]; xop[1] = operands[1]; xop[2] = GEN_INT (32 - pos - len); xop[3] = GEN_INT (32 - len);

output_asm_insn (“%|%.\text\t%$\t%1, %2, %3, %0”, xop); return ""; } [(set_attr “units” “s”) (set_attr “cross” “n”)])

(define_expand “extv” [(set (match_operand:SI 0 “register_operand” "") (any_extract:SI (match_operand:SI 1 “register_operand” "") (match_operand:SI 2 “const_int_operand” "") (match_operand:SI 3 “const_int_operand” "")))] "" { if (INTVAL (operands[2]) < 0 || INTVAL (operands[2]) + INTVAL (operands[3]) > 32) FAIL; })

(define_insn “real_<ext_name>” [(unspec [(match_operand 0 “const_int_operand” “JA,JA,JB,JB”) (any_ext:SI (match_operand:QIHIM 1 “memory_operand” “Q,R,R,Q”))] UNSPEC_REAL_LOAD)] "" “%|%.\tld<LDST_SUFFIX>\t%$\t%1, %k0” [(set_attr “type” “load”) (set_attr “units” “d_addr”) (set_attr “addr_regfile” “a,b,b,a”) (set_attr “dest_regfile” “a,a,b,b”) (set_attr “cross” “n,y,n,y”)])

(define_insn “clrr” [(set (match_operand:SI 0 “register_operand” “=a,b,a,b”) (unspec:SI [(match_operand:SI 1 “register_operand” “0,0,0,0”) (match_operand:SI 2 “register_operand” “a,b,?b,?a”) (match_operand:SI 3 “reg_or_const_int_operand” “ai,bi,a,b”)] UNSPEC_CLR))] "" { if (CONST_INT_P (operands[2])) { rtx xops[4]; int v1 = INTVAL (operands[2]); int v2 = (v1 >> 5) & 0x1f; v1 &= 0x1f; xops[0] = operands[0]; xops[1] = operands[1]; xops[2] = GEN_INT (v1); xops[3] = GEN_INT (v2); output_asm_insn (“%|%.\tclr\t%$\t%1, %3, %2, %0”, xops); return ""; } return “%|%.\tclr\t%$\t%2, %3, %0”; } [(set_attr “units” “s”) (set_attr “cross” “n,n,y,y”)])

(define_insn “extr” [(set (match_operand:SI 0 “register_operand” “=a,b,a,b”) (unspec:SI [(match_operand:SI 1 “register_operand” “a,b,?b,?a”) (match_operand:SI 2 “reg_or_const_int_operand” “ai,bi,a,b”)] UNSPEC_EXT))] "" { if (CONST_INT_P (operands[2])) { rtx xops[4]; int v1 = INTVAL (operands[2]); int v2 = (v1 >> 5) & 0x1f; v1 &= 0x1f; xops[0] = operands[0]; xops[1] = operands[1]; xops[2] = GEN_INT (v1); xops[3] = GEN_INT (v2); output_asm_insn (“%|%.\text\t%$\t%1, %3, %2, %0”, xops); return ""; } return “%|%.\text\t%$\t%1, %2, %0”; } [(set_attr “units” “s”) (set_attr “cross” “n,n,y,y”)])

(define_insn “extru” [(set (match_operand:SI 0 “register_operand” “=a,b,a,b”) (unspec:SI [(match_operand:SI 1 “register_operand” “a,b,?b,?a”) (match_operand:SI 2 “reg_or_const_int_operand” “ai,bi,a,b”)] UNSPEC_EXTU))] "" { if (CONST_INT_P (operands[2])) { rtx xops[4]; int v1 = INTVAL (operands[2]); int v2 = (v1 >> 5) & 0x1f; v1 &= 0x1f; xops[0] = operands[0]; xops[1] = operands[1]; xops[2] = GEN_INT (v1); xops[3] = GEN_INT (v2); output_asm_insn (“%|%.\textu\t%$\t%1, %3, %2, %0”, xops); return ""; } return “%|%.\textu\t%$\t%1, %2, %0”; } [(set_attr “units” “s”) (set_attr “cross” “n,y,n,y”)])

;; ------------------------------------------------------------------------- ;; Compare instructions ;; -------------------------------------------------------------------------

(define_insn “scmpsi_insn” [(set (match_operand:SI 0 “register_operand” “=ab,a,b,a,b”) (match_operator:SI 1 “eqltgt_operator” [(match_operand:SI 2 “register_operand” “ab,a,b,?b,?a”) (match_operand:SI 3 “reg_or_scst5_operand” “Is5,aIs5,bIs5,aIs5,bIs5”)]))] "" “%|%.\tcmp%C1\t%$\t%3, %2, %0” [(set_attr “units” “l”) (set (attr “cross”) (symbol_ref “CROSS_OPERANDS (operands[0], operands[2])”))])

(define_insn “*ucmpsi_insn_64” [(set (match_operand:SI 0 “register_operand” “=ab,a,b,a,b”) (match_operator:SI 1 “ltugtu_operator” [(match_operand:SI 2 “register_operand” “ab,a,b,?b,?a”) (match_operand:SI 3 “reg_or_ucst5_operand” “Iu5,aIu5,bIu5,aIu5,bIu5”)]))] “TARGET_INSNS_64” “%|%.\tcmp%C1\t%$\t%3, %2, %0” [(set_attr “units” “l”) (set (attr “cross”) (symbol_ref “CROSS_OPERANDS (operands[0], operands[2])”))])

(define_insn “*ucmpsi_insn” [(set (match_operand:SI 0 “register_operand” “=ab,a,b,a,b”) (match_operator:SI 1 “ltugtu_operator” [(match_operand:SI 2 “register_operand” “ab,a,b,?b,?a”) (match_operand:SI 3 “reg_or_ucst4_operand” “Iu4,aIu4,bIu4,aIu4,bIu4”)]))] “!TARGET_INSNS_64” “%|%.\tcmp%C1\t%$\t%3, %2, %0” [(set_attr “units” “l”) (set (attr “cross”) (symbol_ref “CROSS_OPERANDS (operands[0], operands[2])”))])

(define_code_iterator andior_eqne [eq ne]) (define_code_attr andior_name [(eq “and”) (ne “ior”)]) (define_code_attr andior_condmod [(eq "") (ne “!”)])

(define_insn “*scmpsi_<andior_name>_insn” [(set (match_operand:SI 0 “register_operand” “=A,B,A,B”) (if_then_else:SI (andior_eqne:SI (match_operand:SI 4 “register_operand” “0,0,0,0”) (const_int 0)) (match_dup 4) (match_operator:SI 1 “eqltgt_operator” [(match_operand:SI 2 “register_operand” “a,b,?b,?a”) (match_operand:SI 3 “reg_or_scst5_operand” “aIs5,bIs5,aIs5,bIs5”)])))] "" “%|[<andior_condmod>%4]\tcmp%C1\t%$\t%3, %2, %0” [(set_attr “units” “l”) (set_attr “cross” “n,n,y,y”) (set_attr “predicable” “no”)])

(define_insn “*ucmpsi_<andior_name>_insn_64” [(set (match_operand:SI 0 “register_operand” “=A,B,A,B”) (if_then_else:SI (andior_eqne:SI (match_operand:SI 4 “register_operand” “0,0,0,0”) (const_int 0)) (match_dup 4) (match_operator:SI 1 “ltugtu_operator” [(match_operand:SI 2 “register_operand” “a,b,?b,?a”) (match_operand:SI 3 “reg_or_ucst5_operand” “aIu5,bIu5,aIu5,bIu5”)])))] “TARGET_INSNS_64” “%|[<andior_condmod>%4]\tcmp%C1\t%$\t%3, %2, %0” [(set_attr “units” “l”) (set_attr “cross” “n,n,y,y”) (set_attr “predicable” “no”)])

(define_insn “*ucmpsi_<andior_name>_insn” [(set (match_operand:SI 0 “register_operand” “=A,B,A,B”) (if_then_else:SI (andior_eqne:SI (match_operand:SI 4 “register_operand” “0,0,0,0”) (const_int 0)) (match_dup 4) (match_operator:SI 1 “ltugtu_operator” [(match_operand:SI 2 “register_operand” “a,b,?b,?a”) (match_operand:SI 3 “reg_or_ucst4_operand” “aIu4,bIu4,aIu4,bIu4”)])))] “!TARGET_INSNS_64” “%|[<andior_condmod>%4]\tcmp%C1\t%$\t%3, %2, %0” [(set_attr “units” “l”) (set_attr “cross” “n,n,y,y”) (set_attr “predicable” “no”)])

(define_expand “cmpsi_<andior_name>” [(set (match_operand:SI 0 “register_operand” "") (if_then_else:SI (andior_eqne:SI (match_operand:SI 4 “register_operand” “0,0,0,0”) (const_int 0)) (match_dup 4) (match_operator:SI 1 “c6x_comparison_operator” [(match_operand:SI 2 “register_operand” "") (match_operand:SI 3 “reg_or_const_int_operand” "")])))] "" { if (c6x_force_op_for_comparison_p (GET_CODE (operands[1]), operands[3])) operands[3] = force_reg (SImode, operands[3]); })

(define_insn “*cmpsf_insn” [(set (match_operand:SI 0 “register_operand” “=a,b,a,b”) (match_operator:SI 1 “eqltgt_operator” [(match_operand:SF 2 “register_operand” “a,b,a,b”) (match_operand:SF 3 “register_operand” “a,b,?b,?a”)]))] “TARGET_FP” “%|%.\tcmp%c1sp\t%$\t%2, %3, %0” [(set_attr “units” “s”) (set_attr “cross” “n,n,y,y”)])

(define_insn “*cmpdf_insn” [(set (match_operand:SI 0 “register_operand” “=a,b,a,b”) (match_operator:SI 1 “eqltgt_operator” [(match_operand:DF 2 “register_operand” “a,b,a,b”) (match_operand:DF 3 “register_operand” “a,b,?b,?a”)]))] “TARGET_FP” “%|%.\tcmp%c1dp\t%$\t%2, %3, %0” [(set_attr “type” “cmpdp”) (set_attr “units” “s”) (set_attr “cross” “n,n,y,y”)])

(define_expand “cmp_<andior_name>” [(set (match_operand:SI 0 “register_operand” "") (if_then_else:SI (andior_eqne:SI (match_operand:SI 4 “register_operand” “0,0,0,0”) (const_int 0)) (match_dup 4) (match_operator:SI 1 “eqltgt_operator” [(match_operand:SFDFM 2 “register_operand” "") (match_operand:SFDFM 3 “register_operand” "")])))] “TARGET_FP”)

(define_insn “*cmpsf_<andior_name>_insn” [(set (match_operand:SI 0 “register_operand” “=A,B,A,B”) (if_then_else:SI (andior_eqne:SI (match_operand:SI 4 “register_operand” “0,0,0,0”) (const_int 0)) (match_dup 4) (match_operator:SI 1 “eqltgt_operator” [(match_operand:SF 2 “register_operand” “a,b,a,b”) (match_operand:SF 3 “register_operand” “a,b,?b,?a”)])))] “TARGET_FP” “%|[<andior_condmod>%4]\tcmp%c1sp\t%$\t%2, %3, %0” [(set_attr “units” “s”) (set_attr “cross” “n,n,y,y”) (set_attr “predicable” “no”)])

;; reload_reg_class_lower will ensure that two-word reloads are allocated first, ;; which could exhaust the predicate registers if we used just “a” and “b” ;; constraints on operands 2 and 3. (define_insn “*cmpdf_<andior_name>_insn” [(set (match_operand:SI 0 “register_operand” “=A,B,A,B”) (if_then_else:SI (andior_eqne:SI (match_operand:SI 4 “register_operand” “0,0,0,0”) (const_int 0)) (match_dup 4) (match_operator:SI 1 “eqltgt_operator” [(match_operand:DF 2 “register_operand” “Da,Db,Da,Db”) (match_operand:DF 3 “register_operand” “Da,Db,?Db,?Da”)])))] “TARGET_FP” “%|[<andior_condmod>%4]\tcmp%c1dp\t%$\t%2, %3, %0” [(set_attr “type” “cmpdp”) (set_attr “units” “s”) (set_attr “cross” “n,n,y,y”) (set_attr “predicable” “no”)])

(define_split [(set (match_operand:SI 0 “register_operand” "") (ior:SI (match_operand 1 “c6x_any_comparison_operand” "") (match_operand 2 “c6x_any_comparison_operand” "")))] “!reg_overlap_mentioned_p (operands[0], operands[2])” [(set (match_dup 0) (match_dup 1)) (set (match_dup 0) (if_then_else:SI (ne:SI (match_dup 0) (const_int 0)) (match_dup 0) (match_dup 2)))])

(define_split [(set (match_operand:SI 0 “register_operand” "") (and:SI (match_operand 1 “c6x_any_comparison_operand” "") (match_operand 2 “c6x_any_comparison_operand” "")))] “!reg_overlap_mentioned_p (operands[0], operands[2])” [(set (match_dup 0) (match_dup 1)) (set (match_dup 0) (if_then_else:SI (eq:SI (match_dup 0) (const_int 0)) (match_dup 0) (match_dup 2)))])

;; ------------------------------------------------------------------------- ;; setcc instructions ;; -------------------------------------------------------------------------

(define_expand “cstoresi4” [(set (match_operand:SI 0 “register_operand” "") (match_operator:SI 1 “comparison_operator” [(match_operand:SI 2 “register_operand” "") (match_operand:SI 3 “reg_or_ucst4_operand” "")]))] "" { if (!c6x_comparison_operator (operands[1], SImode)) { rtx tmpreg = gen_reg_rtx (SImode); rtx t = gen_rtx_fmt_ee (reverse_condition (GET_CODE (operands[1])), SImode, operands[2], operands[3]); emit_insn (gen_rtx_SET (tmpreg, t)); emit_insn (gen_scmpsi_insn (operands[0], gen_rtx_fmt_ee (EQ, SImode, tmpreg, const0_rtx), tmpreg, const0_rtx)); DONE; } })

;; ------------------------------------------------------------------------- ;; Jump instructions ;; -------------------------------------------------------------------------

(define_insn “indirect_jump” [(set (pc) (match_operand:SI 0 “register_operand” “a,b”))] "" “%|%.\tb\t%$\t%0” [(set_attr “type” “branch”) (set_attr “units” “s”) (set_attr “cross” “y,n”) (set_attr “dest_regfile” “b”)])

(define_insn “jump” [(set (pc) (label_ref (match_operand 0 "" "")))] "" “%|%.\tb\t%$\t%l0” [(set_attr “type” “branch”) (set_attr “units” “s”) (set_attr “dest_regfile” “any”)])

(define_expand “tablejump” [(parallel [(set (pc) (match_operand:SI 0 “register_operand” "")) (use (label_ref (match_operand 1 "" "")))])] “!flag_pic || !TARGET_INSNS_64” { })

(define_insn “*tablejump_internal” [(set (pc) (match_operand:SI 0 “register_operand” “b”)) (use (label_ref (match_operand 1 "" "")))] “!flag_pic || !TARGET_INSNS_64” “%|\tb\t%$\t%0” [(set_attr “type” “branch”) (set_attr “predicable” “no”) (set_attr “units” “s”) (set_attr “dest_regfile” “b”)])

;; Implement switch statements when generating PIC code. Switches are ;; implemented by `tablejump' when not using -fpic.

;; Emit code here to do the range checking and make the index zero based. ;; operand 0 is the index ;; operand 1 is the lower bound ;; operand 2 is the range of indices (highest - lowest + 1) ;; operand 3 is the label that precedes the table itself ;; operand 4 is the fall through label

(define_expand “casesi” [(use (match_operand:SI 0 “register_operand” "")) (use (match_operand:SI 1 “const_int_operand” "")) (use (match_operand:SI 2 “const_int_operand” "")) (use (match_operand 3 "" "")) (use (match_operand 4 "" ""))] “flag_pic && TARGET_INSNS_64” { rtx indx; rtx low = operands[1]; rtx range = operands[2]; rtx table = operands[3]; rtx fail = operands[4];

gcc_assert (GET_CODE (operands[1]) == CONST_INT); gcc_assert (GET_CODE (operands[2]) == CONST_INT);

if (!reg_or_ucst4_operand (range, SImode)) range = force_reg (SImode, range);

/* If low bound is 0, we don't have to subtract it. */ if (INTVAL (operands[1]) == 0) indx = operands[0]; else { rtx offset = GEN_INT (-INTVAL (low)); indx = gen_reg_rtx (SImode); if (!addsi_operand (offset, SImode)) offset = force_reg (SImode, offset); emit_insn (gen_addsi3 (indx, operands[0], offset)); } emit_cmp_and_jump_insns (indx, range, GTU, NULL_RTX, SImode, 1, fail);

emit_jump_insn (gen_casesi_internal (indx, table)); DONE; })

;; This is the only instance in this file where a pattern emits more than ;; one instruction. The concern here is that the addkpc insn could otherwise ;; be scheduled too far away from the label. A tablejump always ends an ;; extended basic block, so it shouldn't happen that the scheduler places ;; something in the delay slots. (define_insn “casesi_internal” [(set (pc) (mem:SI (plus:SI (mult:SI (match_operand:SI 0 “register_operand” “b”) (const_int 4)) (label_ref (match_operand 1 "" ""))))) (clobber (match_scratch:SI 2 “=&b”)) (clobber (match_scratch:SI 3 “=b”))] “flag_pic && TARGET_INSNS_64” “addkpc\t.s2\t%l1,%2, 0\n\t\tldw\t.d2t2\t*+%2[%0], %3\n\t\tnop\t\t4\n\t\tadd\t.l2\t%2, %3, %3\n\t\tb\t.s2\t%3” [(set_attr “type” “branch”) (set_attr “predicable” “no”) (set_attr “dest_regfile” “b”)])

(define_expand “cbranch4” [(set (pc) (if_then_else (match_operator 0 “comparison_operator” [(match_operand:SIDIM 1 “register_operand” "") (match_operand:SIDIM 2 “reg_or_const_int_operand” "")]) (label_ref (match_operand 3 "" "")) (pc)))] "" { rtx t = c6x_expand_compare (operands[0], VOIDmode); operands[0] = t; operands[1] = XEXP (t, 0); operands[2] = XEXP (t, 1); })

(define_expand “cbranch4” [(set (pc) (if_then_else (match_operator 0 “c6x_fp_comparison_operator” [(match_operand:SFDFM 1 “register_operand” "") (match_operand:SFDFM 2 “register_operand” "")]) (label_ref (match_operand 3 "" "")) (pc)))] "" { rtx t = c6x_expand_compare (operands[0], VOIDmode); operands[0] = t; operands[1] = XEXP (t, 0); operands[2] = XEXP (t, 1); })

(define_insn “br_true” [(set (pc) (if_then_else (match_operator 0 “predicate_operator” [(match_operand:SI 1 “register_operand” “AB”) (const_int 0)]) (label_ref (match_operand 2 "" "")) (pc)))] "" “%|[%J0]\tb\t%$\t%l2” [(set_attr “type” “branch”) (set_attr “predicable” “no”) (set_attr “units” “s”) (set_attr “dest_regfile” “any”)])

(define_insn “br_false” [(set (pc) (if_then_else (match_operator 0 “predicate_operator” [(match_operand:SI 1 “register_operand” “AB”) (const_int 0)]) (pc) (label_ref (match_operand 2 "" ""))))] "" “%|[%j0]\tb\t%$\t%l2” [(set_attr “type” “branch”) (set_attr “predicable” “no”) (set_attr “units” “s”) (set_attr “dest_regfile” “any”)])

(define_expand “return” [(parallel [(return) (use (reg:SI REG_B3))])] “reload_completed && get_frame_size () == 0 && c6x_nsaved_regs () == 0”)

;; We can't expand this before we know where the link register is stored. (define_insn_and_split “eh_return” [(unspec_volatile [(match_operand:SI 0 “register_operand” “ab”)] UNSPECV_EH_RETURN) (clobber (match_scratch:SI 1 “=&ab”))] "" “#” “&& reload_completed” [(const_int 0)] " { c6x_set_return_address (operands[0], operands[1]); DONE; }" )

;; ------------------------------------------------------------------------- ;; Doloop ;; -------------------------------------------------------------------------

; operand 0 is the loop count pseudo register ; operand 1 is the label to jump to at the top of the loop (define_expand “doloop_end” [(parallel [(set (pc) (if_then_else (ne (match_operand:SI 0 "" "") (const_int 1)) (label_ref (match_operand 1 "" "")) (pc))) (set (match_dup 0) (plus:SI (match_dup 0) (const_int -1))) (clobber (match_dup 2))])] ; match_scratch “TARGET_INSNS_64PLUS && optimize” { /* The loop optimizer doesn't check the predicates... */ if (GET_MODE (operands[0]) != SImode) FAIL; operands[2] = gen_rtx_SCRATCH (SImode); })

(define_insn “mvilc” [(set (reg:SI REG_ILC) (unspec [(match_operand:SI 0 “register_operand” “a,b”)] UNSPEC_MVILC))] “TARGET_INSNS_64PLUS” “%|%.\tmvc\t%$\t%0, ILC” [(set_attr “predicable” “no”) (set_attr “cross” “y,n”) (set_attr “units” “s”) (set_attr “dest_regfile” “b”) (set_attr “type” “mvilc”)])

(define_insn “sploop” [(unspec_volatile [(match_operand:SI 0 “const_int_operand” “i”) (reg:SI REG_ILC)] UNSPECV_SPLOOP)] “TARGET_INSNS_64PLUS” “%|%.\tsploop\t%0” [(set_attr “predicable” “no”) (set_attr “type” “sploop”)])

(define_insn “spkernel” [(set (pc) (if_then_else (ne (unspec_volatile:SI [(match_operand:SI 0 “const_int_operand” “i”) (match_operand:SI 1 “const_int_operand” “i”)] UNSPECV_SPKERNEL) (const_int 1)) (label_ref (match_operand 2 "" "")) (pc)))] “TARGET_INSNS_64PLUS” “%|%.\tspkernel\t%0, %1” [(set_attr “predicable” “no”) (set_attr “type” “spkernel”)])

(define_insn “loop_end” [(set (pc) (if_then_else (ne (match_operand:SI 3 “nonimmediate_operand” “0,0,0,*r”) (const_int 1)) (label_ref (match_operand 1 "" "")) (pc))) (set (match_operand:SI 0 “nonimmediate_operand” “=AB,*r,m,m”) (plus:SI (match_dup 3) (const_int -1))) (clobber (match_scratch:SI 2 “=X,&AB,&AB,&AB”))] “TARGET_INSNS_64PLUS && optimize” “#” [(set_attr “type” “spkernel”)])

(define_split [(set (pc) (if_then_else (ne (match_operand:SI 3 “nonimmediate_operand” "") (const_int 1)) (label_ref (match_operand 1 "" "")) (pc))) (set (match_operand:SI 0 “memory_operand” "") (plus:SI (match_dup 3) (const_int -1))) (clobber (match_scratch 2))] "" [(set (match_dup 2) (plus:SI (match_dup 3) (const_int -1))) (set (match_dup 0) (match_dup 2)) (set (pc) (if_then_else (ne (match_dup 2) (const_int 0)) (label_ref (match_dup 1)) (pc)))] { if (!REG_P (operands[3])) { emit_move_insn (operands[2], operands[3]); operands[3] = operands[2]; } })

;; ------------------------------------------------------------------------- ;; Delayed-branch real jumps and shadows ;; -------------------------------------------------------------------------

(define_insn “real_jump” [(unspec [(match_operand 0 “c6x_jump_operand” “a,b,S3”) (const_int 0)] UNSPEC_REAL_JUMP)] "" { if (GET_CODE (operands[0]) == LABEL_REF) return “%|%.\tb\t%$\t%l0”; return “%|%.\tb\t%$\t%0”; } [(set_attr “type” “branch”) (set_attr “has_shadow” “y”) (set_attr “units” “s”) (set_attr “cross” “y,n,n”) (set_attr “dest_regfile” “b,b,any”)])

(define_insn “real_call” [(unspec [(match_operand 0 “c6x_call_operand” “a,b,S1”) (const_int 1)] UNSPEC_REAL_JUMP) (clobber (reg:SI REG_B3))] "" “%|%.\tcall\t%$\t%0” [(set_attr “type” “call”) (set_attr “has_shadow” “y”) (set_attr “predicable” “no”) (set_attr “units” “s”) (set_attr “cross” “y,n,n”) (set_attr “dest_regfile” “b,b,any”)])

(define_insn “real_ret” [(unspec [(match_operand 0 “register_operand” “a,b”) (const_int 2)] UNSPEC_REAL_JUMP)] "" “%|%.\tret\t%$\t%0” [(set_attr “type” “branch”) (set_attr “has_shadow” “y”) (set_attr “units” “s”) (set_attr “cross” “y,n”) (set_attr “dest_regfile” “b”)])

;; computed_jump_p returns true if it finds a constant; so use one in the ;; unspec. (define_insn “indirect_jump_shadow” [(set (pc) (unspec [(const_int 1)] UNSPEC_JUMP_SHADOW))] "" “;; indirect jump occurs” [(set_attr “type” “shadow”)])

;; Operand 0 may be a PARALLEL which isn‘t handled by output_operand, so ;; we don’t try to print it. (define_insn “indirect_call_value_shadow” [(set (match_operand 0 "" "") (call (unspec [(pc)] UNSPEC_JUMP_SHADOW) (const_int 0)))] "" “;; indirect call occurs, with return value” [(set_attr “type” “shadow”)])

(define_insn “indirect_sibcall_shadow” [(call (unspec [(pc)] UNSPEC_JUMP_SHADOW) (const_int 0))] “SIBLING_CALL_P (insn)” “;; indirect sibcall occurs” [(set_attr “type” “shadow”)])

(define_insn “indirect_call_shadow” [(call (unspec [(pc)] UNSPEC_JUMP_SHADOW) (const_int 0))] "" “;; indirect call occurs” [(set_attr “type” “shadow”)])

(define_insn “call_value_shadow” [(set (match_operand 0 "" "") (call (unspec [(match_operand 1 "" "")] UNSPEC_JUMP_SHADOW) (const_int 0)))] "" “;; call to %1 occurs, with return value” [(set_attr “type” “shadow”)])

(define_insn “call_shadow” [(call (unspec [(match_operand 0 "" "")] UNSPEC_JUMP_SHADOW) (const_int 0))] “!SIBLING_CALL_P (insn)” “;; call to %0 occurs” [(set_attr “type” “shadow”)])

(define_insn “sibcall_shadow” [(call (unspec [(match_operand 0 "" "")] UNSPEC_JUMP_SHADOW) (const_int 0))] “SIBLING_CALL_P (insn)” “;; sibcall to %0 occurs” [(set_attr “type” “shadow”)])

(define_insn “jump_shadow” [(set (pc) (unspec [(match_operand 0 "" "")] UNSPEC_JUMP_SHADOW))] "" “;; jump to %0 occurs” [(set_attr “type” “shadow”)])

(define_insn “condjump_shadow” [(set (pc) (if_then_else (eq (unspec [(const_int 0)] UNSPEC_JUMP_SHADOW) (const_int 0)) (match_operand 0 "" "") (pc)))] "" “;; condjump to %0 occurs” [(set_attr “type” “shadow”)])

(define_insn “return_shadow” [(unspec [(const_int 0)] UNSPEC_JUMP_SHADOW) (return)] "" “;; return occurs” [(set_attr “type” “shadow”)])

;; ------------------------------------------------------------------------- ;; Add instructions ;; -------------------------------------------------------------------------

(define_insn “addsi3” [(set (match_operand:SI 0 “register_operand” “=a ,b , a, b, a, b, a, b, ab, a, b, a, b,ab”) (plus:SI (match_operand:SI 1 “register_operand” “%a ,b , a, b, b, a, b, a, 0, a, b, z, z,0”) (match_operand:SI 2 “addsi_operand” “aIs5,bIs5,?b,?a,?a,?b,?aIs5,?bIs5,I5x,I5x,I5x,Iux,Iux,IsB”)))] "" { if (CONSTANT_P (operands[2])) { HOST_WIDE_INT val = INTVAL (operands[2]);

  if (c6x_get_unit_specifier (insn) == 'd')
{
  bool issp = (TARGET_INSNS_64PLUS
	       && operands[1] == stack_pointer_rtx
	       && GET_CODE (PATTERN (insn)) != COND_EXEC);

  if (get_attr_cross (insn) == CROSS_N)
    {
      if (satisfies_constraint_Iu5 (operands[2]))
	return "%|%.\\tadd\\t%$\\t%1, %2, %0";
      else if (satisfies_constraint_In5 (operands[2]))
	return "%|%.\\tsub\\t%$\\t%1, %n2, %0";
    }

  if (issp && val > 0 && val < 32768)
    {
      return "%|%.\\taddab\\t%$\\t%1, %2, %0";
    }
  if ((val & 1) == 0 && ((val >= -62 && val <= 62)
			 || (issp && val > 0 && val < 65536)))
    {
      if (val < 0)
	return "%|%.\\tsubah\\t%$\\t%1, %r2, %0";
      else
	return "%|%.\\taddah\\t%$\\t%1, %r2, %0";
    }
  else if ((val & 3) == 0 && ((val >= -124 && val <= 124)
			       || (issp && val > 0 && val < 131072)))
    {
      if (val < 0)
	return "%|%.\\tsubaw\\t%$\\t%1, %R2, %0";
      else
	return "%|%.\\taddaw\\t%$\\t%1, %R2, %0";
    }
  else if ((val & 7) == 0 && val > 0 && val <= 248)
    {
      rtx xop[3];
      xop[0] = operands[0];
      xop[1] = operands[1];
      xop[2] = GEN_INT (val >> 3);
      output_asm_insn ("%|%.\\taddad\\t%$\\t%1, %2, %0", xop);
      return "";
    }
}
  else
    {
  if (satisfies_constraint_Is5 (operands[2]))
    return "%|%.\\tadd\\t%$\\t%2, %1, %0";
}
  gcc_assert (rtx_equal_p (operands[0], operands[1]));
  return "%|%.\\taddk\\t%$\\t%2, %0";
}

if (which_alternative == 4 || which_alternative == 5) return “%|%.\tadd\t%$\t%2, %1, %0”; else return “%|%.\tadd\t%$\t%1, %2, %0”; } [(set_attr “units62” “dls,dls,ls,ls,ls,ls,ls,ls,s,d,d,,,s”) (set_attr “units67” “dls,dls,ls,ls,ls,ls,ls,ls,ds,d,d,,,s”) (set_attr “units64” “dls,dls,dls,dls,dls,dls,ls,ls,ds,d,d,d,d,s”) (set_attr “cross” “n,n,y,y,y,y,y,y,n,n,n,y,n,n”) (set_attr “predicable” “yes,yes,yes,yes,yes,yes,yes,yes,yes,yes,yes,no,no,yes”)])

(define_insn “subsi3” [(set (match_operand:SI 0 “register_operand” “=a,b,a,b,a,b”) (minus:SI (match_operand:SI 1 “reg_or_scst5_operand” “a,b,aIs5,bIs5,bIs5,aIs5”) (match_operand:SI 2 “register_operand” “a,b,a,b,?a,?b”)))] "" “%|%.\tsub\t%$\t%1, %2, %0” [(set_attr “units62” “dls,dls,ls,ls,l,l”) (set_attr “units64” “dls,dls,ls,ls,ls,ls”) (set_attr “cross” “n,n,n,n,y,y”)])

(define_insn “*addshiftsi” [(set (match_operand:SI 0 “register_operand” “=a,b”) (plus:SI (mult:SI (match_operand:SI 2 “register_operand” “a,b”) (match_operand:SI 3 “adda_scale_operand” “n,n”)) (match_operand:SI 1 “register_operand” “a,b”)))] "" “%|%.\tadda%d3\t%$\t%1, %2, %0” [(set_attr “units” “d”)])

(define_insn “*subshiftsi” [(set (match_operand:SI 0 “register_operand” “=a,b”) (minus:SI (match_operand:SI 1 “register_operand” “a,b”) (mult:SI (match_operand:SI 2 “register_operand” “a,b”) (match_operand:SI 3 “suba_scale_operand” “n,n”))))] "" “%|%.\tsuba%d3\t%$\t%1, %2, %0” [(set_attr “units” “d”)])

(define_insn “addsidi3_widen” [(set (match_operand:DI 0 “register_operand” “=a,b,a,b”) (plus:DI (zero_extend:DI (match_operand:SI 1 “register_operand” “%a,b,a,b”)) (zero_extend:DI (match_operand:SI 2 “register_operand” “a,b,?b,?a”))))] "" “%|%.\taddu\t%$\t%1, %2, %0” [(set_attr “units” “l”) (set_attr “cross” “n,n,y,y”)])

(define_expand “adddi3” [(set (match_operand:DI 0 “register_operand” "") (plus:DI (match_operand:DI 1 “register_operand” "") (match_operand:DI 2 “register_operand” "")))] "" { rtx tmp; rtx lo_half[3], hi_half[3]; split_di (operands + 1, 2, lo_half + 1, hi_half + 1); if (reg_overlap_mentioned_p (operands[0], hi_half[1]) || reg_overlap_mentioned_p (operands[0], hi_half[2])) tmp = gen_reg_rtx (DImode); else tmp = operands[0]; split_di (&tmp, 1, lo_half, hi_half); emit_insn (gen_addsidi3_widen (tmp, lo_half[1], lo_half[2])); emit_insn (gen_addsi3 (hi_half[0], copy_rtx (hi_half[0]), hi_half[1])); emit_insn (gen_addsi3 (copy_rtx (hi_half[0]), copy_rtx (hi_half[0]), hi_half[2])); if (tmp != operands[0]) emit_move_insn (operands[0], tmp); DONE; })

(define_insn “addsf3” [(set (match_operand:SF 0 “register_operand” “=a,b,a,b”) (plus:SF (match_operand:SF 1 “register_operand” “%a,b,a,b”) (match_operand:SF 2 “register_operand” “a,b,?b,?a”)))] “TARGET_FP” “%|%.\taddsp\t%$\t%1, %2, %0” [(set_attr “type” “fp4”) (set_attr “units67” “l”) (set_attr “units67p” “ls”) (set_attr “units674” “ls”) (set_attr “cross” “n,n,y,y”)])

(define_insn “adddf3” [(set (match_operand:DF 0 “register_operand” “=a,b,a,b”) (plus:DF (match_operand:DF 1 “register_operand” “%a,b,a,b”) (match_operand:DF 2 “register_operand” “a,b,?b,?a”)))] “TARGET_FP” “%|%.\tadddp\t%$\t%1, %2, %0” [(set_attr “type” “adddp”) (set_attr “units67” “l”) (set_attr “units67p” “ls”) (set_attr “units674” “ls”) (set_attr “cross” “n,n,y,y”)])

(define_insn “subsf3” [(set (match_operand:SF 0 “register_operand” “=a,b, a, b, a, b”) (minus:SF (match_operand:SF 1 “register_operand” “a,b, b, a, a, b”) (match_operand:SF 2 “register_operand” “a,b,?a,?b,?b,?a”)))] “TARGET_FP” “%|%.\tsubsp\t%$\t%1, %2, %0” [(set_attr “type” “fp4”) (set_attr “units67” “l”) (set_attr “units67p” “ls”) (set_attr “units674” “ls”) (set_attr “cross” “n,n,y,y,y,y”)])

(define_insn “subdf3” [(set (match_operand:DF 0 “register_operand” “=a,b, a, b, a, b”) (minus:DF (match_operand:DF 1 “register_operand” “a,b, b, a, a, b”) (match_operand:DF 2 “register_operand” “a,b,?a,?b,?b,?a”)))] “TARGET_FP” “%|%.\tsubdp\t%$\t%1, %2, %0” [(set_attr “type” “adddp”) (set_attr “units67” “l”) (set_attr “units67p” “ls”) (set_attr “units674” “ls”) (set_attr “cross” “n,n,y,y,y,y”)])

;; ------------------------------------------------------------------------- ;; Logical instructions ;; -------------------------------------------------------------------------

(define_insn “andsi3” [(set (match_operand:SI 0 “register_operand” “=a,b,a,b,a,b”) (and:SI (match_operand:SI 1 “register_operand” “%a,b,b,a,a,b”) (match_operand:SI 2 “andsi_operand” “aIs5,bIs5,?aIs5,?bIs5,aJc,bJc”)))] "" { if (which_alternative < 4) return “%|%.\tand\t%$\t%2, %1, %0”; else return “%|%.\tclr\t%$\t%1, %f2, %F2, %0”; } [(set_attr “units62” “ls,ls,ls,ls,s,s”) (set_attr “units64” “dls,dls,dls,dls,s,s”) (set_attr “cross” “n,n,y,y,n,n”)])

(define_insn “iorsi3” [(set (match_operand:SI 0 “register_operand” “=a,b,a,b,a,b”) (ior:SI (match_operand:SI 1 “register_operand” “%a,b,b,a,a,b”) (match_operand:SI 2 “iorsi_operand” “aIs5,bIs5,?aIs5,?bIs5,aJs,bJs”)))] "" { if (which_alternative < 4) return “%|%.\tor\t%$\t%2, %1, %0”; else return “%|%.\tset\t%$\t%1, %s2, %S2, %0”; } [(set_attr “units62” “ls,ls,ls,ls,s,s”) (set_attr “units64” “dls,dls,dls,dls,s,s”) (set_attr “cross” “n,n,y,y,n,n”)])

(define_insn “xorsi3” [(set (match_operand:SI 0 “register_operand” “=a,b,a,b”) (xor:SI (match_operand:SI 1 “register_operand” “%a,b,b,a”) (match_operand:SI 2 “reg_or_scst5_operand” “aIs5,bIs5,?aIs5,?bIs5”)))] "" “%|%.\txor\t%$\t%2, %1, %0” [(set_attr “units62” “ls”) (set_attr “units64” “dls”) (set_attr “cross” “n,n,y,y”)])

;; ------------------------------------------------------------------------- ;; Conversions ;; -------------------------------------------------------------------------

(define_insn “extendsfdf2” [(set (match_operand:DF 0 “register_operand” “=a,b,a,b”) (float_extend:DF (match_operand:SF 1 “register_operand” “a,b,?b,?a”)))] “TARGET_FP” “%|%.\tspdp\t%$\t%1,%0” [(set_attr “type” “dp2”) (set_attr “units” “s”) (set_attr “cross” “n,n,y,y”)])

(define_insn “truncdfsf2” [(set (match_operand:SF 0 “register_operand” “=a,b”) (float_truncate:SF (match_operand:DF 1 “register_operand” “a,b”)))] “TARGET_FP” “%|%.\tdpsp\t%$\t%1,%0” [(set_attr “type” “fp4”) (set_attr “units” “l”) (set_attr “cross” “n”)])

;;;; Convert between signed integer types and floating point. (define_insn “floatsisf2” [(set (match_operand:SF 0 “register_operand” “=a,b,a,b”) (float:SF (match_operand:SI 1 “register_operand” “a,b,?b,?a”)))] “TARGET_FP” “%|%.\tintsp\t%$\t%1,%0” [(set_attr “type” “fp4”) (set_attr “units” “l”) (set_attr “cross” “n,n,y,y”)])

(define_insn “floatunssisf2” [(set (match_operand:SF 0 “register_operand” “=a,b,a,b”) (unsigned_float:SF (match_operand:SI 1 “register_operand” “a,b,?b,?a”)))] “TARGET_FP” “%|%.\tintspu\t%$\t%1,%0” [(set_attr “type” “fp4”) (set_attr “units” “l”) (set_attr “cross” “n,n,y,y”)])

(define_insn “floatsidf2” [(set (match_operand:DF 0 “register_operand” “=a,b,a,b”) (float:DF (match_operand:SI 1 “register_operand” “a,b,?b,?a”)))] “TARGET_FP” “%|%.\tintdp\t%$\t%1,%0” [(set_attr “type” “intdp”) (set_attr “units” “l”) (set_attr “cross” “n,n,y,y”)])

(define_insn “floatunssidf2” [(set (match_operand:DF 0 “register_operand” “=a,b,a,b”) (unsigned_float:DF (match_operand:SI 1 “register_operand” “a,b,?b,?a”)))] “TARGET_FP” “%|%.\tintdpu\t%$\t%1,%0” [(set_attr “type” “intdp”) (set_attr “units” “l”) (set_attr “cross” “n,n,y,y”)])

(define_insn “fix_truncsfsi2” [(set (match_operand:SI 0 “register_operand” “=a,b,a,b”) (fix:SI (match_operand:SF 1 “register_operand” “a,b,?b,?a”)))] “TARGET_FP” “%|%.\tsptrunc\t%$\t%1,%0” [(set_attr “type” “fp4”) (set_attr “units” “l”) (set_attr “cross” “n,n,y,y”)])

(define_insn “fix_truncdfsi2” [(set (match_operand:SI 0 “register_operand” “=a,b”) (fix:SI (match_operand:DF 1 “register_operand” “a,b”)))] “TARGET_FP” “%|%.\tdptrunc\t%$\t%1,%0” [(set_attr “type” “fp4”) (set_attr “units” “l”) (set_attr “cross” “n”)])

;; ------------------------------------------------------------------------- ;; Saturating arithmetic ;; -------------------------------------------------------------------------

(define_insn “saddsi3” [(set (match_operand:SI 0 “register_operand” “=a,b,a,b,a,b,a,b”) (ss_plus:SI (match_operand:SI 1 “register_operand” “a,b,?b,?a,a,b,?b,?a”) (match_operand:SI 2 “reg_or_const_int_operand” “a,b,a,b,aIs5,bIs5,aIs5,bIs5”)))] "" “%|%.\tsadd\t%$\t%2, %1, %0” [(set_attr “units” “ls,ls,ls,ls,l,l,l,l”) (set_attr “cross” “n,n,y,y,n,n,y,y”)])

(define_insn “ssubsi3” [(set (match_operand:SI 0 “register_operand” “=a,b,a,b”) (ss_minus:SI (match_operand:SI 1 “reg_or_scst5_operand” “aIs5,bIs5,?bIs5,?aIs5”) (match_operand:SI 2 “register_operand” “a,b,a,b”)))] "" “%|%.\tssub\t%$\t%1, %2, %0” [(set_attr “units” “l”) (set_attr “cross” “n,n,y,y”)])

(define_insn “subcsi3” [(set (match_operand:SI 0 “register_operand” “=a,b,a,b”) (unspec:SI [(match_operand:SI 1 “register_operand” “a,b,a,b”) (match_operand:SI 2 “register_operand” “a,b,?b,?a”)] UNSPEC_SUBC))] "" “%|%.\tsubc\t%$\t%1, %2, %0” [(set_attr “units” “l”) (set_attr “cross” “n,n,y,y”)])

;; ------------------------------------------------------------------------- ;; Call instructions ;; -------------------------------------------------------------------------

(define_expand “call” [(match_operand 0 "" "")] "" { c6x_expand_call (NULL_RTX, operands[0], false); DONE; })

(define_expand “call_value” [(match_operand 0 "" "") (match_operand 1 "" "")] "" { c6x_expand_call (operands[0], operands[1], false); DONE; })

(define_expand “sibcall” [(match_operand 0 "" "")] "" { c6x_expand_call (NULL_RTX, operands[0], true); cfun->machine->contains_sibcall = true; DONE; })

(define_expand “sibcall_value” [(match_operand 0 "" "") (match_operand 1 "" "")] "" { c6x_expand_call (operands[0], operands[1], true); cfun->machine->contains_sibcall = true; DONE; })

(define_insn “call_internal” [(call (mem (match_operand:SI 0 “c6x_call_operand” “S1,a,b”)) (const_int 0))] “!SIBLING_CALL_P (insn)” “%|%.\tcall\t%$\t%0” [(set_attr “type” “call”) (set_attr “predicable” “no”) (set_attr “units” “s”) (set_attr “dest_regfile” “any,b,b”) (set_attr “cross” “n,y,n”)])

(define_insn “call_value_internal” [(set (match_operand 0 "" "") (call (mem (match_operand:SI 1 “c6x_call_operand” “S1,a,b”)) (const_int 0)))] "" “%|%.\tcall\t%$\t%1” [(set_attr “type” “call”) (set_attr “predicable” “no”) (set_attr “units” “s”) (set_attr “dest_regfile” “any,b,b”) (set_attr “cross” “n,y,n”)])

(define_insn “sibcall_internal” [(call (mem (match_operand:SI 0 “c6x_call_operand” “S1,C”)) (const_int 0))] “SIBLING_CALL_P (insn)” “%|%.\tb\t%$\t%0” [(set_attr “type” “branch”) (set_attr “predicable” “no”) (set_attr “units” “s”) (set_attr “dest_regfile” “any,b”)])

(define_insn “callp” [(call (mem (match_operand:SI 0 “c6x_call_operand” “S1”)) (const_int 0)) (unspec [(const_int 6)] UNSPEC_NOP)] “!SIBLING_CALL_P (insn)” “%|%.\tcallp\t%$\t%0, B3” [(set_attr “type” “callp”) (set_attr “predicable” “no”) (set_attr “units” “s”) (set_attr “dest_regfile” “b”) (set_attr “cross” “n”)])

(define_insn “callp_value” [(set (match_operand:SI 0 “register_operand” "") (call (mem (match_operand:SI 1 “c6x_call_operand” “S1”)) (const_int 0))) (unspec [(const_int 6)] UNSPEC_NOP)] “!SIBLING_CALL_P (insn)” “%|%.\tcallp\t%$\t%1, B3” [(set_attr “type” “callp”) (set_attr “predicable” “no”) (set_attr “units” “s”) (set_attr “dest_regfile” “b”) (set_attr “cross” “n”)])

(define_insn “return_internal” [(return) (use (match_operand:SI 0 “register_operand” “b”))] “reload_completed” “%|%.\tret\t%$\t%0” [(set_attr “type” “branch”) (set_attr “units” “s”) (set_attr “dest_regfile” “b”)])

(define_insn “addkpc” [(set (match_operand:SI 0 “register_operand” “=b”) (unspec:SI [(match_operand 1 "" "")] UNSPEC_ADDKPC)) (unspec [(match_operand 2 “const_int_operand” “n”)] UNSPEC_NOP)] “TARGET_INSNS_64” “%|%.\taddkpc\t%$\t%l1, %0, %2” [(set_attr “units” “s”) (set_attr “dest_regfile” “b”)])

;; ------------------------------------------------------------------------- ;; Unary operations ;; -------------------------------------------------------------------------

(define_insn “negsi2” [(set (match_operand:SI 0 “register_operand” “=a, a, b, b”) (neg:SI (match_operand:SI 1 “register_operand” “a,?b, b,?a”)))] "" “%|%.\tneg\t%$\t%1, %0” [(set_attr “units” “ls”) (set_attr “cross” “n,y,n,y”)])

(define_insn “one_cmplsi2” [(set (match_operand:SI 0 “register_operand” “=a, a, b, b”) (not:SI (match_operand:SI 1 “register_operand” “a,?b, b,?a”)))] "" “%|%.\tnot\t%$\t%1, %0” [(set_attr “units” “ls”) (set_attr “cross” “n,y,n,y”)])

(define_insn “clrsbsi2” [(set (match_operand:SI 0 “register_operand” “=a, a, b, b”) (clrsb:SI (match_operand:SI 1 “register_operand” “a,?b, b,?a”)))] "" “%|%.\tnorm\t%$\t%1, %0” [(set_attr “units” “l”) (set_attr “cross” “n,y,n,y”)])

(define_insn “clzsi2” [(set (match_operand:SI 0 “register_operand” “=a, a, b, b”) (clz:SI (match_operand:SI 1 “register_operand” “a,?b, b,?a”)))] "" “%|%.\tlmbd\t%$\t1, %1, %0” [(set_attr “units” “l”) (set_attr “cross” “n,y,n,y”)])

;; bitrevsi2 is defined in c6x-mult.md.in.

(define_expand “ctzsi2” [(set (match_operand:SI 0 “register_operand” "") (ctz:SI (match_operand:SI 1 “register_operand” "")))] “TARGET_INSNS_64” { rtx tmpreg = gen_reg_rtx (SImode); emit_insn (gen_bitrevsi2 (tmpreg, operands[1])); emit_insn (gen_clzsi2 (operands[0], tmpreg)); DONE; })

(define_expand “ctzdi2” [(set (match_operand:DI 0 “register_operand” "") (ctz:DI (match_operand:DI 1 “register_operand” "")))] “TARGET_INSNS_64” { rtx tmpreg = gen_reg_rtx (DImode); rtx out; emit_insn (gen_bitrevsi2 (gen_highpart (SImode, tmpreg), gen_lowpart (SImode, operands[1]))); emit_insn (gen_bitrevsi2 (gen_lowpart (SImode, tmpreg), gen_highpart (SImode, operands[1]))); out = expand_unop (DImode, clz_optab, tmpreg, operands[0], 1); if (!rtx_equal_p (out, operands[0])) emit_move_insn (operands[0], out); DONE; })

(define_insn “ssabssi2” [(set (match_operand:SI 0 “register_operand” “=a, a, b, b”) (ss_abs:SI (match_operand:SI 1 “register_operand” “a,?b, b,?a”)))] "" “%|%.\tabs\t%$\t%1, %0” [(set_attr “units” “l”) (set_attr “cross” “n,y,n,y”)])

;; ------------------------------------------------------------------------- ;; Shift instructions ;; -------------------------------------------------------------------------

(define_code_iterator any_shift [ss_ashift ashift ashiftrt lshiftrt]) (define_code_iterator any_rshift [ashiftrt lshiftrt]) (define_code_attr shift_code [(ss_ashift “ss_ashl”) (ashift “ashl”) (ashiftrt “ashr”) (lshiftrt “lshr”)]) (define_code_attr shift_insn [(ss_ashift “sshl”) (ashift “shl”) (ashiftrt “shr”) (lshiftrt “shru”)])

(define_insn “<shift_code>si3” [(set (match_operand:SI 0 “register_operand” “=a,b,a,b”) (any_shift:SI (match_operand:SI 1 “register_operand” “a,b,?b,?a”) (match_operand:SI 2 “reg_or_ucst5_operand” “aIu5,bIu5,aIu5,bIu5”)))] "" “%|%.\t<shift_insn>\t%$\t%1, %2, %0” [(set_attr “units” “s”) (set_attr “cross” “n,n,y,y”)])

;; See c6x-mult.md.in for the rotlsi3 pattern.

(define_insn “rotrdi3_16” [(set (match_operand:DI 0 “register_operand” “=a,b”) (rotatert:DI (match_operand:DI 1 “register_operand” “a,b”) (const_int 16)))] “TARGET_INSNS_64PLUS” “%|%.\tdpackx2\t%$\t%P1, %p1, %0” [(set_attr “units” “l”) (set_attr “cross” “n”)])

(define_insn “shlmbsi3” [(set (match_operand:SI 0 “register_operand” “=a,b,a,b”) (ior:SI (ashift:SI (match_operand:SI 1 “register_operand” “a,b,?b,?a”) (const_int 8)) (lshiftrt:SI (match_operand:SI 2 “register_operand” “a,b,a,b”) (const_int 24))))] “TARGET_INSNS_64” “%|%.\tshlmb\t%$\t%2, %1, %0” [(set_attr “units” “ls”) (set_attr “cross” “n,n,y,y”)])

(define_expand “ashldi3” [(set (match_operand:DI 0 “register_operand” "") (ashift:DI (match_operand:DI 1 “register_operand” "") (match_operand:SI 2 “const_int_operand” "")))] “TARGET_INSNS_64” { if (CONST_INT_P (operands[2]) && INTVAL (operands[2]) == 8) { rtx lo0, lo1, hi0, hi1, tmp; lo0 = gen_lowpart (SImode, operands[0]); hi0 = gen_highpart (SImode, operands[0]); lo1 = gen_lowpart (SImode, operands[1]); hi1 = gen_highpart (SImode, operands[1]); if (reg_overlap_mentioned_p (hi0, lo1)) tmp = gen_reg_rtx (SImode); else tmp = hi0; emit_insn (gen_shlmbsi3 (tmp, hi1, lo1)); emit_insn (gen_ashlsi3 (lo0, lo1, operands[2])); if (tmp != hi0) emit_move_insn (hi0, tmp); DONE; } FAIL; })

(define_expand “rotrdi3” [(set (match_operand:DI 0 “register_operand” "") (rotatert:DI (match_operand:DI 1 “register_operand” "") (match_operand:SI 2 “const_int_operand” "")))] “TARGET_INSNS_64PLUS” { if (CONST_INT_P (operands[2]) && INTVAL (operands[2]) == 16) { emit_insn (gen_rotrdi3_16 (operands[0], operands[1])); DONE; } FAIL; })

(define_insn “bswapv2hi2” [(set (match_operand:V2HI 0 “register_operand” “=a,b,a,b”) (bswap:V2HI (match_operand:V2HI 1 “register_operand” “a,b,?b,?a”)))] “TARGET_INSNS_64” “%|%.\tswap4\t%$\t%1, %0” [(set_attr “units” “l”) (set_attr “cross” “n,n,y,y”)])

(define_expand “bswapsi2” [(set (match_operand:SI 0 “register_operand” "") (bswap:SI (match_operand:SI 1 “register_operand” "")))] “TARGET_INSNS_64” { rtx tmpreg = gen_reg_rtx (SImode); rtx tmpv2 = gen_lowpart (V2HImode, tmpreg); rtx op0v2 = gen_lowpart (V2HImode, operands[0]); emit_insn (gen_rotlsi3 (tmpreg, operands[1], GEN_INT (16))); emit_insn (gen_bswapv2hi2 (op0v2, tmpv2)); DONE; })

;; ------------------------------------------------------------------------- ;; Division ;; -------------------------------------------------------------------------

(define_insn “divsi3_insn” [(set (reg:SI REG_A4) (div:SI (reg:SI REG_A4) (reg:SI REG_B4))) (clobber (reg:SI REG_A0)) (clobber (reg:SI REG_A1)) (clobber (reg:SI REG_A2)) (clobber (reg:SI REG_A6)) (clobber (reg:SI REG_B0)) (clobber (reg:SI REG_B1)) (clobber (reg:SI REG_B2)) (clobber (reg:SI REG_B3)) (clobber (reg:SI REG_B4)) (clobber (reg:SI REG_B5)) (clobber (reg:SI REG_B30)) (clobber (reg:SI REG_B31))] "" “%|%.\tcall\t%$\t__c6xabi_divi” [(set_attr “type” “call”) (set_attr “dest_regfile” “any”) (set_attr “units” “s”) (set_attr “cross” “n”)])

(define_insn “divsi3_insn_indcall” [(set (reg:SI REG_A4) (div:SI (reg:SI REG_A4) (reg:SI REG_B4))) (use (match_operand:SI 0 “register_operand” “b”)) (clobber (reg:SI REG_A0)) (clobber (reg:SI REG_A1)) (clobber (reg:SI REG_A2)) (clobber (reg:SI REG_A6)) (clobber (reg:SI REG_B0)) (clobber (reg:SI REG_B1)) (clobber (reg:SI REG_B2)) (clobber (reg:SI REG_B3)) (clobber (reg:SI REG_B4)) (clobber (reg:SI REG_B5)) (clobber (reg:SI REG_B30)) (clobber (reg:SI REG_B31))] "" “%|%.\tcall\t%$\t%0” [(set_attr “type” “call”) (set_attr “dest_regfile” “any”) (set_attr “units” “s”) (set_attr “cross” “n”)])

(define_insn “udivsi3_insn” [(set (reg:SI REG_A4) (udiv:SI (reg:SI REG_A4) (reg:SI REG_B4))) (clobber (reg:SI REG_A0)) (clobber (reg:SI REG_A1)) (clobber (reg:SI REG_A2)) (clobber (reg:SI REG_A6)) (clobber (reg:SI REG_B0)) (clobber (reg:SI REG_B1)) (clobber (reg:SI REG_B2)) (clobber (reg:SI REG_B3)) (clobber (reg:SI REG_B4)) (clobber (reg:SI REG_B30)) (clobber (reg:SI REG_B31))] "" “%|%.\tcall\t%$\t__c6xabi_divu” [(set_attr “type” “call”) (set_attr “dest_regfile” “any”) (set_attr “units” “s”) (set_attr “cross” “n”)])

(define_insn “udivsi3_insn_indcall” [(set (reg:SI REG_A4) (udiv:SI (reg:SI REG_A4) (reg:SI REG_B4))) (use (match_operand:SI 0 “register_operand” “b”)) (clobber (reg:SI REG_A0)) (clobber (reg:SI REG_A1)) (clobber (reg:SI REG_A2)) (clobber (reg:SI REG_A6)) (clobber (reg:SI REG_B0)) (clobber (reg:SI REG_B1)) (clobber (reg:SI REG_B2)) (clobber (reg:SI REG_B3)) (clobber (reg:SI REG_B4)) (clobber (reg:SI REG_B30)) (clobber (reg:SI REG_B31))] "" “%|%.\tcall\t%$\t%0” [(set_attr “type” “call”) (set_attr “dest_regfile” “any”) (set_attr “units” “s”) (set_attr “cross” “n”)])

(define_insn “modsi3_insn” [(set (reg:SI REG_A4) (mod:SI (reg:SI REG_A4) (reg:SI REG_B4))) (clobber (reg:SI REG_A1)) (clobber (reg:SI REG_A2)) (clobber (reg:SI REG_A5)) (clobber (reg:SI REG_A6)) (clobber (reg:SI REG_B0)) (clobber (reg:SI REG_B1)) (clobber (reg:SI REG_B2)) (clobber (reg:SI REG_B3)) (clobber (reg:SI REG_B4)) (clobber (reg:SI REG_B30)) (clobber (reg:SI REG_B31))] "" “%|%.\tcall\t%$\t__c6xabi_remi” [(set_attr “type” “call”) (set_attr “dest_regfile” “any”) (set_attr “units” “s”) (set_attr “cross” “n”)])

(define_insn “modsi3_insn_indcall” [(set (reg:SI REG_A4) (mod:SI (reg:SI REG_A4) (reg:SI REG_B4))) (use (match_operand:SI 0 “register_operand” “b”)) (clobber (reg:SI REG_A1)) (clobber (reg:SI REG_A2)) (clobber (reg:SI REG_A5)) (clobber (reg:SI REG_A6)) (clobber (reg:SI REG_B0)) (clobber (reg:SI REG_B1)) (clobber (reg:SI REG_B2)) (clobber (reg:SI REG_B3)) (clobber (reg:SI REG_B4)) (clobber (reg:SI REG_B30)) (clobber (reg:SI REG_B31))] "" “%|%.\tcall\t%$\t%0” [(set_attr “type” “call”) (set_attr “dest_regfile” “any”) (set_attr “units” “s”) (set_attr “cross” “n”)])

(define_insn “divmodsi4_insn” [(set (reg:SI REG_A4) (div:SI (reg:SI REG_A4) (reg:SI REG_B4))) (set (reg:SI REG_A5) (mod:SI (reg:SI REG_A4) (reg:SI REG_B4))) (clobber (reg:SI REG_A1)) (clobber (reg:SI REG_A2)) (clobber (reg:SI REG_A6)) (clobber (reg:SI REG_B0)) (clobber (reg:SI REG_B1)) (clobber (reg:SI REG_B2)) (clobber (reg:SI REG_B3)) (clobber (reg:SI REG_B4)) (clobber (reg:SI REG_B30)) (clobber (reg:SI REG_B31))] "" “%|%.\tcall\t%$\t__c6xabi_divremi” [(set_attr “type” “call”) (set_attr “dest_regfile” “any”) (set_attr “units” “s”) (set_attr “cross” “n”)])

(define_insn “divmodsi4_insn_indcall” [(set (reg:SI REG_A4) (div:SI (reg:SI REG_A4) (reg:SI REG_B4))) (set (reg:SI REG_A5) (mod:SI (reg:SI REG_A4) (reg:SI REG_B4))) (use (match_operand:SI 0 “register_operand” “b”)) (clobber (reg:SI REG_A1)) (clobber (reg:SI REG_A2)) (clobber (reg:SI REG_A5)) (clobber (reg:SI REG_A6)) (clobber (reg:SI REG_B0)) (clobber (reg:SI REG_B1)) (clobber (reg:SI REG_B2)) (clobber (reg:SI REG_B3)) (clobber (reg:SI REG_B4)) (clobber (reg:SI REG_B30)) (clobber (reg:SI REG_B31))] "" “%|%.\tcall\t%$\t%0” [(set_attr “type” “call”) (set_attr “dest_regfile” “any”) (set_attr “units” “s”) (set_attr “cross” “n”)])

(define_insn “umodsi3_insn” [(set (reg:SI REG_A4) (umod:SI (reg:SI REG_A4) (reg:SI REG_B4))) (clobber (reg:SI REG_A1)) (clobber (reg:SI REG_A5)) (clobber (reg:SI REG_A7)) (clobber (reg:SI REG_B0)) (clobber (reg:SI REG_B1)) (clobber (reg:SI REG_B2)) (clobber (reg:SI REG_B3)) (clobber (reg:SI REG_B4)) (clobber (reg:SI REG_B30)) (clobber (reg:SI REG_B31))] "" “%|%.\tcall\t%$\t__c6xabi_remu” [(set_attr “type” “call”) (set_attr “dest_regfile” “any”) (set_attr “units” “s”) (set_attr “cross” “n”)])

(define_insn “umodsi3_insn_indcall” [(set (reg:SI REG_A4) (umod:SI (reg:SI REG_A4) (reg:SI REG_B4))) (use (match_operand:SI 0 “register_operand” “b”)) (clobber (reg:SI REG_A1)) (clobber (reg:SI REG_A5)) (clobber (reg:SI REG_A7)) (clobber (reg:SI REG_B0)) (clobber (reg:SI REG_B1)) (clobber (reg:SI REG_B2)) (clobber (reg:SI REG_B3)) (clobber (reg:SI REG_B4)) (clobber (reg:SI REG_B30)) (clobber (reg:SI REG_B31))] "" “%|%.\tcall\t%$\t%0” [(set_attr “type” “call”) (set_attr “dest_regfile” “any”) (set_attr “units” “s”) (set_attr “cross” “n”)])

(define_insn “udivmodsi4_insn” [(set (reg:SI REG_A4) (udiv:SI (reg:SI REG_A4) (reg:SI REG_B4))) (set (reg:SI REG_A5) (umod:SI (reg:SI REG_A4) (reg:SI REG_B4))) (clobber (reg:SI REG_A0)) (clobber (reg:SI REG_A1)) (clobber (reg:SI REG_A2)) (clobber (reg:SI REG_A6)) (clobber (reg:SI REG_B0)) (clobber (reg:SI REG_B1)) (clobber (reg:SI REG_B2)) (clobber (reg:SI REG_B3)) (clobber (reg:SI REG_B4)) (clobber (reg:SI REG_B30)) (clobber (reg:SI REG_B31))] "" “%|%.\tcall\t%$\t__c6xabi_divremu” [(set_attr “type” “call”) (set_attr “dest_regfile” “any”) (set_attr “units” “s”) (set_attr “cross” “n”)])

(define_insn “udivmodsi4_insn_indcall” [(set (reg:SI REG_A4) (udiv:SI (reg:SI REG_A4) (reg:SI REG_B4))) (set (reg:SI REG_A5) (umod:SI (reg:SI REG_A4) (reg:SI REG_B4))) (use (match_operand:SI 0 “register_operand” “b”)) (clobber (reg:SI REG_A0)) (clobber (reg:SI REG_A1)) (clobber (reg:SI REG_A2)) (clobber (reg:SI REG_A6)) (clobber (reg:SI REG_B0)) (clobber (reg:SI REG_B1)) (clobber (reg:SI REG_B2)) (clobber (reg:SI REG_B3)) (clobber (reg:SI REG_B4)) (clobber (reg:SI REG_B30)) (clobber (reg:SI REG_B31))] "" “%|%.\tcall\t%$\t%0” [(set_attr “type” “call”) (set_attr “dest_regfile” “any”) (set_attr “units” “s”) (set_attr “cross” “n”)])

(define_insn_and_split “divmodsi4” [(set (match_operand:SI 0 “register_operand” "") (div:SI (match_operand:SI 1 “register_operand” "") (match_operand:SI 2 “register_operand” ""))) (set (match_operand:SI 3 “register_operand” "") (mod:SI (match_dup 1) (match_dup 2))) (clobber (reg:SI REG_A0)) (clobber (reg:SI REG_A1)) (clobber (reg:SI REG_A2)) (clobber (reg:SI REG_A4)) (clobber (reg:SI REG_A5)) (clobber (reg:SI REG_A6)) (clobber (reg:SI REG_B0)) (clobber (reg:SI REG_B1)) (clobber (reg:SI REG_B2)) (clobber (reg:SI REG_B3)) (clobber (reg:SI REG_B4)) (clobber (reg:SI REG_B5)) (clobber (reg:SI REG_B30)) (clobber (reg:SI REG_B31))] "" “#” "" [(const_int 0)] { rtx reg = NULL_RTX;

if (TARGET_LONG_CALLS) { if (reload_completed) reg = gen_rtx_REG (SImode, REG_A6); else reg = gen_reg_rtx (SImode); } emit_move_insn (gen_rtx_REG (SImode, REG_A4), operands[1]); emit_move_insn (gen_rtx_REG (SImode, REG_B4), operands[2]); if (find_reg_note (curr_insn, REG_UNUSED, operands[3])) { if (TARGET_LONG_CALLS) { emit_move_insn (reg, optab_libfunc (sdiv_optab, SImode)); emit_insn (gen_divsi3_insn_indcall (reg)); } else emit_insn (gen_divsi3_insn ()); emit_move_insn (operands[0], gen_rtx_REG (SImode, REG_A4)); } else if (find_reg_note (curr_insn, REG_UNUSED, operands[0])) { if (TARGET_LONG_CALLS) { emit_move_insn (reg, optab_libfunc (smod_optab, SImode)); emit_insn (gen_modsi3_insn_indcall (reg)); } else emit_insn (gen_modsi3_insn ()); emit_move_insn (operands[3], gen_rtx_REG (SImode, REG_A4)); } else { if (TARGET_LONG_CALLS) { emit_move_insn (reg, optab_libfunc (sdivmod_optab, SImode)); emit_insn (gen_divmodsi4_insn_indcall (reg)); } else emit_insn (gen_divmodsi4_insn ()); emit_move_insn (operands[0], gen_rtx_REG (SImode, REG_A4)); emit_move_insn (operands[3], gen_rtx_REG (SImode, REG_A5)); } DONE; })

(define_insn_and_split “udivmodsi4” [(set (match_operand:SI 0 “register_operand” "") (udiv:SI (match_operand:SI 1 “register_operand” "") (match_operand:SI 2 “register_operand” ""))) (set (match_operand:SI 3 “register_operand” "") (umod:SI (match_dup 1) (match_dup 2))) (clobber (reg:SI REG_A0)) (clobber (reg:SI REG_A1)) (clobber (reg:SI REG_A2)) (clobber (reg:SI REG_A4)) (clobber (reg:SI REG_A5)) (clobber (reg:SI REG_A6)) (clobber (reg:SI REG_A7)) (clobber (reg:SI REG_B0)) (clobber (reg:SI REG_B1)) (clobber (reg:SI REG_B2)) (clobber (reg:SI REG_B3)) (clobber (reg:SI REG_B4)) (clobber (reg:SI REG_B30)) (clobber (reg:SI REG_B31))] "" “#” "" [(const_int 0)] { rtx reg = NULL_RTX;

if (TARGET_LONG_CALLS) { if (reload_completed) reg = gen_rtx_REG (SImode, REG_A6); else reg = gen_reg_rtx (SImode); }

emit_move_insn (gen_rtx_REG (SImode, REG_A4), operands[1]); emit_move_insn (gen_rtx_REG (SImode, REG_B4), operands[2]); if (find_reg_note (curr_insn, REG_UNUSED, operands[3])) { if (TARGET_LONG_CALLS) { emit_move_insn (reg, optab_libfunc (udiv_optab, SImode)); emit_insn (gen_udivsi3_insn_indcall (reg)); } else emit_insn (gen_udivsi3_insn ()); emit_move_insn (operands[0], gen_rtx_REG (SImode, REG_A4)); } else if (find_reg_note (curr_insn, REG_UNUSED, operands[0])) { if (TARGET_LONG_CALLS) { emit_move_insn (reg, optab_libfunc (umod_optab, SImode)); emit_insn (gen_umodsi3_insn_indcall (reg)); } else emit_insn (gen_umodsi3_insn ()); emit_move_insn (operands[3], gen_rtx_REG (SImode, REG_A4)); } else { if (TARGET_LONG_CALLS) { emit_move_insn (reg, optab_libfunc (udivmod_optab, SImode)); emit_insn (gen_udivmodsi4_insn_indcall (reg)); } else emit_insn (gen_udivmodsi4_insn ()); emit_move_insn (operands[0], gen_rtx_REG (SImode, REG_A4)); emit_move_insn (operands[3], gen_rtx_REG (SImode, REG_A5)); } DONE; })

;; ------------------------------------------------------------------------- ;; Multiplication ;; See c6x-mult.md.in for define_insn patterns. ;; -------------------------------------------------------------------------

(define_expand “mulhisi3” [(set (match_operand:SI 0 “register_operand” "") (mult:SI (sign_extend:SI (match_operand:HI 1 “register_operand” "")) (sign_extend:SI (match_operand:HI 2 “reg_or_scst5_operand” ""))))] "" { if (CONSTANT_P (operands[2])) { emit_insn (gen_mulhisi3_const (operands[0], operands[1], operands[2])); DONE; } })

(define_expand “usmulhisi3” [(set (match_operand:SI 0 “register_operand” "") (mult:SI (zero_extend:SI (match_operand:HI 1 “register_operand” "")) (sign_extend:SI (match_operand:HI 2 “reg_or_scst5_operand” ""))))] "" { if (CONSTANT_P (operands[2])) { emit_insn (gen_usmulhisi3_const (operands[0], operands[1], operands[2])); DONE; } })

(define_expand “mulsi3” [(set (match_operand:SI 0 “register_operand” "") (mult:SI (match_operand:SI 1 “register_operand” "") (match_operand:SI 2 “register_operand” "")))] "" { if (!TARGET_MPY32) { rtx lo1 = gen_lowpart (HImode, operands[1]); rtx lo2 = gen_lowpart (HImode, operands[2]); /* (N * AH + AL) * (N * BH + BL) = N*(AH * BL + BH * AL) + AL*BL */ rtx tmp1 = gen_reg_rtx (SImode); rtx tmp2 = gen_reg_rtx (SImode); rtx tmp3 = gen_reg_rtx (SImode); emit_insn (gen_umulhisi3 (tmp1, lo1, lo2)); emit_insn (gen_umulhisi3_lh (tmp2, lo1, operands[2])); emit_insn (gen_umulhisi3_hl (tmp3, operands[1], lo2)); emit_insn (gen_addsi3 (tmp2, tmp2, tmp3)); emit_insn (gen_ashlsi3 (tmp2, tmp2, GEN_INT (16))); emit_insn (gen_addsi3 (operands[0], tmp1, tmp2)); DONE; } })

;; ------------------------------------------------------------------------- ;; Floating point multiplication ;; -------------------------------------------------------------------------

(define_insn “mulsf3” [(set (match_operand:SF 0 “register_operand” “=a,b,a,b”) (mult:SF (match_operand:SF 1 “register_operand” “%a,b,?a,?b”) (match_operand:SF 2 “register_operand” “a,b,b,a”)))] “TARGET_FP” “%|%.\tmpysp\t%$\t%1, %2, %0” [(set_attr “type” “mpy4”) (set_attr “units” “m”) (set_attr “cross” “n,n,y,y”)])

(define_insn “muldf3” [(set (match_operand:DF 0 “register_operand” “=a,b”) (mult:DF (match_operand:DF 1 “register_operand” “%a,b”) (match_operand:DF 2 “register_operand” “a,b”)))] “TARGET_FP” “%|%.\tmpydp\t%$\t%1, %2, %0” [(set_attr “type” “mpydp”) (set_attr “units” “m”) (set_attr “cross” “n”)])

;; Note that mpyspdp and mpysp2dp are available on C67x, despite what the ;; manual says. (define_insn “*muldf_ext1” [(set (match_operand:DF 0 “register_operand” “=a,b,a,b”) (mult:DF (float_extend:DF (match_operand:SF 1 “register_operand” “a,b,a,b”)) (match_operand:DF 2 “register_operand” “a,b,?b,?a”)))] “TARGET_FP_EXT” “%|%.\tmpyspdp\t%$\t%1, %2, %0” [(set_attr “type” “mpyspdp”) (set_attr “units” “m”) (set_attr “cross” “n,n,y,y”)])

(define_insn “*muldf_ext2” [(set (match_operand:DF 0 “register_operand” “=a,b,a,b”) (mult:DF (float_extend:DF (match_operand:SF 1 “register_operand” “%a,b,a,b”)) (float_extend:DF (match_operand:SF 2 “register_operand” “a,b,?b,?a”))))] “TARGET_FP_EXT” “%|%.\tmpysp2dp\t%$\t%1, %2, %0” [(set_attr “type” “mpysp2dp”) (set_attr “units” “m”) (set_attr “cross” “n,n,y,y”)])

;; ------------------------------------------------------------------------- ;; Floating point division ;; -------------------------------------------------------------------------

(define_insn “rcpsf2” [(set (match_operand:SF 0 “register_operand” “=a,b,a,b”) (unspec:SF [(match_operand:SF 1 “register_operand” “a,b,?b,?a”)] UNSPEC_RCP))] “TARGET_FP” “%|%.\trcpsp\t%$\t%1, %0” [(set_attr “units” “s”) (set_attr “cross” “n,n,y,y”)])

(define_insn “rcpdf2” [(set (match_operand:DF 0 “register_operand” “=a,b”) (unspec:DF [(match_operand:DF 1 “register_operand” “a,b”)] UNSPEC_RCP))] “TARGET_FP” “%|%.\trcpdp\t%$\t%1, %0” [(set_attr “type” “dp2”) (set_attr “units” “s”) (set_attr “cross” “n”)])

(define_expand “divsf3” [(set (match_dup 4) (unspec:SF [(match_operand:SF 2 “register_operand” "")] UNSPEC_RCP)) (set (match_dup 5) (mult:SF (match_dup 2) (match_dup 4))) (set (match_dup 6) (minus:SF (match_dup 3) (match_dup 5))) (set (match_dup 4) (mult:SF (match_dup 4) (match_dup 6))) (set (match_dup 5) (mult:SF (match_dup 2) (match_dup 4))) (set (match_dup 6) (minus:SF (match_dup 3) (match_dup 5))) (set (match_dup 4) (mult:SF (match_dup 4) (match_dup 6))) (set (match_operand:SF 0 “register_operand” "") (mult:SF (match_operand:SF 1 “register_operand”) (match_dup 4)))] “TARGET_FP && flag_reciprocal_math” { operands[3] = force_reg (SFmode, const_double_from_real_value (dconst2, SFmode)); operands[4] = gen_reg_rtx (SFmode); operands[5] = gen_reg_rtx (SFmode); operands[6] = gen_reg_rtx (SFmode); })

(define_expand “divdf3” [(set (match_dup 4) (unspec:DF [(match_operand:DF 2 “register_operand” "")] UNSPEC_RCP)) (set (match_dup 5) (mult:DF (match_dup 2) (match_dup 4))) (set (match_dup 6) (minus:DF (match_dup 3) (match_dup 5))) (set (match_dup 4) (mult:DF (match_dup 4) (match_dup 6))) (set (match_dup 5) (mult:DF (match_dup 2) (match_dup 4))) (set (match_dup 6) (minus:DF (match_dup 3) (match_dup 5))) (set (match_dup 4) (mult:DF (match_dup 4) (match_dup 6))) (set (match_dup 5) (mult:DF (match_dup 2) (match_dup 4))) (set (match_dup 6) (minus:DF (match_dup 3) (match_dup 5))) (set (match_dup 4) (mult:DF (match_dup 4) (match_dup 6))) (set (match_operand:DF 0 “register_operand” "") (mult:DF (match_operand:DF 1 “register_operand”) (match_dup 4)))] “TARGET_FP && flag_reciprocal_math” { operands[3] = force_reg (DFmode, const_double_from_real_value (dconst2, DFmode)); operands[4] = gen_reg_rtx (DFmode); operands[5] = gen_reg_rtx (DFmode); operands[6] = gen_reg_rtx (DFmode); })

;; ------------------------------------------------------------------------- ;; Block moves ;; -------------------------------------------------------------------------

(define_expand “cpymemsi” [(use (match_operand:BLK 0 “memory_operand” "")) (use (match_operand:BLK 1 “memory_operand” "")) (use (match_operand:SI 2 “nonmemory_operand” "")) (use (match_operand:SI 3 “const_int_operand” "")) (use (match_operand:SI 4 “const_int_operand” "")) (use (match_operand:SI 5 “const_int_operand” ""))] "" { if (c6x_expand_cpymem (operands[0], operands[1], operands[2], operands[3], operands[4], operands[5])) DONE; else FAIL; })

;; ------------------------------------------------------------------------- ;; Prologue and epilogue. ;; -------------------------------------------------------------------------

;; UNSPEC_VOLATILE is considered to use and clobber all hard registers and ;; all of memory. This blocks insns from being moved across this point.

(define_insn “blockage” [(unspec_volatile [(const_int 0)] UNSPECV_BLOCKAGE)] "" "" [(set_attr “type” “blockage”)])

(define_insn “push_rts” [(set (mem:SI (reg:SI REG_SP)) (reg:SI REG_B14)) (set (mem:DI (plus:SI (reg:SI REG_SP) (const_int -8))) (reg:DI REG_A14)) (set (mem:DI (plus:SI (reg:SI REG_SP) (const_int -16))) (reg:DI REG_B12)) (set (mem:DI (plus:SI (reg:SI REG_SP) (const_int -24))) (reg:DI REG_A12)) (set (mem:DI (plus:SI (reg:SI REG_SP) (const_int -32))) (reg:DI REG_B10)) (set (mem:DI (plus:SI (reg:SI REG_SP) (const_int -40))) (reg:DI REG_A10)) (set (mem:DI (plus:SI (reg:SI REG_SP) (const_int -48))) (reg:DI REG_B2)) (set (reg:SI REG_SP) (plus:SI (reg:SI REG_SP) (const_int -56))) (unspec_volatile [(const_int 0)] UNSPECV_BLOCKAGE) (clobber (reg:SI REG_A3))] “TARGET_INSNS_64PLUS” “%|%.\tcallp\t%$\t__c6xabi_push_rts, a3” [(set_attr “type” “callp”) (set_attr “dest_regfile” “a”) (set_attr “units” “s”) (set_attr “cross” “n”)])

(define_insn “pop_rts” [(set (reg:SI REG_B14) (mem:SI (plus:SI (reg:SI REG_SP) (const_int 56)))) (set (reg:DI REG_A14) (mem:DI (plus:SI (reg:SI REG_SP) (const_int 48)))) (set (reg:DI REG_B12) (mem:DI (plus:SI (reg:SI REG_SP) (const_int 40)))) (set (reg:DI REG_A12) (mem:DI (plus:SI (reg:SI REG_SP) (const_int 32)))) (set (reg:DI REG_B10) (mem:DI (plus:SI (reg:SI REG_SP) (const_int 24)))) (set (reg:DI REG_A10) (mem:DI (plus:SI (reg:SI REG_SP) (const_int 16)))) (set (reg:DI REG_B2) (mem:DI (plus:SI (reg:SI REG_SP) (const_int 8)))) (set (reg:SI REG_SP) (plus:SI (reg:SI REG_SP) (const_int 56))) (clobber (reg:SI REG_A3)) (return)] “TARGET_INSNS_64PLUS” “%|%.\tretp\t%$\t__c6xabi_pop_rts, a3” [(set_attr “type” “callp”) (set_attr “dest_regfile” “a”) (set_attr “units” “s”) (set_attr “cross” “n”)])

(define_expand “prologue” [(const_int 1)] "" “c6x_expand_prologue (); DONE;”)

(define_expand “epilogue” [(const_int 1)] "" “c6x_expand_epilogue (false); DONE;”)

(define_expand “sibcall_epilogue” [(return)] "" { c6x_expand_epilogue (true); DONE; })

(define_insn “setup_dsbt” [(set (match_operand:SI 0 “pic_register_operand” “+Z”) (unspec:SI [(match_dup 0) (match_operand:SI 1 “symbolic_operand” "")] UNSPEC_SETUP_DSBT))] “TARGET_DSBT” “%|%.\tldw\t%$\t*+%0($DSBT_index%1), %0” [(set_attr “type” “load”) (set_attr “units” “d_addr”) (set_attr “dest_regfile” “b”) (set_attr “addr_regfile” “b”)])

;; A dummy use/set to prevent prologue and epiloge overlapping. ;; This can be caused by sched-ebb in the presence of multiple ;; exit sequences, and causes the unwinding table generation to explode. (define_insn “epilogue_barrier” [(set (match_operand:SI 0 “register_operand” "") (unspec:SI [(match_operand:SI 1 “register_operand” "")] UNSPEC_EPILOGUE_BARRIER))] "" "" [(set_attr “type” “blockage”)])

;; ------------------------------------------------------------------------- ;; Vector insns ;; -------------------------------------------------------------------------

(define_code_iterator logical [and ior xor]) (define_code_attr logical_insn [(and “and”) (ior “ior”) (xor “xor”)]) (define_code_attr logical_opcode [(and “and”) (ior “or”) (xor “xor”)]) (define_code_iterator plusminus [plus minus]) (define_code_attr plusminus_insn [(plus “add”) (minus “sub”)]) (define_code_iterator ss_plusminus [ss_plus ss_minus]) (define_code_attr ss_plusminus_insn [(ss_plus “add”) (ss_minus “sub”)])

;; Vector logical insns

(define_insn “<logical_insn>3” [(set (match_operand:VEC4M 0 “register_operand” “=a,b,a,b”) (logical:VEC4M (match_operand:VEC4M 1 “register_operand” “a,b,a,b”) (match_operand:VEC4M 2 “register_operand” “a,b,?b,?a”)))] "" “%|%.\t<logical_opcode>\t%$\t%1, %2, %0” [(set_attr “units62” “ls”) (set_attr “units64” “dls”) (set_attr “cross” “n,n,y,y”)])

;; Vector add/subtract

(define_insn “<plusminus_insn>v2hi3” [(set (match_operand:V2HI 0 “register_operand” “=a,b,a,b”) (plusminus:V2HI (match_operand:V2HI 1 “register_operand” “a,b,a,b”) (match_operand:V2HI 2 “register_operand” “a,b,?b,?a”)))] "" “%|%.\t<plusminus_insn>2\t%$\t%1, %2, %0” [(set_attr “units62” “l”) (set_attr “units64” “dls”) (set_attr “cross” “n,n,y,y”)])

(define_insn “<plusminus_insn>v4qi3” [(set (match_operand:V4QI 0 “register_operand” “=a,b,a,b”) (plusminus:V4QI (match_operand:V4QI 1 “register_operand” “a,b,a,b”) (match_operand:V4QI 2 “register_operand” “a,b,?b,?a”)))] “TARGET_INSNS_64” “%|%.\t<plusminus_insn>4\t%$\t%1, %2, %0” [(set_attr “units” “l”) (set_attr “cross” “n,n,y,y”)])

(define_insn “ss_addv2hi3” [(set (match_operand:V2HI 0 “register_operand” “=a,b,a,b”) (ss_plus:V2HI (match_operand:V2HI 1 “register_operand” “a,b,a,b”) (match_operand:V2HI 2 “register_operand” “a,b,?b,?a”)))] “TARGET_INSNS_64” “%|%.\tsadd2\t%$\t%1, %2, %0” [(set_attr “units” “s”) (set_attr “cross” “n,n,y,y”)])

(define_insn “ss_subv2hi3” [(set (match_operand:V2HI 0 “register_operand” “=a,b,a,b”) (ss_minus:V2HI (match_operand:V2HI 1 “register_operand” “a,b,a,b”) (match_operand:V2HI 2 “register_operand” “a,b,?b,?a”)))] “TARGET_INSNS_64” “%|%.\tssub2\t%$\t%1, %2, %0” [(set_attr “units” “l”) (set_attr “cross” “n,n,y,y”)])

(define_insn “us_addv4qi3” [(set (match_operand:V4QI 0 “register_operand” “=a,b,a,b”) (ss_plus:V4QI (match_operand:V4QI 1 “register_operand” “a,b,a,b”) (match_operand:V4QI 2 “register_operand” “a,b,?b,?a”)))] “TARGET_INSNS_64” “%|%.\tsaddu4\t%$\t%1, %2, %0” [(set_attr “units” “s”) (set_attr “cross” “n,n,y,y”)])

;; Vector/scalar min/max

(define_mode_iterator SMINMAX [HI V2HI]) (define_mode_iterator UMINMAX [QI V4QI])

(define_insn “smax3” [(set (match_operand:SMINMAX 0 “register_operand” “=a,b,a,b”) (smax:SMINMAX (match_operand:SMINMAX 1 “register_operand” “a,b,a,b”) (match_operand:SMINMAX 2 “register_operand” “a,b,?b,?a”)))] “TARGET_INSNS_64” “%|%.\tmax2\t%$\t%1, %2, %0” [(set_attr “units64” “l”) (set_attr “units64p” “ls”) (set_attr “cross” “n,n,y,y”)])

(define_insn “smin3” [(set (match_operand:SMINMAX 0 “register_operand” “=a,b,a,b”) (smin:SMINMAX (match_operand:SMINMAX 1 “register_operand” “a,b,a,b”) (match_operand:SMINMAX 2 “register_operand” “a,b,?b,?a”)))] “TARGET_INSNS_64” “%|%.\tmin2\t%$\t%1, %2, %0” [(set_attr “units64” “l”) (set_attr “units64p” “ls”) (set_attr “cross” “n,n,y,y”)])

(define_insn “umax3” [(set (match_operand:UMINMAX 0 “register_operand” “=a,b,a,b”) (umax:UMINMAX (match_operand:UMINMAX 1 “register_operand” “a,b,a,b”) (match_operand:UMINMAX 2 “register_operand” “a,b,?b,?a”)))] “TARGET_INSNS_64” “%|%.\tmaxu4\t%$\t%1, %2, %0” [(set_attr “units” “l”) (set_attr “cross” “n,n,y,y”)])

(define_insn “umin3” [(set (match_operand:UMINMAX 0 “register_operand” “=a,b,a,b”) (umin:UMINMAX (match_operand:UMINMAX 1 “register_operand” “a,b,a,b”) (match_operand:UMINMAX 2 “register_operand” “a,b,?b,?a”)))] “TARGET_INSNS_64” “%|%.\tminu4\t%$\t%1, %2, %0” [(set_attr “units” “l”) (set_attr “cross” “n,n,y,y”)])

;; Vector shifts

(define_insn “<shift_code>v2hi3” [(set (match_operand:V2HI 0 “register_operand” “=a,b,a,b”) (any_rshift:V2HI (match_operand:V2HI 1 “register_operand” “a,b,?b,?a”) (match_operand:SI 2 “reg_or_ucst5_operand” “aIu5,bIu5,aIu5,bIu5”)))] “TARGET_INSNS_64” “%|%.\t<shift_insn>2\t%$\t%1, %2, %0” [(set_attr “units” “s”) (set_attr “cross” “n,n,y,y”)])

;; See c6x-mult.md.in for avg2/avgu4

;; Widening vector multiply and dot product. ;; See c6x-mult.md.in for the define_insn patterns

(define_expand “sdot_prodv2hi” [(match_operand:SI 0 “register_operand” "") (match_operand:V2HI 1 “register_operand” "") (match_operand:V2HI 2 “register_operand” "") (match_operand:SI 3 “register_operand” "")] “TARGET_INSNS_64” { rtx t = gen_reg_rtx (SImode); emit_insn (gen_dotv2hi (t, operands[1], operands[2])); emit_insn (gen_addsi3 (operands[0], operands[3], t)); DONE; })

;; Unary vector operations

(define_insn “ssabsv2hi2” [(set (match_operand:V2HI 0 “register_operand” “=a, a, b, b”) (ss_abs:V2HI (match_operand:V2HI 1 “register_operand” “a,?b, b,?a”)))] “TARGET_INSNS_64” “%|%.\tabs2\t%$\t%1, %0” [(set_attr “units” “l”) (set_attr “cross” “n,y,n,y”)])

;; Pack insns

(define_insn “*packv2hi_insv” [(set (zero_extract:SI (match_operand:SI 0 “register_operand” “+a,b,a,b,ab”) (const_int 16) (const_int 16)) (match_operand:SI 1 “nonmemory_operand” “a,b,?b,?a,n”))] “TARGET_INSNS_64” “@ %|%.\tpack2\t%$\t%1, %0, %0 %|%.\tpack2\t%$\t%1, %0, %0 %|%.\tpack2\t%$\t%1, %0, %0 %|%.\tpack2\t%$\t%1, %0, %0 %|%.\tmvklh\t%$\t%1, %0” [(set_attr “units” “ls”) (set_attr “cross” “n,n,y,y,n”)])

(define_insn “movstricthi” [(set (strict_low_part (match_operand:HI 0 “register_operand” “+a,b,a,b”)) (match_operand:HI 1 “register_operand” “a,b,?b,?a”))] “TARGET_INSNS_64” “%|%.\tpackhl2\t%$\t%0, %1, %0” [(set_attr “units” “ls”) (set_attr “cross” “n,n,y,y”)])

(include “c6x-mult.md”) (include “sync.md”)