OSDN Git Service

* config/sh/sh.c (prepare_cbranch_operands): Use
[pf3gnuchains/gcc-fork.git] / gcc / config / sh / sh.md
index ca112ef..dc6a7ab 100644 (file)
@@ -1,6 +1,6 @@
 ;;- Machine description for Renesas / SuperH SH.
 ;;  Copyright (C) 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
-;;  2003, 2004, 2005, 2006 Free Software Foundation, Inc.
+;;  2003, 2004, 2005, 2006, 2007, 2008 Free Software Foundation, Inc.
 ;;  Contributed by Steve Chamberlain (sac@cygnus.com).
 ;;  Improved by Jim Wilson (wilson@cygnus.com).
 
@@ -8,7 +8,7 @@
 
 ;; 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 2, or (at your option)
+;; 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,
@@ -17,9 +17,8 @@
 ;; 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 COPYING.  If not, write to
-;; the Free Software Foundation, 51 Franklin Street, Fifth Floor,
-;; Boston, MA 02110-1301, USA.
+;; along with GCC; see the file COPYING3.  If not see
+;; <http://www.gnu.org/licenses/>.
 
 
 ;; ??? Should prepend a * to all pattern names which are not used.
   (UNSPEC_FSINA                16)
   (UNSPEC_NSB          17)
   (UNSPEC_ALLOCO       18)
-  (UNSPEC_EH_RETURN    19)
   (UNSPEC_TLSGD                20)
   (UNSPEC_TLSLDM       21)
   (UNSPEC_TLSIE                22)
   (UNSPEC_SP_TEST      41)
   (UNSPEC_MOVUA                42)
 
+  ;; (unspec [VAL SHIFT] UNSPEC_EXTRACT_S16) computes (short) (VAL >> SHIFT).
+  ;; UNSPEC_EXTRACT_U16 is the unsigned equivalent.
+  (UNSPEC_EXTRACT_S16  43)
+  (UNSPEC_EXTRACT_U16  44)
+
+  ;; (unspec [TARGET ANCHOR] UNSPEC_SYMOFF) == TARGET - ANCHOR.
+  (UNSPEC_SYMOFF       45)
+
+  ;; (unspec [OFFSET ANCHOR] UNSPEC_PCREL_SYMOFF) == OFFSET - (ANCHOR - .).
+  (UNSPEC_PCREL_SYMOFF 46)
+
   ;; These are used with unspec_volatile.
   (UNSPECV_BLOCKAGE    0)
   (UNSPECV_ALIGN       1)
   (UNSPECV_CONST8      6)
   (UNSPECV_WINDOW_END  10)
   (UNSPECV_CONST_END   11)
+  (UNSPECV_EH_RETURN   12)
 ])
 
 ;; -------------------------------------------------------------------------
 ;; load_si     Likewise, SImode variant for general register.
 ;; fload       Likewise, but load to fp register.
 ;; store       to memory
+;; fstore      floating point register to memory
 ;; move                general purpose register to register
+;; movi8       8-bit immediate to general purpose register
 ;; mt_group    other sh4 mt instructions
 ;; fmove       register to register, floating point
 ;; smpy                word precision integer multiply
 ;; sfunc       special function call with known used registers
 ;; call                function call
 ;; fp          floating point
+;; fpscr_toggle        toggle a bit in the fpscr
 ;; fdiv                floating point divide (or square root)
 ;; gp_fpul     move from general purpose register to fpul
 ;; fpul_gp     move from fpul to general purpose register
 ;; mac_gp      move from mac[lh] to general purpose register
-;; dfp_arith, dfp_cmp,dfp_conv
+;; gp_mac      move from general purpose register to mac[lh]
+;; mac_mem     move from mac[lh] to memory
+;; mem_mac     move from memory to mac[lh]
+;; dfp_arith,dfp_mul, fp_cmp,dfp_cmp,dfp_conv
 ;; ftrc_s      fix_truncsfsi2_i4
 ;; dfdiv       double precision floating point divide (or square root)
 ;; cwb         ic_invalidate_line_i
 ;; store_media SHmedia general register store instructions
 ;; mcmp_media  SHmedia multimedia compare, absolute, saturating ops
 ;; mac_media   SHmedia mac-style fixed point operations
-;; d2mpy_media SHmedia: two 32 bit integer multiplies
+;; d2mpy_media SHmedia: two 32-bit integer multiplies
 ;; atrans_media        SHmedia approximate transcendental functions
 ;; ustore_media        SHmedia unaligned stores
 ;; nil         no-op move, will be deleted.
 
 (define_attr "type"
- "mt_group,cbranch,jump,jump_ind,arith,arith3,arith3b,dyn_shift,load,load_si,fload,store,move,fmove,smpy,dmpy,return,pload,prset,pstore,prget,pcload,pcload_si,pcfload,rte,sfunc,call,fp,fdiv,ftrc_s,dfp_arith,dfp_cmp,dfp_conv,dfdiv,gp_fpul,fpul_gp,mac_gp,mem_fpscr,gp_fpscr,cwb,movua,fsrra,fsca,tls_load,arith_media,cbranch_media,cmp_media,dfdiv_media,dfmul_media,dfparith_media,dfpconv_media,dmpy_media,fcmp_media,fdiv_media,fload_media,fmove_media,fparith_media,fpconv_media,fstore_media,gettr_media,invalidate_line_media,jump_media,load_media,pt_media,ptabs_media,store_media,mcmp_media,mac_media,d2mpy_media,atrans_media,ustore_media,nil,other"
+ "mt_group,cbranch,jump,jump_ind,arith,arith3,arith3b,dyn_shift,load,load_si,fload,store,fstore,move,movi8,fmove,smpy,dmpy,return,pload,prset,pstore,prget,pcload,pcload_si,pcfload,rte,sfunc,call,fp,fpscr_toggle,fdiv,ftrc_s,dfp_arith,dfp_mul,fp_cmp,dfp_cmp,dfp_conv,dfdiv,gp_fpul,fpul_gp,mac_gp,gp_mac,mac_mem,mem_mac,mem_fpscr,gp_fpscr,cwb,movua,fsrra,fsca,tls_load,arith_media,cbranch_media,cmp_media,dfdiv_media,dfmul_media,dfparith_media,dfpconv_media,dmpy_media,fcmp_media,fdiv_media,fload_media,fmove_media,fparith_media,fpconv_media,fstore_media,gettr_media,invalidate_line_media,jump_media,load_media,pt_media,ptabs_media,store_media,mcmp_media,mac_media,d2mpy_media,atrans_media,ustore_media,nil,other"
   (const_string "other"))
 
 ;; We define a new attribute namely "insn_class".We use
 (define_attr "insn_class"
   "mt_group,ex_group,ls_group,br_group,fe_group,co_group,none"
   (cond [(eq_attr "type" "move,mt_group") (const_string "mt_group")
-         (eq_attr "type" "arith,dyn_shift") (const_string "ex_group")
-        (eq_attr "type" "fmove,load,pcload,load_si,pcload_si,fload,pcfload,store,gp_fpul,fpul_gp") (const_string "ls_group")
+         (eq_attr "type" "movi8,arith,dyn_shift") (const_string "ex_group")
+        (eq_attr "type" "fmove,load,pcload,load_si,pcload_si,fload,pcfload,store,fstore,gp_fpul,fpul_gp") (const_string "ls_group")
         (eq_attr "type" "cbranch,jump") (const_string "br_group")
-        (eq_attr "type" "fp,fdiv,ftrc_s,dfp_arith,dfp_conv,dfdiv")
+        (eq_attr "type" "fp,fp_cmp,fdiv,ftrc_s,dfp_arith,dfp_mul,dfp_conv,dfdiv")
           (const_string "fe_group")
-        (eq_attr "type" "jump_ind,smpy,dmpy,mac_gp,return,pload,prset,pstore,prget,rte,sfunc,call,dfp_cmp,mem_fpscr,gp_fpscr,cwb") (const_string "co_group")]
+        (eq_attr "type" "jump_ind,smpy,dmpy,mac_gp,return,pload,prset,pstore,prget,rte,sfunc,call,dfp_cmp,mem_fpscr,gp_fpscr,cwb,gp_mac,mac_mem,mem_mac") (const_string "co_group")]
        (const_string "none")))
 ;; nil are zero instructions, and arith3 / arith3b are multiple instructions,
 ;; so these do not belong in an insn group, although they are modeled
         (eq_attr "type" "jump")
         (cond [(eq_attr "med_branch_p" "yes")
                (const_int 2)
-               (and (eq (symbol_ref "GET_CODE (prev_nonnote_insn (insn))")
-                         (symbol_ref "INSN"))
-                     (eq (symbol_ref "INSN_CODE (prev_nonnote_insn (insn))")
-                         (symbol_ref "code_for_indirect_jump_scratch")))
+               (and (ne (symbol_ref "prev_nonnote_insn (insn)")
+                        (const_int 0))
+                    (and (eq (symbol_ref "GET_CODE (prev_nonnote_insn (insn))")
+                             (symbol_ref "INSN"))
+                         (eq (symbol_ref "INSN_CODE (prev_nonnote_insn (insn))")
+                             (symbol_ref "code_for_indirect_jump_scratch"))))
                 (cond [(eq_attr "braf_branch_p" "yes")
                        (const_int 6)
                        (eq (symbol_ref "flag_pic") (const_int 0))
 (include "sh4.md")
 
 (include "predicates.md")
+(include "constraints.md")
 
 ;; Definitions for filling delay slots
 
 (define_attr "needs_delay_slot" "yes,no" (const_string "no"))
 
+(define_attr "banked" "yes,no" 
+       (cond [(eq (symbol_ref "sh_loads_bankedreg_p (insn)")
+                  (const_int 1))
+              (const_string "yes")]
+             (const_string "no")))
+
 ;; ??? This should be (nil) instead of (const_int 0)
 (define_attr "hit_stack" "yes,no"
        (cond [(eq (symbol_ref "find_regno_note (insn, REG_INC, SP_REG)")
 ;; SH4 Double-precision computation with double-precision result -
 ;; the two halves are ready at different times.
 (define_attr "dfp_comp" "yes,no"
-  (cond [(eq_attr "type" "dfp_arith,dfp_conv,dfdiv") (const_string "yes")]
+  (cond [(eq_attr "type" "dfp_arith,dfp_mul,dfp_conv,dfdiv") (const_string "yes")]
        (const_string "no")))
 
 ;; Insns for which the latency of a preceding fp insn is decreased by one.
 (define_attr "late_fp_use" "yes,no" (const_string "no"))
 ;; And feeding insns for which this relevant.
 (define_attr "any_fp_comp" "yes,no"
-  (cond [(eq_attr "type" "fp,fdiv,ftrc_s,dfp_arith,dfp_conv,dfdiv")
+  (cond [(eq_attr "type" "fp,fdiv,ftrc_s,dfp_arith,dfp_mul,dfp_conv,dfdiv")
         (const_string "yes")]
        (const_string "no")))
 
                  (eq_attr "type" "!pload,prset"))
             (and (eq_attr "interrupt_function" "yes")
                  (ior
-                  (ne (symbol_ref "TARGET_SH3") (const_int 0))
-                  (eq_attr "hit_stack" "no"))))) (nil) (nil)])
+                  (eq (symbol_ref "TARGET_SH3") (const_int 0))
+                  (eq_attr "hit_stack" "no")
+                  (eq_attr "banked" "no"))))) (nil) (nil)])
 
 ;; Since a call implicitly uses the PR register, we can't allow
 ;; a PR register store in a jsr delay slot.
    [(set_attr "type" "mt_group")])
 
 ;; -------------------------------------------------------------------------
+;; SImode compare and branch
+;; -------------------------------------------------------------------------
+
+(define_expand "cbranchsi4"
+  [(set (pc)
+       (if_then_else (match_operator 0 "comparison_operator"
+                       [(match_operand:SI 1 "arith_operand" "")
+                        (match_operand:SI 2 "arith_operand" "")])
+                     (label_ref (match_operand 3 "" ""))
+                     (pc)))
+   (clobber (reg:SI T_REG))]
+  "TARGET_CBRANCHDI4"
+  "expand_cbranchsi4 (operands, LAST_AND_UNUSED_RTX_CODE, -1); DONE;")
+
+;; -------------------------------------------------------------------------
 ;; SImode unsigned integer comparisons
 ;; -------------------------------------------------------------------------
 
-(define_insn "cmpgeusi_t"
+(define_insn_and_split "cmpgeusi_t"
   [(set (reg:SI T_REG)
        (geu:SI (match_operand:SI 0 "arith_reg_operand" "r")
-               (match_operand:SI 1 "arith_reg_operand" "r")))]
+               (match_operand:SI 1 "arith_reg_or_0_operand" "rN")))]
   "TARGET_SH1"
   "cmp/hs      %1,%0"
+  "&& operands[1] == CONST0_RTX (SImode)"
+  [(pc)]
+  "
+{
+  emit_insn (gen_sett ());
+  DONE;
+}"
    [(set_attr "type" "mt_group")])
 
 (define_insn "cmpgtusi_t"
 }")
 \f
 ;; -------------------------------------------------------------------------
-;; DImode signed integer comparisons
+;; DImode compare and branch
 ;; -------------------------------------------------------------------------
 
-;; ??? Could get better scheduling by splitting the initial test from the
-;; rest of the insn after reload.  However, the gain would hardly justify
-;; the sh.md size increase necessary to do that.
+
+;; arith3 patterns don't work well with the sh4-300 branch prediction mechanism.
+;; Therefore, we aim to have a set of three branches that go straight to the
+;; destination, i.e. only one of them is taken at any one time.
+;; This mechanism should also be slightly better for the sh4-200.
+
+(define_expand "cbranchdi4"
+  [(set (pc)
+       (if_then_else (match_operator 0 "comparison_operator"
+                       [(match_operand:DI 1 "arith_operand" "")
+                        (match_operand:DI 2 "arith_operand" "")])
+                     (label_ref (match_operand 3 "" ""))
+                     (pc)))
+   (clobber (match_dup 4))
+   (clobber (reg:SI T_REG))]
+  "TARGET_CBRANCHDI4"
+  "
+{
+  enum rtx_code comparison;
+
+  if (TARGET_EXPAND_CBRANCHDI4)
+    {
+      if (expand_cbranchdi4 (operands, LAST_AND_UNUSED_RTX_CODE))
+       DONE;
+    }
+  comparison = prepare_cbranch_operands (operands, DImode,
+                                        LAST_AND_UNUSED_RTX_CODE);
+  if (comparison != GET_CODE (operands[0]))
+    operands[0]
+      = gen_rtx_fmt_ee (comparison, VOIDmode, operands[1], operands[2]);
+   operands[4] = gen_rtx_SCRATCH (SImode);
+}")
+
+(define_insn_and_split "cbranchdi4_i"
+  [(set (pc)
+       (if_then_else (match_operator 0 "comparison_operator"
+                       [(match_operand:DI 1 "arith_operand" "r,r")
+                        (match_operand:DI 2 "arith_operand" "rN,i")])
+                     (label_ref (match_operand 3 "" ""))
+                     (pc)))
+   (clobber (match_scratch:SI 4 "=X,&r"))
+   (clobber (reg:SI T_REG))]
+  "TARGET_CBRANCHDI4"
+  "#"
+  "&& reload_completed"
+  [(pc)]
+  "
+{
+  if (!expand_cbranchdi4 (operands, GET_CODE (operands[0])))
+    FAIL;
+  DONE;
+}")
+
+;; -------------------------------------------------------------------------
+;; DImode signed integer comparisons
+;; -------------------------------------------------------------------------
 
 (define_insn ""
   [(set (reg:SI T_REG)
    (set_attr "type" "arith3")])
 
 (define_insn "cmpeqsi_media"
-  [(set (match_operand:DI 0 "register_operand" "=r")
-       (eq:DI (match_operand:SI 1 "logical_operand" "%r")
-              (match_operand:SI 2 "cmp_operand" "Nr")))]
-  "TARGET_SHMEDIA"
-  "cmpeq       %1, %N2, %0"
-  [(set_attr "type" "cmp_media")])
-
-(define_insn "cmpeqdi_media"
-  [(set (match_operand:DI 0 "register_operand" "=r")
-       (eq:DI (match_operand:DI 1 "register_operand" "%r")
-              (match_operand:DI 2 "cmp_operand" "Nr")))]
-  "TARGET_SHMEDIA"
-  "cmpeq       %1, %N2, %0"
-  [(set_attr "type" "cmp_media")])
-
-(define_insn "cmpgtsi_media"
-  [(set (match_operand:DI 0 "register_operand" "=r")
-       (gt:DI (match_operand:SI 1 "cmp_operand" "Nr")
-              (match_operand:SI 2 "cmp_operand" "rN")))]
-  "TARGET_SHMEDIA"
-  "cmpgt       %N1, %N2, %0"
-  [(set_attr "type" "cmp_media")])
-
-(define_insn "cmpgtdi_media"
-  [(set (match_operand:DI 0 "register_operand" "=r")
-       (gt:DI (match_operand:DI 1 "arith_reg_or_0_operand" "Nr")
-              (match_operand:DI 2 "arith_reg_or_0_operand" "rN")))]
-  "TARGET_SHMEDIA"
-  "cmpgt       %N1, %N2, %0"
-  [(set_attr "type" "cmp_media")])
-
-(define_insn "cmpgtusi_media"
-  [(set (match_operand:DI 0 "register_operand" "=r")
-       (gtu:DI (match_operand:SI 1 "cmp_operand" "Nr")
-               (match_operand:SI 2 "cmp_operand" "rN")))]
-  "TARGET_SHMEDIA"
-  "cmpgtu      %N1, %N2, %0"
-  [(set_attr "type" "cmp_media")])
-
-(define_insn "cmpgtudi_media"
-  [(set (match_operand:DI 0 "register_operand" "=r")
-       (gtu:DI (match_operand:DI 1 "arith_reg_or_0_operand" "Nr")
-               (match_operand:DI 2 "arith_reg_or_0_operand" "rN")))]
-  "TARGET_SHMEDIA"
-  "cmpgtu      %N1, %N2, %0"
-  [(set_attr "type" "cmp_media")])
-
-(define_insn "cmpsieqsi_media"
   [(set (match_operand:SI 0 "register_operand" "=r")
        (eq:SI (match_operand:SI 1 "logical_operand" "%r")
               (match_operand:SI 2 "cmp_operand" "Nr")))]
   "cmpeq       %1, %N2, %0"
   [(set_attr "type" "cmp_media")])
 
-(define_insn "cmpsieqdi_media"
+(define_insn "cmpeqdi_media"
   [(set (match_operand:SI 0 "register_operand" "=r")
        (eq:SI (match_operand:DI 1 "register_operand" "%r")
               (match_operand:DI 2 "cmp_operand" "Nr")))]
   "cmpeq       %1, %N2, %0"
   [(set_attr "type" "cmp_media")])
 
-(define_insn "cmpsigtsi_media"
+(define_insn "cmpgtsi_media"
   [(set (match_operand:SI 0 "register_operand" "=r")
        (gt:SI (match_operand:SI 1 "cmp_operand" "Nr")
               (match_operand:SI 2 "cmp_operand" "rN")))]
   "cmpgt       %N1, %N2, %0"
   [(set_attr "type" "cmp_media")])
 
-(define_insn "cmpsigtdi_media"
+(define_insn "cmpgtdi_media"
   [(set (match_operand:SI 0 "register_operand" "=r")
        (gt:SI (match_operand:DI 1 "arith_reg_or_0_operand" "Nr")
               (match_operand:DI 2 "arith_reg_or_0_operand" "rN")))]
   "cmpgt       %N1, %N2, %0"
   [(set_attr "type" "cmp_media")])
 
-(define_insn "cmpsigtusi_media"
+(define_insn "cmpgtusi_media"
   [(set (match_operand:SI 0 "register_operand" "=r")
        (gtu:SI (match_operand:SI 1 "cmp_operand" "Nr")
                (match_operand:SI 2 "cmp_operand" "rN")))]
   "cmpgtu      %N1, %N2, %0"
   [(set_attr "type" "cmp_media")])
 
-(define_insn "cmpsigtudi_media"
+(define_insn "cmpgtudi_media"
   [(set (match_operand:SI 0 "register_operand" "=r")
        (gtu:SI (match_operand:DI 1 "arith_reg_or_0_operand" "Nr")
                (match_operand:DI 2 "arith_reg_or_0_operand" "rN")))]
   [(set_attr "type" "cmp_media")])
 
 ; These two patterns are for combine.
-(define_insn "*cmpne0si_media"
-  [(set (match_operand:DI 0 "register_operand" "=r")
-       (ne:DI (match_operand:SI 1 "arith_reg_operand" "r") (const_int 0)))]
-  "TARGET_SHMEDIA"
-  "cmpgtu      %1,r63,%0"
-  [(set_attr "type" "cmp_media")])
-
 (define_insn "*cmpne0sisi_media"
   [(set (match_operand:SI 0 "register_operand" "=r")
        (ne:SI (match_operand:SI 1 "arith_reg_operand" "r") (const_int 0)))]
     {
       rtx tmp;
 
-      if (no_new_pseudos)
+      if (!can_create_pseudo_p ())
        FAIL;
 
       tmp = gen_reg_rtx (DImode);
    (set (match_dup 4) (match_dup 5))]
   "
 {
-  rtx set1, set2;
+  rtx set1, set2, insn2;
   rtx replacements[4];
 
   /* We want to replace occurrences of operands[0] with operands[1] and
   extract_insn (emit_insn (set1));
   if (! constrain_operands (1))
     goto failure;
-  extract_insn (emit (set2));
+  insn2 = emit (set2);
+  if (GET_CODE (insn2) == BARRIER)
+    goto failure;
+  extract_insn (insn2);
   if (! constrain_operands (1))
     {
       rtx tmp;
                   (match_operand:SI 3 "register_operand" "0"))
                 (match_operand:SI 4 "arith_reg_or_0_operand" "r")))
    (clobber (match_scratch:SI 5 "=&r"))]
-  "TARGET_SHMEDIA && no_new_pseudos"
+  "TARGET_SHMEDIA && !can_create_pseudo_p ()"
   "#"
   "TARGET_SHMEDIA && reload_completed"
   [(pc)]
 {
   emit_insn (gen_movsicc_false (operands[0], operands[1], operands[2],
                                operands[3]));
-  emit_insn (gen_cmpsigtusi_media (operands[5], operands[4], operands[0]));
+  emit_insn (gen_cmpgtusi_media (operands[5], operands[4], operands[0]));
   emit_insn (gen_movsicc_false (operands[0], operands[5], operands[4],
                                operands[0]));
   DONE;
   "TARGET_PRETEND_CMOVE
    && (arith_reg_operand (operands[1], SImode)
        || (immediate_operand (operands[1], SImode)
-          && CONST_OK_FOR_I08 (INTVAL (operands[1]))))"
+          && satisfies_constraint_I08 (operands[1])))"
   "bt 0f\;mov %1,%0\\n0:"
   [(set_attr "type" "mt_group,arith") ;; poor approximation
    (set_attr "length" "4")])
   "TARGET_PRETEND_CMOVE
    && (arith_reg_operand (operands[1], SImode)
        || (immediate_operand (operands[1], SImode)
-          && CONST_OK_FOR_I08 (INTVAL (operands[1]))))"
+          && satisfies_constraint_I08 (operands[1])))"
   "bf 0f\;mov %1,%0\\n0:"
   [(set_attr "type" "mt_group,arith") ;; poor approximation
    (set_attr "length" "4")])
     {
       rtx tmp;
 
-      if (no_new_pseudos)
+      if (!can_create_pseudo_p ())
        FAIL;
 
       tmp = gen_reg_rtx (SImode);
 {
   if (TARGET_SH1)
     {
-      if (no_new_pseudos && ! arith_reg_operand (operands[2], DImode))
+      if (!can_create_pseudo_p () && ! arith_reg_operand (operands[2], DImode))
         FAIL;
       operands[2] = force_reg (DImode, operands[2]);
       emit_insn (gen_adddi3_compact (operands[0], operands[1], operands[2]));
     }
   if (TARGET_SHMEDIA)
     {
-      if (no_new_pseudos && ! arith_reg_or_0_operand (operands[1], SImode))
+      if (!can_create_pseudo_p ()
+         && ! arith_reg_or_0_operand (operands[1], SImode))
        FAIL;
       if (operands[1] != const0_rtx && GET_CODE (operands[1]) != SUBREG)
        operands[1] = force_reg (SImode, operands[1]);
    (clobber (reg:DI TR0_REG))
    (clobber (reg:DI TR1_REG))
    (clobber (reg:DI TR2_REG))
-   (use (match_operand 1 "target_operand" "b"))]
+   (use (match_operand 1 "target_reg_operand" "b"))]
   "TARGET_SHMEDIA && (! TARGET_SHMEDIA_FPU || ! TARGET_DIVIDE_FP)"
   "blink       %1, r18"
   [(set_attr "type" "sfunc")
   ""
   "
 {
-  rtx first, last;
+  rtx last;
 
   operands[3] = gen_reg_rtx (Pmode);
   /* Emit the move of the address to a pseudo outside of the libcall.  */
       function_symbol (operands[3], \"__udivsi3\", SFUNC_STATIC);
       last = gen_udivsi3_i1 (operands[0], operands[3]);
     }
-  first = emit_move_insn (gen_rtx_REG (SImode, 4), operands[1]);
+  emit_move_insn (gen_rtx_REG (SImode, 4), operands[1]);
   emit_move_insn (gen_rtx_REG (SImode, 5), operands[2]);
-  last = emit_insn (last);
-  /* Wrap the sequence in REG_LIBCALL / REG_RETVAL notes so that loop
-     invariant code motion can move it.  */
-  REG_NOTES (first) = gen_rtx_INSN_LIST (REG_LIBCALL, last, REG_NOTES (first));
-  REG_NOTES (last) = gen_rtx_INSN_LIST (REG_RETVAL, first, REG_NOTES (last));
+  emit_insn (last);
   DONE;
 }")
 
    (clobber (reg:SI R20_REG))
    (clobber (reg:SI R21_REG))
    (clobber (reg:SI TR0_REG))
-   (use (match_operand 1 "target_operand" "b"))]
+   (use (match_operand 1 "target_reg_operand" "b"))]
   "TARGET_SHMEDIA && (! TARGET_SHMEDIA_FPU || ! TARGET_DIVIDE_FP)"
   "blink       %1, r18"
   [(set_attr "type" "sfunc")])
    (clobber (reg:SI R21_REG))
    (clobber (reg:SI TR0_REG))
    (use (reg:SI R20_REG))
-   (use (match_operand 1 "target_operand" "b"))]
+   (use (match_operand 1 "target_reg_operand" "b"))]
   "TARGET_SHMEDIA && (! TARGET_SHMEDIA_FPU || ! TARGET_DIVIDE_FP)"
   "blink       %1, r18"
   [(set_attr "type" "sfunc")])
   ""
   "
 {
-  rtx first, last;
+  rtx last;
 
   operands[3] = gen_reg_rtx (Pmode);
   /* Emit the move of the address to a pseudo outside of the libcall.  */
       function_symbol (operands[3], sh_divsi3_libfunc, SFUNC_GOT);
       last = gen_divsi3_i1 (operands[0], operands[3]);
     }
-  first = emit_move_insn (gen_rtx_REG (SImode, 4), operands[1]);
+  emit_move_insn (gen_rtx_REG (SImode, 4), operands[1]);
   emit_move_insn (gen_rtx_REG (SImode, 5), operands[2]);
-  last = emit_insn (last);
-  /* Wrap the sequence in REG_LIBCALL / REG_RETVAL notes so that loop
-     invariant code motion can move it.  */
-  REG_NOTES (first) = gen_rtx_INSN_LIST (REG_LIBCALL, last, REG_NOTES (first));
-  REG_NOTES (last) = gen_rtx_INSN_LIST (REG_RETVAL, first, REG_NOTES (last));
+  emit_insn (last);
   DONE;
 }")
 
@@ -2330,7 +2372,7 @@ norm32: r25
    (clobber (match_operand:DI 8 "register_operand" "=r"))]
   "TARGET_SHMEDIA"
   "#"
-  "&& no_new_pseudos"
+  "&& !can_create_pseudo_p ()"
   [(pc)]
   "
 {
@@ -2374,7 +2416,7 @@ norm32: r25
    (clobber (match_operand:DI 4 "register_operand" "=r"))]
   "TARGET_SHMEDIA"
   "#"
-  "&& no_new_pseudos"
+  "&& !can_create_pseudo_p ()"
   [(pc)]
   "
 {
@@ -2418,7 +2460,7 @@ norm32: r25
    (clobber (match_operand:DI 13 "register_operand" "=r"))]
   "TARGET_SHMEDIA"
   "#"
-  "&& no_new_pseudos"
+  "&& !can_create_pseudo_p ()"
   [(pc)]
   "
 {
@@ -2444,6 +2486,12 @@ norm32: r25
   rtx scratch1 = operands[8];
   rtx scratch2 = operands[9];
 
+  if (satisfies_constraint_N (dividend))
+    {
+      emit_move_insn (result, dividend);
+      DONE;
+    }
+
   emit_insn (gen_mulsidi3_media (scratch0, inv1, dividend));
   emit_insn (gen_mulsidi3_media (scratch1, inv2, dividend));
   emit_insn (gen_ashrdi3_media (scratch2, scratch0, GEN_INT (63)));
@@ -2485,7 +2533,7 @@ norm32: r25
    && (TARGET_DIVIDE_INV_MINLAT
        || TARGET_DIVIDE_INV20U || TARGET_DIVIDE_INV20L)"
   "#"
-  "&& no_new_pseudos"
+  "&& !can_create_pseudo_p ()"
   [(pc)]
   "
 {
@@ -2652,7 +2700,7 @@ label:
    (clobber (match_operand:DF 9 "fp_arith_reg_operand" ""))
    (clobber (match_operand:DF 10 "fp_arith_reg_operand" ""))
    (clobber (match_operand:DF 11 "fp_arith_reg_operand" ""))]
-  "TARGET_SHMEDIA_FPU && TARGET_DIVIDE_INV_FP && no_new_pseudos"
+  "TARGET_SHMEDIA_FPU && TARGET_DIVIDE_INV_FP && !can_create_pseudo_p ()"
   "#"
   "&& 1"
   [(set (match_dup 9) (float:DF (match_dup 1)))
@@ -2711,22 +2759,22 @@ label:
   "TARGET_SH1"
   "
 {
-  rtx first, last;
+  rtx insn, macl;
 
-  first = emit_insn (gen_mulhisi3_i (operands[1], operands[2]));
-  last = emit_move_insn (operands[0], gen_rtx_REG (SImode, MACL_REG));
-  /* Wrap the sequence in REG_LIBCALL / REG_RETVAL notes so that loop
-     invariant code motion can move it.  */
-  REG_NOTES (first) = gen_rtx_INSN_LIST (REG_LIBCALL, last, REG_NOTES (first));
-  REG_NOTES (last) = gen_rtx_INSN_LIST (REG_RETVAL, first, REG_NOTES (last));
+  macl = gen_rtx_REG (SImode, MACL_REG);
+  start_sequence ();
+  emit_insn (gen_mulhisi3_i (operands[1], operands[2]));
+  insn = get_insns ();  
+  end_sequence ();
   /* expand_binop can't find a suitable code in umul_widen_optab to
      make a REG_EQUAL note from, so make one here.
      See also smulsi3_highpart.
      ??? Alternatively, we could put this at the calling site of expand_binop,
      i.e. expand_expr.  */
-  REG_NOTES (last)
-    = gen_rtx_EXPR_LIST (REG_EQUAL, copy_rtx (SET_SRC (single_set (first))),
-                        REG_NOTES (last));
+  /* Use emit_libcall_block for loop invariant code motion and to make
+     a REG_EQUAL note.  */
+  emit_libcall_block (insn, operands[0], macl, SET_SRC (single_set (insn)));
+
   DONE;
 }")
 
@@ -2741,22 +2789,22 @@ label:
   "TARGET_SH1"
   "
 {
-  rtx first, last;
+  rtx insn, macl;
 
-  first = emit_insn (gen_umulhisi3_i (operands[1], operands[2]));
-  last = emit_move_insn (operands[0], gen_rtx_REG (SImode, MACL_REG));
-  /* Wrap the sequence in REG_LIBCALL / REG_RETVAL notes so that loop
-     invariant code motion can move it.  */
-  REG_NOTES (first) = gen_rtx_INSN_LIST (REG_LIBCALL, last, REG_NOTES (first));
-  REG_NOTES (last) = gen_rtx_INSN_LIST (REG_RETVAL, first, REG_NOTES (last));
+  macl = gen_rtx_REG (SImode, MACL_REG);
+  start_sequence ();
+  emit_insn (gen_umulhisi3_i (operands[1], operands[2]));
+  insn = get_insns ();  
+  end_sequence ();
   /* expand_binop can't find a suitable code in umul_widen_optab to
      make a REG_EQUAL note from, so make one here.
      See also smulsi3_highpart.
      ??? Alternatively, we could put this at the calling site of expand_binop,
      i.e. expand_expr.  */
-  REG_NOTES (last)
-    = gen_rtx_EXPR_LIST (REG_EQUAL, copy_rtx (SET_SRC (single_set (first))),
-                        REG_NOTES (last));
+  /* Use emit_libcall_block for loop invariant code motion and to make
+     a REG_EQUAL note.  */
+  emit_libcall_block (insn, operands[0], macl, SET_SRC (single_set (insn)));
+
   DONE;
 }")
 
@@ -2819,8 +2867,6 @@ label:
   "TARGET_SH1"
   "
 {
-  rtx first, last;
-
   if (!TARGET_SH2)
     {
       /* The address must be set outside the libcall,
@@ -2829,23 +2875,18 @@ label:
       rtx addr = force_reg (SImode, sym);
       rtx insns = gen_mulsi3_call (operands[0], operands[1],
                                   operands[2], addr);
-      first = insns;
-      last = emit_insn (insns);
+      emit_insn (insns);
     }
   else
     {
       rtx macl = gen_rtx_REG (SImode, MACL_REG);
 
-      first = emit_insn (gen_mul_l (operands[1], operands[2]));
+      emit_insn (gen_mul_l (operands[1], operands[2]));
       /* consec_sets_giv can only recognize the first insn that sets a
         giv as the giv insn.  So we must tag this also with a REG_EQUAL
         note.  */
-      last = emit_insn (gen_movsi_i ((operands[0]), macl));
+      emit_insn (gen_movsi_i ((operands[0]), macl));
     }
-  /* Wrap the sequence in REG_LIBCALL / REG_RETVAL notes so that loop
-     invariant code motion can move it.  */
-  REG_NOTES (first) = gen_rtx_INSN_LIST (REG_LIBCALL, last, REG_NOTES (first));
-  REG_NOTES (last) = gen_rtx_INSN_LIST (REG_RETVAL, first, REG_NOTES (last));
   DONE;
 }")
 
@@ -3020,22 +3061,22 @@ label:
   "TARGET_SH2"
   "
 {
-  rtx first, last;
+  rtx insn, mach;
 
-  first = emit_insn (gen_smulsi3_highpart_i (operands[1], operands[2]));
-  last = emit_move_insn (operands[0], gen_rtx_REG (SImode, MACH_REG));
-  /* Wrap the sequence in REG_LIBCALL / REG_RETVAL notes so that loop
-     invariant code motion can move it.  */
-  REG_NOTES (first) = gen_rtx_INSN_LIST (REG_LIBCALL, last, REG_NOTES (first));
-  REG_NOTES (last) = gen_rtx_INSN_LIST (REG_RETVAL, first, REG_NOTES (last));
+  mach = gen_rtx_REG (SImode, MACH_REG);
+  start_sequence ();
+  emit_insn (gen_smulsi3_highpart_i (operands[1], operands[2]));
+  insn = get_insns ();  
+  end_sequence ();
   /* expand_binop can't find a suitable code in mul_highpart_optab to
      make a REG_EQUAL note from, so make one here.
      See also {,u}mulhisi.
      ??? Alternatively, we could put this at the calling site of expand_binop,
      i.e. expand_mult_highpart.  */
-  REG_NOTES (last)
-    = gen_rtx_EXPR_LIST (REG_EQUAL, copy_rtx (SET_SRC (single_set (first))),
-                        REG_NOTES (last));
+  /* Use emit_libcall_block for loop invariant code motion and to make
+     a REG_EQUAL note.  */
+  emit_libcall_block (insn, operands[0], mach, SET_SRC (single_set (insn)));
+
   DONE;
 }")
 
@@ -3067,14 +3108,17 @@ label:
   "TARGET_SH2"
   "
 {
-  rtx first, last;
+  rtx insn, mach;
+
+  mach = gen_rtx_REG (SImode, MACH_REG);
+  start_sequence ();
+  emit_insn (gen_umulsi3_highpart_i (operands[1], operands[2]));
+  insn = get_insns ();  
+  end_sequence ();
+  /* Use emit_libcall_block for loop invariant code motion and to make
+     a REG_EQUAL note.  */
+  emit_libcall_block (insn, operands[0], mach, SET_SRC (single_set (insn)));
 
-  first = emit_insn (gen_umulsi3_highpart_i (operands[1], operands[2]));
-  last = emit_move_insn (operands[0], gen_rtx_REG (SImode, MACH_REG));
-  /* Wrap the sequence in REG_LIBCALL / REG_RETVAL notes so that loop
-     invariant code motion can move it.  */
-  REG_NOTES (first) = gen_rtx_INSN_LIST (REG_LIBCALL, last, REG_NOTES (first));
-  REG_NOTES (last) = gen_rtx_INSN_LIST (REG_RETVAL, first, REG_NOTES (last));
   DONE;
 }")
 
@@ -3141,6 +3185,14 @@ label:
        andi    %1, %2, %0"
   [(set_attr "type" "arith_media")])
 
+(define_insn "*andsi3_bclr"
+  [(set (match_operand:SI 0 "arith_reg_dest" "=r")
+       (and:SI (match_operand:SI 1 "arith_reg_operand" "%0")
+               (match_operand:SI 2 "const_int_operand" "Psz")))]
+  "TARGET_SH2A && satisfies_constraint_Psz (operands[2])"
+  "bclr\\t%W2,%0"
+  [(set_attr "type" "arith")])
+
 ;; If the constant is 255, then emit an extu.b instruction instead of an
 ;; and, since that will give better code.
 
@@ -3209,7 +3261,8 @@ label:
   [(set (match_operand:SI 0 "arith_reg_dest" "=r,z")
        (ior:SI (match_operand:SI 1 "arith_reg_operand" "%0,0")
                (match_operand:SI 2 "logical_operand" "r,K08")))]
-  "TARGET_SH1"
+  "TARGET_SH1
+   && !(TARGET_SH2A && satisfies_constraint_Pso (operands[2]))"
   "or  %2,%0"
   [(set_attr "type" "arith")])
 
@@ -3223,6 +3276,14 @@ label:
        ori     %1, %2, %0"
   [(set_attr "type" "arith_media")])
 
+(define_insn "*iorsi3_bset"
+  [(set (match_operand:SI 0 "arith_reg_dest" "=r")
+       (ior:SI (match_operand:SI 1 "arith_reg_operand" "%0")
+       (match_operand:SI 2 "const_int_operand" "Pso")))]
+  "TARGET_SH2A && satisfies_constraint_Pso (operands[2])"
+  "bset\\t%V2,%0"
+  [(set_attr "type" "arith")])
+
 (define_insn "iordi3"
   [(set (match_operand:DI 0 "arith_reg_dest" "=r,r")
        (ior:DI (match_operand:DI 1 "arith_reg_operand" "%r,r")
@@ -3297,6 +3358,15 @@ label:
        xori    %1, %2, %0"
   [(set_attr "type" "arith_media")])
 
+;; Store the complements of the T bit in a register.
+(define_insn "xorsi3_movrt"
+  [(set (match_operand:SI 0 "arith_reg_dest" "=r")
+       (xor:SI (reg:SI T_REG)
+               (const_int 1)))]
+  "TARGET_SH2A"
+  "movrt\\t%0"
+  [(set_attr "type" "arith")])
+
 (define_insn "xordi3"
   [(set (match_operand:DI 0 "arith_reg_dest" "=r,r")
        (xor:DI (match_operand:DI 1 "arith_reg_operand" "%r,r")
@@ -3520,8 +3590,7 @@ label:
                   (match_operand:SI 2 "nonmemory_operand" "r,M,P27,?ri")))
    (clobber (match_scratch:SI 3 "=X,X,X,&r"))]
   "TARGET_SH3
-   || (TARGET_SH1 && GET_CODE (operands[2]) == CONST_INT
-       && CONST_OK_FOR_P27 (INTVAL (operands[2])))"
+   || (TARGET_SH1 && satisfies_constraint_P27 (operands[2]))"
   "@
    shld        %2,%0
    add %0,%0
@@ -3530,7 +3599,7 @@ label:
   "TARGET_SH3
    && reload_completed
    && GET_CODE (operands[2]) == CONST_INT
-   && ! CONST_OK_FOR_P27 (INTVAL (operands[2]))"
+   && ! satisfies_constraint_P27 (operands[2])"
   [(set (match_dup 3) (match_dup 2))
    (parallel
     [(set (match_dup 0) (ashift:SI (match_dup 1) (match_dup 3)))
@@ -3543,7 +3612,7 @@ label:
   [(set (match_operand:HI 0 "arith_reg_dest" "=r,r")
        (ashift:HI (match_operand:HI 1 "arith_reg_operand" "0,0")
                   (match_operand:HI 2 "const_int_operand" "M,P27")))]
-  "TARGET_SH1 && CONST_OK_FOR_P27 (INTVAL (operands[2]))"
+  "TARGET_SH1 && satisfies_constraint_P27 (operands[2])"
   "@
        add     %0,%0
        shll%O2 %0"
@@ -3727,7 +3796,7 @@ label:
   "
 {
   emit_insn (gen_ashlsi_c (operands[0], operands[1]));
-  emit_insn (gen_mov_neg_si_t (operands[0]));
+  emit_insn (gen_mov_neg_si_t (copy_rtx (operands[0])));
   DONE;
 }")
 
@@ -3838,7 +3907,7 @@ label:
        (lshiftrt:SI (match_operand:SI 1 "arith_reg_operand" "0")
                     (match_operand:SI 2 "const_int_operand" "M")))
    (clobber (reg:SI T_REG))]
-  "TARGET_SH1 && CONST_OK_FOR_M (INTVAL (operands[2]))"
+  "TARGET_SH1 && satisfies_constraint_M (operands[2])"
   "shlr        %0"
   [(set_attr "type" "arith")])
 
@@ -3846,8 +3915,8 @@ label:
   [(set (match_operand:SI 0 "arith_reg_dest" "=r")
        (lshiftrt:SI (match_operand:SI 1 "arith_reg_operand" "0")
                     (match_operand:SI 2 "const_int_operand" "P27")))]
-  "TARGET_SH1 && CONST_OK_FOR_P27 (INTVAL (operands[2]))
-   && ! CONST_OK_FOR_M (INTVAL (operands[2]))"
+  "TARGET_SH1 && satisfies_constraint_P27 (operands[2])
+   && ! satisfies_constraint_M (operands[2])"
   "shlr%O2     %0"
   [(set_attr "type" "arith")])
 
@@ -4670,7 +4739,12 @@ label:
   "@
        exts.b  %1,%0
        mov.b   %1,%0"
-  [(set_attr "type" "arith,load")])
+  [(set_attr "type" "arith,load")
+   (set_attr_alternative "length"
+     [(const_int 2)
+       (if_then_else
+       (ne (symbol_ref "TARGET_SH2A") (const_int 0))
+       (const_int 4) (const_int 2))])])
 
 (define_insn "*extendqisi2_media"
   [(set (match_operand:SI 0 "register_operand" "=r,r")
@@ -4708,7 +4782,12 @@ label:
   "@
        exts.b  %1,%0
        mov.b   %1,%0"
-  [(set_attr "type" "arith,load")])
+  [(set_attr "type" "arith,load")
+   (set_attr_alternative "length"
+     [(const_int 2)
+       (if_then_else
+       (ne (symbol_ref "TARGET_SH2A") (const_int 0))
+       (const_int 4) (const_int 2))])])
 
 /* It would seem useful to combine the truncXi patterns into the movXi
    patterns, but unary operators are ignored when matching constraints,
@@ -4746,7 +4825,7 @@ label:
 
 ; N.B. This should agree with LOAD_EXTEND_OP and movqi.
 ; Because we use zero extension, we can't provide signed QImode compares
-; using a simple compare or conditional banch insn.
+; using a simple compare or conditional branch insn.
 (define_insn "truncdiqi2"
   [(set (match_operand:QI 0 "general_movdst_operand" "=r,m")
        (truncate:QI (match_operand:DI 1 "register_operand" "r,r")))]
@@ -4791,7 +4870,7 @@ label:
   [(set (mem:SF (pre_dec:SI (reg:SI SP_REG))) (reg:SF FPUL_REG))]
   "TARGET_SH2E && ! TARGET_SH5"
   "sts.l       fpul,@-r15"
-  [(set_attr "type" "store")
+  [(set_attr "type" "fstore")
    (set_attr "late_fp_use" "yes")
    (set_attr "hit_stack" "yes")])
 
@@ -4837,7 +4916,7 @@ label:
                                                 gen_rtx_PRE_DEC (Pmode,
                                                          stack_pointer_rtx)),
                                        get_fpscr_rtx ()));
-  REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_INC, stack_pointer_rtx, NULL_RTX);
+  add_reg_note (insn, REG_INC, stack_pointer_rtx);
   DONE;
 }")
 
@@ -4850,7 +4929,7 @@ label:
                                        gen_frame_mem (PSImode,
                                                 gen_rtx_POST_INC (Pmode,
                                                          stack_pointer_rtx))));
-  REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_INC, stack_pointer_rtx, NULL_RTX);
+  add_reg_note (insn, REG_INC, stack_pointer_rtx);
   DONE;
 }")
 
@@ -4873,9 +4952,9 @@ label:
 ;; (made from (set (subreg:SI (reg:QI ###) 0) ) into T.
 (define_insn "movsi_i"
   [(set (match_operand:SI 0 "general_movdst_operand"
-           "=r,r,t,r,r,r,r,m,<,<,x,l,x,l,r")
+           "=r,r,r,t,r,r,r,r,m,<,<,x,l,x,l,r")
        (match_operand:SI 1 "general_movsrc_operand"
-        "Q,rI08,r,mr,x,l,t,r,x,l,r,r,>,>,i"))]
+        "Q,r,I08,r,mr,x,l,t,r,x,l,r,r,>,>,i"))]
   "TARGET_SH1
    && ! TARGET_SH2E
    && ! TARGET_SH2A
@@ -4884,6 +4963,7 @@ label:
   "@
        mov.l   %1,%0
        mov     %1,%0
+       mov     %1,%0
        cmp/pl  %1
        mov.l   %1,%0
        sts     %1,%0
@@ -4897,8 +4977,8 @@ label:
        lds.l   %1,%0
        lds.l   %1,%0
        fake    %1,%0"
-  [(set_attr "type" "pcload_si,move,mt_group,load_si,mac_gp,prget,move,store,store,pstore,move,prset,load,pload,pcload_si")
-   (set_attr "length" "*,*,*,*,*,*,*,*,*,*,*,*,*,*,*")])
+  [(set_attr "type" "pcload_si,move,movi8,mt_group,load_si,mac_gp,prget,arith,store,mac_mem,pstore,gp_mac,prset,mem_mac,pload,pcload_si")
+   (set_attr "length" "*,*,*,*,*,*,*,*,*,*,*,*,*,*,*,*")])
 
 ;; t/r must come after r/r, lest reload will try to reload stuff like
 ;; (subreg:SI (reg:SF FR14_REG) 0) into T (compiling stdlib/strtod.c -m3e -O2)
@@ -4908,16 +4988,18 @@ label:
 ;; TARGET_FMOVD is in effect, and mode switching is done before reload.
 (define_insn "movsi_ie"
   [(set (match_operand:SI 0 "general_movdst_operand"
-           "=r,r,r,t,r,r,r,r,m,<,<,x,l,x,l,y,<,r,y,r,*f,y,*f,y")
+           "=r,r,r,r,r,t,r,r,r,r,m,<,<,x,l,x,l,y,<,r,y,r,*f,y,*f,y")
        (match_operand:SI 1 "general_movsrc_operand"
-        "Q,rI08,I20,r,mr,x,l,t,r,x,l,r,r,>,>,>,y,i,r,y,y,*f,*f,y"))]
+        "Q,r,I08,I20,I28,r,mr,x,l,t,r,x,l,r,r,>,>,>,y,i,r,y,y,*f,*f,y"))]
   "(TARGET_SH2E || TARGET_SH2A)
    && (register_operand (operands[0], SImode)
        || register_operand (operands[1], SImode))"
   "@
        mov.l   %1,%0
        mov     %1,%0
+       mov     %1,%0
        movi20  %1,%0
+       movi20s %1,%0
        cmp/pl  %1
        mov.l   %1,%0
        sts     %1,%0
@@ -4939,26 +5021,57 @@ label:
        flds    %1,fpul
        fmov    %1,%0
        ! move optimized away"
-  [(set_attr "type" "pcload_si,move,move,*,load_si,mac_gp,prget,move,store,store,pstore,move,prset,load,pload,load,store,pcload_si,gp_fpul,fpul_gp,fmove,fmove,fmove,nil")
-   (set_attr "late_fp_use" "*,*,*,*,*,*,*,*,*,*,*,*,*,*,*,*,yes,*,*,yes,*,*,*,*")
-   (set_attr "length" "*,*,4,*,4,*,*,*,4,*,*,*,*,*,*,*,*,*,*,*,*,*,*,0")])
+  [(set_attr "type" "pcload_si,move,movi8,move,move,*,load_si,mac_gp,prget,arith,store,mac_mem,pstore,gp_mac,prset,mem_mac,pload,load,fstore,pcload_si,gp_fpul,fpul_gp,fmove,fmove,fmove,nil")
+   (set_attr "late_fp_use" "*,*,*,*,*,*,*,*,*,*,*,*,*,*,*,*,*,*,yes,*,*,yes,*,*,*,*")
+   (set_attr_alternative "length"
+     [(const_int 2)
+      (const_int 2)
+      (const_int 2)
+      (const_int 4)
+      (const_int 4)
+      (const_int 2)
+      (if_then_else
+       (ne (symbol_ref "TARGET_SH2A") (const_int 0))
+       (const_int 4) (const_int 2))
+      (const_int 2)
+      (const_int 2)
+      (const_int 2)
+      (if_then_else
+       (ne (symbol_ref "TARGET_SH2A") (const_int 0))
+       (const_int 4) (const_int 2))
+      (const_int 2)
+      (const_int 2)
+      (const_int 2)
+      (const_int 2)
+      (const_int 2)
+      (const_int 2)
+      (const_int 2)
+      (const_int 2)
+      (const_int 2)
+      (const_int 2)
+      (const_int 2)
+      (const_int 2)
+      (const_int 2)
+      (const_int 2)
+      (const_int 0)])])
 
 (define_insn "movsi_i_lowpart"
-  [(set (strict_low_part (match_operand:SI 0 "general_movdst_operand" "+r,r,r,r,r,r,m,r"))
-       (match_operand:SI 1 "general_movsrc_operand" "Q,rI08,mr,x,l,t,r,i"))]
+  [(set (strict_low_part (match_operand:SI 0 "general_movdst_operand" "+r,r,r,r,r,r,r,m,r"))
+       (match_operand:SI 1 "general_movsrc_operand" "Q,r,I08,mr,x,l,t,r,i"))]
    "TARGET_SH1
     && (register_operand (operands[0], SImode)
         || register_operand (operands[1], SImode))"
   "@
        mov.l   %1,%0
        mov     %1,%0
+       mov     %1,%0
        mov.l   %1,%0
        sts     %1,%0
        sts     %1,%0
        movt    %0
        mov.l   %1,%0
        fake    %1,%0"
-  [(set_attr "type" "pcload,move,load,move,prget,move,store,pcload")])
+  [(set_attr "type" "pcload,move,arith,load,mac_gp,prget,arith,store,pcload")])
 
 (define_insn_and_split "load_ra"
   [(set (match_operand:SI 0 "general_movdst_operand" "")
@@ -4969,7 +5082,7 @@ label:
   [(set (match_dup 0) (match_dup 1))]
   "
 {
-  if (TARGET_SHCOMPACT && current_function_has_nonlocal_label)
+  if (TARGET_SHCOMPACT && crtl->saves_all_registers)
     operands[1] = gen_frame_mem (SImode, return_address_pointer_rtx);
 }")
 
@@ -5033,16 +5146,12 @@ label:
 
 (define_expand "movsi_const"
   [(set (match_operand:SI 0 "arith_reg_operand" "=r")
-       (const:SI (sign_extend:SI
-                  (truncate:HI
-                   (ashiftrt:SI
-                    (match_operand:DI 1 "immediate_operand" "s")
-                    (const_int 16))))))
+       (const:SI (unspec:SI [(match_operand:DI 1 "immediate_operand" "s")
+                             (const_int 16)] UNSPEC_EXTRACT_S16)))
    (set (match_dup 0)
        (ior:SI (ashift:SI (match_dup 0) (const_int 16))
-               (const:SI
-                 (zero_extend:SI
-                  (truncate:HI (match_dup 1))))))]
+               (const:SI (unspec:SI [(match_dup 1)
+                                     (const_int 0)] UNSPEC_EXTRACT_U16))))]
   "TARGET_SHMEDIA && reload_completed
    && MOVI_SHORI_BASE_OPERAND_P (operands[1])"
   "
@@ -5068,9 +5177,8 @@ label:
 
 (define_expand "movsi_const_16bit"
   [(set (match_operand:SI 0 "arith_reg_operand" "=r")
-       (const:SI (sign_extend:SI
-                  (truncate:HI
-                   (match_operand:DI 1 "immediate_operand" "s")))))]
+       (const:SI (unspec:SI [(match_operand:DI 1 "immediate_operand" "s")
+                             (const_int 0)] UNSPEC_EXTRACT_S16)))]
   "TARGET_SHMEDIA && flag_pic && reload_completed
    && GET_CODE (operands[1]) == SYMBOL_REF"
   "")
@@ -5085,8 +5193,7 @@ label:
 {
   rtx insn = emit_insn (gen_movsi_const (operands[0], operands[1]));
 
-  REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_EQUAL, operands[1],
-                                       REG_NOTES (insn));
+  set_unique_reg_note (insn, REG_EQUAL, copy_rtx (operands[1]));
 
   DONE;
 }")
@@ -5096,7 +5203,7 @@ label:
        (match_operand:SI 1 "immediate_operand" ""))]
   "TARGET_SHMEDIA && reload_completed
    && ((GET_CODE (operands[1]) == CONST_INT
-       && ! CONST_OK_FOR_I16 (INTVAL (operands[1])))
+       && ! satisfies_constraint_I16 (operands[1]))
        || GET_CODE (operands[1]) == CONST_DOUBLE)"
   [(set (subreg:DI (match_dup 0) 0) (match_dup 1))])
 
@@ -5125,7 +5232,7 @@ label:
       emit_insn (gen_ic_invalidate_line_compact (operands[0], operands[1]));
       DONE;
     }
-  else if (TARGET_SH4A_ARCH)
+  else if (TARGET_SH4A_ARCH || TARGET_SH4_300)
     {
       emit_insn (gen_ic_invalidate_line_sh4a (operands[0]));
       DONE;
@@ -5153,7 +5260,7 @@ label:
 (define_insn "ic_invalidate_line_sh4a"
   [(unspec_volatile [(match_operand:SI 0 "register_operand" "r")]
                    UNSPEC_ICACHE)]
-  "TARGET_SH4A_ARCH"
+  "TARGET_SH4A_ARCH || TARGET_SH4_300"
   "ocbwb\\t@%0\;synco\;icbi\\t@%0"
   [(set_attr "length" "16")
    (set_attr "type" "cwb")])
@@ -5210,19 +5317,32 @@ label:
    (set_attr "needs_delay_slot" "yes")])
 
 (define_insn "movqi_i"
-  [(set (match_operand:QI 0 "general_movdst_operand" "=r,r,m,r,r,l")
-       (match_operand:QI 1 "general_movsrc_operand"  "ri,m,r,t,l,r"))]
+  [(set (match_operand:QI 0 "general_movdst_operand" "=r,r,r,m,r,r,l")
+       (match_operand:QI 1 "general_movsrc_operand"  "r,i,m,r,t,l,r"))]
   "TARGET_SH1
    && (arith_reg_operand (operands[0], QImode)
        || arith_reg_operand (operands[1], QImode))"
   "@
        mov     %1,%0
+       mov     %1,%0
        mov.b   %1,%0
        mov.b   %1,%0
        movt    %0
        sts     %1,%0
        lds     %1,%0"
- [(set_attr "type" "move,load,store,move,move,move")])
+ [(set_attr "type" "move,movi8,load,store,arith,prget,prset")
+  (set_attr_alternative "length"
+     [(const_int 2)
+      (const_int 2)
+      (if_then_else
+       (ne (symbol_ref "TARGET_SH2A") (const_int 0))
+       (const_int 4) (const_int 2))
+      (if_then_else
+       (ne (symbol_ref "TARGET_SH2A") (const_int 0))
+       (const_int 4) (const_int 2))
+      (const_int 2)
+      (const_int 2)
+      (const_int 2)])])
 
 (define_insn "*movqi_media"
   [(set (match_operand:QI 0 "general_movdst_operand" "=r,r,r,m")
@@ -5307,7 +5427,7 @@ label:
   [(set (match_operand:HI 0 "register_operand" "")
        (match_operand:HI 1 "immediate_operand" ""))]
   "TARGET_SHMEDIA && reload_completed
-   && ! CONST_OK_FOR_I16 (INTVAL (operands[1]))"
+   && ! satisfies_constraint_I16 (operands[1])"
   [(set (subreg:DI (match_dup 0) 0) (match_dup 1))])
 
 (define_expand "movhi"
@@ -5468,41 +5588,27 @@ label:
   else
     insn = emit_insn (gen_movdi_const_32bit (operands[0], operands[1]));
 
-  REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_EQUAL, operands[1],
-                                       REG_NOTES (insn));
+  set_unique_reg_note (insn, REG_EQUAL, copy_rtx (operands[1]));
 
   DONE;
 }")
 
 (define_expand "movdi_const"
   [(set (match_operand:DI 0 "arith_reg_operand" "=r")
-       (const:DI (sign_extend:DI
-                  (truncate:HI
-                   (ashiftrt:DI
-                    (match_operand:DI 1 "immediate_operand" "s")
-                    (const_int 48))))))
+       (const:DI (unspec:DI [(match_operand:DI 1 "immediate_operand" "s")
+                             (const_int 48)] UNSPEC_EXTRACT_S16)))
    (set (match_dup 0)
        (ior:DI (ashift:DI (match_dup 0) (const_int 16))
-               (const:DI
-                (zero_extend:DI
-                 (truncate:HI
-                  (ashiftrt:SI
-                   (match_dup 1)
-                   (const_int 32)))))))
+               (const:DI (unspec:DI [(match_dup 1)
+                                     (const_int 32)] UNSPEC_EXTRACT_U16))))
    (set (match_dup 0)
        (ior:DI (ashift:DI (match_dup 0) (const_int 16))
-               (const:DI
-                (zero_extend:DI
-                 (truncate:HI
-                  (ashiftrt:SI
-                   (match_dup 1)
-                   (const_int 16)))))))
+               (const:DI (unspec:DI [(match_dup 1)
+                                     (const_int 16)] UNSPEC_EXTRACT_U16))))
    (set (match_dup 0)
        (ior:DI (ashift:DI (match_dup 0) (const_int 16))
-               (const:DI
-                (zero_extend:DI
-                 (truncate:HI
-                  (match_dup 1))))))]
+               (const:DI (unspec:DI [(match_dup 1)
+                                     (const_int 0)] UNSPEC_EXTRACT_U16))))]
   "TARGET_SHMEDIA64 && reload_completed
    && MOVI_SHORI_BASE_OPERAND_P (operands[1])"
   "
@@ -5512,17 +5618,12 @@ label:
 
 (define_expand "movdi_const_32bit"
   [(set (match_operand:DI 0 "arith_reg_operand" "=r")
-       (const:DI (sign_extend:DI
-                  (truncate:HI
-                   (ashiftrt:DI
-                    (match_operand:DI 1 "immediate_operand" "s")
-                    (const_int 16))))))
+       (const:DI (unspec:DI [(match_operand:DI 1 "immediate_operand" "s")
+                             (const_int 16)] UNSPEC_EXTRACT_S16)))
    (set (match_dup 0)
        (ior:DI (ashift:DI (match_dup 0) (const_int 16))
-               (const:DI
-                (zero_extend:DI
-                 (truncate:HI
-                  (match_dup 1))))))]
+               (const:DI (unspec:DI [(match_dup 1)
+                                     (const_int 0)] UNSPEC_EXTRACT_U16))))]
   "TARGET_SHMEDIA32 && reload_completed
    && MOVI_SHORI_BASE_OPERAND_P (operands[1])"
   "
@@ -5532,9 +5633,8 @@ label:
 
 (define_expand "movdi_const_16bit"
   [(set (match_operand:DI 0 "arith_reg_operand" "=r")
-       (const:DI (sign_extend:DI
-                  (truncate:HI
-                   (match_operand:DI 1 "immediate_operand" "s")))))]
+       (const:DI (unspec:DI [(match_operand:DI 1 "immediate_operand" "s")
+                             (const_int 0)] UNSPEC_EXTRACT_S16)))]
   "TARGET_SHMEDIA && flag_pic && reload_completed
    && GET_CODE (operands[1]) == SYMBOL_REF"
   "")
@@ -5544,7 +5644,7 @@ label:
        (match_operand:DI 1 "immediate_operand" ""))]
   "TARGET_SHMEDIA && reload_completed
    && GET_CODE (operands[1]) == CONST_INT
-   && ! CONST_OK_FOR_I16 (INTVAL (operands[1]))"
+   && ! satisfies_constraint_I16 (operands[1])"
   [(set (match_dup 0) (match_dup 2))
    (match_dup 1)]
   "
@@ -5824,7 +5924,7 @@ label:
       (if_then_else
        (ne (symbol_ref "TARGET_SHCOMPACT") (const_int 0))
        (const_int 10) (const_int 8))])
-   (set_attr "type" "fmove,move,pcfload,fload,store,pcload,load,store,load,fload")
+   (set_attr "type" "fmove,move,pcfload,fload,fstore,pcload,load,store,load,fload")
    (set_attr "late_fp_use" "*,*,*,*,yes,*,*,*,*,*")
    (set (attr "fp_mode") (if_then_else (eq_attr "fmovd" "yes")
                                           (const_string "double")
@@ -5860,7 +5960,7 @@ label:
                             gen_rtx_PRE_DEC (Pmode, stack_pointer_rtx));
   insn = emit_insn (gen_movdf_i4 (tos, operands[1], operands[2]));
   if (! (TARGET_SH5 && true_regnum (operands[1]) < 16))
-    REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_INC, stack_pointer_rtx, NULL_RTX);
+    add_reg_note (insn, REG_INC, stack_pointer_rtx);
   if (TARGET_SH5 && true_regnum (operands[0]) < 16)
     tos = gen_tmp_stack_mem (DFmode, stack_pointer_rtx);
   else
@@ -5870,7 +5970,7 @@ label:
   if (TARGET_SH5 && true_regnum (operands[0]) < 16)
     emit_move_insn (stack_pointer_rtx, plus_constant (stack_pointer_rtx, 8));
   else
-    REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_INC, stack_pointer_rtx, NULL_RTX);
+    add_reg_note (insn, REG_INC, stack_pointer_rtx);
   DONE;
 }")
 
@@ -6027,7 +6127,7 @@ label:
   insn = emit_insn (gen_movsf_ie (gen_rtx_REG (SFmode,
                                           regno + !! TARGET_LITTLE_ENDIAN),
                                  mem2, operands[2]));
-  REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_INC, operands[1], NULL_RTX);
+  add_reg_note (insn, REG_INC, operands[1]);
   insn = emit_insn (gen_movsf_ie (gen_rtx_REG (SFmode,
                                               regno + ! TARGET_LITTLE_ENDIAN),
                                  change_address (mem, SFmode, NULL_RTX),
@@ -6066,12 +6166,12 @@ label:
     }
   addr = XEXP (addr, 0);
   insn = emit_insn (gen_movsf_ie (reg0, mem2, operands[2]));
-  REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_INC, addr, NULL_RTX);
+  add_reg_note (insn, REG_INC, addr);
   insn = emit_insn (gen_movsf_ie (reg1, operands[1], operands[2]));
   if (adjust)
     emit_insn (adjust);
   else
-    REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_INC, addr, NULL_RTX);
+    add_reg_note (insn, REG_INC, addr);
   DONE;
 }")
 
@@ -6104,12 +6204,12 @@ label:
     }
   addr = XEXP (addr, 0);
   if (! adjust)
-    REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_INC, addr, NULL_RTX);
+    add_reg_note (insn, REG_INC, addr);
   insn = emit_insn (gen_movsf_ie (operands[0],
                                  gen_rtx_REG (SFmode,
                                           regno + !! TARGET_LITTLE_ENDIAN),
                                  operands[2]));
-  REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_INC, addr, NULL_RTX);
+  add_reg_note (insn, REG_INC, addr);
   DONE;
 }")
 
@@ -6541,9 +6641,36 @@ label:
        sts.l   %1,%0
        lds.l   %1,%0
        ! move optimized away"
-  [(set_attr "type" "fmove,move,fmove,fmove,pcfload,fload,store,pcload,load,store,fmove,fmove,load,*,fpul_gp,gp_fpul,store,load,nil")
+  [(set_attr "type" "fmove,move,fmove,fmove,pcfload,fload,fstore,pcload,load,store,fmove,fmove,load,*,fpul_gp,gp_fpul,fstore,load,nil")
    (set_attr "late_fp_use" "*,*,*,*,*,*,yes,*,*,*,*,*,*,*,yes,*,yes,*,*")
-   (set_attr "length" "*,*,*,*,4,4,4,*,*,*,2,2,2,4,2,2,2,2,0")
+   (set_attr_alternative "length"
+     [(const_int 2)
+      (const_int 2)
+      (const_int 2)
+      (const_int 2)
+      (const_int 4)
+      (if_then_else
+       (ne (symbol_ref "TARGET_SH2A") (const_int 0))
+       (const_int 4) (const_int 2))
+      (if_then_else
+       (ne (symbol_ref "TARGET_SH2A") (const_int 0))
+       (const_int 4) (const_int 2))
+      (const_int 2)
+      (if_then_else
+       (ne (symbol_ref "TARGET_SH2A") (const_int 0))
+       (const_int 4) (const_int 2))
+      (if_then_else
+       (ne (symbol_ref "TARGET_SH2A") (const_int 0))
+       (const_int 4) (const_int 2))
+      (const_int 2)
+      (const_int 2)
+      (const_int 2)
+      (const_int 4)
+      (const_int 2)
+      (const_int 2)
+      (const_int 2)
+      (const_int 2)
+      (const_int 0)])
    (set (attr "fp_mode") (if_then_else (eq_attr "fmovd" "yes")
                                           (const_string "single")
                                           (const_string "none")))])
@@ -6899,8 +7026,7 @@ label:
 
       sh_compare_op0 = force_reg (mode, sh_compare_op0);
       if (CONSTANT_P (sh_compare_op1)
-         && (GET_CODE (sh_compare_op1) != CONST_INT
-             || ! CONST_OK_FOR_I06 (INTVAL (sh_compare_op1))))
+         && (! satisfies_constraint_I06 (sh_compare_op1)))
        sh_compare_op1 = force_reg (mode, sh_compare_op1);
       emit_jump_insn (gen_beq_media (operands[0],
                                     sh_compare_op0, sh_compare_op1));
@@ -6933,8 +7059,7 @@ label:
 
       sh_compare_op0 = force_reg (mode, sh_compare_op0);
       if (CONSTANT_P (sh_compare_op1)
-         && (GET_CODE (sh_compare_op1) != CONST_INT
-             || ! CONST_OK_FOR_I06 (INTVAL (sh_compare_op1))))
+         && (! satisfies_constraint_I06 (sh_compare_op1)))
        sh_compare_op1 = force_reg (mode, sh_compare_op1);
       emit_jump_insn (gen_bne_media (operands[0],
                                     sh_compare_op0, sh_compare_op1));
@@ -7201,7 +7326,7 @@ label:
 }")
 
 (define_expand "bunordered"
-  [(set (match_dup 1) (unordered:DI (match_dup 2) (match_dup 3)))
+  [(set (match_dup 1) (unordered:SI (match_dup 2) (match_dup 3)))
    (set (pc)
        (if_then_else (ne (match_dup 1) (const_int 0))
                      (match_operand 0 "" "")
@@ -7210,7 +7335,7 @@ label:
   "
 {
   operands[0] = gen_rtx_LABEL_REF (Pmode, operands[0]);
-  operands[1] = gen_reg_rtx (DImode);
+  operands[1] = gen_reg_rtx (SImode);
   operands[2] = force_reg (GET_MODE (sh_compare_op0), sh_compare_op0);
   operands[3] = force_reg (GET_MODE (sh_compare_op1), sh_compare_op1);
 }")
@@ -7243,6 +7368,52 @@ label:
                 ? gen_rtx_GE (VOIDmode, operands[4], const0_rtx)
                 : gen_rtx_GT (VOIDmode, const0_rtx, operands[4]));
 }")
+
+; operand 0 is the loop count pseudo register
+; operand 1 is the number of loop iterations or 0 if it is unknown
+; operand 2 is the maximum number of loop iterations
+; operand 3 is the number of levels of enclosed loops
+; operand 4 is the label to jump to at the top of the loop
+
+(define_expand "doloop_end"
+  [(parallel [(set (pc) (if_then_else
+                         (ne:SI (match_operand:SI 0 "" "")
+                             (const_int 1))
+                         (label_ref (match_operand 4 "" ""))
+                         (pc)))
+             (set (match_dup 0)
+                  (plus:SI (match_dup 0) (const_int -1)))
+             (clobber (reg:SI T_REG))])]
+  "TARGET_SH2"
+  "
+{
+  if (GET_MODE (operands[0]) != SImode)
+    FAIL;
+}
+")
+
+(define_insn_and_split "doloop_end_split"
+  [(set (pc)
+       (if_then_else (ne:SI (match_operand:SI 0 "arith_reg_dest" "+r")
+                         (const_int 1))
+                     (label_ref (match_operand 1 "" ""))
+                     (pc)))
+   (set (match_dup 0)
+       (plus (match_dup 0) (const_int -1)))
+   (clobber (reg:SI T_REG))]
+  "TARGET_SH2"
+  "#"
+  ""
+  [(parallel [(set (reg:SI T_REG)
+                  (eq:SI (match_operand:SI 0 "arith_reg_dest" "+r")
+                         (const_int 1)))
+             (set (match_dup 0) (plus:SI (match_dup 0) (const_int -1)))])
+   (set (pc) (if_then_else (eq (reg:SI T_REG) (const_int 0))
+                          (label_ref (match_operand 1 "" ""))
+                          (pc)))]
+""
+   [(set_attr "type" "cbranch")])
+
 \f
 ;; ------------------------------------------------------------------------
 ;; Jump and linkage insns
@@ -7251,7 +7422,7 @@ label:
 (define_insn "jump_compact"
   [(set (pc)
        (label_ref (match_operand 0 "" "")))]
-  "TARGET_SH1"
+  "TARGET_SH1 && !find_reg_note (insn, REG_CROSSING_JUMP, NULL_RTX)"
   "*
 {
   /* The length is 16 if the delay slot is unfilled.  */
@@ -7316,7 +7487,14 @@ label:
    (use (reg:PSI FPSCR_REG))
    (clobber (reg:SI PR_REG))]
   "TARGET_SH1"
-  "jsr @%0%#"
+  "*
+   {
+     if (TARGET_SH2A && (dbr_sequence_length () == 0))
+       return \"jsr/n\\t@%0\";
+     else
+       return \"jsr\\t@%0%#\";
+   }"
+
   [(set_attr "type" "call")
    (set (attr "fp_mode")
        (if_then_else (eq_attr "fpu_single" "yes")
@@ -7324,6 +7502,31 @@ label:
    (set_attr "needs_delay_slot" "yes")
    (set_attr "fp_set" "unknown")])
 
+;; This is TBR relative jump instruction for SH2A architecture.
+;; Its use is enabled assigning an attribute "function_vector"
+;; and the vector number to a function during its declaration.
+
+(define_insn "calli_tbr_rel"
+  [(call (mem (match_operand:SI 0 "symbol_ref_operand" ""))
+        (match_operand 1 "" ""))
+   (use (reg:PSI FPSCR_REG))
+   (clobber (reg:SI PR_REG))]
+  "TARGET_SH2A && sh2a_is_function_vector_call (operands[0])"
+  "*
+{
+  unsigned HOST_WIDE_INT vect_num;
+  vect_num = sh2a_get_function_vector_number (operands[0]);
+  operands[2] = GEN_INT (vect_num * 4);
+
+  return \"jsr/n\\t@@(%O2,tbr)\";
+}"
+  [(set_attr "type" "call")
+   (set (attr "fp_mode")
+       (if_then_else (eq_attr "fpu_single" "yes")
+                     (const_string "single") (const_string "double")))
+   (set_attr "needs_delay_slot" "no")
+   (set_attr "fp_set" "unknown")])
+
 ;; This is a pc-rel call, using bsrf, for use with PIC.
 
 (define_insn "calli_pcrel"
@@ -7361,7 +7564,7 @@ label:
     emit_insn (gen_sym_label2reg (operands[2], operands[0], lab));
   else
     emit_insn (gen_symPLT_label2reg (operands[2], operands[0], lab));
-  emit_call_insn (gen_calli_pcrel (operands[2], operands[1], lab));
+  emit_call_insn (gen_calli_pcrel (operands[2], operands[1], copy_rtx (lab)));
   DONE;
 }"
   [(set_attr "type" "call")
@@ -7419,7 +7622,13 @@ label:
    (use (reg:PSI FPSCR_REG))
    (clobber (reg:SI PR_REG))]
   "TARGET_SH1"
-  "jsr @%1%#"
+  "*
+   {
+     if (TARGET_SH2A && (dbr_sequence_length () == 0))
+       return \"jsr/n\\t@%1\";
+     else
+       return \"jsr\\t@%1%#\";
+   }"
   [(set_attr "type" "call")
    (set (attr "fp_mode")
        (if_then_else (eq_attr "fpu_single" "yes")
@@ -7427,6 +7636,32 @@ label:
    (set_attr "needs_delay_slot" "yes")
    (set_attr "fp_set" "unknown")])
 
+;; This is TBR relative jump instruction for SH2A architecture.
+;; Its use is enabled assigning an attribute "function_vector"
+;; and the vector number to a function during its declaration.
+
+(define_insn "call_valuei_tbr_rel"
+  [(set (match_operand 0 "" "=rf")
+       (call (mem:SI (match_operand:SI 1 "symbol_ref_operand" ""))
+             (match_operand 2 "" "")))
+   (use (reg:PSI FPSCR_REG))
+   (clobber (reg:SI PR_REG))]
+  "TARGET_SH2A && sh2a_is_function_vector_call (operands[1])"
+  "*
+{
+  unsigned HOST_WIDE_INT vect_num;
+  vect_num = sh2a_get_function_vector_number (operands[1]);
+  operands[3] = GEN_INT (vect_num * 4);
+
+  return \"jsr/n\\t@@(%O3,tbr)\";
+}"
+  [(set_attr "type" "call")
+   (set (attr "fp_mode")
+       (if_then_else (eq_attr "fpu_single" "yes")
+                     (const_string "single") (const_string "double")))
+   (set_attr "needs_delay_slot" "no")
+   (set_attr "fp_set" "unknown")])
+
 (define_insn "call_valuei_pcrel"
   [(set (match_operand 0 "" "=rf")
        (call (mem:SI (match_operand:SI 1 "arith_reg_operand" "r"))
@@ -7465,7 +7700,7 @@ label:
   else
     emit_insn (gen_symPLT_label2reg (operands[3], operands[1], lab));
   emit_call_insn (gen_call_valuei_pcrel (operands[0], operands[3],
-                                        operands[2], lab));
+                                        operands[2], copy_rtx (lab)));
   DONE;
 }"
   [(set_attr "type" "call")
@@ -7588,6 +7823,17 @@ label:
       emit_insn (gen_symGOTPLT2reg (reg, XEXP (operands[0], 0)));
       XEXP (operands[0], 0) = reg;
     }
+  if (!flag_pic && TARGET_SH2A
+      && GET_CODE (operands[0]) == MEM
+      && GET_CODE (XEXP (operands[0], 0)) == SYMBOL_REF)
+    {
+      if (sh2a_is_function_vector_call (XEXP (operands[0], 0)))
+       {
+         emit_call_insn (gen_calli_tbr_rel (XEXP (operands[0], 0),
+                                            operands[1]));
+         DONE;
+       }
+    }
   if (flag_pic && TARGET_SH2
       && GET_CODE (operands[0]) == MEM
       && GET_CODE (XEXP (operands[0], 0)) == SYMBOL_REF)
@@ -7771,6 +8017,17 @@ label:
       emit_insn (gen_symGOTPLT2reg (reg, XEXP (operands[1], 0)));
       XEXP (operands[1], 0) = reg;
     }
+  if (!flag_pic && TARGET_SH2A
+      && GET_CODE (operands[1]) == MEM
+      && GET_CODE (XEXP (operands[1], 0)) == SYMBOL_REF)
+    {
+      if (sh2a_is_function_vector_call (XEXP (operands[1], 0)))
+       {
+         emit_call_insn (gen_call_valuei_tbr_rel (operands[0],
+                                XEXP (operands[1], 0), operands[2]));
+         DONE;
+       }
+    }
   if (flag_pic && TARGET_SH2
       && GET_CODE (operands[1]) == MEM
       && GET_CODE (XEXP (operands[1], 0)) == SYMBOL_REF)
@@ -7846,7 +8103,7 @@ label:
 
   emit_insn (gen_sym_label2reg (operands[2], operands[0], lab));
   call_insn = emit_call_insn (gen_sibcalli_pcrel (operands[2], operands[1],
-                                                 lab));
+                                                 copy_rtx (lab)));
   SIBLING_CALL_P (call_insn) = 1;
   DONE;
 }"
@@ -7984,64 +8241,246 @@ label:
   DONE;
 }")
 
-(define_expand "sibcall_value"
-  [(set (match_operand 0 "" "")
-       (call (match_operand 1 "" "")
-             (match_operand 2 "" "")))
-   (match_operand 3 "" "")]
-  ""
-  "
-{
-  emit_call_insn (gen_sibcall (operands[1], operands[2], operands[3]));
-  DONE;
-}")
-
-(define_insn "call_value_pop_compact"
+(define_insn "sibcall_valuei"
   [(set (match_operand 0 "" "=rf")
-       (call (mem:SI (match_operand:SI 1 "arith_reg_operand" "r"))
+       (call (mem:SI (match_operand:SI 1 "register_operand" "k"))
              (match_operand 2 "" "")))
-   (set (reg:SI SP_REG) (plus:SI (reg:SI SP_REG)
-                                (match_operand 4 "immediate_operand" "n")))
-   (match_operand 3 "immediate_operand" "n")
-   (use (reg:SI R0_REG))
-   (use (reg:SI R1_REG))
    (use (reg:PSI FPSCR_REG))
-   (clobber (reg:SI PR_REG))]
-  "TARGET_SHCOMPACT && ! (INTVAL (operands[3]) & CALL_COOKIE_RET_TRAMP (1))"
-  "jsr @%1%#"
-  [(set_attr "type" "call")
+   (return)]
+  "TARGET_SH1"
+  "jmp @%1%#"
+  [(set_attr "needs_delay_slot" "yes")
    (set (attr "fp_mode")
        (if_then_else (eq_attr "fpu_single" "yes")
                      (const_string "single") (const_string "double")))
-   (set_attr "needs_delay_slot" "yes")])
+   (set_attr "type" "jump_ind")])
 
-(define_insn "call_value_pop_compact_rettramp"
+(define_insn "sibcall_valuei_pcrel"
   [(set (match_operand 0 "" "=rf")
-       (call (mem:SI (match_operand:SI 1 "arith_reg_operand" "r"))
+       (call (mem:SI (match_operand:SI 1 "arith_reg_operand" "k"))
              (match_operand 2 "" "")))
-   (set (reg:SI SP_REG) (plus:SI (reg:SI SP_REG)
-                                (match_operand 4 "immediate_operand" "n")))
-   (match_operand 3 "immediate_operand" "n")
-   (use (reg:SI R0_REG))
-   (use (reg:SI R1_REG))
+   (use (match_operand 3 "" ""))
    (use (reg:PSI FPSCR_REG))
-   (clobber (reg:SI R10_REG))
-   (clobber (reg:SI PR_REG))]
-  "TARGET_SHCOMPACT && (INTVAL (operands[3]) & CALL_COOKIE_RET_TRAMP (1))"
-  "jsr @%1%#"
-  [(set_attr "type" "call")
+   (return)]
+  "TARGET_SH2"
+  "braf        %1\\n%O3:%#"
+  [(set_attr "needs_delay_slot" "yes")
    (set (attr "fp_mode")
        (if_then_else (eq_attr "fpu_single" "yes")
                      (const_string "single") (const_string "double")))
-   (set_attr "needs_delay_slot" "yes")])
+   (set_attr "type" "jump_ind")])
 
-(define_expand "call_value_pop"
-  [(parallel [(set (match_operand 0 "arith_reg_operand" "")
-                  (call (mem:SI (match_operand 1 "arith_reg_operand" ""))
-                                (match_operand 2 "" "")))
-             (match_operand 3 "" "")
-             (set (reg:SI SP_REG) (plus:SI (reg:SI SP_REG)
-                                           (match_operand 4 "" "")))])]
+(define_insn_and_split "sibcall_value_pcrel"
+  [(set (match_operand 0 "" "=rf")
+       (call (mem:SI (match_operand:SI 1 "symbol_ref_operand" ""))
+             (match_operand 2 "" "")))
+   (use (reg:PSI FPSCR_REG))
+   (clobber (match_scratch:SI 3 "=k"))
+   (return)]
+  "TARGET_SH2"
+  "#"
+  "reload_completed"
+  [(const_int 0)]
+  "
+{
+  rtx lab = PATTERN (gen_call_site ());
+  rtx call_insn;
+
+  emit_insn (gen_sym_label2reg (operands[3], operands[1], lab));
+  call_insn = emit_call_insn (gen_sibcall_valuei_pcrel (operands[0],
+                                                       operands[3],
+                                                       operands[2],
+                                                       copy_rtx (lab)));
+  SIBLING_CALL_P (call_insn) = 1;
+  DONE;
+}"
+  [(set_attr "needs_delay_slot" "yes")
+   (set (attr "fp_mode")
+       (if_then_else (eq_attr "fpu_single" "yes")
+                     (const_string "single") (const_string "double")))
+   (set_attr "type" "jump_ind")])
+
+(define_insn "sibcall_value_compact"
+  [(set (match_operand 0 "" "=rf,rf")
+       (call (mem:SI (match_operand:SI 1 "register_operand" "k,k"))
+             (match_operand 2 "" "")))
+   (return)
+   (use (match_operand:SI 3 "register_operand" "z,x"))
+   (use (reg:SI R1_REG))
+   (use (reg:PSI FPSCR_REG))
+   ;; We want to make sure the `x' above will only match MACH_REG
+   ;; because sibcall_epilogue may clobber MACL_REG.
+   (clobber (reg:SI MACL_REG))]
+  "TARGET_SHCOMPACT"
+  "@
+       jmp     @%1%#
+       jmp     @%1\\n  sts     %3, r0"
+  [(set_attr "needs_delay_slot" "yes,no")
+   (set_attr "length" "2,4")
+   (set (attr "fp_mode") (const_string "single"))
+   (set_attr "type" "jump_ind")])
+
+(define_insn "sibcall_value_media"
+  [(set (match_operand 0 "" "=rf")
+       (call (mem:DI (match_operand 1 "target_reg_operand" "k"))
+             (match_operand 2 "" "")))
+   (use (reg:SI PR_MEDIA_REG))
+   (return)]
+  "TARGET_SHMEDIA"
+  "blink       %1, r63"
+  [(set_attr "type" "jump_media")])
+
+(define_expand "sibcall_value"
+  [(parallel
+    [(set (match_operand 0 "arith_reg_operand" "")
+         (call (mem:SI (match_operand 1 "arith_reg_operand" ""))
+               (match_operand 2 "" "")))
+     (match_operand 3 "" "")
+     (use (reg:PSI FPSCR_REG))
+     (return)])]
+  ""
+  "
+{
+  if (TARGET_SHMEDIA)
+    {
+      operands[1] = shmedia_prepare_call_address (operands[1], 1);
+      emit_call_insn (gen_sibcall_value_media (operands[0], operands[1],
+                                              operands[2]));
+      DONE;
+    }
+  else if (TARGET_SHCOMPACT && operands[3]
+          && (INTVAL (operands[3]) & ~ CALL_COOKIE_RET_TRAMP (1)))
+    {
+      rtx cookie_rtx = operands[3];
+      long cookie = INTVAL (cookie_rtx);
+      rtx func = XEXP (operands[1], 0);
+      rtx mach, r1;
+
+      if (flag_pic)
+       {
+         if (GET_CODE (func) == SYMBOL_REF && ! SYMBOL_REF_LOCAL_P (func))
+           {
+             rtx reg = gen_reg_rtx (Pmode);
+
+             emit_insn (gen_symGOT2reg (reg, func));
+             func = reg;
+           }
+         else
+           func = legitimize_pic_address (func, Pmode, 0);
+       }
+
+      /* FIXME: if we could tell whether all argument registers are
+        already taken, we could decide whether to force the use of
+        MACH_REG or to stick to R0_REG.  Unfortunately, there's no
+        simple way to tell.  We could use the CALL_COOKIE, but we
+        can't currently tell a register used for regular argument
+        passing from one that is unused.  If we leave it up to reload
+        to decide which register to use, it seems to always choose
+        R0_REG, which leaves no available registers in SIBCALL_REGS
+        to hold the address of the trampoline.  */
+      mach = gen_rtx_REG (SImode, MACH_REG);
+      r1 = gen_rtx_REG (SImode, R1_REG);
+
+      /* Since such a call function may use all call-clobbered
+        registers, we force a mode switch earlier, so that we don't
+        run out of registers when adjusting fpscr for the call.  */
+      emit_insn (gen_force_mode_for_call ());
+
+      operands[1]
+       = function_symbol (NULL, \"__GCC_shcompact_call_trampoline\",
+                          SFUNC_GOT);
+      operands[1] = force_reg (SImode, operands[1]);
+
+      /* We don't need a return trampoline, since the callee will
+        return directly to the upper caller.  */
+      if (cookie & CALL_COOKIE_RET_TRAMP (1))
+       {
+         cookie &= ~ CALL_COOKIE_RET_TRAMP (1);
+         cookie_rtx = GEN_INT (cookie);
+       }
+
+      emit_move_insn (mach, func);
+      emit_move_insn (r1, cookie_rtx);
+
+      emit_call_insn (gen_sibcall_value_compact (operands[0], operands[1],
+                                                operands[2], mach));
+      DONE;
+    }
+  else if (TARGET_SHCOMPACT && flag_pic
+          && GET_CODE (XEXP (operands[1], 0)) == SYMBOL_REF
+          && ! SYMBOL_REF_LOCAL_P (XEXP (operands[1], 0)))
+    {
+      rtx reg = gen_reg_rtx (Pmode);
+
+      emit_insn (gen_symGOT2reg (reg, XEXP (operands[1], 0)));
+      XEXP (operands[1], 0) = reg;
+    }
+  if (flag_pic && TARGET_SH2
+      && GET_CODE (operands[1]) == MEM
+      && GET_CODE (XEXP (operands[1], 0)) == SYMBOL_REF
+      /* The PLT needs the PIC register, but the epilogue would have
+        to restore it, so we can only use PC-relative PIC calls for
+        static functions.  */
+      && SYMBOL_REF_LOCAL_P (XEXP (operands[1], 0)))
+    {
+      emit_call_insn (gen_sibcall_value_pcrel (operands[0],
+                                              XEXP (operands[1], 0),
+                                              operands[2]));
+      DONE;
+    }
+  else
+    operands[1] = force_reg (SImode, XEXP (operands[1], 0));
+
+  emit_call_insn (gen_sibcall_valuei (operands[0], operands[1], operands[2]));
+  DONE;
+}")
+
+(define_insn "call_value_pop_compact"
+  [(set (match_operand 0 "" "=rf")
+       (call (mem:SI (match_operand:SI 1 "arith_reg_operand" "r"))
+             (match_operand 2 "" "")))
+   (set (reg:SI SP_REG) (plus:SI (reg:SI SP_REG)
+                                (match_operand 4 "immediate_operand" "n")))
+   (match_operand 3 "immediate_operand" "n")
+   (use (reg:SI R0_REG))
+   (use (reg:SI R1_REG))
+   (use (reg:PSI FPSCR_REG))
+   (clobber (reg:SI PR_REG))]
+  "TARGET_SHCOMPACT && ! (INTVAL (operands[3]) & CALL_COOKIE_RET_TRAMP (1))"
+  "jsr @%1%#"
+  [(set_attr "type" "call")
+   (set (attr "fp_mode")
+       (if_then_else (eq_attr "fpu_single" "yes")
+                     (const_string "single") (const_string "double")))
+   (set_attr "needs_delay_slot" "yes")])
+
+(define_insn "call_value_pop_compact_rettramp"
+  [(set (match_operand 0 "" "=rf")
+       (call (mem:SI (match_operand:SI 1 "arith_reg_operand" "r"))
+             (match_operand 2 "" "")))
+   (set (reg:SI SP_REG) (plus:SI (reg:SI SP_REG)
+                                (match_operand 4 "immediate_operand" "n")))
+   (match_operand 3 "immediate_operand" "n")
+   (use (reg:SI R0_REG))
+   (use (reg:SI R1_REG))
+   (use (reg:PSI FPSCR_REG))
+   (clobber (reg:SI R10_REG))
+   (clobber (reg:SI PR_REG))]
+  "TARGET_SHCOMPACT && (INTVAL (operands[3]) & CALL_COOKIE_RET_TRAMP (1))"
+  "jsr @%1%#"
+  [(set_attr "type" "call")
+   (set (attr "fp_mode")
+       (if_then_else (eq_attr "fpu_single" "yes")
+                     (const_string "single") (const_string "double")))
+   (set_attr "needs_delay_slot" "yes")])
+
+(define_expand "call_value_pop"
+  [(parallel [(set (match_operand 0 "arith_reg_operand" "")
+                  (call (mem:SI (match_operand 1 "arith_reg_operand" ""))
+                                (match_operand 2 "" "")))
+             (match_operand 3 "" "")
+             (set (reg:SI SP_REG) (plus:SI (reg:SI SP_REG)
+                                           (match_operand 4 "" "")))])]
   "TARGET_SHCOMPACT"
   "
 {
@@ -8113,19 +8552,14 @@ label:
          {
            rtx r0 = gen_rtx_REG (SImode, R0_REG);
            rtx tmp = gen_rtx_REG (SImode, MACL_REG);
-           rtx i;
 
            /* We can't tell at this point whether the sibcall is a
               sibcall_compact and, if it is, whether it uses r0 or
               mach as operand 2, so let the instructions that
               preserve r0 be optimized away if r0 turns out to be
               dead.  */
-           i = emit_insn_before (gen_rtx_SET (SImode, tmp, r0), insn);
-           REG_NOTES (i) = gen_rtx_EXPR_LIST (REG_MAYBE_DEAD, const0_rtx,
-                                              REG_NOTES (i));
-           i = emit_move_insn (r0, tmp);
-           REG_NOTES (i) = gen_rtx_EXPR_LIST (REG_MAYBE_DEAD, const0_rtx,
-                                              REG_NOTES (i));
+           emit_insn_before (gen_rtx_SET (SImode, tmp, r0), insn);
+           emit_move_insn (r0, tmp);
            break;
          }
     }
@@ -8259,6 +8693,14 @@ label:
    (set (match_dup 0) (plus:SI (match_dup 0) (reg:SI R0_REG)))]
   "" "
 {
+  if (TARGET_VXWORKS_RTP)
+    {
+      rtx gott_base = gen_rtx_SYMBOL_REF (Pmode, VXWORKS_GOTT_BASE);
+      rtx gott_index = gen_rtx_SYMBOL_REF (Pmode, VXWORKS_GOTT_INDEX);
+      emit_insn (gen_vxworks_picreg (gott_base, gott_index));
+      DONE;
+    }
+
   operands[0] = gen_rtx_REG (Pmode, PIC_REG);
   operands[1] = gen_rtx_SYMBOL_REF (VOIDmode, GOT_SYMBOL_NAME);
 
@@ -8270,44 +8712,51 @@ label:
       rtx insn, equiv;
 
       equiv = operands[1];
-      operands[1] = gen_rtx_MINUS (Pmode,
-                                  operands[1],
-                                  gen_rtx_CONST
-                                  (Pmode,
-                                   gen_rtx_MINUS (Pmode,
-                                                  gen_rtx_CONST (Pmode,
-                                                                 lab),
-                                                  pc_rtx)));
-      operands[1] = gen_sym2PIC (operands[1]);
-      PUT_MODE (operands[1], Pmode);
+      operands[1] = gen_rtx_UNSPEC (Pmode, gen_rtvec (2, operands[1], lab),
+                                   UNSPEC_PCREL_SYMOFF);
+      operands[1] = gen_rtx_CONST (Pmode, operands[1]);
 
       if (Pmode == SImode)
        {
          emit_insn (gen_movsi_const (pic, operands[1]));
-         emit_insn (gen_ptrel_si (tr, pic, lab));
+         emit_insn (gen_ptrel_si (tr, pic, copy_rtx (lab)));
        }
       else
        {
          emit_insn (gen_movdi_const (pic, operands[1]));
-         emit_insn (gen_ptrel_di (tr, pic, lab));
+         emit_insn (gen_ptrel_di (tr, pic, copy_rtx (lab)));
        }
 
       insn = emit_move_insn (operands[0], tr);
 
-      REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_EQUAL, equiv,
-                                           REG_NOTES (insn));
+      set_unique_reg_note (insn, REG_EQUAL, equiv);
 
       DONE;
     }
 }
 ")
 
+;; A helper for GOTaddr2picreg to finish up the initialization of the
+;; PIC register.
+
+(define_expand "vxworks_picreg"
+  [(set (reg:SI PIC_REG)
+       (const:SI (unspec:SI [(match_operand:SI 0 "" "")] UNSPEC_PIC)))
+   (set (reg:SI R0_REG)
+       (const:SI (unspec:SI [(match_operand:SI 1 "" "")] UNSPEC_PIC)))
+   (set (reg:SI PIC_REG)
+       (mem:SI (reg:SI PIC_REG)))
+   (set (reg:SI PIC_REG)
+       (mem:SI (plus:SI (reg:SI PIC_REG)
+                        (reg:SI R0_REG))))]
+  "TARGET_VXWORKS_RTP")
+
 (define_insn "*ptb"
   [(set (match_operand 0 "target_reg_operand" "=b")
        (const (unspec [(match_operand 1 "" "Csy")]
                             UNSPEC_DATALABEL)))]
   "TARGET_SHMEDIA && flag_pic
-   && EXTRA_CONSTRAINT_Csy (operands[1])"
+   && satisfies_constraint_Csy (operands[1])"
   "ptb/u       datalabel %1, %0"
   [(set_attr "type" "ptabs_media")
    (set_attr "length" "*")])
@@ -8351,13 +8800,10 @@ label:
 
 (define_expand "sym_label2reg"
   [(set (match_operand:SI 0 "" "")
-       (const:SI (minus:SI
-                  (const:SI
-                   (unspec:SI [(match_operand:SI 1 "" "")] UNSPEC_PIC))
-                  (const:SI
-                   (plus:SI
-                    (match_operand:SI 2 "" "")
-                    (const_int 2))))))]
+       (const:SI (unspec:SI [(match_operand:SI 1 "" "")
+                             (const (plus:SI (match_operand:SI 2 "" "")
+                                             (const_int 2)))]
+                            UNSPEC_SYMOFF)))]
   "TARGET_SH1" "")
 
 (define_expand "symGOT_load"
@@ -8369,8 +8815,8 @@ label:
 {
   rtx insn, mem;
 
-  operands[2] = no_new_pseudos ? operands[0] : gen_reg_rtx (Pmode);
-  operands[3] = no_new_pseudos ? operands[0] : gen_reg_rtx (Pmode);
+  operands[2] = !can_create_pseudo_p () ? operands[0] : gen_reg_rtx (Pmode);
+  operands[3] = !can_create_pseudo_p () ? operands[0] : gen_reg_rtx (Pmode);
 
   if (TARGET_SHMEDIA)
     {
@@ -8398,16 +8844,26 @@ label:
                                             operands[2],
                                             gen_rtx_REG (Pmode, PIC_REG)));
 
+  /* When stack protector inserts codes after the result is set to
+     R0, @(rX, r12) will cause a spill failure for R0.  Don't schedule
+     insns to avoid combining (set A (plus rX r12)) and (set op0 (mem A))
+     when rX is a GOT address for the guard symbol.  Ugly but doesn't
+     matter because this is a rare situation.  */
+  if (!TARGET_SHMEDIA
+      && flag_stack_protect
+      && GET_CODE (operands[1]) == CONST
+      && GET_CODE (XEXP (operands[1], 0)) == UNSPEC
+      && GET_CODE (XVECEXP (XEXP (operands[1], 0), 0, 0)) == SYMBOL_REF
+      && strcmp (XSTR (XVECEXP (XEXP (operands[1], 0), 0, 0), 0),
+                \"__stack_chk_guard\") == 0)
+    emit_insn (gen_blockage ());
+
   /* N.B. This is not constant for a GOTPLT relocation.  */
   mem = gen_rtx_MEM (Pmode, operands[3]);
   MEM_NOTRAP_P (mem) = 1;
   /* ??? Should we have a special alias set for the GOT?  */
   insn = emit_move_insn (operands[0], mem);
 
-  REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_EQUAL, XVECEXP (XEXP (operands[1],
-                                                                 0), 0, 0),
-                                       REG_NOTES (insn));
-
   DONE;
 }")
 
@@ -8456,7 +8912,9 @@ label:
   "
 {
   rtx gotoffsym, insn;
-  rtx t = no_new_pseudos ? operands[0] : gen_reg_rtx (GET_MODE (operands[0]));
+  rtx t = (!can_create_pseudo_p ()
+          ? operands[0]
+          : gen_reg_rtx (GET_MODE (operands[0])));
 
   gotoffsym = gen_sym2GOTOFF (operands[1]);
   PUT_MODE (gotoffsym, Pmode);
@@ -8465,23 +8923,18 @@ label:
                         gen_rtx_PLUS (Pmode, t,
                                       gen_rtx_REG (Pmode, PIC_REG)));
 
-  REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_EQUAL, operands[1],
-                                       REG_NOTES (insn));
+  set_unique_reg_note (insn, REG_EQUAL, operands[1]);
 
   DONE;
 }")
 
 (define_expand "symPLT_label2reg"
   [(set (match_operand:SI 0 "" "")
-       (const:SI (minus:SI
-                  (const:SI
-                   (unspec:SI [(match_operand:SI 1 "" "")] UNSPEC_PLT))
-                  (const:SI
-                   (minus:SI
-                    (const:SI (plus:SI
-                               (match_operand:SI 2 "" "")
-                               (const_int 2)))
-                    (const:SI (unspec:SI [(pc)] UNSPEC_PIC)))))))
+       (const:SI
+        (unspec:SI
+         [(const:SI (unspec:SI [(match_operand:SI 1 "" "")] UNSPEC_PLT))
+          (const:SI (plus:SI (match_operand:SI 2 "" "")
+                             (const_int 2)))] UNSPEC_PCREL_SYMOFF)))
    ;; Even though the PIC register is not really used by the call
    ;; sequence in which this is expanded, the PLT code assumes the PIC
    ;; register is set, so we must not skip its initialization.  Since
@@ -8577,7 +9030,9 @@ mov.l\\t1f,r4\\n\\
   "
 {
   rtx dtpoffsym, insn;
-  rtx t = no_new_pseudos ? operands[0] : gen_reg_rtx (GET_MODE (operands[0]));
+  rtx t = (!can_create_pseudo_p ()
+          ? operands[0]
+          : gen_reg_rtx (GET_MODE (operands[0])));
 
   dtpoffsym = gen_sym2DTPOFF (operands[1]);
   PUT_MODE (dtpoffsym, Pmode);
@@ -8634,7 +9089,7 @@ mov.l\\t1f,r0\\n\\
 }")
 
 (define_insn "load_gbr"
-  [(set (match_operand:SI 0 "register_operand" "") (reg:SI GBR_REG))
+  [(set (match_operand:SI 0 "register_operand" "=r") (reg:SI GBR_REG))
    (use (reg:SI GBR_REG))]
   ""
   "stc gbr,%0"
@@ -8905,7 +9360,7 @@ mov.l\\t1f,r0\\n\\
     }
 
   if (TARGET_SHCOMPACT
-      && (current_function_args_info.call_cookie & CALL_COOKIE_RET_TRAMP (1)))
+      && (crtl->args.info.call_cookie & CALL_COOKIE_RET_TRAMP (1)))
     {
       emit_jump_insn (gen_shcompact_return_tramp ());
       DONE;
@@ -8915,12 +9370,19 @@ mov.l\\t1f,r0\\n\\
 (define_insn "*return_i"
   [(return)]
   "TARGET_SH1 && ! (TARGET_SHCOMPACT
-                   && (current_function_args_info.call_cookie
+                   && (crtl->args.info.call_cookie
                        & CALL_COOKIE_RET_TRAMP (1)))
    && reload_completed
    && lookup_attribute (\"trap_exit\",
                        DECL_ATTRIBUTES (current_function_decl)) == NULL_TREE"
-  "%@  %#"
+  "*
+  {
+    if (TARGET_SH2A && (dbr_sequence_length () == 0)
+                       && !current_function_interrupt)
+       return \"rts/n\";
+    else
+       return \"%@     %#\";
+  }"
   [(set_attr "type" "return")
    (set_attr "needs_delay_slot" "yes")])
 
@@ -8935,7 +9397,7 @@ mov.l\\t1f,r0\\n\\
 (define_expand "shcompact_return_tramp"
   [(return)]
   "TARGET_SHCOMPACT
-   && (current_function_args_info.call_cookie & CALL_COOKIE_RET_TRAMP (1))"
+   && (crtl->args.info.call_cookie & CALL_COOKIE_RET_TRAMP (1))"
   "
 {
   rtx reg = gen_rtx_REG (Pmode, R0_REG);
@@ -8948,7 +9410,7 @@ mov.l\\t1f,r0\\n\\
 (define_insn "shcompact_return_tramp_i"
   [(parallel [(return) (use (reg:SI R0_REG))])]
   "TARGET_SHCOMPACT
-   && (current_function_args_info.call_cookie & CALL_COOKIE_RET_TRAMP (1))"
+   && (crtl->args.info.call_cookie & CALL_COOKIE_RET_TRAMP (1))"
   "jmp @r0%#"
   [(set_attr "type" "jump_ind")
    (set_attr "needs_delay_slot" "yes")])
@@ -9066,19 +9528,22 @@ mov.l\\t1f,r0\\n\\
 ;; until we know where it will be put in the stack frame.
 
 (define_insn "eh_set_ra_si"
-  [(unspec [(match_operand:SI 0 "register_operand" "r")] UNSPEC_EH_RETURN)
+  [(unspec_volatile [(match_operand:SI 0 "register_operand" "r")]
+      UNSPECV_EH_RETURN)
    (clobber (match_scratch:SI 1 "=&r"))]
   "! TARGET_SHMEDIA64"
   "#")
 
 (define_insn "eh_set_ra_di"
-  [(unspec [(match_operand:DI 0 "register_operand" "r")] UNSPEC_EH_RETURN)
+  [(unspec_volatile [(match_operand:DI 0 "register_operand" "r")]
+      UNSPECV_EH_RETURN)
    (clobber (match_scratch:DI 1 "=&r"))]
   "TARGET_SHMEDIA64"
   "#")
 
 (define_split
-  [(unspec [(match_operand 0 "register_operand" "")] UNSPEC_EH_RETURN)
+  [(unspec_volatile [(match_operand 0 "register_operand" "")]
+      UNSPECV_EH_RETURN)
    (clobber (match_scratch 1 ""))]
   "reload_completed"
   [(const_int 0)]
@@ -9105,6 +9570,16 @@ mov.l\\t1f,r0\\n\\
   "movt        %0"
   [(set_attr "type" "arith")])
 
+;; complements the T bit and stores the result in a register
+(define_insn "movrt"
+  [(set (match_operand:SI 0 "arith_reg_dest" "=r")
+        (if_then_else (eq:SI (reg:SI T_REG) (const_int 0))
+        (const_int 1)
+        (const_int 0)))]
+  "TARGET_SH2A"
+  "movrt\\t%0"
+   [(set_attr "type" "arith")])
+
 (define_expand "seq"
   [(set (match_operand:SI 0 "arith_reg_dest" "")
        (match_dup 1))]
@@ -9113,6 +9588,8 @@ mov.l\\t1f,r0\\n\\
 {
   if (TARGET_SHMEDIA)
     {
+      rtx reg;
+
       sh_compare_op0 = force_reg (GET_MODE (sh_compare_op0), sh_compare_op0);
       if (sh_compare_op1 != const0_rtx)
        sh_compare_op1 = force_reg (GET_MODE (sh_compare_op1) == VOIDmode
@@ -9127,26 +9604,26 @@ mov.l\\t1f,r0\\n\\
          switch (GET_MODE (sh_compare_op0))
            {
            case SImode:
-             emit_insn (gen_cmpsieqsi_media (operands[0],
+             emit_insn (gen_cmpeqsi_media (operands[0],
                                              sh_compare_op0, sh_compare_op1));
              break;
 
            case DImode:
-             emit_insn (gen_cmpsieqdi_media (operands[0],
+             emit_insn (gen_cmpeqdi_media (operands[0],
                                              sh_compare_op0, sh_compare_op1));
              break;
 
            case SFmode:
              if (! TARGET_SHMEDIA_FPU)
                FAIL;
-             emit_insn (gen_cmpsieqsf_media (operands[0],
+             emit_insn (gen_cmpeqsf_media (operands[0],
                                              sh_compare_op0, sh_compare_op1));
              break;
 
            case DFmode:
              if (! TARGET_SHMEDIA_FPU)
                FAIL;
-             emit_insn (gen_cmpsieqdf_media (operands[0],
+             emit_insn (gen_cmpeqdf_media (operands[0],
                                              sh_compare_op0, sh_compare_op1));
              break;
 
@@ -9156,38 +9633,45 @@ mov.l\\t1f,r0\\n\\
          DONE;
        }
 
-      if (GET_MODE (operands[0]) != DImode)
-       operands[0] = gen_rtx_SUBREG (DImode, operands[0], 0);
+      reg = operands[0];
+      if (GET_MODE (operands[0]) != SImode)
+       reg = (!can_create_pseudo_p ()
+              ? gen_rtx_SUBREG (SImode, operands[0], 0)
+              : gen_reg_rtx (SImode));
 
       switch (GET_MODE (sh_compare_op0))
        {
        case SImode:
-         emit_insn (gen_cmpeqsi_media (operands[0],
+         emit_insn (gen_cmpeqsi_media (reg,
                                        sh_compare_op0, sh_compare_op1));
          break;
 
        case DImode:
-         emit_insn (gen_cmpeqdi_media (operands[0],
+         emit_insn (gen_cmpeqdi_media (reg,
                                        sh_compare_op0, sh_compare_op1));
          break;
 
        case SFmode:
          if (! TARGET_SHMEDIA_FPU)
            FAIL;
-         emit_insn (gen_cmpeqsf_media (operands[0],
+         emit_insn (gen_cmpeqsf_media (reg,
                                        sh_compare_op0, sh_compare_op1));
          break;
 
        case DFmode:
          if (! TARGET_SHMEDIA_FPU)
            FAIL;
-         emit_insn (gen_cmpeqdf_media (operands[0],
+         emit_insn (gen_cmpeqdf_media (reg,
                                        sh_compare_op0, sh_compare_op1));
          break;
 
        default:
          FAIL;
        }
+
+      if (GET_MODE (operands[0]) == DImode)
+       emit_insn (gen_extendsidi2 (operands[0], reg));
+
       DONE;
     }
   if (sh_expand_t_scc (EQ, operands[0]))
@@ -9205,8 +9689,8 @@ mov.l\\t1f,r0\\n\\
 {
   if (TARGET_SHMEDIA)
     {
-      if (GET_MODE (operands[0]) != DImode)
-       operands[0] = gen_rtx_SUBREG (DImode, operands[0], 0);
+      rtx reg;
+
       sh_compare_op0 = force_reg (GET_MODE (sh_compare_op0), sh_compare_op0);
       if (sh_compare_op1 != const0_rtx)
        sh_compare_op1 = force_reg (GET_MODE (sh_compare_op1) == VOIDmode
@@ -9214,35 +9698,45 @@ mov.l\\t1f,r0\\n\\
                                    : GET_MODE (sh_compare_op1),
                                    sh_compare_op1);
 
+      reg = operands[0];
+      if (GET_MODE (operands[0]) != SImode)
+       reg = (!can_create_pseudo_p ()
+              ? gen_rtx_SUBREG (SImode, operands[0], 0)
+              : gen_reg_rtx (SImode));
+
       switch (GET_MODE (sh_compare_op0))
        {
        case SImode:
-         emit_insn (gen_cmpgtsi_media (operands[0],
+         emit_insn (gen_cmpgtsi_media (reg,
                                        sh_compare_op1, sh_compare_op0));
          break;
 
        case DImode:
-         emit_insn (gen_cmpgtdi_media (operands[0],
+         emit_insn (gen_cmpgtdi_media (reg,
                                        sh_compare_op1, sh_compare_op0));
          break;
 
        case SFmode:
          if (! TARGET_SHMEDIA_FPU)
            FAIL;
-         emit_insn (gen_cmpgtsf_media (operands[0],
+         emit_insn (gen_cmpgtsf_media (reg,
                                        sh_compare_op1, sh_compare_op0));
          break;
 
        case DFmode:
          if (! TARGET_SHMEDIA_FPU)
            FAIL;
-         emit_insn (gen_cmpgtdf_media (operands[0],
+         emit_insn (gen_cmpgtdf_media (reg,
                                        sh_compare_op1, sh_compare_op0));
          break;
 
        default:
          FAIL;
        }
+
+      if (GET_MODE (operands[0]) == DImode)
+       emit_insn (gen_extendsidi2 (operands[0], reg));
+
       DONE;
     }
   if (! currently_expanding_to_rtl)
@@ -9259,8 +9753,8 @@ mov.l\\t1f,r0\\n\\
 
   if (TARGET_SHMEDIA)
     {
-      if (GET_MODE (operands[0]) != DImode)
-       operands[0] = gen_rtx_SUBREG (DImode, operands[0], 0);
+      rtx reg;
+
       sh_compare_op0 = force_reg (GET_MODE (sh_compare_op0), sh_compare_op0);
       if (sh_compare_op1 != const0_rtx)
        sh_compare_op1 = force_reg (GET_MODE (sh_compare_op1) == VOIDmode
@@ -9268,45 +9762,55 @@ mov.l\\t1f,r0\\n\\
                                    : GET_MODE (sh_compare_op1),
                                    sh_compare_op1);
 
+      reg = operands[0];
+      if (GET_MODE (operands[0]) != SImode)
+       reg = (!can_create_pseudo_p ()
+              ? gen_rtx_SUBREG (SImode, operands[0], 0)
+              : gen_reg_rtx (SImode));
+
       switch (GET_MODE (sh_compare_op0))
        {
        case SImode:
          {
-           tmp = no_new_pseudos ? operands[0] : gen_reg_rtx (DImode);
+           tmp = !can_create_pseudo_p () ? reg : gen_reg_rtx (SImode);
 
            emit_insn (gen_cmpgtsi_media (tmp,
                                          sh_compare_op0, sh_compare_op1));
-           emit_insn (gen_cmpeqdi_media (operands[0], tmp, const0_rtx));
+           emit_insn (gen_cmpeqdi_media (reg, tmp, const0_rtx));
            break;
          }
 
        case DImode:
          {
-           tmp = no_new_pseudos ? operands[0] : gen_reg_rtx (DImode);
+           tmp = !can_create_pseudo_p () ? reg : gen_reg_rtx (SImode);
 
            emit_insn (gen_cmpgtdi_media (tmp,
                                          sh_compare_op0, sh_compare_op1));
-           emit_insn (gen_cmpeqdi_media (operands[0], tmp, const0_rtx));
+           emit_insn (gen_cmpeqdi_media (reg, tmp, const0_rtx));
            break;
          }
 
        case SFmode:
          if (! TARGET_SHMEDIA_FPU)
            FAIL;
-         emit_insn (gen_cmpgesf_media (operands[0],
+         emit_insn (gen_cmpgesf_media (reg,
                                        sh_compare_op1, sh_compare_op0));
          break;
 
        case DFmode:
          if (! TARGET_SHMEDIA_FPU)
            FAIL;
-         emit_insn (gen_cmpgedf_media (operands[0],
+         emit_insn (gen_cmpgedf_media (reg,
                                        sh_compare_op1, sh_compare_op0));
          break;
 
        default:
          FAIL;
        }
+
+      if (GET_MODE (operands[0]) == DImode)
+       emit_insn (gen_extendsidi2 (operands[0], reg));
+
       DONE;
     }
 
@@ -9324,8 +9828,13 @@ mov.l\\t1f,r0\\n\\
 {
   if (TARGET_SHMEDIA)
     {
-      if (GET_MODE (operands[0]) != DImode)
-       operands[0] = gen_rtx_SUBREG (DImode, operands[0], 0);
+      rtx reg;
+
+      reg = operands[0];
+      if (GET_MODE (operands[0]) != SImode)
+       reg = (!can_create_pseudo_p () ?
+              gen_rtx_SUBREG (SImode, operands[0], 0)
+              : gen_reg_rtx (SImode));
       sh_compare_op0 = force_reg (GET_MODE (sh_compare_op0), sh_compare_op0);
       if (sh_compare_op1 != const0_rtx)
        sh_compare_op1 = force_reg (GET_MODE (sh_compare_op1) == VOIDmode
@@ -9336,32 +9845,36 @@ mov.l\\t1f,r0\\n\\
       switch (GET_MODE (sh_compare_op0))
        {
        case SImode:
-         emit_insn (gen_cmpgtsi_media (operands[0],
+         emit_insn (gen_cmpgtsi_media (reg,
                                        sh_compare_op0, sh_compare_op1));
          break;
 
        case DImode:
-         emit_insn (gen_cmpgtdi_media (operands[0],
+         emit_insn (gen_cmpgtdi_media (reg,
                                        sh_compare_op0, sh_compare_op1));
          break;
 
        case SFmode:
          if (! TARGET_SHMEDIA_FPU)
            FAIL;
-         emit_insn (gen_cmpgtsf_media (operands[0],
+         emit_insn (gen_cmpgtsf_media (reg,
                                        sh_compare_op0, sh_compare_op1));
          break;
 
        case DFmode:
          if (! TARGET_SHMEDIA_FPU)
            FAIL;
-         emit_insn (gen_cmpgtdf_media (operands[0],
+         emit_insn (gen_cmpgtdf_media (reg,
                                        sh_compare_op0, sh_compare_op1));
          break;
 
        default:
          FAIL;
        }
+
+      if (GET_MODE (operands[0]) == DImode)
+       emit_insn (gen_extendsidi2 (operands[0], reg));
+
       DONE;
     }
   if (! currently_expanding_to_rtl)
@@ -9377,12 +9890,16 @@ mov.l\\t1f,r0\\n\\
 {
   if (TARGET_SHMEDIA)
     {
+      rtx reg;
       enum machine_mode mode = GET_MODE (sh_compare_op0);
 
       if ((mode) == VOIDmode)
        mode = GET_MODE (sh_compare_op1);
-      if (GET_MODE (operands[0]) != DImode)
-       operands[0] = gen_rtx_SUBREG (DImode, operands[0], 0);
+      reg = operands[0];
+      if (GET_MODE (operands[0]) != SImode)
+       reg = (!can_create_pseudo_p ()
+              ? gen_rtx_SUBREG (SImode, operands[0], 0)
+              : gen_reg_rtx (SImode));
       sh_compare_op0 = force_reg (mode, sh_compare_op0);
       if (sh_compare_op1 != const0_rtx)
        sh_compare_op1 = force_reg (mode, sh_compare_op1);
@@ -9391,41 +9908,45 @@ mov.l\\t1f,r0\\n\\
        {
        case SImode:
          {
-           rtx tmp = no_new_pseudos ? operands[0] : gen_reg_rtx (DImode);
+           rtx tmp = !can_create_pseudo_p () ? reg : gen_reg_rtx (SImode);
 
            emit_insn (gen_cmpgtsi_media (tmp,
                                          sh_compare_op1, sh_compare_op0));
-           emit_insn (gen_cmpeqdi_media (operands[0], tmp, const0_rtx));
+           emit_insn (gen_cmpeqdi_media (reg, tmp, const0_rtx));
            break;
          }
 
        case DImode:
          {
-           rtx tmp = no_new_pseudos ? operands[0] : gen_reg_rtx (DImode);
+           rtx tmp = !can_create_pseudo_p () ? reg : gen_reg_rtx (SImode);
 
            emit_insn (gen_cmpgtdi_media (tmp,
                                          sh_compare_op1, sh_compare_op0));
-           emit_insn (gen_cmpeqdi_media (operands[0], tmp, const0_rtx));
+           emit_insn (gen_cmpeqdi_media (reg, tmp, const0_rtx));
            break;
          }
 
        case SFmode:
          if (! TARGET_SHMEDIA_FPU)
            FAIL;
-         emit_insn (gen_cmpgesf_media (operands[0],
+         emit_insn (gen_cmpgesf_media (reg,
                                        sh_compare_op0, sh_compare_op1));
          break;
 
        case DFmode:
          if (! TARGET_SHMEDIA_FPU)
            FAIL;
-         emit_insn (gen_cmpgedf_media (operands[0],
+         emit_insn (gen_cmpgedf_media (reg,
                                        sh_compare_op0, sh_compare_op1));
          break;
 
        default:
          FAIL;
        }
+
+      if (GET_MODE (operands[0]) == DImode)
+       emit_insn (gen_extendsidi2 (operands[0], reg));
+
       DONE;
     }
 
@@ -9457,8 +9978,13 @@ mov.l\\t1f,r0\\n\\
 {
   if (TARGET_SHMEDIA)
     {
-      if (GET_MODE (operands[0]) != DImode)
-       operands[0] = gen_rtx_SUBREG (DImode, operands[0], 0);
+      rtx reg;
+
+      reg = operands[0];
+      if (GET_MODE (operands[0]) == DImode)
+       reg = (!can_create_pseudo_p ()
+              ? gen_rtx_SUBREG (SImode, operands[0], 0)
+              : gen_reg_rtx (SImode));
       sh_compare_op0 = force_reg (GET_MODE (sh_compare_op0), sh_compare_op0);
       if (sh_compare_op1 != const0_rtx)
        sh_compare_op1 = force_reg (GET_MODE (sh_compare_op1) == VOIDmode
@@ -9466,8 +9992,11 @@ mov.l\\t1f,r0\\n\\
                                    : GET_MODE (sh_compare_op1),
                                    sh_compare_op1);
 
-      emit_insn (gen_cmpgtudi_media (operands[0],
+      emit_insn (gen_cmpgtudi_media (reg,
                                     sh_compare_op0, sh_compare_op1));
+      if (GET_MODE (operands[0]) == DImode)
+       emit_insn (gen_extendsidi2 (operands[0], reg));
+
       DONE;
     }
   if (! currently_expanding_to_rtl)
@@ -9483,8 +10012,13 @@ mov.l\\t1f,r0\\n\\
 {
   if (TARGET_SHMEDIA)
     {
-      if (GET_MODE (operands[0]) != DImode)
-       operands[0] = gen_rtx_SUBREG (DImode, operands[0], 0);
+      rtx reg;
+
+      reg = operands[0];
+      if (GET_MODE (operands[0]) == DImode)
+       reg = (!can_create_pseudo_p ()
+              ? gen_rtx_SUBREG (SImode, operands[0], 0)
+              : gen_reg_rtx (SImode));
       sh_compare_op0 = force_reg (GET_MODE (sh_compare_op0), sh_compare_op0);
       if (sh_compare_op1 != const0_rtx)
        sh_compare_op1 = force_reg (GET_MODE (sh_compare_op1) == VOIDmode
@@ -9492,8 +10026,11 @@ mov.l\\t1f,r0\\n\\
                                    : GET_MODE (sh_compare_op1),
                                    sh_compare_op1);
 
-      emit_insn (gen_cmpgtudi_media (operands[0],
+      emit_insn (gen_cmpgtudi_media (reg,
                                     sh_compare_op1, sh_compare_op0));
+      if (GET_MODE (operands[0]) == DImode)
+       emit_insn (gen_extendsidi2 (operands[0], reg));
+
       DONE;
     }
   if (! currently_expanding_to_rtl)
@@ -9509,10 +10046,13 @@ mov.l\\t1f,r0\\n\\
 {
   if (TARGET_SHMEDIA)
     {
-      rtx tmp;
+      rtx tmp, reg;
 
-      if (GET_MODE (operands[0]) != DImode)
-       operands[0] = gen_rtx_SUBREG (DImode, operands[0], 0);
+      reg = operands[0];
+      if (GET_MODE (operands[0]) != SImode)
+       reg = (!can_create_pseudo_p ()
+              ? gen_rtx_SUBREG (SImode, operands[0], 0)
+              : gen_reg_rtx (SImode));
       sh_compare_op0 = force_reg (GET_MODE (sh_compare_op0), sh_compare_op0);
       if (sh_compare_op1 != const0_rtx)
        sh_compare_op1 = force_reg (GET_MODE (sh_compare_op1) == VOIDmode
@@ -9520,10 +10060,12 @@ mov.l\\t1f,r0\\n\\
                                    : GET_MODE (sh_compare_op1),
                                    sh_compare_op1);
 
-      tmp = no_new_pseudos ? operands[0] : gen_reg_rtx (DImode);
+      tmp = !can_create_pseudo_p () ? reg : gen_reg_rtx (SImode);
 
       emit_insn (gen_cmpgtudi_media (tmp, sh_compare_op0, sh_compare_op1));
-      emit_insn (gen_cmpeqdi_media (operands[0], tmp, const0_rtx));
+      emit_insn (gen_cmpeqdi_media (reg, tmp, const0_rtx));
+      if (GET_MODE (operands[0]) == DImode)
+       emit_insn (gen_extendsidi2 (operands[0], reg));
 
       DONE;
     }
@@ -9540,10 +10082,13 @@ mov.l\\t1f,r0\\n\\
 {
   if (TARGET_SHMEDIA)
     {
-      rtx tmp;
+      rtx tmp, reg;
 
-      if (GET_MODE (operands[0]) != DImode)
-       operands[0] = gen_rtx_SUBREG (DImode, operands[0], 0);
+      reg = operands[0];
+      if (GET_MODE (operands[0]) != SImode)
+       reg = (!can_create_pseudo_p ()
+              ? gen_rtx_SUBREG (SImode, operands[0], 0)
+              : gen_reg_rtx (SImode));
       sh_compare_op0 = force_reg (GET_MODE (sh_compare_op0), sh_compare_op0);
       if (sh_compare_op1 != const0_rtx)
        sh_compare_op1 = force_reg (GET_MODE (sh_compare_op1) == VOIDmode
@@ -9551,10 +10096,12 @@ mov.l\\t1f,r0\\n\\
                                    : GET_MODE (sh_compare_op1),
                                    sh_compare_op1);
 
-      tmp = no_new_pseudos ? operands[0] : gen_reg_rtx (DImode);
+      tmp = !can_create_pseudo_p () ? operands[0] : gen_reg_rtx (SImode);
 
       emit_insn (gen_cmpgtudi_media (tmp, sh_compare_op1, sh_compare_op0));
-      emit_insn (gen_cmpeqdi_media (operands[0], tmp, const0_rtx));
+      emit_insn (gen_cmpeqdi_media (reg, tmp, const0_rtx));
+      if (GET_MODE (operands[0]) == DImode)
+       emit_insn (gen_extendsidi2 (operands[0], reg));
 
       DONE;
     }
@@ -9585,11 +10132,13 @@ mov.l\\t1f,r0\\n\\
 {
   if (TARGET_SHMEDIA)
     {
-      rtx tmp;
-
-      if (GET_MODE (operands[0]) != DImode)
-       operands[0] = gen_rtx_SUBREG (DImode, operands[0], 0);
+      rtx tmp, reg;
 
+      reg = operands[0];
+      if (GET_MODE (operands[0]) != SImode)
+       reg = (!can_create_pseudo_p ()
+              ? gen_rtx_SUBREG (SImode, operands[0], 0)
+              : gen_reg_rtx (SImode));
       if (! TARGET_SHMEDIA_FPU
          && GET_MODE (sh_compare_op0) != DImode
          && GET_MODE (sh_compare_op0) != SImode)
@@ -9602,10 +10151,12 @@ mov.l\\t1f,r0\\n\\
                                    : GET_MODE (sh_compare_op1),
                                    sh_compare_op1);
 
-      tmp = no_new_pseudos ? operands[0] : gen_reg_rtx (DImode);
+      tmp = !can_create_pseudo_p () ? reg : gen_reg_rtx (SImode);
 
       emit_insn (gen_seq (tmp));
-      emit_insn (gen_cmpeqdi_media (operands[0], tmp, const0_rtx));
+      emit_insn (gen_cmpeqdi_media (reg, tmp, const0_rtx));
+      if (GET_MODE (operands[0]) == DImode)
+       emit_insn (gen_extendsidi2 (operands[0], reg));
 
       DONE;
     }
@@ -9619,8 +10170,8 @@ mov.l\\t1f,r0\\n\\
 }")
 
 (define_expand "sunordered"
-  [(set (match_operand:DI 0 "arith_reg_operand" "")
-       (unordered:DI (match_dup 1) (match_dup 2)))]
+  [(set (match_operand:SI 0 "arith_reg_operand" "")
+       (unordered:SI (match_dup 1) (match_dup 2)))]
   "TARGET_SHMEDIA_FPU"
   "
 {
@@ -9687,7 +10238,10 @@ mov.l\\t1f,r0\\n\\
  "*
 {
   if (operands[1] != const0_rtx)
-    assemble_integer (operands[0], 4, BITS_PER_UNIT * 4, 1);
+    {
+      assemble_integer (operands[0], 4, BITS_PER_UNIT * 4, 1);
+      mark_symbol_refs_as_used (operands[0]);
+    }
   return \"\";
 }"
  [(set_attr "length" "4")
@@ -9918,7 +10472,7 @@ mov.l\\t1f,r0\\n\\
        sts     fpscr,%0
        sts.l   fpscr,%0"
   [(set_attr "length" "0,2,2,4,2,2,2,2,2")
-   (set_attr "type" "nil,mem_fpscr,load,mem_fpscr,gp_fpscr,move,store,mac_gp,store")])
+   (set_attr "type" "nil,mem_fpscr,load,mem_fpscr,gp_fpscr,move,store,mac_gp,fstore")])
 
 (define_peephole2
   [(set (reg:PSI FPSCR_REG)
@@ -9933,7 +10487,7 @@ mov.l\\t1f,r0\\n\\
   mem = replace_equiv_address (mem, gen_rtx_POST_INC (Pmode, operands[0]));
 
   new_insn = emit_insn (gen_fpu_switch (fpscr, mem));
-  REG_NOTES (new_insn) = gen_rtx_EXPR_LIST (REG_INC, operands[0], NULL_RTX);
+  add_reg_note (new_insn, REG_INC, operands[0]);
   DONE;
 })
 
@@ -9941,7 +10495,7 @@ mov.l\\t1f,r0\\n\\
   [(set (reg:PSI FPSCR_REG)
        (mem:PSI (match_operand:SI 0 "register_operand" "")))]
   "(TARGET_SH4 || TARGET_SH2A_DOUBLE)
-   && (flag_peephole2 ? flow2_completed : reload_completed)"
+   && (flag_peephole2 ? epilogue_completed : reload_completed)"
   [(const_int 0)]
 {
   rtx fpscr, mem, new_insn;
@@ -9951,7 +10505,7 @@ mov.l\\t1f,r0\\n\\
   mem = replace_equiv_address (mem, gen_rtx_POST_INC (Pmode, operands[0]));
 
   new_insn = emit_insn (gen_fpu_switch (fpscr, mem));
-  REG_NOTES (new_insn) = gen_rtx_EXPR_LIST (REG_INC, operands[0], NULL_RTX);
+  add_reg_note (new_insn, REG_INC, operands[0]);
 
   if (!find_regno_note (curr_insn, REG_DEAD, true_regnum (operands[0])))
     emit_insn (gen_addsi3 (operands[0], operands[0], GEN_INT (-4)));
@@ -9969,7 +10523,7 @@ mov.l\\t1f,r0\\n\\
        (xor:PSI (reg:PSI FPSCR_REG) (const_int 1048576)))]
   "(TARGET_SH4 || TARGET_SH2A_DOUBLE)"
   "fschg"
-  [(set_attr "type" "fp") (set_attr "fp_set" "unknown")])
+  [(set_attr "type" "fpscr_toggle") (set_attr "fp_set" "unknown")])
 
 ;; There's no way we can use it today, since optimize mode switching
 ;; doesn't enable us to know from which mode we're switching to the
@@ -9981,7 +10535,7 @@ mov.l\\t1f,r0\\n\\
        (xor:PSI (reg:PSI FPSCR_REG) (const_int 524288)))]
   "TARGET_SH4A_FP && ! TARGET_FPU_SINGLE"
   "fpchg"
-  [(set_attr "type" "fp")])
+  [(set_attr "type" "fpscr_toggle")])
 
 (define_expand "addsf3"
   [(set (match_operand:SF 0 "arith_reg_operand" "")
@@ -10035,39 +10589,61 @@ mov.l\\t1f,r0\\n\\
 }"
   [(set_attr "type" "fparith_media")])
 
-(define_insn_and_split "binary_sf_op"
+(define_insn_and_split "binary_sf_op0"
   [(set (match_operand:V2SF 0 "fp_arith_reg_operand" "=f")
-       (vec_select:V2SF
-        (vec_concat:V2SF
+       (vec_concat:V2SF
+         (match_operator:SF 3 "binary_float_operator"
+           [(vec_select:SF (match_operand:V2SF 1 "fp_arith_reg_operand" "f")
+                           (parallel [(const_int 0)]))
+            (vec_select:SF (match_operand:V2SF 2 "fp_arith_reg_operand" "f")
+                           (parallel [(const_int 0)]))])
          (vec_select:SF
           (match_dup 0)
-          (parallel [(match_operand 7 "const_int_operand" "n")]))
+          (parallel [(const_int 1)]))))]
+  "TARGET_SHMEDIA_FPU"
+  "#"
+  "&& reload_completed"
+  [(set (match_dup 4) (match_dup 5))]
+  "
+{
+  int endian = TARGET_LITTLE_ENDIAN ? 0 : 1;
+  rtx op1 = gen_rtx_REG (SFmode,
+                        true_regnum (operands[1]) + endian);
+  rtx op2 = gen_rtx_REG (SFmode,
+                        true_regnum (operands[2]) + endian);
+
+  operands[4] = gen_rtx_REG (SFmode,
+                            true_regnum (operands[0]) + endian);
+  operands[5] = gen_rtx_fmt_ee (GET_CODE (operands[3]), SFmode, op1, op2);
+}"
+  [(set_attr "type" "fparith_media")])
+
+(define_insn_and_split "binary_sf_op1"
+  [(set (match_operand:V2SF 0 "fp_arith_reg_operand" "=f")
+       (vec_concat:V2SF
+         (vec_select:SF
+          (match_dup 0)
+          (parallel [(const_int 0)]))
          (match_operator:SF 3 "binary_float_operator"
            [(vec_select:SF (match_operand:V2SF 1 "fp_arith_reg_operand" "f")
-                           (parallel [(match_operand 5
-                                       "const_int_operand" "n")]))
+                           (parallel [(const_int 1)]))
             (vec_select:SF (match_operand:V2SF 2 "fp_arith_reg_operand" "f")
-                           (parallel [(match_operand 6
-                                       "const_int_operand" "n")]))]))
-        (parallel [(match_dup 7) (match_operand 4 "const_int_operand" "n")])))]
-  "TARGET_SHMEDIA_FPU && INTVAL (operands[4]) != INTVAL (operands[7])"
+                           (parallel [(const_int 1)]))])))]
+  "TARGET_SHMEDIA_FPU"
   "#"
   "&& reload_completed"
-  [(set (match_dup 8) (match_dup 9))]
+  [(set (match_dup 4) (match_dup 5))]
   "
 {
   int endian = TARGET_LITTLE_ENDIAN ? 0 : 1;
   rtx op1 = gen_rtx_REG (SFmode,
-                        (true_regnum (operands[1])
-                         + (INTVAL (operands[5]) ^ endian)));
+                        true_regnum (operands[1]) + (1 ^ endian));
   rtx op2 = gen_rtx_REG (SFmode,
-                        (true_regnum (operands[2])
-                         + (INTVAL (operands[6]) ^ endian)));
+                        true_regnum (operands[2]) + (1 ^ endian));
 
-  operands[8] = gen_rtx_REG (SFmode,
-                            (true_regnum (operands[0])
-                             + (INTVAL (operands[4]) ^ endian)));
-  operands[9] = gen_rtx_fmt_ee (GET_CODE (operands[3]), SFmode, op1, op2);
+  operands[4] = gen_rtx_REG (SFmode,
+                            true_regnum (operands[0]) + (1 ^ endian));
+  operands[5] = gen_rtx_fmt_ee (GET_CODE (operands[3]), SFmode, op1, op2);
 }"
   [(set_attr "type" "fparith_media")])
 
@@ -10113,25 +10689,12 @@ mov.l\\t1f,r0\\n\\
   [(set_attr "type" "fp")
    (set_attr "fp_mode" "single")])
 
-;; Unfortunately, the combiner is unable to cope with the USE of the FPSCR
-;; register in feeding fp instructions.  Thus, we cannot generate fmac for
-;; mixed-precision SH4 targets.  To allow it to be still generated for the
-;; SH3E, we use a separate insn for SH3E mulsf3.
-
 (define_expand "mulsf3"
   [(set (match_operand:SF 0 "fp_arith_reg_operand" "")
        (mult:SF (match_operand:SF 1 "fp_arith_reg_operand" "")
                 (match_operand:SF 2 "fp_arith_reg_operand" "")))]
   "TARGET_SH2E || TARGET_SHMEDIA_FPU"
-  "
-{
-  if (TARGET_SH4 || TARGET_SH2A_SINGLE)
-    expand_sf_binop (&gen_mulsf3_i4, operands);
-  else if (TARGET_SH2E)
-    emit_insn (gen_mulsf3_ie (operands[0], operands[1], operands[2]));
-  if (! TARGET_SHMEDIA)
-    DONE;
-}")
+  "")
 
 (define_insn "*mulsf3_media"
   [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
@@ -10141,6 +10704,27 @@ mov.l\\t1f,r0\\n\\
   "fmul.s      %1, %2, %0"
   [(set_attr "type" "fparith_media")])
 
+;; Unfortunately, the combiner is unable to cope with the USE of the FPSCR
+;; register in feeding fp instructions.  Thus, in order to generate fmac,
+;; we start out with a mulsf pattern that does not depend on fpscr.
+;; This is split after combine to introduce the dependency, in order to
+;; get mode switching and scheduling right.
+(define_insn_and_split "mulsf3_ie"
+  [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
+       (mult:SF (match_operand:SF 1 "fp_arith_reg_operand" "%0")
+                (match_operand:SF 2 "fp_arith_reg_operand" "f")))]
+  "TARGET_SH2E"
+  "fmul        %2,%0"
+  "TARGET_SH4 || TARGET_SH2A_SINGLE"
+  [(const_int 0)]
+  "
+{
+  emit_insn (gen_mulsf3_i4 (operands[0], operands[1], operands[2],
+            get_fpscr_rtx ()));
+  DONE;
+}"
+  [(set_attr "type" "fp")])
+
 (define_insn "mulsf3_i4"
   [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
        (mult:SF (match_operand:SF 1 "fp_arith_reg_operand" "%0")
@@ -10151,20 +10735,12 @@ mov.l\\t1f,r0\\n\\
   [(set_attr "type" "fp")
    (set_attr "fp_mode" "single")])
 
-(define_insn "mulsf3_ie"
-  [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
-       (mult:SF (match_operand:SF 1 "fp_arith_reg_operand" "%0")
-                (match_operand:SF 2 "fp_arith_reg_operand" "f")))]
-  "TARGET_SH2E && ! (TARGET_SH4 || TARGET_SH2A_SINGLE)"
-  "fmul        %2,%0"
-  [(set_attr "type" "fp")])
-
 (define_insn "mac_media"
   [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
        (plus:SF (mult:SF (match_operand:SF 1 "fp_arith_reg_operand" "%f")
                          (match_operand:SF 2 "fp_arith_reg_operand" "f"))
                 (match_operand:SF 3 "fp_arith_reg_operand" "0")))]
-  "TARGET_SHMEDIA_FPU"
+  "TARGET_SHMEDIA_FPU && TARGET_FMAC"
   "fmac.s %1, %2, %0"
   [(set_attr "type" "fparith_media")])
 
@@ -10174,7 +10750,7 @@ mov.l\\t1f,r0\\n\\
                          (match_operand:SF 2 "fp_arith_reg_operand" "f"))
                 (match_operand:SF 3 "arith_reg_operand" "0")))
    (use (match_operand:PSI 4 "fpscr_operand" "c"))]
-  "TARGET_SH2E && ! TARGET_SH4"
+  "TARGET_SH2E && TARGET_FMAC"
   "fmac        fr0,%2,%0"
   [(set_attr "type" "fp")
    (set_attr "fp_mode" "single")])
@@ -10325,7 +10901,7 @@ mov.l\\t1f,r0\\n\\
               (match_operand:SF 1 "fp_arith_reg_operand" "f")))]
   "TARGET_SH2E && ! (TARGET_SH4 || TARGET_SH2A_SINGLE)"
   "fcmp/gt     %1,%0"
-  [(set_attr "type" "fp")
+  [(set_attr "type" "fp_cmp")
    (set_attr "fp_mode" "single")])
 
 (define_insn "cmpeqsf_t"
@@ -10334,7 +10910,7 @@ mov.l\\t1f,r0\\n\\
               (match_operand:SF 1 "fp_arith_reg_operand" "f")))]
   "TARGET_SH2E && ! (TARGET_SH4 || TARGET_SH2A_SINGLE)"
   "fcmp/eq     %1,%0"
-  [(set_attr "type" "fp")
+  [(set_attr "type" "fp_cmp")
    (set_attr "fp_mode" "single")])
 
 (define_insn "ieee_ccmpeqsf_t"
@@ -10354,7 +10930,7 @@ mov.l\\t1f,r0\\n\\
    (use (match_operand:PSI 2 "fpscr_operand" "c"))]
   "(TARGET_SH4 || TARGET_SH2A_SINGLE)"
   "fcmp/gt     %1,%0"
-  [(set_attr "type" "fp")
+  [(set_attr "type" "fp_cmp")
    (set_attr "fp_mode" "single")])
 
 (define_insn "cmpeqsf_t_i4"
@@ -10364,7 +10940,7 @@ mov.l\\t1f,r0\\n\\
    (use (match_operand:PSI 2 "fpscr_operand" "c"))]
   "(TARGET_SH4 || TARGET_SH2A_SINGLE)"
   "fcmp/eq     %1,%0"
-  [(set_attr "type" "fp")
+  [(set_attr "type" "fp_cmp")
    (set_attr "fp_mode" "single")])
 
 (define_insn "*ieee_ccmpeqsf_t_4"
@@ -10379,14 +10955,6 @@ mov.l\\t1f,r0\\n\\
    (set_attr "fp_mode" "single")])
 
 (define_insn "cmpeqsf_media"
-  [(set (match_operand:DI 0 "register_operand" "=r")
-       (eq:DI (match_operand:SF 1 "fp_arith_reg_operand" "f")
-              (match_operand:SF 2 "fp_arith_reg_operand" "f")))]
-  "TARGET_SHMEDIA_FPU"
-  "fcmpeq.s    %1, %2, %0"
-  [(set_attr "type" "fcmp_media")])
-
-(define_insn "cmpsieqsf_media"
   [(set (match_operand:SI 0 "register_operand" "=r")
        (eq:SI (match_operand:SF 1 "fp_arith_reg_operand" "f")
               (match_operand:SF 2 "fp_arith_reg_operand" "f")))]
@@ -10395,24 +10963,24 @@ mov.l\\t1f,r0\\n\\
   [(set_attr "type" "fcmp_media")])
 
 (define_insn "cmpgtsf_media"
-  [(set (match_operand:DI 0 "register_operand" "=r")
-       (gt:DI (match_operand:SF 1 "fp_arith_reg_operand" "f")
+  [(set (match_operand:SI 0 "register_operand" "=r")
+       (gt:SI (match_operand:SF 1 "fp_arith_reg_operand" "f")
               (match_operand:SF 2 "fp_arith_reg_operand" "f")))]
   "TARGET_SHMEDIA_FPU"
   "fcmpgt.s    %1, %2, %0"
   [(set_attr "type" "fcmp_media")])
 
 (define_insn "cmpgesf_media"
-  [(set (match_operand:DI 0 "register_operand" "=r")
-       (ge:DI (match_operand:SF 1 "fp_arith_reg_operand" "f")
+  [(set (match_operand:SI 0 "register_operand" "=r")
+       (ge:SI (match_operand:SF 1 "fp_arith_reg_operand" "f")
               (match_operand:SF 2 "fp_arith_reg_operand" "f")))]
   "TARGET_SHMEDIA_FPU"
   "fcmpge.s    %1, %2, %0"
   [(set_attr "type" "fcmp_media")])
 
 (define_insn "cmpunsf_media"
-  [(set (match_operand:DI 0 "register_operand" "=r")
-       (unordered:DI (match_operand:SF 1 "fp_arith_reg_operand" "f")
+  [(set (match_operand:SI 0 "register_operand" "=r")
+       (unordered:SI (match_operand:SF 1 "fp_arith_reg_operand" "f")
                      (match_operand:SF 2 "fp_arith_reg_operand" "f")))]
   "TARGET_SHMEDIA_FPU"
   "fcmpun.s    %1, %2, %0"
@@ -10721,7 +11289,7 @@ mov.l\\t1f,r0\\n\\
    (use (match_operand:PSI 3 "fpscr_operand" "c"))]
   "(TARGET_SH4 || TARGET_SH2A_DOUBLE)"
   "fmul        %2,%0"
-  [(set_attr "type" "dfp_arith")
+  [(set_attr "type" "dfp_mul")
    (set_attr "fp_mode" "double")])
 
 (define_expand "divdf3"
@@ -10885,14 +11453,6 @@ mov.l\\t1f,r0\\n\\
    (set_attr "fp_mode" "double")])
 
 (define_insn "cmpeqdf_media"
-  [(set (match_operand:DI 0 "register_operand" "=r")
-       (eq:DI (match_operand:DF 1 "fp_arith_reg_operand" "f")
-              (match_operand:DF 2 "fp_arith_reg_operand" "f")))]
-  "TARGET_SHMEDIA_FPU"
-  "fcmpeq.d    %1,%2,%0"
-  [(set_attr "type" "fcmp_media")])
-
-(define_insn "cmpsieqdf_media"
   [(set (match_operand:SI 0 "register_operand" "=r")
        (eq:SI (match_operand:DF 1 "fp_arith_reg_operand" "f")
               (match_operand:DF 2 "fp_arith_reg_operand" "f")))]
@@ -10901,24 +11461,24 @@ mov.l\\t1f,r0\\n\\
   [(set_attr "type" "fcmp_media")])
 
 (define_insn "cmpgtdf_media"
-  [(set (match_operand:DI 0 "register_operand" "=r")
-       (gt:DI (match_operand:DF 1 "fp_arith_reg_operand" "f")
+  [(set (match_operand:SI 0 "register_operand" "=r")
+       (gt:SI (match_operand:DF 1 "fp_arith_reg_operand" "f")
               (match_operand:DF 2 "fp_arith_reg_operand" "f")))]
   "TARGET_SHMEDIA_FPU"
   "fcmpgt.d    %1,%2,%0"
   [(set_attr "type" "fcmp_media")])
 
 (define_insn "cmpgedf_media"
-  [(set (match_operand:DI 0 "register_operand" "=r")
-       (ge:DI (match_operand:DF 1 "fp_arith_reg_operand" "f")
+  [(set (match_operand:SI 0 "register_operand" "=r")
+       (ge:SI (match_operand:DF 1 "fp_arith_reg_operand" "f")
               (match_operand:DF 2 "fp_arith_reg_operand" "f")))]
   "TARGET_SHMEDIA_FPU"
   "fcmpge.d    %1,%2,%0"
   [(set_attr "type" "fcmp_media")])
 
 (define_insn "cmpundf_media"
-  [(set (match_operand:DI 0 "register_operand" "=r")
-       (unordered:DI (match_operand:DF 1 "fp_arith_reg_operand" "f")
+  [(set (match_operand:SI 0 "register_operand" "=r")
+       (unordered:SI (match_operand:DF 1 "fp_arith_reg_operand" "f")
                      (match_operand:DF 2 "fp_arith_reg_operand" "f")))]
   "TARGET_SHMEDIA_FPU"
   "fcmpun.d    %1,%2,%0"
@@ -11098,6 +11658,36 @@ mov.l\\t1f,r0\\n\\
   HOST_WIDE_INT bitsize, size, v = 0;
   rtx x = operands[3];
 
+  if (TARGET_SH2A && TARGET_BITOPS
+      && (satisfies_constraint_Sbw (operands[0])
+         || satisfies_constraint_Sbv (operands[0]))
+      && satisfies_constraint_M (operands[1])
+      && satisfies_constraint_K03 (operands[2]))
+    {
+      if (satisfies_constraint_N (operands[3]))
+       {
+         emit_insn (gen_bclr_m2a (operands[0], operands[2]));
+         DONE;
+       }
+      else if (satisfies_constraint_M (operands[3]))
+       {
+         emit_insn (gen_bset_m2a (operands[0], operands[2]));
+         DONE;
+       }
+      else if ((REG_P (operands[3]) && REGNO (operands[3]) == T_REG)
+               && satisfies_constraint_M (operands[1]))
+       {
+         emit_insn (gen_bst_m2a (operands[0], operands[2]));
+         DONE;
+       }
+      else if (REG_P (operands[3])
+              && satisfies_constraint_M (operands[1]))
+       {
+         emit_insn (gen_bld_reg (operands[3], const0_rtx));
+         emit_insn (gen_bst_m2a (operands[0], operands[2]));
+         DONE;
+       }
+    }
   /* ??? expmed doesn't care for non-register predicates.  */
   if (! memory_operand (operands[0], VOIDmode)
       || ! immediate_operand (operands[1], VOIDmode)
@@ -11175,8 +11765,19 @@ mov.l\\t1f,r0\\n\\
        (sign_extract:SI (match_operand:QI 1 "unaligned_load_operand" "")
                         (match_operand 2 "const_int_operand" "")
                         (match_operand 3 "const_int_operand" "")))]
-  "TARGET_SH4A_ARCH"
-{
+  "TARGET_SH4A_ARCH || TARGET_SH2A"
+{
+  if (TARGET_SH2A && TARGET_BITOPS
+      && (satisfies_constraint_Sbw (operands[1])
+         || satisfies_constraint_Sbv (operands[1]))
+      && satisfies_constraint_M (operands[2])
+      && satisfies_constraint_K03 (operands[3]))
+   {
+      emit_insn (gen_bldsign_m2a (operands[1], operands[3]));
+      if (REGNO (operands[0]) != T_REG)
+       emit_insn (gen_movsi (operands[0], gen_rtx_REG (SImode, T_REG)));
+      DONE;
+   }
   if (TARGET_SH4A_ARCH
       && INTVAL (operands[2]) == 32
       && INTVAL (operands[3]) == -24 * (BITS_BIG_ENDIAN != BYTES_BIG_ENDIAN)
@@ -11196,8 +11797,19 @@ mov.l\\t1f,r0\\n\\
        (zero_extract:SI (match_operand:QI 1 "unaligned_load_operand" "")
                         (match_operand 2 "const_int_operand" "")
                         (match_operand 3 "const_int_operand" "")))]
-  "TARGET_SH4A_ARCH"
+  "TARGET_SH4A_ARCH || TARGET_SH2A"
 {
+  if (TARGET_SH2A && TARGET_BITOPS
+      && (satisfies_constraint_Sbw (operands[1])
+         || satisfies_constraint_Sbv (operands[1]))
+      && satisfies_constraint_M (operands[2])
+      && satisfies_constraint_K03 (operands[3]))
+    {
+      emit_insn (gen_bld_m2a (operands[1], operands[3]));
+      if (REGNO (operands[0]) != T_REG)
+       emit_insn (gen_movsi (operands[0], gen_rtx_REG (SImode, T_REG)));
+      DONE;
+    }
   if (TARGET_SH4A_ARCH
       && INTVAL (operands[2]) == 32
       && INTVAL (operands[3]) == -24 * (BITS_BIG_ENDIAN != BYTES_BIG_ENDIAN)
@@ -11212,10 +11824,235 @@ mov.l\\t1f,r0\\n\\
   FAIL;
 })
 
+;; SH2A instructions for bitwise operations.
+
+;; Clear a bit in a memory location.
+(define_insn "bclr_m2a"
+  [(set (match_operand:QI 0 "bitwise_memory_operand" "+Sbw,Sbv")
+       (and:QI
+           (not:QI (ashift:QI (const_int 1)
+                       (match_operand:QI 1 "const_int_operand" "K03,K03")))
+           (match_dup 0)))]
+  "TARGET_SH2A && TARGET_BITOPS"
+  "@
+       bclr.b\\t%1,%0
+       bclr.b\\t%1,@(0,%t0)"
+[(set_attr "length" "4,4")])
+
+(define_insn "bclrmem_m2a"
+  [(set (match_operand:QI 0 "bitwise_memory_operand" "+Sbw,Sbv")
+        (and:QI (match_dup 0)
+                (match_operand:QI 1 "const_int_operand" "Psz,Psz")))]
+  "TARGET_SH2A && satisfies_constraint_Psz (operands[1]) && TARGET_BITOPS"
+  "@
+        bclr.b\\t%W1,%0
+        bclr.b\\t%W1,@(0,%t0)"
+  [(set_attr "length" "4,4")])
+
+;; Set a bit in a memory location.
+(define_insn "bset_m2a"
+  [(set (match_operand:QI 0 "bitwise_memory_operand" "+Sbw,Sbv")
+       (ior:QI
+           (ashift:QI (const_int 1)
+                      (match_operand:QI 1 "const_int_operand" "K03,K03"))
+           (match_dup 0)))]
+  "TARGET_SH2A && TARGET_BITOPS"
+  "@
+       bset.b\\t%1,%0
+       bset.b\\t%1,@(0,%t0)"
+  [(set_attr "length" "4,4")])
+
+(define_insn "bsetmem_m2a"
+  [(set (match_operand:QI 0 "bitwise_memory_operand" "+Sbw,Sbv")
+       (ior:QI (match_dup 0)
+               (match_operand:QI 1 "const_int_operand" "Pso,Pso")))]
+  "TARGET_SH2A && satisfies_constraint_Pso (operands[1]) && TARGET_BITOPS"
+  "@
+        bset.b\\t%V1,%0
+        bset.b\\t%V1,@(0,%t0)"
+  [(set_attr "length" "4,4")])
+
+;;; Transfer the contents of the T bit to a specified bit of memory.
+(define_insn "bst_m2a"
+  [(set (match_operand:QI 0 "bitwise_memory_operand" "+Sbw,m")
+       (if_then_else (eq (reg:SI T_REG) (const_int 0))
+           (and:QI
+               (not:QI (ashift:QI (const_int 1)
+                       (match_operand:QI 1 "const_int_operand" "K03,K03")))
+               (match_dup 0))
+           (ior:QI
+               (ashift:QI (const_int 1) (match_dup 1))
+               (match_dup 0))))]
+  "TARGET_SH2A && TARGET_BITOPS"
+  "@
+       bst.b\\t%1,%0
+       bst.b\\t%1,@(0,%t0)"
+  [(set_attr "length" "4")])
+
+;; Store a specified bit of memory in the T bit.
+(define_insn "bld_m2a"
+  [(set (reg:SI T_REG)
+       (zero_extract:SI
+           (match_operand:QI 0 "bitwise_memory_operand" "Sbw,Sbv")
+           (const_int 1)
+           (match_operand 1 "const_int_operand" "K03,K03")))]
+  "TARGET_SH2A && TARGET_BITOPS"
+  "@
+       bld.b\\t%1,%0
+       bld.b\\t%1,@(0,%t0)"
+  [(set_attr "length" "4,4")])
+
+;; Store a specified bit of memory in the T bit.
+(define_insn "bldsign_m2a"
+  [(set (reg:SI T_REG)
+       (sign_extract:SI
+           (match_operand:QI 0 "bitwise_memory_operand" "Sbw,m")
+           (const_int 1)
+           (match_operand 1 "const_int_operand" "K03,K03")))]
+  "TARGET_SH2A && TARGET_BITOPS"
+  "@
+       bld.b\\t%1,%0
+       bld.b\\t%1,@(0,%t0)"
+  [(set_attr "length" "4,4")])
+
+;; Store a specified bit of the LSB 8 bits of a register in the T bit.
+(define_insn "bld_reg"
+  [(set (reg:SI T_REG)
+       (zero_extract:SI (match_operand:SI 0 "arith_reg_operand" "r")
+                        (const_int 1)
+                        (match_operand 1 "const_int_operand" "K03")))]
+  "TARGET_SH2A"
+  "bld\\t%1,%0")
+
+(define_insn "*bld_regqi"
+  [(set (reg:SI T_REG)
+       (zero_extract:SI (match_operand:QI 0 "arith_reg_operand" "r")
+                        (const_int 1)
+                        (match_operand 1 "const_int_operand" "K03")))]
+  "TARGET_SH2A"
+  "bld\\t%1,%0")
+
+;; Take logical and of a specified bit of memory with the T bit and
+;; store its result in the T bit.
+(define_insn "band_m2a"
+  [(set (reg:SI T_REG)
+       (and:SI (reg:SI T_REG)
+               (zero_extract:SI
+                   (match_operand:QI 0 "bitwise_memory_operand" "Sbw,m")
+                   (const_int 1)
+                   (match_operand 1 "const_int_operand" "K03,K03"))))]
+  "TARGET_SH2A && TARGET_BITOPS"
+  "@
+       band.b\\t%1,%0
+       band.b\\t%1,@(0,%t0)"
+  [(set_attr "length" "4,4")])
+
+(define_insn "bandreg_m2a"
+  [(set (match_operand:SI 0 "register_operand" "=r,r")
+       (and:SI (zero_extract:SI
+                   (match_operand:QI 1 "bitwise_memory_operand" "Sbw,Sbv")
+                   (const_int 1)
+                   (match_operand 2 "const_int_operand" "K03,K03"))
+               (match_operand:SI 3 "register_operand" "r,r")))]
+  "TARGET_SH2A && TARGET_BITOPS"
+  "@
+       band.b\\t%2,%1\;movt\\t%0
+       band.b\\t%2,@(0,%t1)\;movt\\t%0"
+  [(set_attr "length" "6,6")])
+
+;; Take logical or of a specified bit of memory with the T bit and
+;; store its result in the T bit.
+(define_insn "bor_m2a"
+  [(set (reg:SI T_REG)
+       (ior:SI (reg:SI T_REG)
+               (zero_extract:SI
+                   (match_operand:QI 0 "bitwise_memory_operand" "Sbw,m")
+                   (const_int 1)
+                   (match_operand 1 "const_int_operand" "K03,K03"))))]
+  "TARGET_SH2A && TARGET_BITOPS"
+  "@
+       bor.b\\t%1,%0
+       bor.b\\t%1,@(0,%t0)"
+  [(set_attr "length" "4,4")])
+
+(define_insn "borreg_m2a"
+  [(set (match_operand:SI 0 "register_operand" "=r,r")
+       (ior:SI (zero_extract:SI
+                   (match_operand:QI 1 "bitwise_memory_operand" "Sbw,Sbv")
+                   (const_int 1)
+                   (match_operand 2 "const_int_operand" "K03,K03"))
+               (match_operand:SI 3 "register_operand" "=r,r")))]
+  "TARGET_SH2A && TARGET_BITOPS"
+  "@
+       bor.b\\t%2,%1\;movt\\t%0
+       bor.b\\t%2,@(0,%t1)\;movt\\t%0"
+  [(set_attr "length" "6,6")])
+
+;; Take exclusive or of a specified bit of memory with the T bit and
+;; store its result in the T bit.
+(define_insn "bxor_m2a"
+  [(set (reg:SI T_REG)
+       (xor:SI (reg:SI T_REG)
+               (zero_extract:SI
+                   (match_operand:QI 0 "bitwise_memory_operand" "Sbw,m")
+                   (const_int 1)
+                   (match_operand 1 "const_int_operand" "K03,K03"))))]
+  "TARGET_SH2A && TARGET_BITOPS"
+  "@
+       bxor.b\\t%1,%0
+       bxor.b\\t%1,@(0,%t0)"
+  [(set_attr "length" "4,4")])
+
+(define_insn "bxorreg_m2a"
+  [(set (match_operand:SI 0 "register_operand" "=r,r")
+       (xor:SI (zero_extract:SI
+                   (match_operand:QI 1 "bitwise_memory_operand" "Sbw,Sbv")
+                   (const_int 1)
+                   (match_operand 2 "const_int_operand" "K03,K03"))
+               (match_operand:SI 3 "register_operand" "=r,r")))]
+  "TARGET_SH2A && TARGET_BITOPS"
+  "@
+       bxor.b\\t%2,%1\;movt\\t%0
+       bxor.b\\t%2,@(0,%t1)\;movt\\t%0"
+  [(set_attr "length" "6,6")])
+
 \f
 ;; -------------------------------------------------------------------------
 ;; Peepholes
 ;; -------------------------------------------------------------------------
+;; This matches cases where the bit in a memory location is set.
+(define_peephole2
+  [(set (match_operand:SI 0 "arith_reg_operand" "r,r")
+       (sign_extend:SI (match_operand:QI 1 "bitwise_memory_operand" "Sbw,Sbv")))
+   (set (match_dup 0)
+       (ior:SI (match_dup 0)
+       (match_operand:SI 2 "const_int_operand" "Pso,Pso")))
+   (set (match_dup 1)
+       (match_operand 3 "arith_reg_operand" "r,r"))]
+  "TARGET_SH2A && TARGET_BITOPS
+   && satisfies_constraint_Pso (operands[2])
+   && REGNO (operands[0]) == REGNO (operands[3])"
+  [(set (match_dup 1)
+        (ior:QI (match_dup 1)
+                (match_dup 2)))]
+  "")
+
+;; This matches cases where the bit in a memory location is cleared.
+(define_peephole2
+  [(set (match_operand:SI 0 "arith_reg_operand" "r,r")
+       (sign_extend:SI (match_operand:QI 1 "bitwise_memory_operand" "Sbw,Sbv")))
+   (set (match_dup 0)
+       (and:SI (match_dup 0)
+       (match_operand:SI 2 "const_int_operand" "Psz,Psz")))
+   (set (match_dup 1)
+       (match_operand 3 "arith_reg_operand" "r,r"))]
+  "TARGET_SH2A && TARGET_BITOPS
+   && satisfies_constraint_Psz (operands[2])
+   && REGNO (operands[0]) == REGNO (operands[3])"
+  [(set (match_dup 1)
+        (and:QI (match_dup 1)
+                (match_dup 2)))]
+  "")
 
 ;; This matches cases where a stack pointer increment at the start of the
 ;; epilogue combines with a stack slot read loading the return value.
@@ -13124,9 +13961,8 @@ mov.l\\t1f,r0\\n\\
   emit_insn (gen_adddi3 (scratch, scratch, GEN_INT (-64)));
   emit_insn (gen_movdicc_false (scratch, operands[1], const0_rtx, scratch));
   last = emit_insn (gen_subdi3 (operands[0], const0_rtx, scratch));
-  REG_NOTES (last)
-    = gen_rtx_EXPR_LIST (REG_EQUAL,
-                        gen_rtx_FFS (DImode, operands[0]), REG_NOTES (last));
+  set_unique_reg_note (last, REG_EQUAL, gen_rtx_FFS (DImode, operands[0]));
+
   DONE;
 }")
 
@@ -13149,9 +13985,8 @@ mov.l\\t1f,r0\\n\\
   emit_insn (gen_nsbsi (scratch, discratch));
   last = emit_insn (gen_subsi3 (operands[0],
                                force_reg (SImode, GEN_INT (63)), scratch));
-  REG_NOTES (last)
-    = gen_rtx_EXPR_LIST (REG_EQUAL,
-                        gen_rtx_FFS (SImode, operands[0]), REG_NOTES (last));
+  set_unique_reg_note (last, REG_EQUAL, gen_rtx_FFS (SImode, operands[0]));
+
   DONE;
 }")
 
@@ -13182,18 +14017,22 @@ mov.l\\t1f,r0\\n\\
   [(prefetch (match_operand:SI 0 "register_operand" "r")
              (match_operand:SI 1 "const_int_operand" "n")
              (match_operand:SI 2 "const_int_operand" "n"))]
-  "TARGET_HARD_SH4 || TARGET_SHCOMPACT"
+  "(TARGET_HARD_SH4 || TARGET_SHCOMPACT) && !TARGET_VXWORKS_RTP"
   "*
 {
   return \"pref @%0\";
 }"
   [(set_attr "type" "other")])
 
+;; In user mode, the "pref" instruction will raise a RADDERR exception
+;; for accesses to [0x80000000,0xffffffff].  This makes it an unsuitable
+;; implementation of __builtin_prefetch for VxWorks RTPs.
 (define_expand "prefetch"
   [(prefetch (match_operand 0 "address_operand" "p")
              (match_operand:SI 1 "const_int_operand" "n")
              (match_operand:SI 2 "const_int_operand" "n"))]
-  "TARGET_HARD_SH4 || TARGET_SH5"
+  "TARGET_SH2A || ((TARGET_HARD_SH4 || TARGET_SH5)
+   && (TARGET_SHMEDIA || !TARGET_VXWORKS_RTP))"
   "
 {
   if (GET_MODE (operands[0]) != Pmode
@@ -13204,6 +14043,14 @@ mov.l\\t1f,r0\\n\\
     operands[0] = force_reg (Pmode, operands[0]);
 }")
 
+(define_insn "prefetch_m2a"
+  [(prefetch (match_operand:SI 0 "register_operand" "r")
+            (match_operand:SI 1 "const_int_operand" "n")
+            (match_operand:SI 2 "const_int_operand" "n"))]
+  "TARGET_SH2A"
+  "pref\\t@%0"
+  [(set_attr "type" "other")])
+
 (define_insn "alloco_i"
   [(set (mem:BLK (match_operand:QI 0 "cache_address_operand" "p"))
        (unspec:BLK [(const_int 0)] UNSPEC_ALLOCO))]