| ;; Machine description for Tilera TILEPro chip for GCC. |
| ;; Copyright (C) 2011-2015 Free Software Foundation, Inc. |
| ;; Contributed by Walter Lee (walt@tilera.com) |
| ;; |
| ;; 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/>. |
| |
| (define_constants [ |
| ;; |
| ;; The following represent intrinsic insns, organized by latency. |
| ;; |
| |
| ;; single cycle |
| (UNSPEC_INSN_ADDLIS 1) |
| (UNSPEC_INSN_AULI 2) |
| (UNSPEC_INSN_AVGB_U 3) |
| (UNSPEC_INSN_AVGH 4) |
| (UNSPEC_INSN_BITX 5) |
| (UNSPEC_INSN_CRC32_32 6) |
| (UNSPEC_INSN_CRC32_8 7) |
| (UNSPEC_INSN_DRAIN 8) |
| (UNSPEC_INSN_DTLBPR 9) |
| (UNSPEC_INSN_DWORD_ALIGN 10) |
| (UNSPEC_INSN_FINV 11) |
| (UNSPEC_INSN_FLUSH 12) |
| (UNSPEC_INSN_FNOP 13) |
| (UNSPEC_INSN_ICOH 14) |
| (UNSPEC_INSN_ILL 15) |
| (UNSPEC_INSN_INFO 16) |
| (UNSPEC_INSN_INFOL 17) |
| (UNSPEC_INSN_INV 18) |
| (UNSPEC_INSN_LNK 19) |
| (UNSPEC_INSN_MFSPR 20) |
| (UNSPEC_INSN_MNZB 21) |
| (UNSPEC_INSN_MNZH 22) |
| (UNSPEC_INSN_MOVELIS 23) |
| (UNSPEC_INSN_MTSPR 24) |
| (UNSPEC_INSN_MZB 25) |
| (UNSPEC_INSN_MZH 26) |
| (UNSPEC_INSN_NAP 27) |
| (UNSPEC_INSN_PACKBS_U 28) |
| (UNSPEC_INSN_PACKHB 29) |
| (UNSPEC_INSN_PACKHS 30) |
| (UNSPEC_INSN_PACKLB 31) |
| (UNSPEC_INSN_PREFETCH_L1 32) |
| (UNSPEC_INSN_TBLIDXB0 33) |
| (UNSPEC_INSN_TBLIDXB1 34) |
| (UNSPEC_INSN_TBLIDXB2 35) |
| (UNSPEC_INSN_TBLIDXB3 36) |
| (UNSPEC_INSN_WH64 37) |
| |
| ;; 2 cycles |
| (UNSPEC_INSN_ADIFFB_U 100) |
| (UNSPEC_INSN_ADIFFH 101) |
| (UNSPEC_INSN_MULHHA_SS 102) |
| (UNSPEC_INSN_MULHHA_SU 103) |
| (UNSPEC_INSN_MULHHA_UU 104) |
| (UNSPEC_INSN_MULHHSA_UU 105) |
| (UNSPEC_INSN_MULHH_SS 106) |
| (UNSPEC_INSN_MULHH_SU 107) |
| (UNSPEC_INSN_MULHH_UU 108) |
| (UNSPEC_INSN_MULHLA_SS 109) |
| (UNSPEC_INSN_MULHLA_SU 110) |
| (UNSPEC_INSN_MULHLA_US 111) |
| (UNSPEC_INSN_MULHLA_UU 112) |
| (UNSPEC_INSN_MULHLSA_UU 113) |
| (UNSPEC_INSN_MULHL_SS 114) |
| (UNSPEC_INSN_MULHL_SU 115) |
| (UNSPEC_INSN_MULHL_US 116) |
| (UNSPEC_INSN_MULHL_UU 117) |
| (UNSPEC_INSN_MULLLA_SS 118) |
| (UNSPEC_INSN_MULLLA_SU 119) |
| (UNSPEC_INSN_MULLLA_UU 120) |
| (UNSPEC_INSN_MULLLSA_UU 121) |
| (UNSPEC_INSN_MULLL_SU 122) |
| (UNSPEC_INSN_MULLL_SS 123) |
| (UNSPEC_INSN_MULLL_UU 124) |
| (UNSPEC_INSN_SADAB_U 125) |
| (UNSPEC_INSN_SADAH 126) |
| (UNSPEC_INSN_SADAH_U 127) |
| (UNSPEC_INSN_SADB_U 128) |
| (UNSPEC_INSN_SADH 129) |
| (UNSPEC_INSN_SADH_U 130) |
| |
| ;; |
| ;; The following are special insns. |
| ;; |
| |
| ;; Blockage |
| (UNSPEC_BLOCKAGE 200) |
| |
| ;; Latency specifying loads. |
| (UNSPEC_LATENCY_L2 201) |
| (UNSPEC_LATENCY_MISS 202) |
| |
| ;; Lnk and its label |
| (UNSPEC_LNK_AND_LABEL 203) |
| |
| ;; Memory fence |
| (UNSPEC_MF 204) |
| |
| ;; A pseudo-op that prevents network operations from being ordered. |
| (UNSPEC_NETWORK_BARRIER 205) |
| |
| ;; Operations that access network registers. |
| (UNSPEC_NETWORK_RECEIVE 206) |
| (UNSPEC_NETWORK_SEND 207) |
| |
| ;; Stack protector operations |
| (UNSPEC_SP_SET 208) |
| (UNSPEC_SP_TEST 209) |
| |
| ;; A call to __tls_get_addr |
| (UNSPEC_TLS_GD_CALL 210) |
| |
| ;; An opaque TLS "add" operation for TLS general dynamic model |
| ;; access. |
| (UNSPEC_TLS_GD_ADD 211) |
| |
| ;; An opaque TLS "load" operation for TLS initial exec model access. |
| (UNSPEC_TLS_IE_LOAD 212) |
| |
| ;; |
| ;; The following are operands. |
| ;; |
| (UNSPEC_PCREL_SYM 300) |
| (UNSPEC_GOT16_SYM 301) |
| (UNSPEC_GOT32_SYM 302) |
| (UNSPEC_TLS_GD 303) |
| (UNSPEC_TLS_IE 304) |
| (UNSPEC_TLS_LE 305) |
| ]) |
| |
| ;; Mark the last instruction of various latencies, used to |
| ;; determine the rtx costs of unspec insns. |
| (define_constants [ |
| (TILEPRO_LAST_LATENCY_1_INSN 99) |
| (TILEPRO_LAST_LATENCY_2_INSN 199) |
| (TILEPRO_LAST_LATENCY_INSN 299) |
| ]) |
| |
| ;; Constants for network registers. |
| (define_constants [ |
| (TILEPRO_NETREG_IDN0 0) |
| (TILEPRO_NETREG_IDN1 1) |
| (TILEPRO_NETREG_SN 2) |
| (TILEPRO_NETREG_UDN0 3) |
| (TILEPRO_NETREG_UDN1 4) |
| (TILEPRO_NETREG_UDN2 5) |
| (TILEPRO_NETREG_UDN3 6) |
| ]) |
| |
| ;; Constants for special purpose registers. |
| (define_constants [ |
| (TILEPRO_NETORDER_REG 66)]) |
| |
| |
| ;; Operand and operator predicates and constraints |
| |
| (include "predicates.md") |
| (include "constraints.md") |
| (include "tilepro-generic.md") |
| |
| ;; Define an insn type attribute. This defines what pipes things can |
| ;; go in. |
| (define_attr "type" |
| "X0,X0_2cycle,X1,X1_branch,X1_2cycle,X1_L2,X1_miss,X01,Y0,Y0_2cycle,Y2,Y2_2cycle,Y2_L2,Y2_miss,Y01,cannot_bundle,cannot_bundle_3cycle,cannot_bundle_4cycle,nothing" |
| (const_string "Y01")) |
| |
| (define_attr "length" "" |
| (cond [(eq_attr "type" "X1_branch") |
| (if_then_else |
| (and (le (minus (match_dup 0) (pc)) (const_int 524280)) |
| (le (minus (pc) (match_dup 0)) (const_int 524288))) |
| (const_int 8) |
| (const_int 16)) |
| ] |
| (const_int 8))) |
| |
| |
| ;; Define iterators. |
| (define_mode_iterator I48MODE [SI DI]) |
| (define_mode_iterator I12MODE [QI HI]) |
| |
| (define_code_iterator binop_u5bit [ashift ashiftrt lshiftrt rotate]) |
| (define_code_iterator binop_with_imm |
| [ashift lshiftrt ashiftrt rotate eq lt and ior xor]) |
| (define_code_iterator unop [bswap clz ctz popcount]) |
| |
| (define_mode_attr load [(QI "lb") (HI "lh") (SI "lw")]) |
| (define_mode_attr store [(QI "sb") (HI "sh") (SI "sw")]) |
| |
| ;; <optab> expands to the name of the optab for a particular code. |
| (define_code_attr optab [(ashift "ashl") |
| (ashiftrt "ashr") |
| (lshiftrt "lshr") |
| (eq "seq") |
| (ne "sne") |
| (lt "slt") |
| (ltu "sltu") |
| (le "sle") |
| (leu "sleu") |
| (minus "sub") |
| (plus "add") |
| (rotate "rotl") |
| (smax "smax") |
| (smin "smin") |
| (umax "umax") |
| (umin "umin") |
| (ss_minus "sssub") |
| (ss_plus "ssadd") |
| (us_minus "ussub") |
| (us_plus "usadd") |
| (and "and") |
| (ior "ior") |
| (xor "xor") |
| (bswap "bswap") |
| (clz "clz") |
| (ctz "ctz") |
| (popcount "popcount")]) |
| |
| ;; <insn> expands to the name of the insn that implements a particular |
| ;; code. |
| (define_code_attr insn [(ashift "shl") |
| (ashiftrt "sra") |
| (lshiftrt "shr") |
| (eq "seq") |
| (ne "sne") |
| (lt "slt") |
| (ltu "slt") |
| (le "slte") |
| (leu "slte") |
| (minus "sub") |
| (plus "add") |
| (rotate "rl") |
| (smax "max") |
| (smin "min") |
| (umax "max") |
| (umin "min") |
| (ss_minus "sub") |
| (ss_plus "add") |
| (us_minus "sub") |
| (us_plus "add") |
| (and "and") |
| (ior "or") |
| (xor "xor") |
| (bswap "bytex") |
| (clz "clz") |
| (ctz "ctz") |
| (popcount "pcnt")]) |
| |
| ;; <u> expands to the suffix of the insn that implements a particular |
| ;; code. |
| (define_code_attr u [(ashift "") |
| (ashiftrt "") |
| (lshiftrt "") |
| (eq "") |
| (ne "") |
| (lt "") |
| (ltu "_u") |
| (le "") |
| (leu "_u") |
| (minus "") |
| (plus "") |
| (rotate "") |
| (smax "") |
| (smin "") |
| (umax "_u") |
| (umin "_u") |
| (ss_minus "s") |
| (ss_plus "s") |
| (us_minus "s_u") |
| (us_plus "s_u") |
| (and "") |
| (ior "") |
| (xor "")]) |
| |
| ;; <comm> indicates whether a particular code is commutative, using |
| ;; the "%" commutative opterator constraint. |
| (define_code_attr comm [(ashift "") |
| (ashiftrt "") |
| (lshiftrt "") |
| (eq "%") |
| (ne "%") |
| (lt "") |
| (ltu "") |
| (le "") |
| (leu "") |
| (minus "") |
| (plus "%") |
| (rotate "") |
| (smax "%") |
| (umax "%") |
| (smin "%") |
| (umin "%") |
| (ss_plus "%") |
| (us_plus "%") |
| (ss_minus "") |
| (us_minus "") |
| (and "%") |
| (ior "%") |
| (xor "%")]) |
| |
| (define_mode_iterator VEC [V4QI V2HI]) |
| |
| ;; Code iterator for all three shifts. |
| (define_code_iterator any_shift [ashift ashiftrt lshiftrt]) |
| |
| ;; Code iterator for all byte ops without immediate variants. |
| (define_code_iterator v1op [us_plus ne le leu minus us_minus]) |
| |
| ;; Code iterator for all 2-byte vector ops without immediate variants. |
| (define_code_iterator v2op [ss_plus ne le leu minus ss_minus]) |
| |
| ;; Code iterator for all byte vector ops with immediate variants. |
| (define_code_iterator v1op_immed [plus umax umin eq lt ltu]) |
| |
| ;; Code iterator for all 2-byte vector ops with immediate variants. |
| (define_code_iterator v2op_immed [plus smax smin eq lt ltu]) |
| |
| ;; Code for packing two 2-byte vectors. |
| (define_code_iterator v2pack [truncate us_truncate]) |
| |
| ;; <pack_optab> expands to the part of the optab name describing how |
| ;; two vectors are packed. |
| (define_code_attr pack_optab [(truncate "trunc") |
| (us_truncate "usat") |
| (ss_truncate "ssat")]) |
| |
| ;; <pack_insn> expands to the insn that implements a particular vector |
| ;; packing code. |
| (define_code_attr pack_insn [(truncate "packl") |
| (us_truncate "pack") |
| (ss_truncate "pack")]) |
| |
| ;; <pack_u> expands to the suffix of the insn that implements a |
| ;; particular vector packing code. |
| (define_code_attr pack_u [(truncate "") |
| (us_truncate "s_u") |
| (ss_truncate "s")]) |
| |
| |
| ;; |
| ;; The basic data move insns. |
| ;; |
| |
| (define_expand "movqi" |
| [(set (match_operand:QI 0 "nonimmediate_operand" "") |
| (match_operand:QI 1 "nonautoinc_operand" ""))] |
| "" |
| { |
| if (tilepro_expand_mov (QImode, operands)) |
| DONE; |
| }) |
| |
| (define_insn "*movqi_insn" |
| [(set (match_operand:QI 0 "nonimmediate_operand" "=r,r,r,r,U,m") |
| (match_operand:QI 1 "move_operand" "r,I,U,m,rO,rO"))] |
| "(register_operand (operands[0], QImode) |
| || reg_or_0_operand (operands[1], QImode))" |
| "@ |
| move\t%0, %r1 |
| movei\t%0, %1 |
| lb_u\t%0, %1 |
| lbadd_u\t%0, %I1, %i1 |
| sb\t%0, %r1 |
| sbadd\t%I0, %r1, %i0" |
| [(set_attr "type" "*,*,Y2_2cycle,X1_2cycle,Y2,X1")]) |
| |
| (define_expand "movhi" |
| [(set (match_operand:HI 0 "nonimmediate_operand" "") |
| (match_operand:HI 1 "nonautoinc_operand" ""))] |
| "" |
| { |
| if (tilepro_expand_mov (HImode, operands)) |
| DONE; |
| }) |
| |
| (define_insn "*movhi_insn" |
| [(set (match_operand:HI 0 "nonimmediate_operand" "=r,r,r,r,r,U,m") |
| (match_operand:HI 1 "move_operand" "r,I,J,U,m,rO,rO"))] |
| "(register_operand (operands[0], HImode) |
| || reg_or_0_operand (operands[1], HImode))" |
| "@ |
| move\t%0, %r1 |
| movei\t%0, %1 |
| moveli\t%0, %1 |
| lh_u\t%0, %1 |
| lhadd_u\t%0, %I1, %i1 |
| sh\t%0, %r1 |
| shadd\t%I0, %r1, %i0" |
| [(set_attr "type" "*,*,X01,Y2_2cycle,X1_2cycle,Y2,X1")]) |
| |
| |
| (define_expand "movsi" |
| [(set (match_operand:SI 0 "nonimmediate_operand" "") |
| (match_operand:SI 1 "nonautoinc_operand" ""))] |
| "" |
| { |
| if (tilepro_expand_mov (SImode, operands)) |
| DONE; |
| }) |
| |
| (define_insn "*movsi_high_insn" |
| [(set (match_operand:SI 0 "register_operand" "=r") |
| (high:SI (match_operand:SI 1 "symbolic_operand" "in")))] |
| "" |
| "auli\t%0, zero, ha16(%1)" |
| [(set_attr "type" "X01")]) |
| |
| (define_insn "*movsi_insn" |
| [(set (match_operand:SI 0 "nonimmediate_operand" "=r,r,r,r,r,r,r,r,U,m") |
| (match_operand:SI 1 "move_operand" "r,I,J,K,N,P,U,m,rO,rO"))] |
| "(register_operand (operands[0], SImode) |
| || reg_or_0_operand (operands[1], SImode))" |
| "@ |
| move\t%0, %r1 |
| movei\t%0, %1 |
| moveli\t%0, %1 |
| auli\t%0, zero, %h1 |
| addib\t%0, zero, %j1 |
| addih\t%0, zero, %h1 |
| lw\t%0, %1 |
| lwadd\t%0, %I1, %i1 |
| sw\t%0, %r1 |
| swadd\t%I0, %r1, %i0" |
| [(set_attr "type" "*,*,X01,X01,X01,X01,Y2_2cycle,X1_2cycle,Y2,X1")]) |
| |
| (define_insn "movstrictqi" |
| [(set (strict_low_part (match_operand:QI 0 "register_operand" "+r")) |
| (match_operand:QI 1 "reg_or_0_operand" "rO"))] |
| "" |
| "mm\t%r0, %r1, %r0, 0, 7" |
| [(set_attr "type" "X01")]) |
| |
| (define_insn "movstricthi" |
| [(set (strict_low_part (match_operand:HI 0 "register_operand" "+r")) |
| (match_operand:HI 1 "reg_or_0_operand" "rO"))] |
| "" |
| "mm\t%r0, %r1, %r0, 0, 15" |
| [(set_attr "type" "X01")]) |
| |
| (define_expand "movmisalign<mode>" |
| [(set (match_operand:VEC 0 "nonautoincmem_nonimmediate_operand" "") |
| (match_operand:VEC 1 "nonautoincmem_general_operand" ""))] |
| "" |
| { |
| tilepro_expand_movmisalign (<MODE>mode, operands); |
| DONE; |
| }) |
| |
| (define_expand "movsf" |
| [(set (match_operand:SF 0 "nonimmediate_operand" "") |
| (match_operand:SF 1 "general_operand" ""))] |
| "" |
| { |
| /* Materialize immediates using clever SImode code, but don't |
| do this after reload starts, since gen_lowpart will choke |
| during reload if given an illegitimate address. */ |
| if (immediate_operand (operands[1], SFmode) |
| && operands[1] != const0_rtx |
| && (register_operand (operands[0], SFmode) |
| || (!reload_in_progress && !reload_completed))) |
| { |
| emit_insn (gen_movsi (gen_lowpart (SImode, operands[0]), |
| gen_lowpart (SImode, operands[1]))); |
| DONE; |
| } |
| }) |
| |
| (define_insn "*movsf" |
| [(set (match_operand:SF 0 "nonimmediate_operand" "=r,r,r,U,m") |
| (match_operand:SF 1 "general_operand" "rO,U,m,rO,rO"))] |
| "" |
| "@ |
| move\t%0, %r1 |
| lw\t%0, %1 |
| lwadd\t%0, %I1, %i1 |
| sw\t%0, %r1 |
| swadd\t%I0, %r1, %i0" |
| [(set_attr "type" "*,Y2_2cycle,X1_2cycle,Y2,X1")]) |
| |
| (define_expand "mov<mode>" |
| [(set (match_operand:VEC 0 "nonimmediate_operand" "") |
| (match_operand:VEC 1 "general_operand" ""))] |
| "" |
| { |
| /* Materialize immediates using clever SImode code, but don't |
| do this after reload starts, since gen_lowpart will choke |
| during reload if given an illegitimate address. */ |
| if (immediate_operand (operands[1], <MODE>mode) |
| && operands[1] != const0_rtx |
| && (register_operand (operands[0], <MODE>mode) |
| || (!reload_in_progress && !reload_completed))) |
| { |
| emit_insn (gen_movsi (gen_lowpart (SImode, operands[0]), |
| gen_lowpart (SImode, operands[1]))); |
| DONE; |
| } |
| }) |
| |
| (define_insn "*mov<mode>" |
| [(set (match_operand:VEC 0 "nonimmediate_operand" "=r,r,r,U,m") |
| (match_operand:VEC 1 "general_operand" "rO,U,m,rO,rO"))] |
| "" |
| "@ |
| move\t%0, %r1 |
| lw\t%0, %1 |
| lwadd\t%0, %I1, %i1 |
| sw\t%0, %r1 |
| swadd\t%I0, %r1, %i0" |
| [(set_attr "type" "*,Y2_2cycle,X1_2cycle,Y2,X1")]) |
| |
| |
| ;; |
| ;; Bit-field extracts |
| ;; |
| |
| (define_expand "extv" |
| [(set (match_operand:SI 0 "register_operand" "") |
| (sign_extract:SI |
| (match_operand:QI 1 "nonautoincmem_operand" "") |
| (match_operand:SI 2 "immediate_operand" "") |
| (match_operand:SI 3 "immediate_operand" "")))] |
| "" |
| { |
| HOST_WIDE_INT bit_offset, bit_width; |
| HOST_WIDE_INT first_byte_offset, last_byte_offset; |
| |
| bit_width = INTVAL (operands[2]); |
| bit_offset = INTVAL (operands[3]); |
| |
| /* Reject bitfields that can be done with a normal load */ |
| if (MEM_ALIGN (operands[1]) >= bit_offset + bit_width) |
| FAIL; |
| |
| /* The value in memory cannot span more than 4 bytes. */ |
| first_byte_offset = bit_offset / BITS_PER_UNIT; |
| last_byte_offset = (bit_offset + bit_width - 1) / BITS_PER_UNIT; |
| if (last_byte_offset - first_byte_offset > 3) |
| FAIL; |
| |
| tilepro_expand_unaligned_load (operands[0], operands[1], |
| bit_width, bit_offset, 1); |
| |
| DONE; |
| }) |
| |
| (define_expand "extzv" |
| [(set (match_operand:SI 0 "register_operand" "") |
| (zero_extract:SI |
| (match_operand:QI 1 "nonautoincmem_operand" "") |
| (match_operand:SI 2 "immediate_operand" "") |
| (match_operand:SI 3 "immediate_operand" "")))] |
| "" |
| { |
| HOST_WIDE_INT bit_offset, bit_width; |
| HOST_WIDE_INT first_byte_offset, last_byte_offset; |
| |
| bit_width = INTVAL (operands[2]); |
| bit_offset = INTVAL (operands[3]); |
| |
| /* Reject bitfields that can be done with a normal load */ |
| if (MEM_ALIGN (operands[1]) >= bit_offset + bit_width) |
| FAIL; |
| |
| /* The value in memory cannot span more than 4 bytes. */ |
| first_byte_offset = bit_offset / BITS_PER_UNIT; |
| last_byte_offset = (bit_offset + bit_width - 1) / BITS_PER_UNIT; |
| if (last_byte_offset - first_byte_offset > 3) |
| FAIL; |
| |
| tilepro_expand_unaligned_load (operands[0], operands[1], |
| bit_width, bit_offset, 0); |
| |
| DONE; |
| }) |
| |
| |
| ;; |
| ;; Arithmetic ops |
| ;; |
| |
| (define_insn "*s123a_insn" |
| [(set (match_operand:SI 0 "register_operand" "=r") |
| (plus:SI (mult:SI (match_operand:SI 1 "reg_or_0_operand" "rO") |
| (match_operand:SI 2 "cint_248_operand" "I")) |
| (match_operand:SI 3 "reg_or_0_operand" "rO")))] |
| "" |
| "s%t2a\t%0, %r1, %r3") |
| |
| (define_expand "addsi3" |
| [(set (match_operand:SI 0 "register_operand" "") |
| (plus:SI (match_operand:SI 1 "register_operand" "") |
| (match_operand:SI 2 "reg_or_cint_operand" "")))] |
| "" |
| " |
| if (tilepro_expand_addsi (operands[0], operands[1], operands[2])) |
| DONE; |
| ") |
| |
| (define_insn "*addsi_high_insn" |
| [(set (match_operand:SI 0 "register_operand" "=r") |
| (plus:SI |
| (match_operand:SI 1 "reg_or_0_operand" "%rO") |
| (high:SI (match_operand:SI 2 "const_symbolic_operand" "T"))))] |
| "" |
| "auli\t%0, %r1, %H2" |
| [(set_attr "type" "X01")]) |
| |
| (define_insn "*addsi_lo_sum_insn" |
| [(set (match_operand:SI 0 "register_operand" "=r") |
| (lo_sum:SI |
| (match_operand:SI 1 "reg_or_0_operand" "%rO") |
| (match_operand:SI 2 "const_symbolic_operand" "T")))] |
| "" |
| "addli\t%0, %r1, %L2" |
| [(set_attr "type" "X01")]) |
| |
| (define_insn "*addsi3_insn" |
| [(set (match_operand:SI 0 "register_operand" "=r,r,r,r") |
| (plus:SI (match_operand:SI 1 "reg_or_0_operand" "%rO,rO,rO,rO") |
| (match_operand:SI 2 "add_operand" "r,I,J,K")))] |
| "" |
| "@ |
| add\t%0, %r1, %r2 |
| addi\t%0, %r1, %2 |
| addli\t%0, %r1, %2 |
| auli\t%0, %r1, %h2" |
| [(set_attr "type" "*,*,X01,X01")]) |
| |
| (define_insn "subsi3" |
| [(set (match_operand:SI 0 "register_operand" "=r") |
| (minus:SI (match_operand:SI 1 "reg_or_0_operand" "rO") |
| (match_operand:SI 2 "reg_or_0_operand" "rO")))] |
| "" |
| "sub\t%0, %r1, %r2") |
| |
| (define_insn "negsi2" |
| [(set (match_operand:SI 0 "register_operand" "=r") |
| (neg:SI (match_operand:SI 1 "reg_or_0_operand" "rO")))] |
| "" |
| "sub\t%0, zero, %r1") |
| |
| (define_insn "ssaddsi3" |
| [(set (match_operand:SI 0 "register_operand" "=r") |
| (ss_plus:SI (match_operand:SI 1 "reg_or_0_operand" "rO") |
| (match_operand:SI 2 "reg_or_0_operand" "rO")))] |
| "" |
| "adds\t%0, %r1, %r2" |
| [(set_attr "type" "X01")]) |
| |
| (define_insn "sssubsi3" |
| [(set (match_operand:SI 0 "register_operand" "=r") |
| (ss_minus:SI (match_operand:SI 1 "reg_or_0_operand" "rO") |
| (match_operand:SI 2 "reg_or_0_operand" "rO")))] |
| "" |
| "subs\t%0, %r1, %r2" |
| [(set_attr "type" "X01")]) |
| |
| ;; |
| ;; Shifts |
| ;; |
| |
| ;; ashift, ashiftrt, lshiftrt, rotate. |
| (define_insn "<optab>si3" |
| [(set (match_operand:SI 0 "register_operand" "=r,r") |
| (binop_u5bit:SI (match_operand:SI 1 "reg_or_0_operand" "rO,rO") |
| (match_operand:SI 2 "reg_or_u5bit_operand" "I,rO")))] |
| "" |
| "@ |
| <insn>i\t%0, %r1, %2 |
| <insn>\t%0, %r1, %r2") |
| |
| |
| ;; |
| ;; Compares |
| ;; |
| |
| (define_expand "cstore<mode>4" |
| [(set (match_operand:SI 0 "register_operand" "") |
| (match_operator:SI 1 "ordered_comparison_operator" |
| [(match_operand:I48MODE 2 "reg_or_cint_operand" "") |
| (match_operand:I48MODE 3 "reg_or_cint_operand" "")]))] |
| "" |
| { if (!tilepro_emit_setcc (operands, <MODE>mode)) FAIL; else DONE; }) |
| |
| (define_insn "insn_seq" |
| [(set (match_operand:SI 0 "register_operand" "=r,r") |
| (eq:SI (match_operand:SI 1 "reg_or_0_operand" "%rO,rO") |
| (match_operand:SI 2 "reg_or_cint_operand" "I,rO")))] |
| "" |
| "@ |
| seqi\t%0, %r1, %2 |
| seq\t%0, %r1, %r2") |
| |
| (define_insn "insn_sne" |
| [(set (match_operand:SI 0 "register_operand" "=r") |
| (ne:SI (match_operand:SI 1 "reg_or_0_operand" "rO") |
| (match_operand:SI 2 "reg_or_cint_operand" "rO")))] |
| "" |
| "sne\t%0, %r1, %r2") |
| |
| (define_insn "insn_slt" |
| [(set (match_operand:SI 0 "register_operand" "=r,r") |
| (lt:SI (match_operand:SI 1 "reg_or_0_operand" "rO,rO") |
| (match_operand:SI 2 "reg_or_cint_operand" "I,rO")))] |
| "" |
| "@ |
| slti\t%0, %r1, %2 |
| slt\t%0, %r1, %r2") |
| |
| (define_insn "insn_slte" |
| [(set (match_operand:SI 0 "register_operand" "=r,r") |
| (le:SI (match_operand:SI 1 "reg_or_0_operand" "rO,rO") |
| (match_operand:SI 2 "reg_or_cint_operand" "L,rO")))] |
| "" |
| "@ |
| slti\t%0, %r1, %P2 |
| slte\t%0, %r1, %r2") |
| |
| (define_insn "insn_slt_u" |
| [(set (match_operand:SI 0 "register_operand" "=r,r") |
| (ltu:SI (match_operand:SI 1 "reg_or_0_operand" "rO,rO") |
| (match_operand:SI 2 "reg_or_cint_operand" "I,rO")))] |
| "" |
| "@ |
| slti_u\t%0, %r1, %2 |
| slt_u\t%0, %r1, %r2") |
| |
| (define_insn "insn_slte_u" |
| [(set (match_operand:SI 0 "register_operand" "=r,r") |
| (leu:SI (match_operand:SI 1 "reg_or_0_operand" "rO,rO") |
| (match_operand:SI 2 "reg_or_cint_operand" "Q,rO")))] |
| "" |
| "@ |
| slti_u\t%0, %r1, %P2 |
| slte_u\t%0, %r1, %r2") |
| |
| |
| ;; |
| ;; Logical ops |
| ;; |
| |
| (define_insn "andsi3" |
| [(set (match_operand:SI 0 "register_operand" "=r,r,r") |
| (and:SI (match_operand:SI 1 "reg_or_0_operand" "%rO,rO,rO") |
| (match_operand:SI 2 "and_operand" "I,M,rO")))] |
| "" |
| "@ |
| andi\t%0, %r1, %2 |
| mm\t%0, %r1, zero, %M2 |
| and\t%0, %r1, %r2" |
| [(set_attr "type" "*,X01,*")]) |
| |
| (define_insn "iorsi3" |
| [(set (match_operand:SI 0 "register_operand" "=r,r") |
| (ior:SI (match_operand:SI 1 "reg_or_0_operand" "%rO,rO") |
| (match_operand:SI 2 "reg_or_s8bit_operand" "I,rO")))] |
| "" |
| "@ |
| ori\t%0, %r1, %2 |
| or\t%0, %r1, %r2") |
| |
| (define_insn "xorsi3" |
| [(set (match_operand:SI 0 "register_operand" "=r,r") |
| (xor:SI (match_operand:SI 1 "reg_or_0_operand" "%rO,rO") |
| (match_operand:SI 2 "reg_or_s8bit_operand" "rO,I")))] |
| "" |
| "@ |
| xor\t%0, %r1, %r2 |
| xori\t%0, %r1, %2" |
| [(set_attr "type" "*,X01")]) |
| |
| ;; bswap, clz, ctz, popcount |
| (define_insn "<optab>si2" |
| [(set (match_operand:SI 0 "register_operand" "=r") |
| (unop:SI (match_operand:SI 1 "reg_or_0_operand" "rO")))] |
| "" |
| "<insn>\t%0, %r1" |
| [(set_attr "type" "Y0")]) |
| |
| (define_expand "ctzdi2" |
| [(set (match_operand:DI 0 "register_operand" "") |
| (ctz:DI (match_operand:DI 1 "register_operand" "")))] |
| "" |
| { |
| rtx lo, hi, ctz_lo, ctz_hi, ctz_hi_plus_32, result; |
| |
| split_di (&operands[1], 1, &lo, &hi); |
| lo = force_reg (SImode, lo); |
| hi = force_reg (SImode, hi); |
| |
| ctz_lo = gen_reg_rtx (SImode); |
| emit_insn (gen_ctzsi2 (ctz_lo, lo)); |
| |
| ctz_hi = gen_reg_rtx (SImode); |
| emit_insn (gen_ctzsi2 (ctz_hi, hi)); |
| |
| ctz_hi_plus_32 = gen_reg_rtx (SImode); |
| emit_insn (gen_addsi3 (ctz_hi_plus_32, ctz_hi, GEN_INT (32))); |
| |
| result = gen_reg_rtx (SImode); |
| emit_insn (gen_insn_mvz (result, ctz_lo, lo, ctz_hi_plus_32)); |
| |
| emit_move_insn (operands[0], convert_to_mode (DImode, result, 1)); |
| |
| DONE; |
| }) |
| |
| (define_expand "clzdi2" |
| [(set (match_operand:DI 0 "register_operand" "") |
| (clz:DI (match_operand:DI 1 "register_operand" "")))] |
| "" |
| { |
| rtx lo, hi, clz_lo, clz_hi, clz_lo_plus_32, result; |
| |
| split_di (&operands[1], 1, &lo, &hi); |
| lo = force_reg (SImode, lo); |
| hi = force_reg (SImode, hi); |
| |
| clz_lo = gen_reg_rtx (SImode); |
| emit_insn (gen_clzsi2 (clz_lo, lo)); |
| |
| clz_hi = gen_reg_rtx (SImode); |
| emit_insn (gen_clzsi2 (clz_hi, hi)); |
| |
| clz_lo_plus_32 = gen_reg_rtx (SImode); |
| emit_insn (gen_addsi3 (clz_lo_plus_32, clz_lo, GEN_INT (32))); |
| |
| result = gen_reg_rtx (SImode); |
| emit_insn (gen_insn_mvz (result, clz_hi, hi, clz_lo_plus_32)); |
| |
| emit_move_insn (operands[0], convert_to_mode (DImode, result, 1)); |
| |
| DONE; |
| }) |
| |
| (define_expand "ffsdi2" |
| [(set (match_operand:DI 0 "register_operand" "") |
| (ffs:DI (match_operand:DI 1 "register_operand" "")))] |
| "" |
| { |
| rtx lo, hi, ctz_lo, ctz_hi, ctz_hi_plus_32, ctz, ctz_plus_1,ctz_cond; |
| rtx result; |
| |
| split_di (&operands[1], 1, &lo, &hi); |
| lo = force_reg (SImode, lo); |
| hi = force_reg (SImode, hi); |
| |
| ctz_lo = gen_reg_rtx (SImode); |
| emit_insn (gen_ctzsi2 (ctz_lo, lo)); |
| |
| ctz_hi = gen_reg_rtx (SImode); |
| emit_insn (gen_ctzsi2 (ctz_hi, hi)); |
| |
| ctz_hi_plus_32 = gen_reg_rtx (SImode); |
| emit_insn (gen_addsi3 (ctz_hi_plus_32, ctz_hi, GEN_INT (32))); |
| |
| ctz = gen_reg_rtx (SImode); |
| emit_insn (gen_insn_mvz (ctz, ctz_lo, lo, ctz_hi_plus_32)); |
| |
| ctz_plus_1 = gen_reg_rtx (SImode); |
| emit_insn (gen_addsi3 (ctz_plus_1, ctz, GEN_INT (1))); |
| |
| ctz_cond = gen_reg_rtx (SImode); |
| emit_insn (gen_iorsi3 (ctz_cond, lo, hi)); |
| |
| result = gen_reg_rtx (SImode); |
| emit_insn (gen_insn_mvz (result, ctz_plus_1, ctz_cond, const0_rtx)); |
| |
| emit_move_insn (operands[0], convert_to_mode (DImode, result, 1)); |
| |
| DONE; |
| }) |
| |
| (define_expand "popcountdi2" |
| [(set (match_operand:DI 0 "register_operand" "") |
| (popcount:DI (match_operand:DI 1 "nonmemory_operand" "")))] |
| "" |
| { |
| rtx lo, hi, popcount_lo, popcount_hi, result; |
| |
| split_di (&operands[1], 1, &lo, &hi); |
| lo = force_reg (SImode, lo); |
| hi = force_reg (SImode, hi); |
| |
| popcount_lo = gen_reg_rtx (SImode); |
| emit_insn (gen_popcountsi2 (popcount_lo, lo)); |
| |
| popcount_hi = gen_reg_rtx (SImode); |
| emit_insn (gen_popcountsi2 (popcount_hi, hi)); |
| |
| result = gen_reg_rtx (SImode); |
| emit_insn (gen_addsi3 (result, popcount_lo, popcount_hi)); |
| |
| emit_move_insn (operands[0], convert_to_mode (DImode, result, 1)); |
| |
| DONE; |
| }) |
| |
| (define_expand "paritysi2" |
| [(set (match_operand:SI 0 "register_operand" "") |
| (parity:SI (match_operand:SI 1 "reg_or_0_operand" "")))] |
| "" |
| { |
| operands[2] = gen_reg_rtx (SImode); |
| emit_insn (gen_popcountsi2 (operands[2], operands[1])); |
| emit_insn (gen_andsi3 (operands[0], operands[2], const1_rtx)); |
| DONE; |
| }) |
| |
| (define_expand "paritydi2" |
| [(set (match_operand:DI 0 "register_operand" "") |
| (parity:DI (match_operand:DI 1 "nonmemory_operand" "")))] |
| "" |
| { |
| rtx lo, hi, xor_lohi, result; |
| |
| split_di (&operands[1], 1, &lo, &hi); |
| lo = force_reg (SImode, lo); |
| hi = force_reg (SImode, hi); |
| |
| xor_lohi = gen_reg_rtx (SImode); |
| emit_insn (gen_xorsi3 (xor_lohi, lo, hi)); |
| |
| result = gen_reg_rtx (SImode); |
| emit_insn (gen_paritysi2 (result, xor_lohi)); |
| |
| emit_move_insn (operands[0], convert_to_mode (DImode, result, 1)); |
| |
| DONE; |
| }) |
| |
| (define_insn "one_cmplsi2" |
| [(set (match_operand:SI 0 "register_operand" "=r") |
| (not:SI (match_operand:SI 1 "reg_or_0_operand" "rO")))] |
| "" |
| "nor\t%0, %r1, zero") |
| |
| |
| ;; |
| ;; Conditional moves. |
| ;; |
| |
| (define_expand "movsicc" |
| [(set (match_operand:SI 0 "register_operand" "") |
| (if_then_else:SI (match_operand 1 "comparison_operator" "") |
| (match_operand:SI 2 "reg_or_0_operand" "") |
| (match_operand:SI 3 "reg_or_0_operand" "")))] |
| "" |
| { operands[1] = tilepro_emit_conditional_move (operands[1]); }) |
| |
| (define_insn "movcc_insn" |
| [(set (match_operand:SI 0 "register_operand" "=r,r,r,r") |
| (if_then_else:SI |
| (match_operator 4 "eqne_operator" |
| [(match_operand:SI 1 "reg_or_0_operand" "rO,rO,rO,rO") |
| (const_int 0)]) |
| (match_operand:SI 2 "reg_or_0_operand" "rO,O,rO,0") |
| (match_operand:SI 3 "reg_or_0_operand" "O,rO,0,rO")))] |
| "" |
| "@ |
| m%c4\t%0, %r1, %r2 |
| m%C4\t%0, %r1, %r3 |
| mv%c4\t%0, %r1, %r2 |
| mv%C4\t%0, %r1, %r3" |
| [(set_attr "type" "*,*,Y0,Y0")]) |
| |
| (define_expand "insn_mz" |
| [(set (match_operand:SI 0 "register_operand" "") |
| (if_then_else:SI |
| (eq (match_operand:SI 1 "reg_or_0_operand" "") |
| (const_int 0)) |
| (match_operand:SI 2 "reg_or_0_operand" "") |
| (const_int 0)))]) |
| |
| (define_expand "insn_mnz" |
| [(set (match_operand:SI 0 "register_operand" "") |
| (if_then_else:SI |
| (ne (match_operand:SI 1 "reg_or_0_operand" "") |
| (const_int 0)) |
| (match_operand:SI 2 "reg_or_0_operand" "") |
| (const_int 0)))]) |
| |
| (define_expand "insn_mvz" |
| [(set (match_operand:SI 0 "register_operand" "") |
| (if_then_else:SI |
| (eq (match_operand:SI 2 "reg_or_0_operand" "") |
| (const_int 0)) |
| (match_operand:SI 3 "reg_or_0_operand" "") |
| (match_operand:SI 1 "reg_or_0_operand" "")))]) |
| |
| (define_expand "insn_mvnz" |
| [(set (match_operand:SI 0 "register_operand" "") |
| (if_then_else:SI |
| (ne (match_operand:SI 2 "reg_or_0_operand" "") |
| (const_int 0)) |
| (match_operand:SI 3 "reg_or_0_operand" "") |
| (match_operand:SI 1 "reg_or_0_operand" "")))]) |
| |
| |
| ;; |
| ;; Conversions |
| ;; |
| |
| (define_insn "zero_extendqisi2" |
| [(set (match_operand:SI 0 "register_operand" "=r,r,r") |
| (zero_extend:SI (match_operand:QI 1 "move_operand" "rO,U,m")))] |
| "" |
| "@ |
| mm\t%0, %r1, zero, 0, 7 |
| lb_u\t%0, %1 |
| lbadd_u\t%0, %I1, %i1" |
| [(set_attr "type" "X01,Y2_2cycle,X1_2cycle")]) |
| |
| (define_insn "zero_extendhisi2" |
| [(set (match_operand:SI 0 "register_operand" "=r,r,r") |
| (zero_extend:SI (match_operand:HI 1 "move_operand" "rO,U,m")))] |
| "" |
| "@ |
| mm\t%0, %r1, zero, 0, 15 |
| lh_u\t%0, %1 |
| lhadd_u\t%0, %I1, %i1" |
| [(set_attr "type" "X01,Y2_2cycle,X1_2cycle")]) |
| |
| (define_expand "extendhisi2" |
| [(set (match_operand:SI 0 "register_operand" "") |
| (sign_extend:SI (match_operand:HI 1 "move_operand" "")))] |
| "" |
| { |
| if (!memory_operand (operands[1], HImode)) |
| { |
| operands[1] = gen_lowpart (SImode, operands[1]); |
| operands[2] = can_create_pseudo_p () ? gen_reg_rtx (SImode) : operands[0]; |
| |
| emit_move_insn (operands[2], gen_rtx_ASHIFT (SImode, operands[1], |
| GEN_INT (16))); |
| emit_move_insn (operands[0], gen_rtx_ASHIFTRT (SImode, operands[2], |
| GEN_INT (16))); |
| DONE; |
| } |
| }) |
| |
| (define_insn "*lh" |
| [(set (match_operand:SI 0 "register_operand" "=r,r") |
| (sign_extend:SI (match_operand:HI 1 "memory_operand" "U,m")))] |
| "" |
| "@ |
| lh\t%0, %1 |
| lhadd\t%0, %I1, %i1" |
| [(set_attr "type" "Y2_2cycle,X1_2cycle")]) |
| |
| (define_expand "extendqisi2" |
| [(set (match_operand:SI 0 "register_operand" "") |
| (sign_extend:SI (match_operand:QI 1 "move_operand" "")))] |
| "" |
| { |
| if (!memory_operand (operands[1], QImode)) |
| { |
| operands[1] = gen_lowpart (SImode, operands[1]); |
| operands[2] = can_create_pseudo_p () ? gen_reg_rtx (SImode) : operands[0]; |
| |
| emit_move_insn (operands[2], gen_rtx_ASHIFT (SImode, operands[1], |
| GEN_INT (24))); |
| emit_move_insn (operands[0], gen_rtx_ASHIFTRT (SImode, operands[2], |
| GEN_INT (24))); |
| DONE; |
| } |
| }) |
| |
| (define_insn "*lb" |
| [(set (match_operand:SI 0 "register_operand" "=r,r") |
| (sign_extend:SI (match_operand:QI 1 "memory_operand" "U,m")))] |
| "" |
| "@ |
| lb\t%0, %1 |
| lbadd\t%0, %I1, %i1" |
| [(set_attr "type" "Y2_2cycle,X1_2cycle")]) |
| |
| ;; |
| ;; insv patterns |
| ;; |
| (define_expand "insv" |
| [(set (zero_extract:SI (match_operand:SI 0 "register_operand" "") |
| (match_operand:SI 1 "u5bit_cint_operand" "") |
| (match_operand:SI 2 "u5bit_cint_operand" "")) |
| (match_operand:SI 3 "reg_or_cint_operand" ""))] |
| "" |
| { |
| tilepro_expand_insv (operands); |
| DONE; |
| }) |
| |
| (define_insn "*insv_tblidxb0" |
| [(set (zero_extract:SI |
| (match_operand:SI 0 "register_operand" "+r") |
| (const_int 8) |
| (const_int 2)) |
| (match_operand:SI 1 "register_operand" "rO"))] |
| "" |
| "tblidxb0\t%0, %r1" |
| [(set_attr "type" "Y0")]) |
| |
| (define_insn "*insv_tblidxb1" |
| [(set (zero_extract:SI |
| (match_operand:SI 0 "register_operand" "+r") |
| (const_int 8) |
| (const_int 2)) |
| (zero_extract:SI |
| (const_int 8) |
| (const_int 8) |
| (match_operand:SI 1 "register_operand" "rO")))] |
| "" |
| "tblidxb1\t%0, %r1" |
| [(set_attr "type" "Y0")]) |
| |
| (define_insn "*insv_tblidxb2" |
| [(set (zero_extract:SI |
| (match_operand:SI 0 "register_operand" "+r") |
| (const_int 8) |
| (const_int 2)) |
| (zero_extract:SI |
| (const_int 8) |
| (const_int 16) |
| (match_operand:SI 1 "register_operand" "rO")))] |
| "" |
| "tblidxb2\t%0, %r1" |
| [(set_attr "type" "Y0")]) |
| |
| (define_insn "*insv_tblidxb3" |
| [(set (zero_extract:SI |
| (match_operand:SI 0 "register_operand" "+r") |
| (const_int 8) |
| (const_int 2)) |
| (zero_extract:SI |
| (const_int 8) |
| (const_int 24) |
| (match_operand:SI 1 "register_operand" "rO")))] |
| "" |
| "tblidxb3\t%0, %r1" |
| [(set_attr "type" "Y0")]) |
| |
| (define_insn "*insv_mm1" |
| [(set (zero_extract:SI |
| (match_operand:SI 0 "register_operand" "+r") |
| (match_operand:SI 1 "u5bit_cint_operand" "n") |
| (const_int 0)) |
| (match_operand:SI 2 "register_operand" "rO"))] |
| "" |
| "mm\t%0, %r2, %0, 0, %1-1" |
| [(set_attr "type" "X01")]) |
| |
| (define_insn "*insv_mm2" |
| [(set (zero_extract:SI |
| (match_operand:SI 0 "register_operand" "+r") |
| (match_operand:SI 1 "u5bit_cint_operand" "n") |
| (match_operand:SI 2 "u5bit_cint_operand" "n")) |
| (zero_extract:SI |
| (match_operand:SI 3 "register_operand" "rO") |
| (match_dup 1) |
| (match_dup 2)))] |
| "" |
| "mm\t%0, %r3, %0, %2, %2+%1-1" |
| [(set_attr "type" "X01")]) |
| |
| |
| ;; |
| ;; Multiplies |
| ;; |
| |
| (define_expand "mulsi3" |
| [(set (match_operand:SI 0 "register_operand" "=r") |
| (mult:SI (zero_extend:SI |
| (subreg:HI (match_operand:SI 1 "nonmemory_operand" "") 0)) |
| (zero_extend:SI |
| (subreg:HI (match_operand:SI 2 "nonmemory_operand" "") 0)))) |
| (set (match_dup 0) |
| (unspec:SI [(match_dup 0) (match_dup 1) (match_dup 2)] |
| UNSPEC_INSN_MULHLSA_UU)) |
| (set (match_dup 0) |
| (unspec:SI [(match_dup 0) (match_dup 2) (match_dup 1)] |
| UNSPEC_INSN_MULHLSA_UU))] |
| "" |
| { |
| operands[1] = force_reg (SImode, operands[1]); |
| operands[1] = make_safe_from (operands[1], operands[0]); |
| |
| if (tilepro_expand_mulsi (operands[0], operands[1], operands[2])) |
| DONE; |
| else |
| { |
| operands[2] = force_reg (SImode, operands[2]); |
| operands[2] = make_safe_from (operands[2], operands[0]); |
| } |
| }) |
| |
| (define_insn "mulhisi3" |
| [(set (match_operand:SI 0 "register_operand" "=r") |
| (mult:SI (sign_extend:SI |
| (match_operand:HI 1 "reg_or_0_operand" "rO")) |
| (sign_extend:SI |
| (match_operand:HI 2 "reg_or_0_operand" "rO"))))] |
| "" |
| "mulll_ss\t%0, %r1, %r2" |
| [(set_attr "type" "Y0_2cycle")]) |
| |
| (define_insn "umulhisi3" |
| [(set (match_operand:SI 0 "register_operand" "=r") |
| (mult:SI (zero_extend:SI |
| (match_operand:HI 1 "reg_or_0_operand" "rO")) |
| (zero_extend:SI |
| (match_operand:HI 2 "reg_or_0_operand" "rO"))))] |
| "" |
| "mulll_uu\t%0, %r1, %r2" |
| [(set_attr "type" "Y0_2cycle")]) |
| |
| (define_insn "usmulhisi3" |
| [(set (match_operand:SI 0 "register_operand" "=r") |
| (mult:SI (zero_extend:SI |
| (match_operand:HI 1 "reg_or_0_operand" "rO")) |
| (sign_extend:SI |
| (match_operand:HI 2 "reg_or_0_operand" "rO"))))] |
| "" |
| "mulll_su\t%0, %r2, %r1" |
| [(set_attr "type" "X0_2cycle")]) |
| |
| (define_insn "maddhisi4" |
| [(set (match_operand:SI 0 "register_operand" "=r") |
| (plus:SI |
| (mult:SI (sign_extend:SI |
| (match_operand:HI 1 "reg_or_0_operand" "rO")) |
| (sign_extend:SI |
| (match_operand:HI 2 "reg_or_0_operand" "rO"))) |
| (match_operand:SI 3 "register_operand" "0")))] |
| "" |
| "mullla_ss\t%0, %r1, %r2" |
| [(set_attr "type" "Y0_2cycle")]) |
| |
| (define_insn "umaddhisi4" |
| [(set (match_operand:SI 0 "register_operand" "=r") |
| (plus:SI |
| (mult:SI (zero_extend:SI |
| (match_operand:HI 1 "reg_or_0_operand" "rO")) |
| (zero_extend:SI |
| (match_operand:HI 2 "reg_or_0_operand" "rO"))) |
| (match_operand:SI 3 "register_operand" "0")))] |
| "" |
| "mullla_uu\t%0, %r1, %r2" |
| [(set_attr "type" "Y0_2cycle")]) |
| |
| |
| (define_insn "mulqihi3" |
| [(set (match_operand:HI 0 "register_operand" "=r") |
| (mult:HI (sign_extend:HI |
| (match_operand:QI 1 "reg_or_0_operand" "rO")) |
| (sign_extend:HI |
| (match_operand:QI 2 "reg_or_0_operand" "rO"))))] |
| "" |
| "mulll_ss\t%0, %r1, %r2" |
| [(set_attr "type" "Y0_2cycle")]) |
| |
| (define_insn "umulqihi3" |
| [(set (match_operand:HI 0 "register_operand" "=r") |
| (mult:HI (zero_extend:HI |
| (match_operand:QI 1 "reg_or_0_operand" "rO")) |
| (zero_extend:HI |
| (match_operand:QI 2 "reg_or_0_operand" "rO"))))] |
| "" |
| "mulll_uu\t%0, %r1, %r2" |
| [(set_attr "type" "Y0_2cycle")]) |
| |
| (define_expand "smulsi3_highpart" |
| [(set (match_operand:SI 0 "register_operand" "") |
| (truncate:SI |
| (ashiftrt:DI |
| (mult:DI (sign_extend:DI (match_operand:SI 1 "reg_or_0_operand" "")) |
| (sign_extend:DI (match_operand:SI 2 "reg_or_0_operand" ""))) |
| (const_int 32))))] |
| "" |
| { |
| tilepro_expand_smulsi3_highpart (operands[0], operands[1], operands[2]); |
| DONE; |
| }) |
| |
| (define_expand "umulsi3_highpart" |
| [(set (match_operand:SI 0 "register_operand" "") |
| (truncate:SI |
| (lshiftrt:DI |
| (mult:DI (zero_extend:DI (match_operand:SI 1 "reg_or_0_operand" "")) |
| (zero_extend:DI (match_operand:SI 2 "reg_or_0_operand" ""))) |
| (const_int 32))))] |
| "" |
| { |
| tilepro_expand_umulsi3_highpart (operands[0], operands[1], operands[2]); |
| DONE; |
| }) |
| |
| |
| ;; |
| ;; Loops |
| ;; |
| |
| ;; Define the subtract-one-and-jump insns so loop.c knows what to |
| ;; generate. |
| (define_expand "doloop_end" |
| [(use (match_operand 0 "" "")) ;; loop pseudo |
| (use (match_operand 1 "" ""))] ;; label |
| "" |
| { |
| if (optimize > 0) |
| { |
| rtx s0; |
| rtx bcomp; |
| rtx loc_ref; |
| |
| /* only deal with loop counters in SImode */ |
| if (GET_MODE (operands[0]) != SImode) |
| FAIL; |
| |
| s0 = operands [0]; |
| |
| emit_move_insn (s0, gen_rtx_PLUS (SImode, s0, GEN_INT (-1))); |
| bcomp = gen_rtx_NE(SImode, s0, const0_rtx); |
| loc_ref = gen_rtx_LABEL_REF (VOIDmode, operands [1]); |
| emit_jump_insn (gen_rtx_SET (VOIDmode, pc_rtx, |
| gen_rtx_IF_THEN_ELSE (VOIDmode, bcomp, |
| loc_ref, pc_rtx))); |
| DONE; |
| } |
| else |
| FAIL; |
| |
| }) |
| |
| ;; |
| ;; Prologue/epilogue |
| ;; |
| (define_expand "prologue" |
| [(const_int 0)] |
| "" |
| { |
| tilepro_expand_prologue (); |
| DONE; |
| }) |
| |
| (define_expand "epilogue" |
| [(const_int 0)] |
| "" |
| { |
| tilepro_expand_epilogue (false); |
| DONE; |
| }) |
| |
| (define_expand "sibcall_epilogue" |
| [(const_int 0)] |
| "" |
| { |
| tilepro_expand_epilogue (true); |
| DONE; |
| }) |
| |
| ;; |
| ;; Stack manipulations |
| ;; |
| |
| ;; An insn to allocate new stack space for dynamic use (e.g., alloca). |
| (define_expand "allocate_stack" |
| [(set (match_operand 0 "register_operand" "") |
| (minus (reg 54) (match_operand 1 "nonmemory_operand" ""))) |
| (set (reg 54) |
| (minus (reg 54) (match_dup 1)))] |
| "" |
| "tilepro_allocate_stack (operands[0], operands[1]); DONE;") |
| |
| ;; |
| ;; Branches |
| ;; |
| (define_expand "call" |
| [(parallel [(call (match_operand:SI 0 "call_operand" "") |
| (match_operand 1 "" "")) |
| (use (reg:SI 54)) |
| (clobber (reg:SI 55))])] |
| "" |
| "") |
| |
| (define_insn "*call_insn" |
| [(call (mem:SI (match_operand:SI 0 "call_address_operand" "rO,i")) |
| (match_operand 1 "" "")) |
| (use (reg:SI 54)) |
| (clobber (reg:SI 55))] |
| "" |
| "@ |
| jalr\t%r0 |
| jal\t%p0" |
| [(set_attr "type" "X1,X1")]) |
| |
| (define_expand "call_value" |
| [(parallel [(set (match_operand 0 "register_operand" "") |
| (call (match_operand:SI 1 "call_operand" "") |
| (match_operand 2 "" ""))) |
| (use (reg:SI 54)) |
| (clobber (reg:SI 55))])] |
| "") |
| |
| (define_insn "*call_value_insn" |
| [(set (match_operand 0 "register_operand" "=r,r") |
| (call (mem:SI (match_operand:SI 1 "call_address_operand" "rO,i")) |
| (match_operand 2 "" ""))) |
| (use (reg:SI 54)) |
| (clobber (reg:SI 55))] |
| "" |
| "@ |
| jalr\t%r1 |
| jal\t%p1" |
| [(set_attr "type" "X1,X1")]) |
| |
| (define_expand "sibcall" |
| [(parallel [(call (match_operand:SI 0 "call_operand" "") |
| (match_operand 1 "" "")) |
| (use (reg:SI 54))])] |
| "" |
| "") |
| |
| (define_insn "*sibcall_insn" |
| [(call (mem:SI (match_operand:SI 0 "call_address_operand" "rO,i")) |
| (match_operand 1 "" "")) |
| (use (reg:SI 54))] |
| "SIBLING_CALL_P(insn)" |
| "@ |
| jr\t%r0 |
| j\t%p0" |
| [(set_attr "type" "X1,X1")]) |
| |
| (define_expand "sibcall_value" |
| [(parallel [(set (match_operand 0 "" "") |
| (call (match_operand:SI 1 "call_operand" "") |
| (match_operand:SI 2 "" ""))) |
| (use (reg:SI 54))])] |
| "" |
| "") |
| |
| (define_insn "*sibcall_value" |
| [(set (match_operand 0 "" "") |
| (call (mem:SI (match_operand:SI 1 "call_address_operand" "rO,i")) |
| (match_operand:SI 2 "" ""))) |
| (use (reg:SI 54))] |
| "SIBLING_CALL_P(insn)" |
| "@ |
| jr\t%r1 |
| j\t%p1" |
| [(set_attr "type" "X1,X1")]) |
| |
| (define_insn "jump" |
| [(set (pc) (label_ref (match_operand 0 "" "")))] |
| "" |
| "j\t%l0" |
| [(set_attr "type" "X1")]) |
| |
| (define_insn "indirect_jump" |
| [(set (pc) (match_operand:SI 0 "register_operand" "rO"))] |
| "" |
| "jr\t%r0" |
| [(set_attr "type" "X1")]) |
| |
| (define_expand "return" |
| [(parallel |
| [(return) |
| (use (reg:SI 55))])] |
| "tilepro_can_use_return_insn_p ()" |
| "") |
| |
| (define_insn "_return" |
| [(return) |
| (use (reg:SI 55))] |
| "reload_completed" |
| "jrp\tlr" |
| [(set_attr "type" "X1")]) |
| |
| (define_expand "tablejump" |
| [(set (pc) (match_operand:SI 0 "register_operand" "")) |
| (use (label_ref (match_operand 1 "" "")))] |
| "" |
| { |
| tilepro_expand_tablejump (operands[0], operands[1]); |
| DONE; |
| }) |
| |
| (define_insn "tablejump_aux" |
| [(set (pc) (match_operand:SI 0 "register_operand" "r")) |
| (use (label_ref (match_operand 1 "" "")))] |
| "" |
| "jr\t%0" |
| [(set_attr "type" "X1")]) |
| |
| ;; Call subroutine returning any type. |
| (define_expand "untyped_call" |
| [(parallel [(call (match_operand 0 "" "") |
| (const_int 0)) |
| (match_operand 1 "" "") |
| (match_operand 2 "" "")])] |
| "" |
| { |
| int i; |
| |
| emit_call_insn (GEN_CALL (operands[0], const0_rtx, NULL, const0_rtx)); |
| |
| for (i = 0; i < XVECLEN (operands[2], 0); i++) |
| { |
| rtx set = XVECEXP (operands[2], 0, i); |
| emit_move_insn (SET_DEST (set), SET_SRC (set)); |
| } |
| |
| /* The optimizer does not know that the call sets the function value |
| registers we stored in the result block. We avoid problems by |
| claiming that all hard registers are used and clobbered at this |
| point. */ |
| emit_insn (gen_blockage ()); |
| |
| DONE; |
| }) |
| |
| ;; UNSPEC_VOLATILE is considered to use and clobber all hard registers |
| ;; and all of memory. This blocks insns from being moved across this |
| ;; point. |
| (define_insn "blockage" |
| [(unspec_volatile [(const_int 0)] UNSPEC_BLOCKAGE)] |
| "" |
| "pseudo" |
| [(set_attr "type" "nothing") |
| (set_attr "length" "0")]) |
| |
| ;; Internal expanders to prevent memory ops from moving around frame |
| ;; allocation/deallocation. |
| ;; |
| ;; TODO: really this clobber should just clobber the frame memory. Is |
| ;; this possibly by clobbering memory @ the sp reg (as alpha does?) |
| ;; or by explicitly setting the alias set to the frame? |
| (define_insn "sp_adjust" |
| [(set (match_operand:SI 0 "register_operand" "=r,r,r") |
| (plus:SI |
| (match_operand:SI 1 "register_operand" "%r,r,r") |
| (match_operand:SI 2 "add_operand" "r,I,J"))) |
| (clobber (mem:BLK (scratch)))] |
| "" |
| "@ |
| add\t%0, %1, %2 |
| addi\t%0, %1, %2 |
| addli\t%0, %1, %2" |
| [(set_attr "type" "*,*,X01")]) |
| |
| ;; Used for move sp, r52, to pop a stack frame. We need to make sure |
| ;; that stack frame memory operations have been issued before we do |
| ;; this. TODO: see above TODO. |
| (define_insn "sp_restore" |
| [(set (match_operand:SI 0 "register_operand" "=r") |
| (match_operand:SI 1 "register_operand" "r")) |
| (clobber (mem:BLK (scratch)))] |
| "" |
| "move\t%0, %1") |
| |
| (define_insn "nop" |
| [(const_int 0)] |
| "" |
| "nop" |
| [(set_attr "type" "Y01")]) |
| |
| |
| ;; |
| ;; Conditional branches |
| ;; |
| |
| (define_expand "cbranchsi4" |
| [(set (pc) |
| (if_then_else (match_operator 0 "ordered_comparison_operator" |
| [(match_operand:SI 1 "reg_or_cint_operand") |
| (match_operand:SI 2 "reg_or_cint_operand")]) |
| (label_ref (match_operand 3 "")) |
| (pc)))] |
| "" |
| { tilepro_emit_conditional_branch (operands, SImode); DONE; }) |
| |
| |
| (define_expand "cbranchdi4" |
| [(set (pc) |
| (if_then_else (match_operator 0 "ordered_comparison_operator" |
| [(match_operand:DI 1 "reg_or_cint_operand") |
| (match_operand:DI 2 "reg_or_cint_operand")]) |
| (label_ref (match_operand 3 "")) |
| (pc)))] |
| "" |
| { tilepro_emit_conditional_branch (operands, DImode); DONE; }) |
| |
| |
| (define_insn "*bcc_normal" |
| [(set (pc) |
| (if_then_else |
| (match_operator 1 "signed_comparison_operator" |
| [(match_operand:SI 2 "reg_or_0_operand" "rO") |
| (const_int 0)]) |
| (label_ref (match_operand 0 "" "")) |
| (pc)))] |
| "" |
| { return tilepro_output_cbranch (insn, operands, false); } |
| [(set_attr "type" "X1_branch")]) |
| |
| (define_insn "*bcc_reverse" |
| [(set (pc) |
| (if_then_else |
| (match_operator 1 "signed_comparison_operator" |
| [(match_operand:SI 2 "reg_or_0_operand" "rO") |
| (const_int 0)]) |
| (pc) |
| (label_ref (match_operand 0 "" ""))))] |
| "" |
| { return tilepro_output_cbranch (insn, operands, true); } |
| [(set_attr "type" "X1_branch")]) |
| |
| ;; FIXME: the straight forward versions which do not include the |
| ;; subreg:QI does not match for some unknown reason. |
| (define_insn "*bbs_normal" |
| [(set (pc) |
| (if_then_else |
| (ne (zero_extract:SI (subreg:QI |
| (match_operand:SI 1 "reg_or_0_operand" "rO") 0) |
| (const_int 1) |
| (const_int 0)) |
| (const_int 0)) |
| (label_ref (match_operand 0 "" "")) |
| (pc)))] |
| "" |
| { return tilepro_output_cbranch_with_opcode (insn, operands, "bbs", "bbns", |
| 1, 0); } |
| [(set_attr "type" "X1_branch")]) |
| |
| (define_insn "*bbc_normal" |
| [(set (pc) |
| (if_then_else |
| (eq (zero_extract:SI (subreg:QI |
| (match_operand:SI 1 "reg_or_0_operand" "rO") 0) |
| (const_int 1) |
| (const_int 0)) |
| (const_int 0)) |
| (label_ref (match_operand 0 "" "")) |
| (pc)))] |
| "" |
| { return tilepro_output_cbranch_with_opcode (insn, operands, "bbns", "bbs", |
| 1, 0); } |
| [(set_attr "type" "X1_branch")]) |
| |
| ;; Note that __insn_mf() expands to this. |
| (define_expand "memory_barrier" |
| [(set (match_dup 0) |
| (unspec_volatile:BLK [(match_dup 0)] UNSPEC_MF))] |
| "" |
| { |
| operands[0] = gen_rtx_MEM (BLKmode, gen_rtx_SCRATCH (Pmode)); |
| MEM_VOLATILE_P (operands[0]) = 1; |
| }) |
| |
| (define_insn "*memory_barrier" |
| [(set (match_operand:BLK 0 "" "") |
| (unspec_volatile:BLK [(match_dup 0)] UNSPEC_MF))] |
| "" |
| "mf" |
| [(set_attr "type" "X1")]) |
| |
| (define_insn "prefetch" |
| [(prefetch (match_operand:SI 0 "address_operand" "rO") |
| (match_operand:SI 1 "const_int_operand" "") |
| (match_operand:SI 2 "const_int_operand" ""))] |
| "" |
| "prefetch\t%r0" |
| [(set_attr "type" "Y2")]) |
| |
| |
| ;; |
| ;; Network intrinsics |
| ;; |
| |
| ;; Note the "pseudo" text is handled specially by the |
| ;; asm_output_opcode routine. If the output is an empty string, the |
| ;; instruction would bypass the asm_output_opcode routine, bypassing |
| ;; the bundle handling code. |
| (define_insn "tilepro_network_barrier" |
| [(unspec_volatile:SI [(const_int 0)] UNSPEC_NETWORK_BARRIER)] |
| "" |
| "pseudo" |
| [(set_attr "type" "nothing") |
| (set_attr "length" "0")]) |
| |
| (define_insn "*netreg_receive" |
| [(set (match_operand:SI 0 "nonimmediate_operand" "=r,U,m") |
| (unspec_volatile:SI [(match_operand:SI 1 "netreg_operand" "i,i,i") |
| (reg:SI TILEPRO_NETORDER_REG)] |
| UNSPEC_NETWORK_RECEIVE)) |
| (clobber (reg:SI TILEPRO_NETORDER_REG))] |
| "" |
| "@ |
| move\t%0, %N1 |
| sw\t%0, %N1 |
| swadd\t%I0, %N1, %i0" |
| [(set_attr "type" "*,Y2,X1")]) |
| |
| (define_insn "*netreg_send" |
| [(unspec_volatile:SI |
| [(match_operand:SI 0 "netreg_operand" "i,i,i,i,i,i") |
| (match_operand:SI 1 "reg_or_cint_operand" "rO,I,J,K,N,P") |
| (reg:SI TILEPRO_NETORDER_REG)] |
| UNSPEC_NETWORK_SEND) |
| (clobber (reg:SI TILEPRO_NETORDER_REG))] |
| "" |
| "@ |
| move\t%N0, %r1 |
| movei\t%N0, %1 |
| moveli\t%N0, %1 |
| auli\t%N0, zero, %h1 |
| addib\t%N0, zero, %j1 |
| addih\t%N0, zero, %h1" |
| [(set_attr "type" "*,*,X01,X01,X01,X01")]) |
| |
| (define_insn "*netreg_copy" |
| [(unspec_volatile:SI |
| [(match_operand:SI 0 "netreg_operand" "i") |
| (unspec_volatile:SI [(match_operand:SI 1 "netreg_operand" "i") |
| (reg:SI TILEPRO_NETORDER_REG)] |
| UNSPEC_NETWORK_RECEIVE) |
| (reg:SI TILEPRO_NETORDER_REG)] |
| UNSPEC_NETWORK_SEND) |
| (clobber (reg:SI TILEPRO_NETORDER_REG)) |
| (clobber (reg:SI TILEPRO_NETORDER_REG))] |
| "" |
| "move %N0, %N1") |
| |
| (define_expand "tilepro_idn0_receive" |
| [(parallel |
| [(set (match_operand:SI 0 "register_operand" "") |
| (unspec_volatile:SI [(const_int TILEPRO_NETREG_IDN0) |
| (reg:SI TILEPRO_NETORDER_REG)] |
| UNSPEC_NETWORK_RECEIVE)) |
| (clobber (reg:SI TILEPRO_NETORDER_REG))])] |
| "") |
| |
| (define_expand "tilepro_idn1_receive" |
| [(parallel |
| [(set (match_operand:SI 0 "register_operand" "") |
| (unspec_volatile:SI [(const_int TILEPRO_NETREG_IDN1) |
| (reg:SI TILEPRO_NETORDER_REG)] |
| UNSPEC_NETWORK_RECEIVE)) |
| (clobber (reg:SI TILEPRO_NETORDER_REG))])] |
| "") |
| |
| (define_expand "tilepro_idn_send" |
| [(parallel |
| [(unspec_volatile:SI [(const_int TILEPRO_NETREG_IDN0) |
| (match_operand:SI 0 "reg_or_cint_operand" "") |
| (reg:SI TILEPRO_NETORDER_REG)] |
| UNSPEC_NETWORK_SEND) |
| (clobber (reg:SI TILEPRO_NETORDER_REG))])] |
| "") |
| |
| (define_expand "tilepro_sn_receive" |
| [(parallel |
| [(set (match_operand:SI 0 "register_operand" "") |
| (unspec_volatile:SI [(const_int TILEPRO_NETREG_SN) |
| (reg:SI TILEPRO_NETORDER_REG)] |
| UNSPEC_NETWORK_RECEIVE)) |
| (clobber (reg:SI TILEPRO_NETORDER_REG))])] |
| "") |
| |
| (define_expand "tilepro_sn_send" |
| [(parallel |
| [(unspec_volatile:SI [(const_int TILEPRO_NETREG_SN) |
| (match_operand:SI 0 "reg_or_cint_operand" "") |
| (reg:SI TILEPRO_NETORDER_REG)] |
| UNSPEC_NETWORK_SEND) |
| (clobber (reg:SI TILEPRO_NETORDER_REG))])] |
| "") |
| |
| (define_expand "tilepro_udn0_receive" |
| [(parallel |
| [(set (match_operand:SI 0 "register_operand" "") |
| (unspec_volatile:SI [(const_int TILEPRO_NETREG_UDN0) |
| (reg:SI TILEPRO_NETORDER_REG)] |
| UNSPEC_NETWORK_RECEIVE)) |
| (clobber (reg:SI TILEPRO_NETORDER_REG))])] |
| "") |
| |
| (define_expand "tilepro_udn1_receive" |
| [(parallel |
| [(set (match_operand:SI 0 "register_operand" "") |
| (unspec_volatile:SI [(const_int TILEPRO_NETREG_UDN1) |
| (reg:SI TILEPRO_NETORDER_REG)] |
| UNSPEC_NETWORK_RECEIVE)) |
| (clobber (reg:SI TILEPRO_NETORDER_REG))])] |
| "") |
| |
| (define_expand "tilepro_udn2_receive" |
| [(parallel |
| [(set (match_operand:SI 0 "register_operand" "") |
| (unspec_volatile:SI [(const_int TILEPRO_NETREG_UDN2) |
| (reg:SI TILEPRO_NETORDER_REG)] |
| UNSPEC_NETWORK_RECEIVE)) |
| (clobber (reg:SI TILEPRO_NETORDER_REG))])] |
| "") |
| |
| (define_expand "tilepro_udn3_receive" |
| [(parallel |
| [(set (match_operand:SI 0 "register_operand" "") |
| (unspec_volatile:SI [(const_int TILEPRO_NETREG_UDN3) |
| (reg:SI TILEPRO_NETORDER_REG)] |
| UNSPEC_NETWORK_RECEIVE)) |
| (clobber (reg:SI TILEPRO_NETORDER_REG))])] |
| "") |
| |
| (define_expand "tilepro_udn_send" |
| [(parallel |
| [(unspec_volatile:SI [(const_int TILEPRO_NETREG_UDN0) |
| (match_operand:SI 0 "reg_or_cint_operand" "") |
| (reg:SI TILEPRO_NETORDER_REG)] |
| UNSPEC_NETWORK_SEND) |
| (clobber (reg:SI TILEPRO_NETORDER_REG))])] |
| "") |
| |
| (define_insn "*netreg_add_to_network" |
| [(unspec_volatile:SI |
| [(match_operand:SI 0 "netreg_operand" "i,i,i,i") |
| (plus:SI (match_operand:SI 1 "reg_or_0_operand" "%rO,rO,rO,rO") |
| (match_operand:SI 2 "add_operand" "r,I,J,K")) |
| (reg:SI TILEPRO_NETORDER_REG)] |
| UNSPEC_NETWORK_SEND) |
| (clobber (reg:SI TILEPRO_NETORDER_REG))] |
| "" |
| "@ |
| add\t%N0, %r1, %2 |
| addi\t%N0, %r1, %2 |
| addli\t%N0, %r1, %2 |
| auli\t%N0, %r1, %h2" |
| [(set_attr "type" "*,*,X01,X01")]) |
| |
| (define_insn "*netreg_add_from_network" |
| [(set (match_operand:SI 0 "register_operand" "=r,r,r,r") |
| (plus:SI |
| (unspec_volatile:SI [(match_operand:SI 1 "netreg_operand" "i,i,i,i") |
| (reg:SI TILEPRO_NETORDER_REG)] |
| UNSPEC_NETWORK_RECEIVE) |
| (match_operand:SI 2 "add_operand" "rO,I,J,K"))) |
| (clobber (reg:SI TILEPRO_NETORDER_REG))] |
| "" |
| "@ |
| add\t%0, %N1, %r2 |
| addi\t%0, %N1, %2 |
| addli\t%0, %N1, %2 |
| auli\t%0, %N1, %h2" |
| [(set_attr "type" "*,*,X01,X01")]) |
| |
| (define_insn "*netreg_add_from_to_network" |
| [(unspec_volatile:SI |
| [(match_operand:SI 0 "netreg_operand" "i,i,i,i") |
| (plus:SI |
| (unspec_volatile:SI [(match_operand:SI 1 "netreg_operand" "i,i,i,i") |
| (reg:SI TILEPRO_NETORDER_REG)] |
| UNSPEC_NETWORK_RECEIVE) |
| (match_operand:SI 2 "add_operand" "rO,I,J,K")) |
| (reg:SI TILEPRO_NETORDER_REG)] |
| UNSPEC_NETWORK_SEND) |
| (clobber (reg:SI TILEPRO_NETORDER_REG)) |
| (clobber (reg:SI TILEPRO_NETORDER_REG))] |
| "" |
| "@ |
| add\t%N0, %N1, %r2 |
| addi\t%N0, %N1, %2 |
| addli\t%N0, %N1, %2 |
| auli\t%N0, %N1, %h2" |
| [(set_attr "type" "*,*,X01,X01")]) |
| |
| (define_code_iterator netreg_binop |
| [minus]) |
| |
| (define_insn "*netreg_binop_to_network" |
| [(unspec_volatile:SI |
| [(match_operand:SI 0 "netreg_operand" "i") |
| (netreg_binop:SI (match_operand:SI 1 "reg_or_0_operand" "rO") |
| (match_operand:SI 2 "reg_or_0_operand" "rO")) |
| (reg:SI TILEPRO_NETORDER_REG)] |
| UNSPEC_NETWORK_SEND) |
| (clobber (reg:SI TILEPRO_NETORDER_REG))] |
| "" |
| "<insn>\t%N0, %r1, %r2") |
| |
| (define_insn "*netreg_binop_from_network0" |
| [(set (match_operand:SI 0 "register_operand" "=r") |
| (netreg_binop:SI |
| (unspec_volatile:SI [(match_operand:SI 1 "netreg_operand" "i") |
| (reg:SI TILEPRO_NETORDER_REG)] |
| UNSPEC_NETWORK_RECEIVE) |
| (match_operand:SI 2 "reg_or_0_operand" "rO"))) |
| (clobber (reg:SI TILEPRO_NETORDER_REG))] |
| "" |
| "<insn>\t%0, %N1, %r2") |
| |
| (define_insn "*netreg_binop_from_network1" |
| [(set (match_operand:SI 0 "register_operand" "=r") |
| (netreg_binop:SI |
| (match_operand:SI 1 "reg_or_0_operand" "rO") |
| (unspec_volatile:SI [(match_operand:SI 2 "netreg_operand" "i") |
| (reg:SI TILEPRO_NETORDER_REG)] |
| UNSPEC_NETWORK_RECEIVE))) |
| (clobber (reg:SI TILEPRO_NETORDER_REG))] |
| "" |
| "<insn>\t%0, %r1, %N2") |
| |
| (define_insn "*netreg_binop_from_to_network0" |
| [(unspec_volatile:SI |
| [(match_operand:SI 0 "netreg_operand" "i") |
| (netreg_binop:SI |
| (unspec_volatile:SI [(match_operand:SI 1 "netreg_operand" "i") |
| (reg:SI TILEPRO_NETORDER_REG)] |
| UNSPEC_NETWORK_RECEIVE) |
| (match_operand:SI 2 "reg_or_0_operand" "rO")) |
| (reg:SI TILEPRO_NETORDER_REG)] |
| UNSPEC_NETWORK_SEND) |
| (clobber (reg:SI TILEPRO_NETORDER_REG)) |
| (clobber (reg:SI TILEPRO_NETORDER_REG))] |
| "" |
| "<insn>\t%N0, %N1, %r2") |
| |
| (define_insn "*netreg_binop_from_to_network1" |
| [(unspec_volatile:SI |
| [(match_operand:SI 0 "netreg_operand" "i") |
| (netreg_binop:SI |
| (match_operand:SI 1 "reg_or_0_operand" "rO") |
| (unspec_volatile:SI [(match_operand:SI 2 "netreg_operand" "i") |
| (reg:SI TILEPRO_NETORDER_REG)] |
| UNSPEC_NETWORK_RECEIVE)) |
| (reg:SI TILEPRO_NETORDER_REG)] |
| UNSPEC_NETWORK_SEND) |
| (clobber (reg:SI TILEPRO_NETORDER_REG)) |
| (clobber (reg:SI TILEPRO_NETORDER_REG))] |
| "" |
| "<insn>\t%N0, %r1, %N2") |
| |
| (define_insn "*netreg_binop_to_network" |
| [(unspec_volatile:SI |
| [(match_operand:SI 0 "netreg_operand" "i,i") |
| (binop_with_imm:SI (match_operand:SI 1 "reg_or_0_operand" "rO,rO") |
| (match_operand:SI 2 "reg_or_cint_operand" "I,rO")) |
| (reg:SI TILEPRO_NETORDER_REG)] |
| UNSPEC_NETWORK_SEND) |
| (clobber (reg:SI TILEPRO_NETORDER_REG))] |
| "" |
| "@ |
| <insn>i<u>\t%N0, %r1, %2 |
| <insn><u>\t%N0, %r1, %r2") |
| |
| (define_insn "*netreg_binop_from_network" |
| [(set (match_operand:SI 0 "register_operand" "=r,r") |
| (binop_with_imm:SI |
| (unspec_volatile:SI [(match_operand:SI 1 "netreg_operand" "i,i") |
| (reg:SI TILEPRO_NETORDER_REG)] |
| UNSPEC_NETWORK_RECEIVE) |
| (match_operand:SI 2 "reg_or_cint_operand" "I,rO"))) |
| (clobber (reg:SI TILEPRO_NETORDER_REG))] |
| "" |
| "@ |
| <insn>i<u>\t%0, %N1, %2 |
| <insn><u>\t%0, %N1, %r2") |
| |
| (define_insn "*netreg_binop_from_to_network" |
| [(unspec_volatile:SI |
| [(match_operand:SI 0 "netreg_operand" "i,i") |
| (binop_with_imm:SI |
| (unspec_volatile:SI [(match_operand:SI 1 "netreg_operand" "i,i") |
| (reg:SI TILEPRO_NETORDER_REG)] |
| UNSPEC_NETWORK_RECEIVE) |
| (match_operand:SI 2 "reg_or_cint_operand" "I,rO")) |
| (reg:SI TILEPRO_NETORDER_REG)] |
| UNSPEC_NETWORK_SEND) |
| (clobber (reg:SI TILEPRO_NETORDER_REG)) |
| (clobber (reg:SI TILEPRO_NETORDER_REG))] |
| "" |
| "@ |
| <insn>i<u>\t%N0, %N1, %2 |
| <insn><u>\t%N0, %N1, %r2") |
| |
| (define_insn "*netreg_unop_to_network" |
| [(unspec_volatile:SI [(match_operand:SI 0 "netreg_operand" "i") |
| (unop:SI (match_operand:SI 1 "reg_or_0_operand" "rO")) |
| (reg:SI TILEPRO_NETORDER_REG)] |
| UNSPEC_NETWORK_SEND) |
| (clobber (reg:SI TILEPRO_NETORDER_REG))] |
| "" |
| "<insn>\t%N0, %r1" |
| [(set_attr "type" "Y0")]) |
| |
| (define_insn "*netreg_unop_from_network" |
| [(set (match_operand:SI 0 "register_operand" "=r") |
| (unop:SI |
| (unspec_volatile:SI [(match_operand:SI 1 "netreg_operand" "i") |
| (reg:SI TILEPRO_NETORDER_REG)] |
| UNSPEC_NETWORK_RECEIVE))) |
| (clobber (reg:SI TILEPRO_NETORDER_REG))] |
| "" |
| "<insn>\t%0, %N1" |
| [(set_attr "type" "Y0")]) |
| |
| (define_insn "*netreg_unop_from_to_network" |
| [(unspec_volatile:SI |
| [(match_operand:SI 0 "netreg_operand" "i") |
| (unop:SI |
| (unspec_volatile:SI [(match_operand:SI 1 "netreg_operand" "i") |
| (reg:SI TILEPRO_NETORDER_REG)] |
| UNSPEC_NETWORK_RECEIVE)) |
| (reg:SI TILEPRO_NETORDER_REG)] |
| UNSPEC_NETWORK_SEND) |
| (clobber (reg:SI TILEPRO_NETORDER_REG)) |
| (clobber (reg:SI TILEPRO_NETORDER_REG))] |
| "" |
| "<insn>\t%N0, %N1" |
| [(set_attr "type" "Y0")]) |
| |
| (define_insn "*netreg_sadh_u_from_network0" |
| [(set (match_operand:SI 0 "register_operand" "=r") |
| (unspec:SI |
| [(unspec_volatile:SI [(match_operand:SI 1 "netreg_operand" "i") |
| (reg:SI TILEPRO_NETORDER_REG)] |
| UNSPEC_NETWORK_RECEIVE) |
| (match_operand:SI 2 "reg_or_0_operand" "rO")] |
| UNSPEC_INSN_SADH_U)) |
| (clobber (reg:SI TILEPRO_NETORDER_REG))] |
| "" |
| "sadh_u\t%0, %N1, %r2" |
| [(set_attr "type" "X0_2cycle")]) |
| |
| (define_insn "*netreg_sadh_u_from_network1" |
| [(set (match_operand:SI 0 "register_operand" "=r") |
| (unspec:SI |
| [(match_operand:SI 1 "reg_or_0_operand" "rO") |
| (unspec_volatile:SI [(match_operand:SI 2 "netreg_operand" "i") |
| (reg:SI TILEPRO_NETORDER_REG)] |
| UNSPEC_NETWORK_RECEIVE)] |
| UNSPEC_INSN_SADH_U)) |
| (clobber (reg:SI TILEPRO_NETORDER_REG))] |
| "" |
| "sadh_u\t%0, %r1, %N2" |
| [(set_attr "type" "X0_2cycle")]) |
| |
| (define_insn "*netreg_sadah_u_from_network0" |
| [(set (match_operand:SI 0 "register_operand" "=r") |
| (unspec:SI |
| [(match_operand:SI 1 "reg_or_0_operand" "0") |
| (unspec_volatile:SI [(match_operand:SI 2 "netreg_operand" "i") |
| (reg:SI TILEPRO_NETORDER_REG)] |
| UNSPEC_NETWORK_RECEIVE) |
| (match_operand:SI 3 "reg_or_0_operand" "rO")] |
| UNSPEC_INSN_SADAH_U)) |
| (clobber (reg:SI TILEPRO_NETORDER_REG))] |
| "" |
| "sadah_u\t%0, %N2, %r3" |
| [(set_attr "type" "X0_2cycle")]) |
| |
| (define_insn "*netreg_sadah_u_from_network1" |
| [(set (match_operand:SI 0 "register_operand" "=r") |
| (unspec:SI |
| [(match_operand:SI 1 "reg_or_0_operand" "0") |
| (match_operand:SI 2 "reg_or_0_operand" "rO") |
| (unspec_volatile:SI [(match_operand:SI 3 "netreg_operand" "i") |
| (reg:SI TILEPRO_NETORDER_REG)] |
| UNSPEC_NETWORK_RECEIVE)] |
| UNSPEC_INSN_SADAH_U)) |
| (clobber (reg:SI TILEPRO_NETORDER_REG))] |
| "" |
| "sadah_u\t%0, %r2, %N3" |
| [(set_attr "type" "X0_2cycle")]) |
| |
| (define_code_iterator mm_combiner [ior xor plus]) |
| |
| ;; This doesn't seem to match -- too complex for 'combine'? |
| ;; |
| ;; (define_insn "*netreg_mm_to_network" |
| ;; [(unspec_volatile:SI |
| ;; [(match_operand:SI 0 "netreg_operand" "i") |
| ;; (mm_combiner:SI |
| ;; (and:SI (match_operand:SI 1 "reg_or_0_operand" "rO") |
| ;; (match_operand:SI 3 "const_int_operand" "n")) |
| ;; (and:SI (match_operand:SI 2 "reg_or_0_operand" "rO") |
| ;; (match_operand:SI 4 "const_int_operand" "n")))] |
| ;; UNSPEC_NETWORK_SEND)] |
| ;; "tilepro_bitfield_operand_p (INTVAL (operands[3]), NULL, NULL) |
| ;; && INTVAL (operands[3]) == ~INTVAL (operands[4])" |
| ;; "mm\t%N0, %r1, %r2, %M3" |
| ;; [(set_attr "type" "X01")]) |
| |
| ;; FIXME: the straight forward versions which do not include the |
| ;; subreg:QI does not match for some unknown reason. |
| (define_insn "*netreg_bbs_normal" |
| [(set (pc) |
| (if_then_else |
| (ne (zero_extract:SI |
| (subreg:QI |
| (unspec_volatile:SI [(match_operand:SI 1 "netreg_operand" "i") |
| (reg:SI TILEPRO_NETORDER_REG)] |
| UNSPEC_NETWORK_RECEIVE) 0) |
| (const_int 1) |
| (const_int 0)) |
| (const_int 0)) |
| (label_ref (match_operand 0 "" "")) |
| (pc))) |
| (clobber (reg:SI TILEPRO_NETORDER_REG))] |
| "" |
| { return tilepro_output_cbranch_with_opcode (insn, operands, "bbs", "bbns", |
| 1, 1); } |
| [(set_attr "type" "X1_branch")]) |
| |
| (define_insn "*netreg_bbc_normal" |
| [(set (pc) |
| (if_then_else |
| (eq (zero_extract:SI |
| (subreg:QI |
| (unspec_volatile:SI [(match_operand:SI 1 "netreg_operand" "i") |
| (reg:SI TILEPRO_NETORDER_REG)] |
| UNSPEC_NETWORK_RECEIVE) 0) |
| (const_int 1) |
| (const_int 0)) |
| (const_int 0)) |
| (label_ref (match_operand 0 "" "")) |
| (pc))) |
| (clobber (reg:SI TILEPRO_NETORDER_REG))] |
| "" |
| { return tilepro_output_cbranch_with_opcode (insn, operands, "bbns", "bbns", |
| 1, 1); } |
| [(set_attr "type" "X1_branch")]) |
| |
| |
| ;; |
| ;; "__insn" Intrinsics (some expand directly to normal patterns above). |
| ;; |
| |
| (define_insn "insn_addlis" |
| [(set (match_operand:SI 0 "register_operand" "=r") |
| (unspec_volatile:SI [(match_operand:SI 1 "reg_or_0_operand" "rO") |
| (match_operand:SI 2 "s16bit_cint_operand" "i")] |
| UNSPEC_INSN_ADDLIS))] |
| "" |
| "addlis\t%0, %r1, %2" |
| [(set_attr "type" "X01")]) |
| |
| (define_insn "insn_auli" |
| [(set (match_operand:SI 0 "register_operand" "=r") |
| (unspec:SI [(match_operand:SI 1 "reg_or_0_operand" "rO") |
| (match_operand:SI 2 "s16bit_cint_operand" "i")] |
| UNSPEC_INSN_AULI))] |
| "" |
| "auli\t%0, %r1, %2" |
| [(set_attr "type" "X01")]) |
| |
| (define_insn "insn_drain" |
| [(unspec_volatile:VOID [(const_int 0)] UNSPEC_INSN_DRAIN)] |
| "" |
| "drain" |
| [(set_attr "type" "cannot_bundle")]) |
| |
| (define_insn "insn_icoh" |
| [(unspec_volatile:VOID [(match_operand:SI 0 "reg_or_0_operand" "rO")] |
| UNSPEC_INSN_ICOH)] |
| "" |
| "icoh\t%r0" |
| [(set_attr "type" "X1")]) |
| |
| |
| (define_insn "insn_info" |
| [(unspec_volatile:VOID [(match_operand:SI 0 "s8bit_cint_operand" "i")] |
| UNSPEC_INSN_INFO)] |
| "" |
| "info\t%0") |
| |
| (define_insn "insn_infol" |
| [(unspec_volatile:VOID [(match_operand:SI 0 "s16bit_cint_operand" "i")] |
| UNSPEC_INSN_INFOL)] |
| "" |
| "infol\t%0" |
| [(set_attr "type" "X01")]) |
| |
| ;; loads |
| |
| (define_expand "insn_<load>" |
| [(set (match_operand:SI 0 "register_operand" "") |
| (sign_extend:SI |
| (mem:I12MODE (match_operand:SI 1 "address_operand" ""))))] |
| "") |
| |
| (define_expand "insn_<load>_u" |
| [(set (match_operand:SI 0 "register_operand" "") |
| (zero_extend:SI |
| (mem:I12MODE (match_operand:SI 1 "address_operand" ""))))] |
| "") |
| |
| (define_insn "insn_<load>add" |
| [(set (match_operand:SI 1 "register_operand" "=r") |
| (plus:SI (match_operand:SI 3 "register_operand" "1") |
| (match_operand:SI 2 "s8bit_cint_operand" "i"))) |
| (set (match_operand:SI 0 "register_operand" "=r") |
| (sign_extend:SI (mem:I12MODE (match_dup 3))))] |
| "" |
| "<load>add\t%0, %1, %2" |
| [(set_attr "type" "X1_2cycle")]) |
| |
| (define_insn "insn_<load>add_u" |
| [(set (match_operand:SI 1 "register_operand" "=r") |
| (plus:SI (match_operand:SI 3 "register_operand" "1") |
| (match_operand:SI 2 "s8bit_cint_operand" "i"))) |
| (set (match_operand:SI 0 "register_operand" "=r") |
| (zero_extend:SI (mem:I12MODE (match_dup 3))))] |
| "" |
| "<load>add_u\t%0, %1, %2" |
| [(set_attr "type" "X1_2cycle")]) |
| |
| (define_expand "insn_lw" |
| [(set (match_operand:SI 0 "register_operand" "") |
| (mem:SI (match_operand:SI 1 "address_operand" "")))] |
| "") |
| |
| (define_insn "insn_lwadd" |
| [(set (match_operand:SI 1 "register_operand" "=r") |
| (plus:SI (match_operand:SI 3 "register_operand" "1") |
| (match_operand:SI 2 "s8bit_cint_operand" "i"))) |
| (set (match_operand:SI 0 "register_operand" "=r") |
| (mem:SI (match_dup 3)))] |
| "" |
| "lwadd\t%0, %1, %2" |
| [(set_attr "type" "X1_2cycle")]) |
| |
| (define_insn "insn_lwadd_na" |
| [(set (match_operand:SI 1 "register_operand" "=r") |
| (plus:SI (match_operand:SI 3 "register_operand" "1") |
| (match_operand:SI 2 "s8bit_cint_operand" "i"))) |
| (set (match_operand:SI 0 "register_operand" "=r") |
| (mem:SI (and:SI (match_dup 3) (const_int -4))))] |
| "" |
| "lwadd_na\t%0, %1, %2" |
| [(set_attr "type" "X1_2cycle")]) |
| |
| (define_insn "insn_lw_na" |
| [(set (match_operand:SI 0 "register_operand" "=r") |
| (mem:SI (and:SI (match_operand:SI 1 "address_operand" "rO") |
| (const_int -4))))] |
| "" |
| "lw_na\t%0, %r1" |
| [(set_attr "type" "X1_2cycle")]) |
| |
| ;; L2 hits |
| |
| (define_insn "insn_<load>_L2" |
| [(set (match_operand:SI 0 "register_operand" "=r") |
| (sign_extend:SI |
| (unspec:I12MODE |
| [(mem:I12MODE (match_operand:SI 1 "address_operand" "rO"))] |
| UNSPEC_LATENCY_L2)))] |
| "" |
| "<load>\t%0, %r1" |
| [(set_attr "type" "Y2_L2")]) |
| |
| (define_insn "insn_<load>_u_L2" |
| [(set (match_operand:SI 0 "register_operand" "=r") |
| (zero_extend:SI |
| (unspec:I12MODE |
| [(mem:I12MODE (match_operand:SI 1 "address_operand" "rO"))] |
| UNSPEC_LATENCY_L2)))] |
| "" |
| "<load>_u\t%0, %r1" |
| [(set_attr "type" "Y2_L2")]) |
| |
| (define_insn "insn_<load>add_L2" |
| [(set (match_operand:SI 1 "register_operand" "=r") |
| (plus:SI (match_operand:SI 3 "register_operand" "1") |
| (match_operand:SI 2 "s8bit_cint_operand" "i"))) |
| (set (match_operand:SI 0 "register_operand" "=r") |
| (sign_extend:SI (unspec:I12MODE [(mem:I12MODE (match_dup 3))] |
| UNSPEC_LATENCY_L2)))] |
| "" |
| "<load>add\t%0, %1, %2" |
| [(set_attr "type" "X1_L2")]) |
| |
| (define_insn "insn_<load>add_u_L2" |
| [(set (match_operand:SI 1 "register_operand" "=r") |
| (plus:SI (match_operand:SI 3 "register_operand" "1") |
| (match_operand:SI 2 "s8bit_cint_operand" "i"))) |
| (set (match_operand:SI 0 "register_operand" "=r") |
| (zero_extend:SI (unspec:I12MODE [(mem:I12MODE (match_dup 3))] |
| UNSPEC_LATENCY_L2)))] |
| "" |
| "<load>add_u\t%0, %1, %2" |
| [(set_attr "type" "X1_L2")]) |
| |
| (define_insn "insn_lwadd_L2" |
| [(set (match_operand:SI 1 "register_operand" "=r") |
| (plus:SI (match_operand:SI 3 "register_operand" "1") |
| (match_operand:SI 2 "s8bit_cint_operand" "i"))) |
| (set (match_operand:SI 0 "register_operand" "=r") |
| (unspec:SI [(mem:SI (match_dup 3))] UNSPEC_LATENCY_L2))] |
| "" |
| "lwadd\t%0, %1, %2" |
| [(set_attr "type" "X1_L2")]) |
| |
| (define_insn "insn_lwadd_na_L2" |
| [(set (match_operand:SI 1 "register_operand" "=r") |
| (plus:SI (match_operand:SI 3 "register_operand" "1") |
| (match_operand:SI 2 "s8bit_cint_operand" "i"))) |
| (set (match_operand:SI 0 "register_operand" "=r") |
| (unspec:SI [(mem:SI (and:SI (match_dup 3) (const_int -4)))] |
| UNSPEC_LATENCY_L2))] |
| "" |
| "lwadd_na\t%0, %1, %2" |
| [(set_attr "type" "X1_L2")]) |
| |
| (define_insn "insn_lw_na_L2" |
| [(set (match_operand:SI 0 "register_operand" "=r") |
| (unspec:SI [(mem:SI (and:SI (match_operand:SI 1 "address_operand" "rO") |
| (const_int -4)))] |
| UNSPEC_LATENCY_L2))] |
| "" |
| "lw_na\t%0, %r1" |
| [(set_attr "type" "X1_L2")]) |
| |
| (define_insn "insn_lw_L2" |
| [(set (match_operand:SI 0 "register_operand" "=r") |
| (unspec:SI [(mem:SI (match_operand:SI 1 "address_operand" "rO"))] |
| UNSPEC_LATENCY_L2))] |
| "" |
| "lw\t%0, %r1" |
| [(set_attr "type" "Y2_L2")]) |
| |
| ;; L2 miss |
| |
| (define_insn "insn_<load>_miss" |
| [(set (match_operand:SI 0 "register_operand" "=r") |
| (sign_extend:SI |
| (unspec:I12MODE |
| [(mem:I12MODE (match_operand:SI 1 "address_operand" "rO"))] |
| UNSPEC_LATENCY_MISS)))] |
| "" |
| "<load>\t%0, %r1" |
| [(set_attr "type" "Y2_miss")]) |
| |
| (define_insn "insn_<load>_u_miss" |
| [(set (match_operand:SI 0 "register_operand" "=r") |
| (zero_extend:SI |
| (unspec:I12MODE |
| [(mem:I12MODE (match_operand:SI 1 "address_operand" "rO"))] |
| UNSPEC_LATENCY_MISS)))] |
| "" |
| "<load>_u\t%0, %r1" |
| [(set_attr "type" "Y2_miss")]) |
| |
| (define_insn "insn_<load>add_miss" |
| [(set (match_operand:SI 1 "register_operand" "=r") |
| (plus:SI (match_operand:SI 3 "register_operand" "1") |
| (match_operand:SI 2 "s8bit_cint_operand" "i"))) |
| (set (match_operand:SI 0 "register_operand" "=r") |
| (sign_extend:SI (unspec:I12MODE [(mem:I12MODE (match_dup 3))] |
| UNSPEC_LATENCY_MISS)))] |
| "" |
| "<load>add\t%0, %1, %2" |
| [(set_attr "type" "X1_miss")]) |
| |
| (define_insn "insn_<load>add_u_miss" |
| [(set (match_operand:SI 1 "register_operand" "=r") |
| (plus:SI (match_operand:SI 3 "register_operand" "1") |
| (match_operand:SI 2 "s8bit_cint_operand" "i"))) |
| (set (match_operand:SI 0 "register_operand" "=r") |
| (zero_extend:SI (unspec:I12MODE [(mem:I12MODE (match_dup 3))] |
| UNSPEC_LATENCY_MISS)))] |
| "" |
| "<load>add_u\t%0, %1, %2" |
| [(set_attr "type" "X1_miss")]) |
| |
| (define_insn "insn_lwadd_miss" |
| [(set (match_operand:SI 1 "register_operand" "=r") |
| (plus:SI (match_operand:SI 3 "register_operand" "1") |
| (match_operand:SI 2 "s8bit_cint_operand" "i"))) |
| (set (match_operand:SI 0 "register_operand" "=r") |
| (unspec:SI [(mem:SI (match_dup 3))] UNSPEC_LATENCY_MISS))] |
| "" |
| "lwadd\t%0, %1, %2" |
| [(set_attr "type" "X1_miss")]) |
| |
| (define_insn "insn_lwadd_na_miss" |
| [(set (match_operand:SI 1 "register_operand" "=r") |
| (plus:SI (match_operand:SI 3 "register_operand" "1") |
| (match_operand:SI 2 "s8bit_cint_operand" "i"))) |
| (set (match_operand:SI 0 "register_operand" "=r") |
| (unspec:SI [(mem:SI (and:SI (match_dup 3) (const_int -4)))] |
| UNSPEC_LATENCY_MISS))] |
| "" |
| "lwadd_na\t%0, %1, %2" |
| [(set_attr "type" "X1_miss")]) |
| |
| (define_insn "insn_lw_na_miss" |
| [(set (match_operand:SI 0 "register_operand" "=r") |
| (unspec:SI [(mem:SI (and:SI (match_operand:SI 1 "address_operand" "rO") |
| (const_int -4)))] |
| UNSPEC_LATENCY_MISS))] |
| "" |
| "lw_na\t%0, %r1" |
| [(set_attr "type" "X1_miss")]) |
| |
| (define_insn "insn_lw_miss" |
| [(set (match_operand:SI 0 "register_operand" "=r") |
| (unspec:SI [(mem:SI (match_operand:SI 1 "address_operand" "rO"))] |
| UNSPEC_LATENCY_MISS))] |
| "" |
| "lw\t%0, %r1" |
| [(set_attr "type" "Y2_miss")]) |
| |
| ;; end loads |
| |
| (define_insn "insn_mfspr" |
| [(set (match_operand:SI 0 "register_operand" "=r") |
| (unspec_volatile:SI [(match_operand:SI 1 "u15bit_cint_operand" "i")] |
| UNSPEC_INSN_MFSPR)) |
| (clobber (mem:BLK (const_int 0)))] |
| "" |
| "mfspr\t%0, %1" |
| [(set_attr "type" "X1")]) |
| |
| (define_insn "*mm" |
| [(set (match_operand:SI 0 "register_operand" "=r") |
| (mm_combiner:SI |
| (and:SI (match_operand:SI 1 "reg_or_0_operand" "rO") |
| (match_operand:SI 3 "const_int_operand" "n")) |
| (and:SI (match_operand:SI 2 "reg_or_0_operand" "rO") |
| (match_operand:SI 4 "const_int_operand" "n"))))] |
| "tilepro_bitfield_operand_p (INTVAL (operands[3]), NULL, NULL) |
| && INTVAL (operands[3]) == ~INTVAL (operands[4])" |
| "mm\t%0, %r1, %r2, %M3" |
| [(set_attr "type" "X01")]) |
| |
| (define_expand "insn_mm" |
| [(set (match_operand:SI 0 "register_operand" "") |
| (ior:SI |
| (and:SI (match_operand:SI 1 "reg_or_cint_operand" "") |
| (match_operand:SI 3 "u5bit_cint_operand" "")) |
| (and:SI (match_operand:SI 2 "reg_or_cint_operand" "") |
| (match_operand:SI 4 "u5bit_cint_operand" ""))))] |
| "" |
| { |
| int first, last, i; |
| HOST_WIDE_INT mask; |
| |
| first = INTVAL (operands[3]) & 31; |
| last = INTVAL (operands[4]) & 31; |
| |
| if (((last + 1) & 31) == first) |
| { |
| /* Handle pathological case of a mask that includes only the |
| first operand. The reordering code below can't handle this. */ |
| emit_move_insn (operands[0], operands[1]); |
| DONE; |
| } |
| |
| /* Canonicalize order by putting constant second, if any. */ |
| if (CONST_INT_P (operands[1])) |
| { |
| int tmp_first; |
| |
| rtx tmp = operands[1]; |
| operands[1] = operands[2]; |
| operands[2] = tmp; |
| |
| /* Invert the bit range. */ |
| tmp_first = first; |
| first = (last + 1) & 31; |
| last = (tmp_first - 1) & 31; |
| } |
| |
| /* Convert the first/last bit range into a bit mask. */ |
| mask = 0; |
| |
| for (i = first; ; i = (i + 1) & 31) |
| { |
| mask |= ((HOST_WIDE_INT)1) << i; |
| if (i == last) |
| break; |
| } |
| |
| mask = trunc_int_for_mode (mask, SImode); |
| |
| operands[1] = force_reg (SImode, operands[1]); |
| operands[3] = GEN_INT (mask); |
| operands[4] = GEN_INT (~mask); |
| |
| if (CONST_INT_P (operands[2])) |
| { |
| HOST_WIDE_INT inserted_bits = INTVAL (operands[2]) & ~mask; |
| |
| if (inserted_bits == 0) |
| { |
| /* All inserted bits are zero. Use a bitwise AND. */ |
| emit_insn (gen_andsi3 (operands[0], operands[1], operands[3])); |
| DONE; |
| } |
| else if (inserted_bits == ~mask) |
| { |
| /* All inserted bits are ones. Use a bitwise IOR if we can. */ |
| if (satisfies_constraint_I (operands[4])) |
| { |
| emit_insn (gen_iorsi3 (operands[0], operands[1], operands[4])); |
| DONE; |
| } |
| |
| /* Canonicalize to inserting -1 when setting all masked bits |
| to 1, to facilitate CSE. */ |
| inserted_bits = -1; |
| } |
| |
| /* Sign extend the inserted bits to make them easier to materialize |
| in a register, but only if the inserted bits (~mask) do not already |
| include the high bits. */ |
| if ((~mask & 0x80000000) == 0) |
| { |
| int shift = sizeof (HOST_WIDE_INT) * 8 - first; |
| inserted_bits = (inserted_bits << shift) >> shift; |
| } |
| |
| operands[2] = GEN_INT (inserted_bits); |
| } |
| |
| operands[2] = force_reg (SImode, operands[2]); |
| }) |
| |
| (define_insn "insn_movelis" |
| [(set (match_operand:SI 0 "register_operand" "=r") |
| (unspec_volatile:SI [(match_operand:SI 1 "s16bit_cint_operand" "i")] |
| UNSPEC_INSN_MOVELIS))] |
| "" |
| "movelis\t%0, %1" |
| [(set_attr "type" "X01")]) |
| |
| (define_insn "insn_mtspr" |
| [(unspec_volatile:SI [(match_operand:SI 0 "u15bit_cint_operand" "i") |
| (match_operand:SI 1 "reg_or_0_operand" "rO")] |
| UNSPEC_INSN_MTSPR) |
| (clobber (mem:BLK (const_int 0)))] |
| "" |
| "mtspr\t%0, %r1" |
| [(set_attr "type" "X1")]) |
| |
| (define_expand "insn_prefetch" |
| [(prefetch (match_operand:SI 0 "address_operand" "") |
| (const_int 0) |
| (const_int 2))]) |
| |
| (define_expand "insn_prefetch_L1" |
| [(use (match_operand:SI 0 "address_operand" ""))] |
| "" |
| { |
| /* Generate a volatile byte load to a dummy register. */ |
| rtx mem = gen_rtx_MEM (QImode, operands[0]); |
| MEM_VOLATILE_P (mem) = 1; |
| |
| emit_insn (gen_zero_extendqisi2 (gen_reg_rtx (SImode), mem)); |
| DONE; |
| }) |
| |
| (define_expand "insn_s1a" |
| [(set (match_operand:SI 0 "register_operand" "") |
| (plus:SI (mult:SI (match_operand:SI 1 "reg_or_0_operand" "") |
| (const_int 2)) |
| (match_operand:SI 2 "reg_or_0_operand" "")))] |
| "") |
| |
| (define_expand "insn_s2a" |
| [(set (match_operand:SI 0 "register_operand" "") |
| (plus:SI (mult:SI (match_operand:SI 1 "reg_or_0_operand" "") |
| (const_int 4)) |
| (match_operand:SI 2 "reg_or_0_operand" "")))] |
| "") |
| |
| (define_expand "insn_s3a" |
| [(set (match_operand:SI 0 "register_operand" "") |
| (plus:SI (mult:SI (match_operand:SI 1 "reg_or_0_operand" "") |
| (const_int 8)) |
| (match_operand:SI 2 "reg_or_0_operand" "")))] |
| "") |
| |
| (define_expand "insn_<store>" |
| [(set (mem:I12MODE (match_operand:SI 0 "address_operand" "")) |
| (match_operand:SI 1 "reg_or_0_operand" ""))] |
| "" |
| { |
| operands[1] = simplify_gen_subreg (<MODE>mode, operands[1], SImode, 0); |
| }) |
| |
| (define_expand "insn_sw" |
| [(set (mem:SI (match_operand:SI 0 "address_operand" "")) |
| (match_operand:SI 1 "reg_or_0_operand" ""))] |
| "") |
| |
| (define_expand "insn_<store>add" |
| [(parallel |
| [(set (match_operand:SI 0 "register_operand" "") |
| (plus:SI (match_operand:SI 3 "register_operand" "") |
| (match_operand:SI 2 "s8bit_cint_operand" ""))) |
| (set (mem:I12MODE (match_dup 3)) |
| (match_operand:SI 1 "reg_or_0_operand" ""))])] |
| "" |
| { |
| operands[1] = simplify_gen_subreg (<MODE>mode, operands[1], SImode, 0); |
| }) |
| |
| (define_insn "*insn_<store>add" |
| [(set (match_operand:SI 0 "register_operand" "=r") |
| (plus:SI (match_operand:SI 3 "register_operand" "0") |
| (match_operand:SI 2 "s8bit_cint_operand" "i"))) |
| (set (mem:I12MODE (match_dup 3)) |
| (match_operand:I12MODE 1 "reg_or_0_operand" "rO"))] |
| "" |
| "<store>add\t%0, %r1, %2" |
| [(set_attr "type" "X1")]) |
| |
| (define_insn "insn_swadd" |
| [(set (match_operand:SI 0 "register_operand" "=r") |
| (plus:SI (match_operand:SI 3 "register_operand" "0") |
| (match_operand:SI 2 "s8bit_cint_operand" "i"))) |
| (set (mem:SI (match_dup 3)) |
| (match_operand:SI 1 "reg_or_0_operand" "rO"))] |
| "" |
| "swadd\t%0, %r1, %2" |
| [(set_attr "type" "X1")]) |
| |
| (define_insn "insn_wh64" |
| [(unspec_volatile:VOID [(match_operand:SI 0 "reg_or_0_operand" "rO")] |
| UNSPEC_INSN_WH64) |
| (clobber (mem:BLK (const_int 0)))] |
| "" |
| "wh64\t%r0" |
| [(set_attr "type" "X1")]) |
| |
| (define_insn "insn_tns" |
| [(set (match_operand:SI 0 "register_operand" "=r") |
| (mem:SI (match_operand:SI 1 "reg_or_0_operand" "rO"))) |
| (set (mem:SI (match_dup 1)) (const_int 1))] |
| "" |
| "tns\t%0, %1" |
| [(set_attr "type" "X1")]) |
| |
| ;; insn_addb |
| ;; insn_addib |
| ;; insn_maxb_u |
| ;; insn_maxib_u |
| ;; insn_minb_u |
| ;; insn_minib_u |
| ;; insn_seqb |
| ;; insn_seqib |
| ;; insn_sltb |
| ;; insn_sltib |
| ;; insn_sltb_u |
| ;; insn_sltib_u |
| (define_insn "<optab>v4qi3" |
| [(set (match_operand:V4QI 0 "register_operand" "=r,r") |
| (v1op_immed:V4QI |
| (match_operand:V4QI 1 "reg_or_0_operand" "<comm>rO,rO") |
| (match_operand:V4QI 2 "reg_or_v4s8bit_operand" "W,rO")))] |
| "" |
| "@ |
| <insn>ib<u>\t%0, %r1, %j2 |
| <insn>b<u>\t%0, %r1, %r2" |
| [(set_attr "type" "X01,X01")]) |
| |
| (define_expand "insn_<insn>b<u>" |
| [(set (match_operand:SI 0 "register_operand" "") |
| (v1op_immed:V4QI |
| (match_operand:SI 1 "reg_or_0_operand" "") |
| (match_operand:SI 2 "reg_or_0_operand" "")))] |
| "" |
| { |
| tilepro_expand_builtin_vector_binop (gen_<optab>v4qi3, V4QImode, operands[0], |
| V4QImode, operands[1], operands[2], true); |
| DONE; |
| }) |
| |
| (define_expand "insn_<insn>ib<u>" |
| [(set (match_operand:SI 0 "register_operand" "") |
| (v1op_immed:V4QI |
| (match_operand:SI 1 "reg_or_0_operand" "") |
| (match_operand:SI 2 "s8bit_cint_operand" "")))] |
| "" |
| { |
| /* Tile out immediate and expand to general case. */ |
| rtx n = tilepro_simd_int (operands[2], QImode); |
| tilepro_expand_builtin_vector_binop (gen_<optab>v4qi3, V4QImode, operands[0], |
| V4QImode, operands[1], n, true); |
| DONE; |
| }) |
| |
| ;; insn_shlb |
| ;; insn_shlib |
| ;; insn_shrb |
| ;; insn_shrib |
| ;; insn_srab |
| ;; insn_sraib |
| (define_insn "<optab>v4qi3" |
| [(set (match_operand:V4QI 0 "register_operand" "=r,r") |
| (any_shift:V4QI |
| (match_operand:V4QI 1 "reg_or_0_operand" "rO,rO") |
| (match_operand:SI 2 "reg_or_u5bit_operand" "I,rO")))] |
| "" |
| "@ |
| <insn>ib<u>\t%0, %r1, %2 |
| <insn>b<u>\t%0, %r1, %r2" |
| [(set_attr "type" "X01,X01")]) |
| |
| (define_expand "insn_<insn>b<u>" |
| [(set (match_operand:SI 0 "register_operand" "") |
| (any_shift:V4QI |
| (match_operand:SI 1 "reg_or_0_operand" "") |
| (match_operand:SI 2 "reg_or_u5bit_operand" "")))] |
| "" |
| { |
| tilepro_expand_builtin_vector_binop (gen_<optab>v4qi3, V4QImode, operands[0], |
| V4QImode, operands[1], operands[2], false); |
| DONE; |
| }) |
| |
| ;; insn_addh |
| ;; insn_addih |
| ;; insn_maxh |
| ;; insn_maxih |
| ;; insn_minh |
| ;; insn_minih |
| ;; insn_seqh |
| ;; insn_seqih |
| ;; insn_slth |
| ;; insn_sltih |
| ;; insn_slth_u |
| ;; insn_sltih_u |
| (define_insn "<optab>v2hi3" |
| [(set (match_operand:V2HI 0 "register_operand" "=r,r") |
| (v2op_immed:V2HI |
| (match_operand:V2HI 1 "reg_or_0_operand" "<comm>rO,rO") |
| (match_operand:V2HI 2 "reg_or_v2s8bit_operand" "Y,rO")))] |
| "" |
| "@ |
| <insn>ih<u>\t%0, %r1, %j2 |
| <insn>h<u>\t%0, %r1, %r2" |
| [(set_attr "type" "X01,X01")]) |
| |
| (define_expand "insn_<insn>h<u>" |
| [(set (match_operand:SI 0 "register_operand" "") |
| (v2op_immed:V2HI |
| (match_operand:SI 1 "reg_or_0_operand" "") |
| (match_operand:SI 2 "reg_or_0_operand" "")))] |
| "" |
| { |
| tilepro_expand_builtin_vector_binop (gen_<optab>v2hi3, V2HImode, operands[0], |
| V2HImode, operands[1], operands[2], true); |
| DONE; |
| }) |
| |
| (define_expand "insn_<insn>ih<u>" |
| [(set (match_operand:SI 0 "register_operand" "") |
| (v2op_immed:V2HI |
| (match_operand:SI 1 "reg_or_0_operand" "") |
| (match_operand:SI 2 "s8bit_cint_operand" "")))] |
| "" |
| { |
| /* Tile out immediate and expand to general case. */ |
| rtx n = tilepro_simd_int (operands[2], HImode); |
| tilepro_expand_builtin_vector_binop (gen_<optab>v2hi3, V2HImode, operands[0], |
| V2HImode, operands[1], n, true); |
| DONE; |
| }) |
| |
| ;; insn_shlh |
| ;; insn_shlih |
| ;; insn_shrh |
| ;; insn_shrih |
| ;; insn_srah |
| ;; insn_sraih |
| (define_insn "<optab>v2hi3" |
| [(set (match_operand:V2HI 0 "register_operand" "=r,r") |
| (any_shift:V2HI |
| (match_operand:V2HI 1 "reg_or_0_operand" "rO,rO") |
| (match_operand:SI 2 "reg_or_u5bit_operand" "I,rO")))] |
| "" |
| "@ |
| <insn>ih<u>\t%0, %r1, %2 |
| <insn>h<u>\t%0, %r1, %r2" |
| [(set_attr "type" "X01,X01")]) |
| |
| (define_expand "insn_<insn>h<u>" |
| [(set (match_operand:SI 0 "register_operand" "") |
| (any_shift:V2HI |
| (match_operand:SI 1 "reg_or_0_operand" "") |
| (match_operand:SI 2 "reg_or_0_operand" "")))] |
| "" |
| { |
| tilepro_expand_builtin_vector_binop (gen_<optab>v2hi3, V2HImode, operands[0], |
| V2HImode, operands[1], operands[2], false); |
| DONE; |
| }) |
| |
| ;; insn_addbs_u |
| ;; insn_subbs_u |
| ;; insn_subb |
| ;; insn_slteb |
| ;; insn_slteb_u |
| ;; insn_sneb |
| (define_insn "<optab>v4qi3" |
| [(set (match_operand:V4QI 0 "register_operand" "=r") |
| (v1op:V4QI |
| (match_operand:V4QI 1 "reg_or_0_operand" "<comm>rO") |
| (match_operand:V4QI 2 "reg_or_0_operand" "rO")))] |
| "" |
| "<insn>b<u>\t%0, %r1, %r2" |
| [(set_attr "type" "X01")]) |
| |
| (define_expand "insn_<insn>b<u>" |
| [(set (match_operand:SI 0 "register_operand" "") |
| (v1op:V4QI |
| (match_operand:SI 1 "reg_or_0_operand" "") |
| (match_operand:SI 2 "reg_or_0_operand" "")))] |
| "" |
| { |
| tilepro_expand_builtin_vector_binop (gen_<optab>v4qi3, V4QImode, operands[0], |
| V4QImode, operands[1], operands[2], true); |
| DONE; |
| }) |
| |
| ;; insn_addhs |
| ;; insn_subhs |
| ;; insn_subh |
| ;; insn_slteh |
| ;; insn_slteh_u |
| ;; insn_sneh |
| (define_insn "<optab>v2hi3" |
| [(set (match_operand:V2HI 0 "register_operand" "=r") |
| (v2op:V2HI |
| (match_operand:V2HI 1 "reg_or_0_operand" "<comm>rO") |
| (match_operand:V2HI 2 "reg_or_0_operand" "rO")))] |
| "" |
| "<insn>h<u>\t%0, %r1, %r2" |
| [(set_attr "type" "X01")]) |
| |
| (define_expand "insn_<insn>h<u>" |
| [(set (match_operand:SI 0 "register_operand" "") |
| (v2op:V2HI |
| (match_operand:SI 1 "reg_or_0_operand" "") |
| (match_operand:SI 2 "reg_or_0_operand" "")))] |
| "" |
| { |
| tilepro_expand_builtin_vector_binop (gen_<optab>v2hi3, V2HImode, operands[0], |
| V2HImode, operands[1], operands[2], true); |
| DONE; |
| }) |
| |
| ;; insn_inthb |
| |
| ;; Byte ordering of these vectors is endian dependent. We concat |
| ;; right-to-left for little endian. We concat and interleave in the |
| ;; opposite way gcc's vector patterns work, so we need to reverse the |
| ;; order of source operands. |
| |
| ;; {B3,B2,B1,B0} {A3,A2,A1,A0} |
| ;; => {A3,A2,A1,A0,B3,B2,B1,B0} |
| ;; => {A3,B3,A2,B2} |
| (define_insn "vec_interleave_highv4qi" |
| [(set (match_operand:V4QI 0 "register_operand" "=r") |
| (vec_select:V4QI |
| (vec_concat:V8QI (match_operand:V4QI 1 "reg_or_0_operand" "rO") |
| (match_operand:V4QI 2 "reg_or_0_operand" "rO")) |
| (parallel [(const_int 2) (const_int 6) |
| (const_int 3) (const_int 7)])))] |
| "" |
| "inthb\t%0, %r2, %r1" |
| [(set_attr "type" "X01")]) |
| |
| (define_expand "insn_inthb" |
| [(match_operand:SI 0 "register_operand" "") |
| (match_operand:SI 1 "reg_or_0_operand" "") |
| (match_operand:SI 2 "reg_or_0_operand" "")] |
| "" |
| { |
| /* Our instruction interleaves opposite of the way vec_interleave |
| works, so we need to reverse the source operands. */ |
| tilepro_expand_builtin_vector_binop (gen_vec_interleave_highv4qi, V4QImode, |
| operands[0], V4QImode, operands[2], |
| operands[1], true); |
| DONE; |
| }) |
| |
| ;; insn_intlb |
| ;; {B3,B2,B1,B0} {A3,A2,A1,A0} |
| ;; => {A3,A2,A1,A0,B3,B2,B1,B0} |
| ;; => {A1,B1,A0,B0} |
| (define_insn "vec_interleave_lowv4qi" |
| [(set (match_operand:V4QI 0 "register_operand" "=r") |
| (vec_select:V4QI |
| (vec_concat:V8QI (match_operand:V4QI 1 "reg_or_0_operand" "rO") |
| (match_operand:V4QI 2 "reg_or_0_operand" "rO")) |
| (parallel [(const_int 0) (const_int 4) |
| (const_int 1) (const_int 5)])))] |
| "" |
| "intlb\t%0, %r2, %r1" |
| [(set_attr "type" "X01")]) |
| |
| (define_expand "insn_intlb" |
| [(match_operand:SI 0 "register_operand" "") |
| (match_operand:SI 1 "reg_or_0_operand" "") |
| (match_operand:SI 2 "reg_or_0_operand" "")] |
| "" |
| { |
| /* Our instruction interleaves opposite of the way vec_interleave |
| works, so we need to reverse the source operands. */ |
| tilepro_expand_builtin_vector_binop (gen_vec_interleave_lowv4qi, V4QImode, |
| operands[0], V4QImode, operands[2], |
| operands[1], true); |
| DONE; |
| }) |
| |
| ;; insn_inthh |
| ;; {B1,B0} {A1,A0} |
| ;; => {A1,A0,B1,B0} |
| ;; => {A1,B1} |
| (define_insn "vec_interleave_highv2hi" |
| [(set (match_operand:V2HI 0 "register_operand" "=r") |
| (vec_select:V2HI |
| (vec_concat:V4HI (match_operand:V2HI 1 "reg_or_0_operand" "rO") |
| (match_operand:V2HI 2 "reg_or_0_operand" "rO")) |
| (parallel [(const_int 1) (const_int 3)])))] |
| "" |
| "inthh\t%0, %r2, %r1" |
| [(set_attr "type" "X01")]) |
| |
| (define_expand "insn_inthh" |
| [(match_operand:SI 0 "register_operand" "") |
| (match_operand:SI 1 "reg_or_0_operand" "") |
| (match_operand:SI 2 "reg_or_0_operand" "")] |
| "" |
| { |
| /* Our instruction interleaves opposite of the way vec_interleave |
| works, so we need to reverse the source operands. */ |
| tilepro_expand_builtin_vector_binop (gen_vec_interleave_highv2hi, V2HImode, |
| operands[0], V2HImode, operands[2], |
| operands[1], true); |
| DONE; |
| }) |
| |
| ;; insn_intlh |
| ;; {B1,B0} {A1,A0} |
| ;; => {A1,A0,B1,B0} |
| ;; => {A0,B0} |
| (define_insn "vec_interleave_lowv2hi" |
| [(set (match_operand:V2HI 0 "register_operand" "=r") |
| (vec_select:V2HI |
| (vec_concat:V4HI (match_operand:V2HI 1 "reg_or_0_operand" "rO") |
| (match_operand:V2HI 2 "reg_or_0_operand" "rO")) |
| (parallel [(const_int 0) (const_int 2)])))] |
| "" |
| "intlh\t%0, %r2, %r1" |
| [(set_attr "type" "X01")]) |
| |
| (define_expand "insn_intlh" |
| [(match_operand:SI 0 "register_operand" "") |
| (match_operand:SI 1 "reg_or_0_operand" "") |
| (match_operand:SI 2 "reg_or_0_operand" "")] |
| "" |
| { |
| /* Our instruction interleaves opposite of the way vec_interleave |
| works, so we need to reverse the source operands. */ |
| tilepro_expand_builtin_vector_binop (gen_vec_interleave_lowv2hi, V2HImode, |
| operands[0], V2HImode, operands[2], |
| operands[1], true); |
| DONE; |
| }) |
| |
| ;; insn_packbs_u |
| ;; insn_packlb |
| ;; {B1,B0} {A1,A0} |
| ;; => {A1,A0,B1,B0} |
| (define_insn "vec_pack_<pack_optab>_v2hi" |
| [(set (match_operand:V4QI 0 "register_operand" "=r") |
| (vec_concat:V4QI |
| (v2pack:V2QI (match_operand:V2HI 1 "reg_or_0_operand" "rO")) |
| (v2pack:V2QI (match_operand:V2HI 2 "reg_or_0_operand" "rO"))))] |
| "" |
| "<pack_insn>b<pack_u>\t%0, %r2, %r1" |
| [(set_attr "type" "X01")]) |
| |
| (define_expand "insn_<pack_insn>b<pack_u>" |
| [(set (match_operand:SI 0 "register_operand" "") |
| (vec_concat:V4QI |
| (v2pack:V2QI (match_operand:SI 1 "reg_or_0_operand" "")) |
| (v2pack:V2QI (match_operand:SI 2 "reg_or_0_operand" ""))))] |
| "" |
| { |
| /* Our instruction concats opposite of the way vec_pack works, so we |
| need to reverse the source operands. */ |
| tilepro_expand_builtin_vector_binop (gen_vec_pack_<pack_optab>_v2hi, |
| V4QImode, operands[0], |
| V2HImode, operands[2], operands[1], true); |
| DONE; |
| }) |
| |
| ;; insn_packhb |
| ;; {B1,B0} {A1,A0} |
| ;; => {A1,A0,B1,B0} |
| (define_insn "vec_pack_hipart_v2hi" |
| [(set (match_operand:V4QI 0 "register_operand" "=r") |
| (vec_concat:V4QI |
| (truncate:V2QI |
| (ashiftrt:V2HI (match_operand:V2HI 1 "reg_or_0_operand" "rO") |
| (const_int 8))) |
| (truncate:V2QI |
| (ashiftrt:V2HI (match_operand:V2HI 2 "reg_or_0_operand" "rO") |
| (const_int 8)))))] |
| "" |
| "packhb\t%0, %r2, %r1" |
| [(set_attr "type" "X01")]) |
| |
| (define_expand "insn_packhb" |
| [(set (match_operand:SI 0 "register_operand" "") |
| (vec_concat:V4QI |
| (truncate:V2QI |
| (ashiftrt:V2HI (match_operand:SI 2 "reg_or_0_operand" "") |
| (const_int 8))) |
| (truncate:V2QI |
| (ashiftrt:V2HI (match_operand:SI 1 "reg_or_0_operand" "") |
| (const_int 8)))))] |
| "" |
| { |
| /* Our instruction concats opposite of the way vec_pack works, so we |
| need to reverse the source operands. */ |
| tilepro_expand_builtin_vector_binop (gen_vec_pack_hipart_v2hi, |
| V4QImode, operands[0], |
| V2HImode, operands[2], operands[1], true); |
| DONE; |
| }) |
| |
| ;; insn_packhs |
| ;; {B0} {A0} |
| ;; => {A0,B0} |
| (define_insn "vec_pack_ssat_si" |
| [(set (match_operand:V2HI 0 "register_operand" "=r") |
| (vec_concat:V2HI |
| (ss_truncate:HI (match_operand:SI 1 "reg_or_0_operand" "rO")) |
| (ss_truncate:HI (match_operand:SI 2 "reg_or_0_operand" "rO"))))] |
| "" |
| "packhs\t%0, %r2, %r1" |
| [(set_attr "type" "X01")]) |
| |
| (define_expand "insn_packhs" |
| [(set (match_operand:SI 0 "register_operand" "") |
| (vec_concat:V2HI |
| (ss_truncate:HI (match_operand:SI 2 "reg_or_0_operand" "")) |
| (ss_truncate:HI (match_operand:SI 1 "reg_or_0_operand" ""))))] |
| "" |
| { |
| /* Our instruction concats opposite of the way vec_pack works, so we |
| need to reverse the source operands. */ |
| tilepro_expand_builtin_vector_binop (gen_vec_pack_ssat_si, |
| V2HImode, operands[0], |
| SImode, operands[2], operands[1], true); |
| DONE; |
| }) |
| |
| ;; Rest of the intrinsics |
| (define_insn "insn_adiffb_u" |
| [(set (match_operand:SI 0 "register_operand" "=r") |
| (unspec:SI [(match_operand:SI 1 "reg_or_0_operand" "rO") |
| (match_operand:SI 2 "reg_or_0_operand" "rO")] |
| UNSPEC_INSN_ADIFFB_U))] |
| "" |
| "adiffb_u\t%0, %r1, %r2" |
| [(set_attr "type" "X0_2cycle")]) |
| |
| (define_insn "insn_adiffh" |
| [(set (match_operand:SI 0 "register_operand" "=r") |
| (unspec:SI [(match_operand:SI 1 "reg_or_0_operand" "rO") |
| (match_operand:SI 2 "reg_or_0_operand" "rO")] |
| UNSPEC_INSN_ADIFFH))] |
| "" |
| "adiffh\t%0, %r1, %r2" |
| [(set_attr "type" "X0_2cycle")]) |
| |
| (define_insn "insn_avgb_u" |
| [(set (match_operand:SI 0 "register_operand" "=r") |
| (unspec:SI [(match_operand:SI 1 "reg_or_0_operand" "rO") |
| (match_operand:SI 2 "reg_or_0_operand" "rO")] |
| UNSPEC_INSN_AVGB_U))] |
| "" |
| "avgb_u\t%0, %r1, %r2" |
| [(set_attr "type" "X0")]) |
| |
| (define_insn "insn_avgh" |
| [(set (match_operand:SI 0 "register_operand" "=r") |
| (unspec:SI [(match_operand:SI 1 "reg_or_0_operand" "rO") |
| (match_operand:SI 2 "reg_or_0_operand" "rO")] |
| UNSPEC_INSN_AVGH))] |
| "" |
| "avgh\t%0, %r1, %r2" |
| [(set_attr "type" "X0")]) |
| |
| (define_insn "insn_bitx" |
| [(set (match_operand:SI 0 "register_operand" "=r") |
| (unspec:SI [(match_operand:SI 1 "reg_or_0_operand" "rO")] |
| UNSPEC_INSN_BITX))] |
| "" |
| "bitx\t%0, %r1" |
| [(set_attr "type" "Y0")]) |
| |
| (define_insn "insn_crc32_32" |
| [(set (match_operand:SI 0 "register_operand" "=r") |
| (unspec:SI [(match_operand:SI 1 "reg_or_0_operand" "rO") |
| (match_operand:SI 2 "reg_or_0_operand" "rO")] |
| UNSPEC_INSN_CRC32_32))] |
| "" |
| "crc32_32\t%0, %r1, %r2" |
| [(set_attr "type" "X0")]) |
| |
| (define_insn "insn_crc32_8" |
| [(set (match_operand:SI 0 "register_operand" "=r") |
| (unspec:SI [(match_operand:SI 1 "reg_or_0_operand" "rO") |
| (match_operand:SI 2 "reg_or_0_operand" "rO")] |
| UNSPEC_INSN_CRC32_8))] |
| "" |
| "crc32_8\t%0, %r1, %r2" |
| [(set_attr "type" "X0")]) |
| |
| (define_insn "insn_dtlbpr" |
| [(unspec_volatile:VOID [(match_operand:SI 0 "reg_or_0_operand" "rO")] |
| UNSPEC_INSN_DTLBPR)] |
| "" |
| "dtlbpr\t%r0" |
| [(set_attr "type" "X1")]) |
| |
| (define_insn "insn_dword_align" |
| [(set (match_operand:SI 0 "register_operand" "=r") |
| (unspec:SI [(match_operand:SI 1 "reg_or_0_operand" "0") |
| (match_operand:SI 2 "reg_or_0_operand" "rO") |
| (match_operand:SI 3 "reg_or_0_operand" "rO")] |
| UNSPEC_INSN_DWORD_ALIGN))] |
| "" |
| "dword_align\t%0, %r2, %r3" |
| [(set_attr "type" "X0")]) |
| |
| (define_insn "insn_finv" |
| [(unspec_volatile:VOID [(match_operand:SI 0 "reg_or_0_operand" "rO")] |
| UNSPEC_INSN_FINV)] |
| "" |
| "finv\t%r0" |
| [(set_attr "type" "X1")]) |
| |
| (define_insn "insn_flush" |
| [(unspec_volatile:VOID [(match_operand:SI 0 "reg_or_0_operand" "rO")] |
| UNSPEC_INSN_FLUSH)] |
| "" |
| "flush\t%r0" |
| [(set_attr "type" "X1")]) |
| |
| (define_insn "insn_fnop" |
| [(unspec_volatile:VOID [(const_int 0)] UNSPEC_INSN_FNOP)] |
| "" |
| "fnop") |
| |
| (define_insn "insn_ill" |
| [(unspec_volatile:VOID [(const_int 0)] UNSPEC_INSN_ILL)] |
| "" |
| "ill" |
| [(set_attr "type" "cannot_bundle")]) |
| |
| (define_insn "insn_inv" |
| [(unspec_volatile:VOID [(match_operand:SI 0 "reg_or_0_operand" "rO")] |
| UNSPEC_INSN_INV)] |
| "" |
| "inv\t%r0" |
| [(set_attr "type" "X1")]) |
| |
| (define_insn "insn_lnk" |
| [(set (match_operand:SI 0 "register_operand" "=r") |
| (unspec:SI [(const_int 0)] UNSPEC_INSN_LNK))] |
| "" |
| "lnk\t%0" |
| [(set_attr "type" "X1")]) |
| |
| (define_insn "insn_mnzb" |
| [(set (match_operand:SI 0 "register_operand" "=r") |
| (unspec:SI [(match_operand:SI 1 "reg_or_0_operand" "rO") |
| (match_operand:SI 2 "reg_or_0_operand" "rO")] |
| UNSPEC_INSN_MNZB))] |
| "" |
| "mnzb\t%0, %r1, %r2" |
| [(set_attr "type" "X01")]) |
| |
| (define_insn "insn_mnzh" |
| [(set (match_operand:SI 0 "register_operand" "=r") |
| (unspec:SI [(match_operand:SI 1 "reg_or_0_operand" "rO") |
| (match_operand:SI 2 "reg_or_0_operand" "rO")] |
| UNSPEC_INSN_MNZH))] |
| "" |
| "mnzh\t%0, %r1, %r2" |
| [(set_attr "type" "X01")]) |
| |
| (define_insn "insn_mulhh_ss" |
| [(set (match_operand:SI 0 "register_operand" "=r") |
| (unspec:SI [(match_operand:SI 1 "reg_or_0_operand" "rO") |
| (match_operand:SI 2 "reg_or_0_operand" "rO")] |
| UNSPEC_INSN_MULHH_SS))] |
| "" |
| "mulhh_ss\t%0, %r1, %r2" |
| [(set_attr "type" "Y0_2cycle")]) |
| |
| (define_insn "insn_mulhh_su" |
| [(set (match_operand:SI 0 "register_operand" "=r") |
| (unspec:SI [(match_operand:SI 1 "reg_or_0_operand" "rO") |
| (match_operand:SI 2 "reg_or_0_operand" "rO")] |
| UNSPEC_INSN_MULHH_SU))] |
| "" |
| "mulhh_su\t%0, %r1, %r2" |
| [(set_attr "type" "X0_2cycle")]) |
| |
| (define_insn "insn_mulhh_uu" |
| [(set (match_operand:SI 0 "register_operand" "=r") |
| (unspec:SI [(match_operand:SI 1 "reg_or_0_operand" "rO") |
| (match_operand:SI 2 "reg_or_0_operand" "rO")] |
| UNSPEC_INSN_MULHH_UU))] |
| "" |
| "mulhh_uu\t%0, %r1, %r2" |
| [(set_attr "type" "Y0_2cycle")]) |
| |
| (define_insn "insn_mulhha_ss" |
| [(set (match_operand:SI 0 "register_operand" "=r") |
| (unspec:SI [(match_operand:SI 1 "reg_or_0_operand" "0") |
| (match_operand:SI 2 "reg_or_0_operand" "rO") |
| (match_operand:SI 3 "reg_or_0_operand" "rO")] |
| UNSPEC_INSN_MULHHA_SS))] |
| "" |
| "mulhha_ss\t%0, %r2, %r3" |
| [(set_attr "type" "Y0_2cycle")]) |
| |
| (define_insn "insn_mulhha_su" |
| [(set (match_operand:SI 0 "register_operand" "=r") |
| (unspec:SI [(match_operand:SI 1 "reg_or_0_operand" "0") |
| (match_operand:SI 2 "reg_or_0_operand" "rO") |
| (match_operand:SI 3 "reg_or_0_operand" "rO")] |
| UNSPEC_INSN_MULHHA_SU))] |
| "" |
| "mulhha_su\t%0, %r2, %r3" |
| [(set_attr "type" "X0_2cycle")]) |
| |
| (define_insn "insn_mulhha_uu" |
| [(set (match_operand:SI 0 "register_operand" "=r") |
| (unspec:SI [(match_operand:SI 1 "reg_or_0_operand" "0") |
| (match_operand:SI 2 "reg_or_0_operand" "rO") |
| (match_operand:SI 3 "reg_or_0_operand" "rO")] |
| UNSPEC_INSN_MULHHA_UU))] |
| "" |
| "mulhha_uu\t%0, %r2, %r3" |
| [(set_attr "type" "Y0_2cycle")]) |
| |
| (define_insn "insn_mulhhsa_uu" |
| [(set (match_operand:SI 0 "register_operand" "=r") |
| (unspec:SI [(match_operand:SI 1 "reg_or_0_operand" "0") |
| (match_operand:SI 2 "reg_or_0_operand" "rO") |
| (match_operand:SI 3 "reg_or_0_operand" "rO")] |
| UNSPEC_INSN_MULHHSA_UU))] |
| "" |
| "mulhhsa_uu\t%0, %r2, %r3" |
| [(set_attr "type" "X0_2cycle")]) |
| |
| (define_insn "insn_mulhl_ss" |
| [(set (match_operand:SI 0 "register_operand" "=r") |
| (unspec:SI [(match_operand:SI 1 "reg_or_0_operand" "rO") |
| (match_operand:SI 2 "reg_or_0_operand" "rO")] |
| UNSPEC_INSN_MULHL_SS))] |
| "" |
| "mulhl_ss\t%0, %r1, %r2" |
| [(set_attr "type" "X0_2cycle")]) |
| |
| (define_insn "insn_mulhl_su" |
| [(set (match_operand:SI 0 "register_operand" "=r") |
| (unspec:SI [(match_operand:SI 1 "reg_or_0_operand" "rO") |
| (match_operand:SI 2 "reg_or_0_operand" "rO")] |
| UNSPEC_INSN_MULHL_SU))] |
| "" |
| "mulhl_su\t%0, %r1, %r2" |
| [(set_attr "type" "X0_2cycle")]) |
| |
| (define_insn "insn_mulhl_us" |
| [(set (match_operand:SI 0 "register_operand" "=r") |
| (unspec:SI [(match_operand:SI 1 "reg_or_0_operand" "rO") |
| (match_operand:SI 2 "reg_or_0_operand" "rO")] |
| UNSPEC_INSN_MULHL_US))] |
| "" |
| "mulhl_us\t%0, %r1, %r2" |
| [(set_attr "type" "X0_2cycle")]) |
| |
| (define_insn "insn_mulhl_uu" |
| [(set (match_operand:SI 0 "register_operand" "=r") |
| (unspec:SI [(match_operand:SI 1 "reg_or_0_operand" "rO") |
| (match_operand:SI 2 "reg_or_0_operand" "rO")] |
| UNSPEC_INSN_MULHL_UU))] |
| "" |
| "mulhl_uu\t%0, %r1, %r2" |
| [(set_attr "type" "X0_2cycle")]) |
| |
| (define_insn "insn_mulhla_ss" |
| [(set (match_operand:SI 0 "register_operand" "=r") |
| (unspec:SI [(match_operand:SI 1 "reg_or_0_operand" "0") |
| (match_operand:SI 2 "reg_or_0_operand" "rO") |
| (match_operand:SI 3 "reg_or_0_operand" "rO")] |
| UNSPEC_INSN_MULHLA_SS))] |
| "" |
| "mulhla_ss\t%0, %r2, %r3" |
| [(set_attr "type" "X0_2cycle")]) |
| |
| (define_insn "insn_mulhla_su" |
| [(set (match_operand:SI 0 "register_operand" "=r") |
| (unspec:SI [(match_operand:SI 1 "reg_or_0_operand" "0") |
| (match_operand:SI 2 "reg_or_0_operand" "rO") |
| (match_operand:SI 3 "reg_or_0_operand" "rO")] |
| UNSPEC_INSN_MULHLA_SU))] |
| "" |
| "mulhla_su\t%0, %r2, %r3" |
| [(set_attr "type" "X0_2cycle")]) |
| |
| (define_insn "insn_mulhla_us" |
| [(set (match_operand:SI 0 "register_operand" "=r") |
| (unspec:SI [(match_operand:SI 1 "reg_or_0_operand" "0") |
| (match_operand:SI 2 "reg_or_0_operand" "rO") |
| (match_operand:SI 3 "reg_or_0_operand" "rO")] |
| UNSPEC_INSN_MULHLA_US))] |
| "" |
| "mulhla_us\t%0, %r2, %r3" |
| [(set_attr "type" "X0_2cycle")]) |
| |
| (define_insn "insn_mulhla_uu" |
| [(set (match_operand:SI 0 "register_operand" "=r") |
| (unspec:SI [(match_operand:SI 1 "reg_or_0_operand" "0") |
| (match_operand:SI 2 "reg_or_0_operand" "rO") |
| (match_operand:SI 3 "reg_or_0_operand" "rO")] |
| UNSPEC_INSN_MULHLA_UU))] |
| "" |
| "mulhla_uu\t%0, %r2, %r3" |
| [(set_attr "type" "X0_2cycle")]) |
| |
| (define_insn "insn_mulhlsa_uu" |
| [(set (match_operand:SI 0 "register_operand" "=r") |
| (unspec:SI [(match_operand:SI 1 "reg_or_0_operand" "0") |
| (match_operand:SI 2 "reg_or_0_operand" "rO") |
| (match_operand:SI 3 "reg_or_0_operand" "rO")] |
| UNSPEC_INSN_MULHLSA_UU))] |
| "" |
| "mulhlsa_uu\t%0, %r2, %r3" |
| [(set_attr "type" "Y0_2cycle")]) |
| |
| (define_insn "insn_mulll_ss" |
| [(set (match_operand:SI 0 "register_operand" "=r") |
| (unspec:SI [(match_operand:SI 1 "reg_or_0_operand" "rO") |
| (match_operand:SI 2 "reg_or_0_operand" "rO")] |
| UNSPEC_INSN_MULLL_SS))] |
| "" |
| "mulll_ss\t%0, %r1, %r2" |
| [(set_attr "type" "Y0_2cycle")]) |
| |
| (define_insn "insn_mulll_su" |
| [(set (match_operand:SI 0 "register_operand" "=r") |
| (unspec:SI [(match_operand:SI 1 "reg_or_0_operand" "rO") |
| (match_operand:SI 2 "reg_or_0_operand" "rO")] |
| UNSPEC_INSN_MULLL_SU))] |
| "" |
| "mulll_su\t%0, %r1, %r2" |
| [(set_attr "type" "X0_2cycle")]) |
| |
| (define_insn "insn_mulll_uu" |
| [(set (match_operand:SI 0 "register_operand" "=r") |
| (unspec:SI [(match_operand:SI 1 "reg_or_0_operand" "rO") |
| (match_operand:SI 2 "reg_or_0_operand" "rO")] |
| UNSPEC_INSN_MULLL_UU))] |
| "" |
| "mulll_uu\t%0, %r1, %r2" |
| [(set_attr "type" "Y0_2cycle")]) |
| |
| (define_insn "insn_mullla_ss" |
| [(set (match_operand:SI 0 "register_operand" "=r") |
| (unspec:SI [(match_operand:SI 1 "reg_or_0_operand" "0") |
| (match_operand:SI 2 "reg_or_0_operand" "rO") |
| (match_operand:SI 3 "reg_or_0_operand" "rO")] |
| UNSPEC_INSN_MULLLA_SS))] |
| "" |
| "mullla_ss\t%0, %r2, %r3" |
| [(set_attr "type" "Y0_2cycle")]) |
| |
| (define_insn "insn_mullla_su" |
| [(set (match_operand:SI 0 "register_operand" "=r") |
| (unspec:SI [(match_operand:SI 1 "reg_or_0_operand" "0") |
| (match_operand:SI 2 "reg_or_0_operand" "rO") |
| (match_operand:SI 3 "reg_or_0_operand" "rO")] |
| UNSPEC_INSN_MULLLA_SU))] |
| "" |
| "mullla_su\t%0, %r2, %r3" |
| [(set_attr "type" "X0_2cycle")]) |
| |
| (define_insn "insn_mullla_uu" |
| [(set (match_operand:SI 0 "register_operand" "=r") |
| (unspec:SI [(match_operand:SI 1 "reg_or_0_operand" "0") |
| (match_operand:SI 2 "reg_or_0_operand" "rO") |
| (match_operand:SI 3 "reg_or_0_operand" "rO")] |
| UNSPEC_INSN_MULLLA_UU))] |
| "" |
| "mullla_uu\t%0, %r2, %r3" |
| [(set_attr "type" "Y0_2cycle")]) |
| |
| (define_insn "insn_mulllsa_uu" |
| [(set (match_operand:SI 0 "register_operand" "=r") |
| (unspec:SI [(match_operand:SI 1 "reg_or_0_operand" "0") |
| (match_operand:SI 2 "reg_or_0_operand" "rO") |
| (match_operand:SI 3 "reg_or_0_operand" "rO")] |
| UNSPEC_INSN_MULLLSA_UU))] |
| "" |
| "mulllsa_uu\t%0, %r2, %r3" |
| [(set_attr "type" "X0_2cycle")]) |
| |
| (define_insn "insn_mzb" |
| [(set (match_operand:SI 0 "register_operand" "=r") |
| (unspec:SI [(match_operand:SI 1 "reg_or_0_operand" "rO") |
| (match_operand:SI 2 "reg_or_0_operand" "rO")] |
| UNSPEC_INSN_MZB))] |
| "" |
| "mzb\t%0, %r1, %r2" |
| [(set_attr "type" "X01")]) |
| |
| (define_insn "insn_mzh" |
| [(set (match_operand:SI 0 "register_operand" "=r") |
| (unspec:SI [(match_operand:SI 1 "reg_or_0_operand" "rO") |
| (match_operand:SI 2 "reg_or_0_operand" "rO")] |
| UNSPEC_INSN_MZH))] |
| "" |
| "mzh\t%0, %r1, %r2" |
| [(set_attr "type" "X01")]) |
| |
| (define_insn "insn_nap" |
| [(unspec_volatile:VOID [(const_int 0)] UNSPEC_INSN_NAP)] |
| "" |
| "nap" |
| [(set_attr "type" "cannot_bundle")]) |
| |
| (define_insn "insn_nor" |
| [(set (match_operand:SI 0 "register_operand" "=r") |
| (and:SI (not:SI (match_operand:SI 1 "reg_or_0_operand" "rO")) |
| (not:SI (match_operand:SI 2 "reg_or_0_operand" "rO"))))] |
| "" |
| "nor\t%0, %r1, %r2") |
| |
| (define_insn "insn_sadab_u" |
| [(set (match_operand:SI 0 "register_operand" "=r") |
| (unspec:SI [(match_operand:SI 1 "reg_or_0_operand" "0") |
| (match_operand:SI 2 "reg_or_0_operand" "rO") |
| (match_operand:SI 3 "reg_or_0_operand" "rO")] |
| UNSPEC_INSN_SADAB_U))] |
| "" |
| "sadab_u\t%0, %r2, %r3" |
| [(set_attr "type" "X0_2cycle")]) |
| |
| (define_insn "insn_sadah" |
| [(set (match_operand:SI 0 "register_operand" "=r") |
| (unspec:SI [(match_operand:SI 1 "reg_or_0_operand" "0") |
| (match_operand:SI 2 "reg_or_0_operand" "rO") |
| (match_operand:SI 3 "reg_or_0_operand" "rO")] |
| UNSPEC_INSN_SADAH))] |
| "" |
| "sadah\t%0, %r2, %r3" |
| [(set_attr "type" "X0_2cycle")]) |
| |
| (define_insn "insn_sadah_u" |
| [(set (match_operand:SI 0 "register_operand" "=r") |
| (unspec:SI [(match_operand:SI 1 "reg_or_0_operand" "0") |
| (match_operand:SI 2 "reg_or_0_operand" "rO") |
| (match_operand:SI 3 "reg_or_0_operand" "rO")] |
| UNSPEC_INSN_SADAH_U))] |
| "" |
| "sadah_u\t%0, %r2, %r3" |
| [(set_attr "type" "X0_2cycle")]) |
| |
| (define_insn "insn_sadb_u" |
| [(set (match_operand:SI 0 "register_operand" "=r") |
| (unspec:SI [(match_operand:SI 1 "reg_or_0_operand" "rO") |
| (match_operand:SI 2 "reg_or_0_operand" "rO")] |
| UNSPEC_INSN_SADB_U))] |
| "" |
| "sadb_u\t%0, %r1, %r2" |
| [(set_attr "type" "X0_2cycle")]) |
| |
| (define_insn "insn_sadh" |
| [(set (match_operand:SI 0 "register_operand" "=r") |
| (unspec:SI [(match_operand:SI 1 "reg_or_0_operand" "rO") |
| (match_operand:SI 2 "reg_or_0_operand" "rO")] |
| UNSPEC_INSN_SADH))] |
| "" |
| "sadh\t%0, %r1, %r2" |
| [(set_attr "type" "X0_2cycle")]) |
| |
| (define_insn "insn_sadh_u" |
| [(set (match_operand:SI 0 "register_operand" "=r") |
| (unspec:SI [(match_operand:SI 1 "reg_or_0_operand" "rO") |
| (match_operand:SI 2 "reg_or_0_operand" "rO")] |
| UNSPEC_INSN_SADH_U))] |
| "" |
| "sadh_u\t%0, %r1, %r2" |
| [(set_attr "type" "X0_2cycle")]) |
| |
| (define_insn "insn_tblidxb0" |
| [(set (match_operand:SI 0 "register_operand" "=r") |
| (unspec:SI [(match_operand:SI 1 "reg_or_0_operand" "0") |
| (match_operand:SI 2 "reg_or_0_operand" "rO")] |
| UNSPEC_INSN_TBLIDXB0))] |
| "" |
| "tblidxb0\t%0, %r2" |
| [(set_attr "type" "Y0")]) |
| |
| (define_insn "insn_tblidxb1" |
| [(set (match_operand:SI 0 "register_operand" "=r") |
| (unspec:SI [(match_operand:SI 1 "reg_or_0_operand" "0") |
| (match_operand:SI 2 "reg_or_0_operand" "rO")] |
| UNSPEC_INSN_TBLIDXB1))] |
| "" |
| "tblidxb1\t%0, %r2" |
| [(set_attr "type" "Y0")]) |
| |
| (define_insn "insn_tblidxb2" |
| [(set (match_operand:SI 0 "register_operand" "=r") |
| (unspec:SI [(match_operand:SI 1 "reg_or_0_operand" "0") |
| (match_operand:SI 2 "reg_or_0_operand" "rO")] |
| UNSPEC_INSN_TBLIDXB2))] |
| "" |
| "tblidxb2\t%0, %r2" |
| [(set_attr "type" "Y0")]) |
| |
| (define_insn "insn_tblidxb3" |
| [(set (match_operand:SI 0 "register_operand" "=r") |
| (unspec:SI [(match_operand:SI 1 "reg_or_0_operand" "0") |
| (match_operand:SI 2 "reg_or_0_operand" "rO")] |
| UNSPEC_INSN_TBLIDXB3))] |
| "" |
| "tblidxb3\t%0, %r2" |
| [(set_attr "type" "Y0")]) |
| |
| |
| ;; |
| ;; pic related instructions |
| ;; |
| |
| ;; NOTE: We compute the label in this unusual way because if we place |
| ;; the label after the lnk, whether it is at the same address as the |
| ;; lnk will vary depending on whether the optimization level chooses to |
| ;; insert bundling braces. |
| (define_insn "insn_lnk_and_label" |
| [(set (match_operand:SI 0 "register_operand" "=r") |
| (unspec_volatile:SI [(match_operand:SI 1 "symbolic_operand" "")] |
| UNSPEC_LNK_AND_LABEL))] |
| "" |
| "%1 = . + 8\n\tlnk\t%0" |
| [(set_attr "type" "X1")]) |
| |
| (define_expand "addli_pcrel" |
| [(set (match_operand:SI 0 "register_operand" "") |
| (lo_sum:SI |
| (match_operand:SI 1 "register_operand" "") |
| (const:SI |
| (unspec:SI [(match_operand:SI 2 "symbolic_operand" "") |
| (match_operand:SI 3 "symbolic_operand" "")] |
| UNSPEC_PCREL_SYM))))] |
| "flag_pic") |
| |
| (define_expand "auli_pcrel" |
| [(set (match_operand:SI 0 "register_operand" "") |
| (plus:SI |
| (match_operand:SI 1 "reg_or_0_operand" "") |
| (high:SI |
| (const:SI |
| (unspec:SI [(match_operand:SI 2 "symbolic_operand" "") |
| (match_operand:SI 3 "symbolic_operand" "")] |
| UNSPEC_PCREL_SYM)))))] |
| "flag_pic") |
| |
| (define_expand "add_got16" |
| [(set (match_operand:SI 0 "register_operand" "") |
| (lo_sum:SI |
| (match_operand:SI 1 "reg_or_0_operand" "") |
| (const:SI (unspec:SI [(match_operand:SI 2 "symbolic_operand" "")] |
| UNSPEC_GOT16_SYM))))] |
| "flag_pic == 1") |
| |
| (define_expand "addhi_got32" |
| [(set (match_operand:SI 0 "register_operand" "") |
| (plus:SI |
| (match_operand:SI 1 "reg_or_0_operand" "") |
| (high:SI |
| (const:SI (unspec:SI [(match_operand:SI 2 "symbolic_operand" "")] |
| UNSPEC_GOT32_SYM)))))] |
| "flag_pic == 2") |
| |
| (define_expand "addlo_got32" |
| [(set (match_operand:SI 0 "register_operand" "") |
| (lo_sum:SI |
| (match_operand:SI 1 "reg_or_0_operand" "") |
| (const:SI (unspec:SI [(match_operand:SI 2 "symbolic_operand" "")] |
| UNSPEC_GOT32_SYM))))] |
| "flag_pic == 2") |
| |
| |
| ;; |
| ;; TLS |
| ;; |
| |
| (define_expand "tls_gd_addhi" |
| [(set (match_operand:SI 0 "register_operand" "") |
| (plus:SI |
| (match_operand:SI 1 "reg_or_0_operand" "") |
| (high:SI |
| (const:SI (unspec:SI [(match_operand 2 "tls_symbolic_operand" "")] |
| UNSPEC_TLS_GD)))))] |
| "HAVE_AS_TLS") |
| |
| (define_expand "tls_gd_addlo" |
| [(set (match_operand:SI 0 "register_operand" "") |
| (lo_sum:SI |
| (match_operand:SI 1 "reg_or_0_operand" "") |
| (const:SI (unspec:SI [(match_operand 2 "tls_symbolic_operand" "")] |
| UNSPEC_TLS_GD))))] |
| "HAVE_AS_TLS") |
| |
| (define_expand "tls_gd_call" |
| [(parallel |
| [(set (reg:SI 0) |
| (unspec:SI [(match_operand:SI 0 "tls_symbolic_operand" "") |
| (reg:SI 0)] |
| UNSPEC_TLS_GD_CALL)) |
| (clobber (reg:SI 25)) |
| (clobber (reg:SI 26)) |
| (clobber (reg:SI 27)) |
| (clobber (reg:SI 28)) |
| (clobber (reg:SI 29)) |
| (clobber (reg:SI 55))])] |
| "" |
| { |
| cfun->machine->calls_tls_get_addr = true; |
| }) |
| |
| (define_insn "*tls_gd_call" |
| [(set (reg:SI 0) |
| (unspec:SI [(match_operand:SI 0 "tls_symbolic_operand" "") |
| (reg:SI 0)] |
| UNSPEC_TLS_GD_CALL)) |
| (clobber (reg:SI 25)) |
| (clobber (reg:SI 26)) |
| (clobber (reg:SI 27)) |
| (clobber (reg:SI 28)) |
| (clobber (reg:SI 29)) |
| (clobber (reg:SI 55))] |
| "" |
| "jal\ttls_gd_call(%0)" |
| [(set_attr "type" "X1")]) |
| |
| (define_insn "tls_gd_add" |
| [(set (match_operand:SI 0 "register_operand" "=r") |
| (unspec:SI [(match_operand:SI 1 "register_operand" "r") |
| (match_operand:SI 2 "tls_symbolic_operand" "")] |
| UNSPEC_TLS_GD_ADD))] |
| "HAVE_AS_TLS" |
| "addi\t%0, %1, tls_gd_add(%2)") |
| |
| (define_insn "tls_ie_load" |
| [(set (match_operand:SI 0 "register_operand" "=r") |
| (unspec:SI [(match_operand:SI 1 "register_operand" "r") |
| (match_operand:SI 2 "tls_symbolic_operand" "")] |
| UNSPEC_TLS_IE_LOAD))] |
| "HAVE_AS_TLS" |
| "lw_tls\t%0, %1, tls_ie_load(%2)" |
| [(set_attr "type" "X1_2cycle")]) |
| |
| (define_expand "tls_ie_addhi" |
| [(set (match_operand:SI 0 "register_operand" "") |
| (plus:SI |
| (match_operand:SI 1 "register_operand" "") |
| (high:SI |
| (const:SI (unspec:SI [(match_operand 2 "tls_ie_symbolic_operand" "")] |
| UNSPEC_TLS_IE)))))] |
| "HAVE_AS_TLS") |
| |
| (define_expand "tls_ie_addlo" |
| [(set (match_operand:SI 0 "register_operand" "") |
| (lo_sum:SI |
| (match_operand:SI 1 "register_operand" "") |
| (const:SI (unspec:SI [(match_operand 2 "tls_ie_symbolic_operand" "")] |
| UNSPEC_TLS_IE))))] |
| "HAVE_AS_TLS") |
| |
| (define_expand "tls_le_addhi" |
| [(set (match_operand:SI 0 "register_operand" "") |
| (plus:SI |
| (match_operand:SI 1 "register_operand" "") |
| (high:SI |
| (const:SI (unspec:SI [(match_operand 2 "tls_le_symbolic_operand" "")] |
| UNSPEC_TLS_LE)))))] |
| "HAVE_AS_TLS") |
| |
| (define_expand "tls_le_addlo" |
| [(set (match_operand:SI 0 "register_operand" "") |
| (lo_sum:SI |
| (match_operand:SI 1 "register_operand" "") |
| (const:SI (unspec:SI [(match_operand 2 "tls_le_symbolic_operand" "")] |
| UNSPEC_TLS_LE))))] |
| "HAVE_AS_TLS") |
| |
| |
| ;; |
| ;; Stack protector instructions. |
| ;; |
| |
| (define_expand "stack_protect_set" |
| [(set (match_operand 0 "nonautoincmem_operand" "") |
| (match_operand 1 "nonautoincmem_operand" ""))] |
| "" |
| { |
| #ifdef TARGET_THREAD_SSP_OFFSET |
| rtx tp = gen_rtx_REG (Pmode, THREAD_POINTER_REGNUM); |
| rtx ssp_addr = gen_rtx_PLUS (Pmode, tp, GEN_INT (TARGET_THREAD_SSP_OFFSET)); |
| rtx ssp = gen_reg_rtx (Pmode); |
| |
| emit_insn (gen_rtx_SET (VOIDmode, ssp, ssp_addr)); |
| |
| operands[1] = gen_rtx_MEM (Pmode, ssp); |
| #endif |
| |
| emit_insn (gen_stack_protect_setsi (operands[0], operands[1])); |
| |
| DONE; |
| }) |
| |
| (define_insn "stack_protect_setsi" |
| [(set (match_operand:SI 0 "nonautoincmem_operand" "=U") |
| (unspec:SI [(match_operand:SI 1 "nonautoincmem_operand" "U")] |
| UNSPEC_SP_SET)) |
| (set (match_scratch:SI 2 "=&r") (const_int 0))] |
| "" |
| "lw\t%2, %1; { sw\t%0, %2; move\t%2, zero }" |
| [(set_attr "length" "16") |
| (set_attr "type" "cannot_bundle_3cycle")]) |
| |
| |
| (define_expand "stack_protect_test" |
| [(match_operand 0 "nonautoincmem_operand" "") |
| (match_operand 1 "nonautoincmem_operand" "") |
| (match_operand 2 "" "")] |
| "" |
| { |
| rtx compare_result; |
| rtx bcomp, loc_ref; |
| |
| #ifdef TARGET_THREAD_SSP_OFFSET |
| rtx tp = gen_rtx_REG (Pmode, THREAD_POINTER_REGNUM); |
| rtx ssp_addr = gen_rtx_PLUS (Pmode, tp, GEN_INT (TARGET_THREAD_SSP_OFFSET)); |
| rtx ssp = gen_reg_rtx (Pmode); |
| |
| emit_insn (gen_rtx_SET (VOIDmode, ssp, ssp_addr)); |
| |
| operands[1] = gen_rtx_MEM (Pmode, ssp); |
| #endif |
| |
| compare_result = gen_reg_rtx (SImode); |
| |
| emit_insn (gen_stack_protect_testsi (compare_result, operands[0], |
| operands[1])); |
| |
| bcomp = gen_rtx_NE (SImode, compare_result, const0_rtx); |
| |
| loc_ref = gen_rtx_LABEL_REF (VOIDmode, operands[2]); |
| |
| emit_jump_insn (gen_rtx_SET (VOIDmode, pc_rtx, |
| gen_rtx_IF_THEN_ELSE (VOIDmode, bcomp, |
| loc_ref, pc_rtx))); |
| |
| DONE; |
| }) |
| |
| (define_insn "stack_protect_testsi" |
| [(set (match_operand:SI 0 "register_operand" "=&r") |
| (unspec:SI [(match_operand:SI 1 "nonautoincmem_operand" "U") |
| (match_operand:SI 2 "nonautoincmem_operand" "U")] |
| UNSPEC_SP_TEST)) |
| (set (match_scratch:SI 3 "=&r") (const_int 0))] |
| "" |
| "lw\t%0, %1; lw\t%3, %2; { seq\t%0, %0, %3; move\t%3, zero }" |
| [(set_attr "length" "24") |
| (set_attr "type" "cannot_bundle_4cycle")]) |
| |