OSDN Git Service

Merge remote-tracking branch 'gnu/gcc-4_7-branch' into rework
[pf3gnuchains/gcc-fork.git] / gcc / config / tilepro / tilepro.md
diff --git a/gcc/config/tilepro/tilepro.md b/gcc/config/tilepro/tilepro.md
new file mode 100644 (file)
index 0000000..30c8d8f
--- /dev/null
@@ -0,0 +1,3817 @@
+;; Machine description for Tilera TILEPro chip for GCC.
+;; Copyright (C) 2011, 2012
+;; 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)))
+
+\f
+;; 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")])
+
+\f
+;;
+;; 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")])
+
+\f
+;;
+;; 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;
+})
+
+\f
+;;
+;; 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")
+
+\f
+;;
+;; 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")
+
+\f
+;;
+;; 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")
+
+\f
+;;
+;; 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" "")))])
+   
+\f
+;;
+;; 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")])
+
+\f
+;;
+;; 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;
+})
+
+\f
+;;
+;; 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 "" ""))    ;; iterations; zero if unknown
+   (use (match_operand 2 "" ""))    ;; max iterations
+   (use (match_operand 3 "" ""))    ;; loop level
+   (use (match_operand 4 "" ""))]   ;; label
+   ""
+{
+  if (optimize > 0)
+  {
+     rtx s0;
+     rtx bcomp;
+     rtx loc_ref;
+
+     /* only do inner loop  */
+     if (INTVAL (operands[3]) > 1)
+       FAIL;
+     /* 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 [4]);
+     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")])
+
+\f
+;;
+;; 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")])
+
+\f
+;;
+;; 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")])
+
+\f
+;;
+;; "__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")])
+
+\f
+;;
+;; 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")
+
+\f
+;;
+;; 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")
+
+\f
+;;
+;; 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")])
+