]> oss.titaniummirror.com Git - msp430-gcc.git/blobdiff - gcc/config/sh/sh.h
Imported gcc-4.4.3
[msp430-gcc.git] / gcc / config / sh / sh.h
index 1a486214e333b94b1d636a010ab598a55a772e29..6a4ccb0f0e64f80ac44a0174e329ce396c1461af 100644 (file)
@@ -1,97 +1,99 @@
-/* Definitions of target machine for GNU compiler for Hitachi / SuperH SH.
-   Copyright (C) 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002
-   Free Software Foundation, Inc.
+/* Definitions of target machine for GNU compiler for Renesas / SuperH SH.
+   Copyright (C) 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
+   2003, 2004, 2005, 2006, 2007, 2008 Free Software Foundation, Inc.
    Contributed by Steve Chamberlain (sac@cygnus.com).
    Improved by Jim Wilson (wilson@cygnus.com).
 
-This file is part of GNU CC.
+This file is part of GCC.
 
-GNU CC is free software; you can redistribute it and/or modify
+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.
 
-GNU CC is distributed in the hope that it will be useful,
+GCC is distributed in the hope that it will be useful,
 but WITHOUT ANY WARRANTY; without even the implied warranty of
 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 GNU General Public License for more details.
 
 You should have received a copy of the GNU General Public License
-along with GNU CC; see the file COPYING.  If not, write to
-the Free Software Foundation, 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA.  */
+along with GCC; see the file COPYING3.  If not see
+<http://www.gnu.org/licenses/>.  */
 
 #ifndef GCC_SH_H
 #define GCC_SH_H
 
+#include "config/vxworks-dummy.h"
+
 #define TARGET_VERSION \
   fputs (" (Hitachi SH)", stderr);
 
 /* Unfortunately, insn-attrtab.c doesn't include insn-codes.h.  We can't
-   include it here, because hconfig.h is also included by gencodes.c .  */
+   include it here, because bconfig.h is also included by gencodes.c .  */
 /* ??? No longer true.  */
 extern int code_for_indirect_jump_scratch;
 
-/* Generate SDB debugging information.  */
-
-#define SDB_DEBUGGING_INFO
-
-/* Output DBX (stabs) debugging information if doing -gstabs.  */
-
-#include "dbxcoff.h"
-
-#define SDB_DELIM ";"
-
-#define CPP_SPEC " \
-%{m5-64media|m5-64media-nofpu|m5-32media|m5-32media-nofpu:-D__SHMEDIA__=1} \
-%{m5-compact|m5-compact-nofpu:-D__SHMEDIA__=0} \
-%{m5-64media|m5-64media-nofpu:-D__SH5__=64 -D__LONG_MAX__=9223372036854775807L} \
-%{m5-32media|m5-32media-nofpu|m5-compact|m5-compact-nofpu:-D__SH5__=32} \
-%{m5-64media-nofpu|m5-32media-nofpu|m5-compact-nofpu:-D__SH4_NOFPU__} \
-%{m1:-D__sh1__} \
-%{m2:-D__sh2__} \
-%{m3:-D__sh3__} \
-%{m3e:-D__SH3E__} \
-%{m4-single-only:-D__SH4_SINGLE_ONLY__} \
-%{m4-single:-D__SH4_SINGLE__} \
-%{m4-nofpu:-D__sh3__ -D__SH4_NOFPU__} \
-%{m4:-D__SH4__} \
-%{!m1:%{!m2:%{!m3*:%{!m4*:%{!m5*:%(cpp_default_cpu_spec)}}}}} \
-%{mhitachi:-D__HITACHI__} \
-%(subtarget_cpp_spec) \
-%(subtarget_cpp_ptr_spec) \
-%(subtarget_cpp_endian_spec) "
-
-#ifndef SUBTARGET_CPP_ENDIAN_SPEC
-#define SUBTARGET_CPP_ENDIAN_SPEC "%{ml:-D__LITTLE_ENDIAN__}"
-#endif
-
-#ifndef SUBTARGET_CPP_SPEC
-#define SUBTARGET_CPP_SPEC ""
-#endif
-
-#ifndef CPP_DEFAULT_CPU_SPEC
-#define CPP_DEFAULT_CPU_SPEC "-D__sh1__"
-#endif
-
-#ifndef SUBTARGET_CPP_PTR_SPEC
-#define SUBTARGET_CPP_PTR_SPEC "\
-%{m5-64media|m5-64media-nofpu|m5-32media|m5-32media-nofpu|m5-compact|m5-compact-nofpu:-D__SIZE_TYPE__=long\\ unsigned\\ int -D__PTRDIFF_TYPE__=long\\ int} \
-%{!m5-64media:%{!m5-64media-nofpu:%{!m5-32media:%{!m5-32media-nofpu:%{!m5-compact:%{!m5-compact-nofpu:-D__SIZE_TYPE__=unsigned\\ int -D__PTRDIFF_TYPE__=int}}}}}} \
-"
-#endif
-
-#define EXTRA_SPECS                                            \
-  { "subtarget_cpp_spec", SUBTARGET_CPP_SPEC },                        \
-  { "subtarget_cpp_endian_spec", SUBTARGET_CPP_ENDIAN_SPEC },  \
-  { "subtarget_cpp_ptr_spec", SUBTARGET_CPP_PTR_SPEC },                \
-  { "cpp_default_cpu_spec", CPP_DEFAULT_CPU_SPEC },
-
-#define CPP_PREDEFINES "-D__sh__ -Acpu=sh -Amachine=sh"
-
-#define ASM_SPEC  "%{ml:-little} %{mrelax:-relax}"
-
-#define LINK_SPEC "%{ml:-m shl} %{mrelax:-relax}"
+#define TARGET_CPU_CPP_BUILTINS() \
+do { \
+  builtin_define ("__sh__"); \
+  builtin_assert ("cpu=sh"); \
+  builtin_assert ("machine=sh"); \
+  switch ((int) sh_cpu) \
+    { \
+    case PROCESSOR_SH1: \
+      builtin_define ("__sh1__"); \
+      break; \
+    case PROCESSOR_SH2: \
+      builtin_define ("__sh2__"); \
+      break; \
+    case PROCESSOR_SH2E: \
+      builtin_define ("__SH2E__"); \
+      break; \
+    case PROCESSOR_SH2A: \
+      builtin_define ("__SH2A__"); \
+      builtin_define (TARGET_SH2A_DOUBLE \
+                     ? (TARGET_FPU_SINGLE ? "__SH2A_SINGLE__" : "__SH2A_DOUBLE__") \
+                     : TARGET_FPU_ANY ? "__SH2A_SINGLE_ONLY__" \
+                     : "__SH2A_NOFPU__"); \
+      break; \
+    case PROCESSOR_SH3: \
+      builtin_define ("__sh3__"); \
+      builtin_define ("__SH3__"); \
+      if (TARGET_HARD_SH4) \
+       builtin_define ("__SH4_NOFPU__"); \
+      break; \
+    case PROCESSOR_SH3E: \
+      builtin_define (TARGET_HARD_SH4 ? "__SH4_SINGLE_ONLY__" : "__SH3E__"); \
+      break; \
+    case PROCESSOR_SH4: \
+      builtin_define (TARGET_FPU_SINGLE ? "__SH4_SINGLE__" : "__SH4__"); \
+      break; \
+    case PROCESSOR_SH4A: \
+      builtin_define ("__SH4A__"); \
+      builtin_define (TARGET_SH4 \
+                     ? (TARGET_FPU_SINGLE ? "__SH4_SINGLE__" : "__SH4__") \
+                     : TARGET_FPU_ANY ? "__SH4_SINGLE_ONLY__" \
+                     : "__SH4_NOFPU__"); \
+      break; \
+    case PROCESSOR_SH5: \
+      { \
+       builtin_define_with_value ("__SH5__", \
+                                  TARGET_SHMEDIA64 ? "64" : "32", 0); \
+       builtin_define_with_value ("__SHMEDIA__", \
+                                  TARGET_SHMEDIA ? "1" : "0", 0); \
+       if (! TARGET_FPU_DOUBLE) \
+         builtin_define ("__SH4_NOFPU__"); \
+      } \
+    } \
+  if (TARGET_FPU_ANY) \
+    builtin_define ("__SH_FPU_ANY__"); \
+  if (TARGET_FPU_DOUBLE) \
+    builtin_define ("__SH_FPU_DOUBLE__"); \
+  if (TARGET_HITACHI) \
+    builtin_define ("__HITACHI__"); \
+  builtin_define (TARGET_LITTLE_ENDIAN \
+                 ? "__LITTLE_ENDIAN__" : "__BIG_ENDIAN__"); \
+} while (0)
 
 /* We can not debug without a frame pointer.  */
 /* #define CAN_DEBUG_WITHOUT_FP */
@@ -104,8 +106,12 @@ extern int code_for_indirect_jump_scratch;
       fixed_regs[regno] = call_used_regs[regno] = 1;                   \
   /* R8 and R9 are call-clobbered on SH5, but not on earlier SH ABIs.  */ \
   if (TARGET_SH5)                                                      \
-    call_used_regs[FIRST_GENERAL_REG + 8]                              \
-      = call_used_regs[FIRST_GENERAL_REG + 9] = 1;                     \
+    {                                                                  \
+      call_used_regs[FIRST_GENERAL_REG + 8]                            \
+       = call_used_regs[FIRST_GENERAL_REG + 9] = 1;                    \
+      call_really_used_regs[FIRST_GENERAL_REG + 8]                     \
+       = call_really_used_regs[FIRST_GENERAL_REG + 9] = 1;             \
+    }                                                                  \
   if (TARGET_SHMEDIA)                                                  \
     {                                                                  \
       regno_reg_class[FIRST_GENERAL_REG] = GENERAL_REGS;               \
@@ -113,97 +119,74 @@ extern int code_for_indirect_jump_scratch;
       regno_reg_class[FIRST_FP_REG] = FP_REGS;                         \
     }                                                                  \
   if (flag_pic)                                                                \
-    fixed_regs[PIC_OFFSET_TABLE_REGNUM] = 1;                           \
-  /* Hitachi saves and restores mac registers on call.  */             \
+    {                                                                  \
+      fixed_regs[PIC_OFFSET_TABLE_REGNUM] = 1;                         \
+      call_used_regs[PIC_OFFSET_TABLE_REGNUM] = 1;                     \
+    }                                                                  \
+  /* Renesas saves and restores mac registers on call.  */             \
   if (TARGET_HITACHI && ! TARGET_NOMACSAVE)                            \
     {                                                                  \
-      call_used_regs[MACH_REG] = 0;                                    \
-      call_used_regs[MACL_REG] = 0;                                    \
+      call_really_used_regs[MACH_REG] = 0;                             \
+      call_really_used_regs[MACL_REG] = 0;                             \
     }                                                                  \
+  for (regno = FIRST_FP_REG + (TARGET_LITTLE_ENDIAN != 0);             \
+       regno <= LAST_FP_REG; regno += 2)                               \
+    SET_HARD_REG_BIT (reg_class_contents[DF_HI_REGS], regno);          \
   if (TARGET_SHMEDIA)                                                  \
     {                                                                  \
       for (regno = FIRST_TARGET_REG; regno <= LAST_TARGET_REG; regno ++)\
-       if (! fixed_regs[regno] && call_used_regs[regno])               \
+       if (! fixed_regs[regno] && call_really_used_regs[regno])        \
          SET_HARD_REG_BIT (reg_class_contents[SIBCALL_REGS], regno);   \
     }                                                                  \
   else                                                                 \
     for (regno = FIRST_GENERAL_REG; regno <= LAST_GENERAL_REG; regno++)        \
-      if (! fixed_regs[regno] && call_used_regs[regno])                        \
+      if (! fixed_regs[regno] && call_really_used_regs[regno])         \
        SET_HARD_REG_BIT (reg_class_contents[SIBCALL_REGS], regno);     \
 } while (0)
 \f
-/* ??? Need to write documentation for all SH options and add it to the
-   invoke.texi file.  */
-
-/* Run-time compilation parameters selecting different hardware subsets.  */
-
-extern int target_flags;
-#define ISIZE_BIT              (1<<1)
-#define DALIGN_BIT             (1<<6)
-#define SH1_BIT                (1<<8)
-#define SH2_BIT                (1<<9)
-#define SH3_BIT                (1<<10)
-#define SH3E_BIT       (1<<11)
-#define HARD_SH4_BIT   (1<<5)
-#define FPU_SINGLE_BIT (1<<7)
-#define SH4_BIT                (1<<12)
-#define FMOVD_BIT      (1<<4)
-#define SH5_BIT                (1<<0)
-#define SPACE_BIT      (1<<13)
-#define BIGTABLE_BIT   (1<<14)
-#define RELAX_BIT      (1<<15)
-#define USERMODE_BIT   (1<<16)
-#define HITACHI_BIT     (1<<22)
-#define NOMACSAVE_BIT   (1<<23)
-#define PREFERGOT_BIT  (1<<24)
-#define PADSTRUCT_BIT  (1<<28)
-#define LITTLE_ENDIAN_BIT (1<<29)
-#define IEEE_BIT (1<<30)
-
-/* Nonzero if we should dump out instruction size info.  */
-#define TARGET_DUMPISIZE  (target_flags & ISIZE_BIT)
-
-/* Nonzero to align doubles on 64 bit boundaries.  */
-#define TARGET_ALIGN_DOUBLE (target_flags & DALIGN_BIT)
-
-/* Nonzero if we should generate code using type 1 insns.  */
-#define TARGET_SH1 (target_flags & SH1_BIT)
-
-/* Nonzero if we should generate code using type 2 insns.  */
-#define TARGET_SH2 (target_flags & SH2_BIT)
-
-/* Nonzero if we should generate code using type 3 insns.  */
-#define TARGET_SH3 (target_flags & SH3_BIT)
+/* Nonzero if this is an ELF target - compile time only */
+#define TARGET_ELF 0
+
+/* Nonzero if we should generate code using type 2E insns.  */
+#define TARGET_SH2E (TARGET_SH2 && TARGET_SH_E)
+
+/* Nonzero if we should generate code using type 2A insns.  */
+#define TARGET_SH2A TARGET_HARD_SH2A
+/* Nonzero if we should generate code using type 2A SF insns.  */
+#define TARGET_SH2A_SINGLE (TARGET_SH2A && TARGET_SH2E)
+/* Nonzero if we should generate code using type 2A DF insns.  */
+#define TARGET_SH2A_DOUBLE (TARGET_HARD_SH2A_DOUBLE && TARGET_SH2A)
 
 /* Nonzero if we should generate code using type 3E insns.  */
-#define TARGET_SH3E ((target_flags & SH3E_BIT) && (target_flags & SH1_BIT))
+#define TARGET_SH3E (TARGET_SH3 && TARGET_SH_E)
 
 /* Nonzero if the cache line size is 32.  */
-#define TARGET_CACHE32 (target_flags & HARD_SH4_BIT || TARGET_SH5)
+#define TARGET_CACHE32 (TARGET_HARD_SH4 || TARGET_SH5)
 
 /* Nonzero if we schedule for a superscalar implementation.  */
-#define TARGET_SUPERSCALAR (target_flags & HARD_SH4_BIT)
+#define TARGET_SUPERSCALAR TARGET_HARD_SH4
 
 /* Nonzero if the target has separate instruction and data caches.  */
-#define TARGET_HARVARD (target_flags & HARD_SH4_BIT)
-
-/* Nonzero if compiling for SH4 hardware (to be used for insn costs etc.)  */
-#define TARGET_HARD_SH4 (target_flags & HARD_SH4_BIT)
-
-/* Nonzero if the default precision of th FPU is single */
-#define TARGET_FPU_SINGLE (target_flags & FPU_SINGLE_BIT)
+#define TARGET_HARVARD (TARGET_HARD_SH4 || TARGET_SH5)
 
 /* Nonzero if a double-precision FPU is available.  */
-#define TARGET_FPU_DOUBLE (target_flags & SH4_BIT)
+#define TARGET_FPU_DOUBLE \
+  ((target_flags & MASK_SH4) != 0 || TARGET_SH2A_DOUBLE)
 
 /* Nonzero if an FPU is available.  */
-#define TARGET_FPU_ANY (TARGET_SH3E || TARGET_FPU_DOUBLE)
+#define TARGET_FPU_ANY (TARGET_SH2E || TARGET_FPU_DOUBLE)
 
 /* Nonzero if we should generate code using type 4 insns.  */
-#define TARGET_SH4 ((target_flags & SH4_BIT) && (target_flags & SH1_BIT))
+#undef TARGET_SH4
+#define TARGET_SH4 ((target_flags & MASK_SH4) != 0 && TARGET_SH1)
 
-/* Nonzero if we should generate code for a SH5 CPU (either ISA).  */
-#define TARGET_SH5 (target_flags & SH5_BIT)
+/* Nonzero if we're generating code for the common subset of
+   instructions present on both SH4a and SH4al-dsp.  */
+#define TARGET_SH4A_ARCH TARGET_SH4A
+
+/* Nonzero if we're generating code for SH4a, unless the use of the
+   FPU is disabled (which makes it compatible with SH4al-dsp).  */
+#define TARGET_SH4A_FP (TARGET_SH4A_ARCH && TARGET_FPU_ANY)
 
 /* Nonzero if we should generate code using the SHcompact instruction
    set and 32-bit ABI.  */
@@ -215,131 +198,365 @@ extern int target_flags;
 
 /* Nonzero if we should generate code using the SHmedia ISA and 32-bit
    ABI.  */
-#define TARGET_SHMEDIA32 (TARGET_SH5 && ! TARGET_SH1 \
-                         && (target_flags & SH3E_BIT))
+#define TARGET_SHMEDIA32 (TARGET_SH5 && ! TARGET_SH1 && TARGET_SH_E)
 
 /* Nonzero if we should generate code using the SHmedia ISA and 64-bit
    ABI.  */
-#define TARGET_SHMEDIA64 (TARGET_SH5 && ! TARGET_SH1 \
-                         && ! (target_flags & SH3E_BIT))
+#define TARGET_SHMEDIA64 (TARGET_SH5 && ! TARGET_SH1 && ! TARGET_SH_E)
 
 /* Nonzero if we should generate code using SHmedia FPU instructions.  */
 #define TARGET_SHMEDIA_FPU (TARGET_SHMEDIA && TARGET_FPU_DOUBLE)
-/* Nonzero if we should generate fmovd.  */
-#define TARGET_FMOVD (target_flags & FMOVD_BIT)
 
-/* Nonzero if we respect NANs.  */
-#define TARGET_IEEE (target_flags & IEEE_BIT)
+/* This is not used by the SH2E calling convention  */
+#define TARGET_VARARGS_PRETEND_ARGS(FUN_DECL) \
+  (TARGET_SH1 && ! TARGET_SH2E && ! TARGET_SH5 \
+   && ! (TARGET_HITACHI || sh_attr_renesas_p (FUN_DECL)))
+
+#ifndef TARGET_CPU_DEFAULT
+#define TARGET_CPU_DEFAULT SELECT_SH1
+#define SUPPORT_SH1 1
+#define SUPPORT_SH2E 1
+#define SUPPORT_SH4 1
+#define SUPPORT_SH4_SINGLE 1
+#define SUPPORT_SH2A 1
+#define SUPPORT_SH2A_SINGLE 1
+#endif
+
+#define TARGET_DIVIDE_INV \
+  (sh_div_strategy == SH_DIV_INV || sh_div_strategy == SH_DIV_INV_MINLAT \
+   || sh_div_strategy == SH_DIV_INV20U || sh_div_strategy == SH_DIV_INV20L \
+   || sh_div_strategy == SH_DIV_INV_CALL \
+   || sh_div_strategy == SH_DIV_INV_CALL2 || sh_div_strategy == SH_DIV_INV_FP)
+#define TARGET_DIVIDE_FP (sh_div_strategy == SH_DIV_FP)
+#define TARGET_DIVIDE_INV_FP (sh_div_strategy == SH_DIV_INV_FP)
+#define TARGET_DIVIDE_CALL2 (sh_div_strategy == SH_DIV_CALL2)
+#define TARGET_DIVIDE_INV_MINLAT (sh_div_strategy == SH_DIV_INV_MINLAT)
+#define TARGET_DIVIDE_INV20U (sh_div_strategy == SH_DIV_INV20U)
+#define TARGET_DIVIDE_INV20L (sh_div_strategy == SH_DIV_INV20L)
+#define TARGET_DIVIDE_INV_CALL (sh_div_strategy == SH_DIV_INV_CALL)
+#define TARGET_DIVIDE_INV_CALL2 (sh_div_strategy == SH_DIV_INV_CALL2)
+#define TARGET_DIVIDE_CALL_DIV1 (sh_div_strategy == SH_DIV_CALL_DIV1)
+#define TARGET_DIVIDE_CALL_FP (sh_div_strategy == SH_DIV_CALL_FP)
+#define TARGET_DIVIDE_CALL_TABLE (sh_div_strategy == SH_DIV_CALL_TABLE)
+
+#define SELECT_SH1               (MASK_SH1)
+#define SELECT_SH2               (MASK_SH2 | SELECT_SH1)
+#define SELECT_SH2E              (MASK_SH_E | MASK_SH2 | MASK_SH1 \
+                                 | MASK_FPU_SINGLE)
+#define SELECT_SH2A              (MASK_SH_E | MASK_HARD_SH2A \
+                                 | MASK_HARD_SH2A_DOUBLE \
+                                 | MASK_SH2 | MASK_SH1)
+#define SELECT_SH2A_NOFPU        (MASK_HARD_SH2A | MASK_SH2 | MASK_SH1)
+#define SELECT_SH2A_SINGLE_ONLY  (MASK_SH_E | MASK_HARD_SH2A | MASK_SH2 \
+                                 | MASK_SH1 | MASK_FPU_SINGLE)
+#define SELECT_SH2A_SINGLE       (MASK_SH_E | MASK_HARD_SH2A \
+                                 | MASK_FPU_SINGLE | MASK_HARD_SH2A_DOUBLE \
+                                 | MASK_SH2 | MASK_SH1)
+#define SELECT_SH3               (MASK_SH3 | SELECT_SH2)
+#define SELECT_SH3E              (MASK_SH_E | MASK_FPU_SINGLE | SELECT_SH3)
+#define SELECT_SH4_NOFPU         (MASK_HARD_SH4 | SELECT_SH3)
+#define SELECT_SH4_SINGLE_ONLY   (MASK_HARD_SH4 | SELECT_SH3E)
+#define SELECT_SH4               (MASK_SH4 | MASK_SH_E | MASK_HARD_SH4 \
+                                 | SELECT_SH3)
+#define SELECT_SH4_SINGLE        (MASK_FPU_SINGLE | SELECT_SH4)
+#define SELECT_SH4A_NOFPU        (MASK_SH4A | SELECT_SH4_NOFPU)
+#define SELECT_SH4A_SINGLE_ONLY  (MASK_SH4A | SELECT_SH4_SINGLE_ONLY)
+#define SELECT_SH4A              (MASK_SH4A | SELECT_SH4)
+#define SELECT_SH4A_SINGLE       (MASK_SH4A | SELECT_SH4_SINGLE)
+#define SELECT_SH5_64MEDIA       (MASK_SH5 | MASK_SH4)
+#define SELECT_SH5_64MEDIA_NOFPU (MASK_SH5)
+#define SELECT_SH5_32MEDIA       (MASK_SH5 | MASK_SH4 | MASK_SH_E)
+#define SELECT_SH5_32MEDIA_NOFPU (MASK_SH5 | MASK_SH_E)
+#define SELECT_SH5_COMPACT       (MASK_SH5 | MASK_SH4 | SELECT_SH3E)
+#define SELECT_SH5_COMPACT_NOFPU (MASK_SH5 | SELECT_SH3)
+
+#if SUPPORT_SH1
+#define SUPPORT_SH2 1
+#endif
+#if SUPPORT_SH2
+#define SUPPORT_SH3 1
+#define SUPPORT_SH2A_NOFPU 1
+#endif
+#if SUPPORT_SH3
+#define SUPPORT_SH4_NOFPU 1
+#endif
+#if SUPPORT_SH4_NOFPU
+#define SUPPORT_SH4A_NOFPU 1
+#define SUPPORT_SH4AL 1
+#endif
+
+#if SUPPORT_SH2E
+#define SUPPORT_SH3E 1
+#define SUPPORT_SH2A_SINGLE_ONLY 1
+#endif
+#if SUPPORT_SH3E
+#define SUPPORT_SH4_SINGLE_ONLY 1
+#endif
+#if SUPPORT_SH4_SINGLE_ONLY
+#define SUPPORT_SH4A_SINGLE_ONLY 1
+#endif
+
+#if SUPPORT_SH4
+#define SUPPORT_SH4A 1
+#endif
+
+#if SUPPORT_SH4_SINGLE
+#define SUPPORT_SH4A_SINGLE 1
+#endif
+
+#if SUPPORT_SH5_COMPAT
+#define SUPPORT_SH5_32MEDIA 1
+#endif
 
-/* Nonzero if we should generate smaller code rather than faster code.  */
-#define TARGET_SMALLCODE   (target_flags & SPACE_BIT)
+#if SUPPORT_SH5_COMPACT_NOFPU
+#define SUPPORT_SH5_32MEDIA_NOFPU 1
+#endif
 
-/* Nonzero to use long jump tables.  */
-#define TARGET_BIGTABLE     (target_flags & BIGTABLE_BIT)
+#define SUPPORT_ANY_SH5_32MEDIA \
+  (SUPPORT_SH5_32MEDIA || SUPPORT_SH5_32MEDIA_NOFPU)
+#define SUPPORT_ANY_SH5_64MEDIA \
+  (SUPPORT_SH5_64MEDIA || SUPPORT_SH5_64MEDIA_NOFPU)
+#define SUPPORT_ANY_SH5 \
+  (SUPPORT_ANY_SH5_32MEDIA || SUPPORT_ANY_SH5_64MEDIA)
 
-/* Nonzero to generate pseudo-ops needed by the assembler and linker
-   to do function call relaxing.  */
-#define TARGET_RELAX (target_flags & RELAX_BIT)
+/* Reset all target-selection flags.  */
+#define MASK_ARCH (MASK_SH1 | MASK_SH2 | MASK_SH3 | MASK_SH_E | MASK_SH4 \
+                  | MASK_HARD_SH2A | MASK_HARD_SH2A_DOUBLE | MASK_SH4A \
+                  | MASK_HARD_SH4 | MASK_FPU_SINGLE | MASK_SH5)
 
-/* Nonzero if using Hitachi's calling convention.  */
-#define TARGET_HITACHI                 (target_flags & HITACHI_BIT)
+/* This defaults us to big-endian.  */
+#ifndef TARGET_ENDIAN_DEFAULT
+#define TARGET_ENDIAN_DEFAULT 0
+#endif
 
-/* Nonzero if not saving macl/mach when using -mhitachi */
-#define TARGET_NOMACSAVE       (target_flags & NOMACSAVE_BIT)
+#ifndef TARGET_OPT_DEFAULT
+#define TARGET_OPT_DEFAULT  MASK_ADJUST_UNROLL
+#endif
 
-/* Nonzero if padding structures to a multiple of 4 bytes.  This is
-   incompatible with Hitachi's compiler, and gives unusual structure layouts
-   which confuse programmers.
-   ??? This option is not useful, but is retained in case there are people
-   who are still relying on it.  It may be deleted in the future.  */
-#define TARGET_PADSTRUCT       (target_flags & PADSTRUCT_BIT)
+#define TARGET_DEFAULT \
+  (TARGET_CPU_DEFAULT | TARGET_ENDIAN_DEFAULT | TARGET_OPT_DEFAULT)
 
-/* Nonzero if generating code for a little endian SH.  */
-#define TARGET_LITTLE_ENDIAN     (target_flags & LITTLE_ENDIAN_BIT)
+#ifndef SH_MULTILIB_CPU_DEFAULT
+#define SH_MULTILIB_CPU_DEFAULT "m1"
+#endif
 
-/* Nonzero if we should do everything in userland.  */
-#define TARGET_USERMODE                (target_flags & USERMODE_BIT)
+#if TARGET_ENDIAN_DEFAULT
+#define MULTILIB_DEFAULTS { "ml", SH_MULTILIB_CPU_DEFAULT }
+#else
+#define MULTILIB_DEFAULTS { "mb", SH_MULTILIB_CPU_DEFAULT }
+#endif
 
-/* Nonzero if we should prefer @GOT calls when generating PIC.  */
-#define TARGET_PREFERGOT       (target_flags & PREFERGOT_BIT)
+#define CPP_SPEC " %(subtarget_cpp_spec) "
 
-/* Reset all target-selection flags.  */
-#define TARGET_NONE -(SH1_BIT | SH2_BIT | SH3_BIT | SH3E_BIT | SH4_BIT \
-                     | HARD_SH4_BIT | FPU_SINGLE_BIT | SH5_BIT)
-
-#define TARGET_SWITCHES                        \
-{ {"1",                TARGET_NONE, "" },              \
-  {"1",                SH1_BIT, "" },                  \
-  {"2",                TARGET_NONE, "" },              \
-  {"2",                SH2_BIT|SH1_BIT, "" },          \
-  {"3",                TARGET_NONE, "" },              \
-  {"3",                SH3_BIT|SH2_BIT|SH1_BIT, "" },  \
-  {"3e",       TARGET_NONE, "" },              \
-  {"3e",       SH3E_BIT|SH3_BIT|SH2_BIT|SH1_BIT|FPU_SINGLE_BIT, "" },  \
-  {"4-single-only",    TARGET_NONE, "" },      \
-  {"4-single-only",    SH3E_BIT|SH3_BIT|SH2_BIT|SH1_BIT|HARD_SH4_BIT|FPU_SINGLE_BIT, "" },     \
-  {"4-single", TARGET_NONE, "" },              \
-  {"4-single", SH4_BIT|SH3E_BIT|SH3_BIT|SH2_BIT|SH1_BIT|HARD_SH4_BIT|FPU_SINGLE_BIT, "" },\
-  {"4-nofpu",  TARGET_NONE, "" },              \
-  {"4-nofpu",  SH3_BIT|SH2_BIT|SH1_BIT|HARD_SH4_BIT, "" },\
-  {"4",                TARGET_NONE, "" },              \
-  {"4",                SH4_BIT|SH3E_BIT|SH3_BIT|SH2_BIT|SH1_BIT|HARD_SH4_BIT, "" }, \
-  {"5-64media",        TARGET_NONE, "" },              \
-  {"5-64media", SH5_BIT|SH4_BIT, "Generate 64-bit SHmedia code" }, \
-  {"5-64media-nofpu", TARGET_NONE, "" },       \
-  {"5-64media-nofpu", SH5_BIT, "Generate 64-bit FPU-less SHmedia code" }, \
-  {"5-32media",        TARGET_NONE, "" },              \
-  {"5-32media", SH5_BIT|SH4_BIT|SH3E_BIT, "Generate 32-bit SHmedia code" }, \
-  {"5-32media-nofpu", TARGET_NONE, "" },       \
-  {"5-32media-nofpu", SH5_BIT|SH3E_BIT, "Generate 32-bit FPU-less SHmedia code" }, \
-  {"5-compact",        TARGET_NONE, "" },              \
-  {"5-compact",        SH5_BIT|SH4_BIT|SH3E_BIT|SH3_BIT|SH2_BIT|SH1_BIT|FPU_SINGLE_BIT, "Generate SHcompact code" }, \
-  {"5-compact-nofpu", TARGET_NONE, "" },       \
-  {"5-compact-nofpu", SH5_BIT|SH3_BIT|SH2_BIT|SH1_BIT, "Generate FPU-less SHcompact code" }, \
-  {"b",                -LITTLE_ENDIAN_BIT, "" },       \
-  {"bigtable",         BIGTABLE_BIT, "" },             \
-  {"dalign",   DALIGN_BIT, "" },               \
-  {"fmovd",    FMOVD_BIT, "" },                \
-  {"hitachi",  HITACHI_BIT, "" },              \
-  {"nomacsave", NOMACSAVE_BIT, "" },           \
-  {"ieee",     IEEE_BIT, "" },                 \
-  {"isize",    ISIZE_BIT, "" },                \
-  {"l",                LITTLE_ENDIAN_BIT, "" },        \
-  {"no-ieee",          -IEEE_BIT, "" },                \
-  {"padstruct", PADSTRUCT_BIT, "" },           \
-  {"prefergot",        PREFERGOT_BIT, "" },            \
-  {"relax",    RELAX_BIT, "" },                \
-  {"space",    SPACE_BIT, "" },                \
-  {"usermode", USERMODE_BIT, "" },             \
-  SUBTARGET_SWITCHES                            \
-  {"",         TARGET_DEFAULT, "" }            \
-}
+#ifndef SUBTARGET_CPP_SPEC
+#define SUBTARGET_CPP_SPEC ""
+#endif
+
+#ifndef SUBTARGET_EXTRA_SPECS
+#define SUBTARGET_EXTRA_SPECS
+#endif
+
+#define EXTRA_SPECS                                            \
+  { "subtarget_cpp_spec", SUBTARGET_CPP_SPEC },                        \
+  { "link_emul_prefix", LINK_EMUL_PREFIX },                    \
+  { "link_default_cpu_emul", LINK_DEFAULT_CPU_EMUL },          \
+  { "subtarget_link_emul_suffix", SUBTARGET_LINK_EMUL_SUFFIX },        \
+  { "subtarget_link_spec", SUBTARGET_LINK_SPEC },              \
+  { "subtarget_asm_endian_spec", SUBTARGET_ASM_ENDIAN_SPEC },  \
+  { "subtarget_asm_relax_spec", SUBTARGET_ASM_RELAX_SPEC },    \
+  { "subtarget_asm_isa_spec", SUBTARGET_ASM_ISA_SPEC },                \
+  { "subtarget_asm_spec", SUBTARGET_ASM_SPEC },                        \
+  SUBTARGET_EXTRA_SPECS
+
+#if TARGET_CPU_DEFAULT & MASK_HARD_SH4
+#define SUBTARGET_ASM_RELAX_SPEC "%{!m1:%{!m2:%{!m3*:%{!m5*:-isa=sh4-up}}}}"
+#else
+#define SUBTARGET_ASM_RELAX_SPEC "%{m4*:-isa=sh4-up}"
+#endif
+
+#define SH_ASM_SPEC \
+ "%(subtarget_asm_endian_spec) %{mrelax:-relax %(subtarget_asm_relax_spec)}\
+%(subtarget_asm_isa_spec) %(subtarget_asm_spec)\
+%{m2a:--isa=sh2a} \
+%{m2a-single:--isa=sh2a} \
+%{m2a-single-only:--isa=sh2a} \
+%{m2a-nofpu:--isa=sh2a-nofpu} \
+%{m5-compact*:--isa=SHcompact} \
+%{m5-32media*:--isa=SHmedia --abi=32} \
+%{m5-64media*:--isa=SHmedia --abi=64} \
+%{m4al:-dsp} %{mcut2-workaround:-cut2-workaround}"
+
+#define ASM_SPEC SH_ASM_SPEC
+
+#ifndef SUBTARGET_ASM_ENDIAN_SPEC
+#if TARGET_ENDIAN_DEFAULT == MASK_LITTLE_ENDIAN
+#define SUBTARGET_ASM_ENDIAN_SPEC "%{mb:-big} %{!mb:-little}"
+#else
+#define SUBTARGET_ASM_ENDIAN_SPEC "%{ml:-little} %{!ml:-big}"
+#endif
+#endif
+
+#if STRICT_NOFPU == 1
+/* Strict nofpu means that the compiler should tell the assembler
+   to reject FPU instructions. E.g. from ASM inserts.  */
+#if TARGET_CPU_DEFAULT & MASK_HARD_SH4 && !(TARGET_CPU_DEFAULT & MASK_SH_E)
+#define SUBTARGET_ASM_ISA_SPEC "%{!m1:%{!m2:%{!m3*:%{m4-nofpu|!m4*:%{!m5:-isa=sh4-nofpu}}}}}"
+#else
+/* If there were an -isa option for sh5-nofpu then it would also go here. */
+#define SUBTARGET_ASM_ISA_SPEC \
+ "%{m4-nofpu:-isa=sh4-nofpu} " ASM_ISA_DEFAULT_SPEC
+#endif
+#else /* ! STRICT_NOFPU */
+#define SUBTARGET_ASM_ISA_SPEC ASM_ISA_DEFAULT_SPEC
+#endif
+
+#ifndef SUBTARGET_ASM_SPEC
+#define SUBTARGET_ASM_SPEC ""
+#endif
 
-/* This are meant to be redefined in the host dependent files */
-#define SUBTARGET_SWITCHES
+#if TARGET_ENDIAN_DEFAULT == MASK_LITTLE_ENDIAN
+#define LINK_EMUL_PREFIX "sh%{!mb:l}"
+#else
+#define LINK_EMUL_PREFIX "sh%{ml:l}"
+#endif
 
-#define TARGET_DEFAULT  (SH1_BIT)
+#if TARGET_CPU_DEFAULT & MASK_SH5
+#if TARGET_CPU_DEFAULT & MASK_SH_E
+#define LINK_DEFAULT_CPU_EMUL "32"
+#if TARGET_CPU_DEFAULT & MASK_SH1
+#define ASM_ISA_SPEC_DEFAULT "--isa=SHcompact"
+#else
+#define ASM_ISA_SPEC_DEFAULT "--isa=SHmedia --abi=32"
+#endif /* MASK_SH1 */
+#else /* !MASK_SH_E */
+#define LINK_DEFAULT_CPU_EMUL "64"
+#define ASM_ISA_SPEC_DEFAULT "--isa=SHmedia --abi=64"
+#endif /* MASK_SH_E */
+#define ASM_ISA_DEFAULT_SPEC \
+" %{!m1:%{!m2*:%{!m3*:%{!m4*:%{!m5*:" ASM_ISA_SPEC_DEFAULT "}}}}}"
+#else /* !MASK_SH5 */
+#define LINK_DEFAULT_CPU_EMUL ""
+#define ASM_ISA_DEFAULT_SPEC ""
+#endif /* MASK_SH5 */
+
+#define SUBTARGET_LINK_EMUL_SUFFIX ""
+#define SUBTARGET_LINK_SPEC ""
+
+/* svr4.h redefines LINK_SPEC inappropriately, so go via SH_LINK_SPEC,
+   so that we can undo the damage without code replication.  */
+#define LINK_SPEC SH_LINK_SPEC
+
+#define SH_LINK_SPEC "\
+-m %(link_emul_prefix)\
+%{m5-compact*|m5-32media*:32}\
+%{m5-64media*:64}\
+%{!m1:%{!m2:%{!m3*:%{!m4*:%{!m5*:%(link_default_cpu_emul)}}}}}\
+%(subtarget_link_emul_suffix) \
+%{mrelax:-relax} %(subtarget_link_spec)"
+
+#ifndef SH_DIV_STR_FOR_SIZE
+#define SH_DIV_STR_FOR_SIZE "call"
+#endif
 
+#define DRIVER_SELF_SPECS "%{m2a:%{ml:%eSH2a does not support little-endian}}"
 #define OPTIMIZATION_OPTIONS(LEVEL,SIZE)                               \
 do {                                                                   \
   if (LEVEL)                                                           \
-    flag_omit_frame_pointer = -1;                                      \
+    {                                                                  \
+      flag_omit_frame_pointer = 2;                                     \
+      if (! SIZE)                                                      \
+       sh_div_str = "inv:minlat";                                      \
+    }                                                                  \
   if (SIZE)                                                            \
-    target_flags |= SPACE_BIT;                                         \
+    {                                                                  \
+      target_flags |= MASK_SMALLCODE;                                  \
+      sh_div_str = SH_DIV_STR_FOR_SIZE ;                               \
+    }                                                                  \
+  else                                                                 \
+    {                                                                  \
+      TARGET_CBRANCHDI4 = 1;                                           \
+      TARGET_EXPAND_CBRANCHDI4 = 1;                                    \
+    }                                                                  \
+  /* We can't meaningfully test TARGET_SHMEDIA here, because -m options        \
+     haven't been parsed yet, hence we'd read only the default.        \
+     sh_target_reg_class will return NO_REGS if this is not SHMEDIA, so        \
+     it's OK to always set flag_branch_target_load_optimize.  */       \
+  if (LEVEL > 1)                                                       \
+    {                                                                  \
+      flag_branch_target_load_optimize = 1;                            \
+      if (! (SIZE))                                                    \
+       target_flags |= MASK_SAVE_ALL_TARGET_REGS;                      \
+    }                                                                  \
+  /* Likewise, we can't meaningfully test TARGET_SH2E / TARGET_IEEE    \
+     here, so leave it to OVERRIDE_OPTIONS to set                      \
+    flag_finite_math_only.  We set it to 2 here so we know if the user \
+    explicitly requested this to be on or off.  */                     \
+  flag_finite_math_only = 2;                                           \
+  /* If flag_schedule_insns is 1, we set it to 2 here so we know if    \
+     the user explicitly requested this to be on or off.  */           \
+  if (flag_schedule_insns > 0)                                         \
+    flag_schedule_insns = 2;                                           \
+                                                                       \
+  set_param_value ("simultaneous-prefetches", 2);                      \
 } while (0)
 
 #define ASSEMBLER_DIALECT assembler_dialect
 
 extern int assembler_dialect;
 
+enum sh_divide_strategy_e {
+  /* SH5 strategies.  */
+  SH_DIV_CALL,
+  SH_DIV_CALL2,
+  SH_DIV_FP, /* We could do this also for SH4.  */
+  SH_DIV_INV,
+  SH_DIV_INV_MINLAT,
+  SH_DIV_INV20U,
+  SH_DIV_INV20L,
+  SH_DIV_INV_CALL,
+  SH_DIV_INV_CALL2,
+  SH_DIV_INV_FP,
+  /* SH1 .. SH4 strategies.  Because of the small number of registers
+     available, the compiler uses knowledge of the actual set of registers
+     being clobbered by the different functions called.  */
+  SH_DIV_CALL_DIV1, /* No FPU, medium size, highest latency.  */
+  SH_DIV_CALL_FP,     /* FPU needed, small size, high latency.  */
+  SH_DIV_CALL_TABLE,  /* No FPU, large size, medium latency. */
+  SH_DIV_INTRINSIC
+};
+
+extern enum sh_divide_strategy_e sh_div_strategy;
+
+#ifndef SH_DIV_STRATEGY_DEFAULT
+#define SH_DIV_STRATEGY_DEFAULT SH_DIV_CALL
+#endif
+
+#define SUBTARGET_OVERRIDE_OPTIONS (void) 0
+
+extern const char *sh_fixed_range_str;
+
 #define OVERRIDE_OPTIONS                                               \
 do {                                                                   \
   int regno;                                                           \
                                                                        \
+  SUBTARGET_OVERRIDE_OPTIONS;                                          \
+  if (flag_finite_math_only == 2)                                      \
+    flag_finite_math_only                                              \
+      = !flag_signaling_nans && TARGET_SH2E && ! TARGET_IEEE;          \
+  if (TARGET_SH2E && !flag_finite_math_only)                           \
+    target_flags |= MASK_IEEE;                                         \
   sh_cpu = CPU_SH1;                                                    \
   assembler_dialect = 0;                                               \
   if (TARGET_SH2)                                                      \
     sh_cpu = CPU_SH2;                                                  \
+  if (TARGET_SH2E)                                                     \
+    sh_cpu = CPU_SH2E;                                                 \
+  if (TARGET_SH2A)                                                     \
+    {                                                                  \
+      sh_cpu = CPU_SH2A;                                               \
+      if (TARGET_SH2A_DOUBLE)                                          \
+        target_flags |= MASK_FMOVD;                                    \
+    }                                                                  \
   if (TARGET_SH3)                                                      \
     sh_cpu = CPU_SH3;                                                  \
   if (TARGET_SH3E)                                                     \
@@ -349,23 +566,66 @@ do {                                                                      \
       assembler_dialect = 1;                                           \
       sh_cpu = CPU_SH4;                                                        \
     }                                                                  \
+  if (TARGET_SH4A_ARCH)                                                        \
+    {                                                                  \
+      assembler_dialect = 1;                                           \
+      sh_cpu = CPU_SH4A;                                               \
+    }                                                                  \
   if (TARGET_SH5)                                                      \
     {                                                                  \
       sh_cpu = CPU_SH5;                                                        \
-      target_flags |= DALIGN_BIT;                                      \
-      if (TARGET_FPU_ANY)                                              \
-       target_flags |= FMOVD_BIT;                                      \
+      target_flags |= MASK_ALIGN_DOUBLE;                               \
+      if (TARGET_SHMEDIA_FPU)                                          \
+       target_flags |= MASK_FMOVD;                                     \
       if (TARGET_SHMEDIA)                                              \
        {                                                               \
          /* There are no delay slots on SHmedia.  */                   \
          flag_delayed_branch = 0;                                      \
          /* Relaxation isn't yet supported for SHmedia */              \
-         target_flags &= ~RELAX_BIT;                                   \
-       }                                                               \
-      if (profile_flag || profile_arc_flag)                            \
-       {                                                               \
-         warning ("Profiling is not supported on this target.");       \
-         profile_flag = profile_arc_flag = 0;                          \
+         target_flags &= ~MASK_RELAX;                                  \
+         /* After reload, if conversion does little good but can cause \
+            ICEs:                                                      \
+            - find_if_block doesn't do anything for SH because we don't\
+              have conditional execution patterns.  (We use conditional\
+              move patterns, which are handled differently, and only   \
+              before reload).                                          \
+            - find_cond_trap doesn't do anything for the SH because we \       
+              don't have conditional traps.                            \
+            - find_if_case_1 uses redirect_edge_and_branch_force in    \
+              the only path that does an optimization, and this causes \
+              an ICE when branch targets are in registers.             \
+            - find_if_case_2 doesn't do anything for the SHmedia after \
+              reload except when it can redirect a tablejump - and     \
+              that's rather rare.  */                                  \
+         flag_if_conversion2 = 0;                                      \
+         if (! strcmp (sh_div_str, "call"))                            \
+           sh_div_strategy = SH_DIV_CALL;                              \
+         else if (! strcmp (sh_div_str, "call2"))                      \
+           sh_div_strategy = SH_DIV_CALL2;                             \
+         if (! strcmp (sh_div_str, "fp") && TARGET_FPU_ANY)            \
+           sh_div_strategy = SH_DIV_FP;                                \
+         else if (! strcmp (sh_div_str, "inv"))                        \
+           sh_div_strategy = SH_DIV_INV;                               \
+         else if (! strcmp (sh_div_str, "inv:minlat"))                 \
+           sh_div_strategy = SH_DIV_INV_MINLAT;                        \
+         else if (! strcmp (sh_div_str, "inv20u"))                     \
+           sh_div_strategy = SH_DIV_INV20U;                            \
+         else if (! strcmp (sh_div_str, "inv20l"))                     \
+           sh_div_strategy = SH_DIV_INV20L;                            \
+         else if (! strcmp (sh_div_str, "inv:call2"))                  \
+           sh_div_strategy = SH_DIV_INV_CALL2;                         \
+         else if (! strcmp (sh_div_str, "inv:call"))                   \
+           sh_div_strategy = SH_DIV_INV_CALL;                          \
+         else if (! strcmp (sh_div_str, "inv:fp"))                     \
+           {                                                           \
+             if (TARGET_FPU_ANY)                                       \
+               sh_div_strategy = SH_DIV_INV_FP;                        \
+             else                                                      \
+               sh_div_strategy = SH_DIV_INV;                           \
+           }                                                           \
+         TARGET_CBRANCHDI4 = 0;                                        \
+         /* Assembler CFI isn't yet fully supported for SHmedia.  */   \
+         flag_dwarf2_cfi_asm = 0;                                      \
        }                                                               \
     }                                                                  \
   else                                                                 \
@@ -374,6 +634,55 @@ do {                                                                       \
        targetm.asm_out.aligned_op.di = NULL;                           \
        targetm.asm_out.unaligned_op.di = NULL;                         \
     }                                                                  \
+  if (TARGET_SH1)                                                      \
+    {                                                                  \
+      if (! strcmp (sh_div_str, "call-div1"))                          \
+       sh_div_strategy = SH_DIV_CALL_DIV1;                             \
+      else if (! strcmp (sh_div_str, "call-fp")                                \
+              && (TARGET_FPU_DOUBLE                                    \
+                  || (TARGET_HARD_SH4 && TARGET_SH2E)                  \
+                  || (TARGET_SHCOMPACT && TARGET_FPU_ANY)))            \
+       sh_div_strategy = SH_DIV_CALL_FP;                               \
+      else if (! strcmp (sh_div_str, "call-table") && TARGET_SH2)      \
+       sh_div_strategy = SH_DIV_CALL_TABLE;                            \
+      else                                                             \
+       /* Pick one that makes most sense for the target in general.    \
+          It is not much good to use different functions depending     \
+          on -Os, since then we'll end up with two different functions \
+          when some of the code is compiled for size, and some for     \
+          speed.  */                                                   \
+                                                                       \
+       /* SH4 tends to emphasize speed.  */                            \
+       if (TARGET_HARD_SH4)                                            \
+         sh_div_strategy = SH_DIV_CALL_TABLE;                          \
+       /* These have their own way of doing things.  */                \
+       else if (TARGET_SH2A)                                           \
+         sh_div_strategy = SH_DIV_INTRINSIC;                           \
+       /* ??? Should we use the integer SHmedia function instead?  */  \
+       else if (TARGET_SHCOMPACT && TARGET_FPU_ANY)                    \
+         sh_div_strategy = SH_DIV_CALL_FP;                             \
+        /* SH1 .. SH3 cores often go into small-footprint systems, so  \
+          default to the smallest implementation available.  */        \
+       else if (TARGET_SH2)    /* ??? EXPERIMENTAL */                  \
+         sh_div_strategy = SH_DIV_CALL_TABLE;                          \
+       else                                                            \
+         sh_div_strategy = SH_DIV_CALL_DIV1;                           \
+    }                                                                  \
+  if (!TARGET_SH1)                                                     \
+    TARGET_PRETEND_CMOVE = 0;                                          \
+  if (sh_divsi3_libfunc[0])                                            \
+    ; /* User supplied - leave it alone.  */                           \
+  else if (TARGET_DIVIDE_CALL_FP)                                      \
+    sh_divsi3_libfunc = "__sdivsi3_i4";                                        \
+  else if (TARGET_DIVIDE_CALL_TABLE)                                   \
+    sh_divsi3_libfunc = "__sdivsi3_i4i";                               \
+  else if (TARGET_SH5)                                                 \
+    sh_divsi3_libfunc = "__sdivsi3_1";                                 \
+  else                                                                 \
+    sh_divsi3_libfunc = "__sdivsi3";                                   \
+  if (sh_branch_cost == -1)                                            \
+    sh_branch_cost                                                     \
+      = TARGET_SH5 ? 1 : ! TARGET_SH2 || TARGET_HARD_SH4 ? 2 : 1;      \
                                                                        \
   for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)              \
     if (! VALID_REGISTER_P (regno))                                    \
@@ -383,33 +692,79 @@ do {                                                                      \
     if (! VALID_REGISTER_P (ADDREGNAMES_REGNO (regno)))                        \
       sh_additional_register_names[regno][0] = '\0';                   \
                                                                        \
-  if (flag_omit_frame_pointer < 0)                                     \
+  if (flag_omit_frame_pointer == 2)                                    \
    {                                                                   \
      /* The debugging information is sufficient,                       \
         but gdb doesn't implement this yet */                          \
      if (0)                                                            \
       flag_omit_frame_pointer                                          \
-        = (PREFERRED_DEBUGGING_TYPE == DWARF_DEBUG                     \
-          || PREFERRED_DEBUGGING_TYPE == DWARF2_DEBUG);                \
+        = (PREFERRED_DEBUGGING_TYPE == DWARF2_DEBUG);                  \
      else                                                              \
       flag_omit_frame_pointer = 0;                                     \
    }                                                                   \
                                                                        \
-  if (flag_pic && ! TARGET_PREFERGOT)                                  \
+  if ((flag_pic && ! TARGET_PREFERGOT)                                 \
+      || (TARGET_SHMEDIA && !TARGET_PT_FIXED))                         \
     flag_no_function_cse = 1;                                          \
                                                                        \
-  /* Never run scheduling before reload, since that can                        \
-     break global alloc, and generates slower code anyway due          \
-     to the pressure on R0.  */                                                \
-  flag_schedule_insns = 0;                                             \
+  if (SMALL_REGISTER_CLASSES)                                          \
+    {                                                                  \
+      /* Never run scheduling before reload, since that can            \
+        break global alloc, and generates slower code anyway due       \
+        to the pressure on R0.  */                                     \
+      /* Enable sched1 for SH4; ready queue will be reordered by       \
+        the target hooks when pressure is high. We can not do this for \
+        PIC, SH3 and lower as they give spill failures for R0.  */     \
+      if (!TARGET_HARD_SH4 || flag_pic)                                        \
+        flag_schedule_insns = 0;                                       \
+      /* ??? Current exception handling places basic block boundaries  \
+        after call_insns.  It causes the high pressure on R0 and gives \
+        spill failures for R0 in reload.  See PR 22553 and the thread  \
+        on gcc-patches                                                 \
+         <http://gcc.gnu.org/ml/gcc-patches/2005-10/msg00816.html>.  */        \
+      else if (flag_exceptions)                                                \
+       {                                                               \
+         if (flag_schedule_insns == 1)                                 \
+           warning (0, "ignoring -fschedule-insns because of exception handling bug"); \
+         flag_schedule_insns = 0;                                      \
+       }                                                               \
+    }                                                                  \
+                                                                       \
+  if (align_loops == 0)                                                        \
+    align_loops =  1 << (TARGET_SH5 ? 3 : 2);                          \
+  if (align_jumps == 0)                                                        \
+    align_jumps = 1 << CACHE_LOG;                                      \
+  else if (align_jumps < (TARGET_SHMEDIA ? 4 : 2))                     \
+    align_jumps = TARGET_SHMEDIA ? 4 : 2;                              \
+                                                                       \
+  /* Allocation boundary (in *bytes*) for the code of a function.      \
+     SH1: 32 bit alignment is faster, because instructions are always  \
+     fetched as a pair from a longword boundary.                       \
+     SH2 .. SH5 : align to cache line start.  */                       \
+  if (align_functions == 0)                                            \
+    align_functions                                                    \
+      = TARGET_SMALLCODE ? FUNCTION_BOUNDARY/8 : (1 << CACHE_LOG);     \
+  /* The linker relaxation code breaks when a function contains                \
+     alignments that are larger than that at the start of a            \
+     compilation unit.  */                                             \
+  if (TARGET_RELAX)                                                    \
+    {                                                                  \
+      int min_align                                                    \
+       = align_loops > align_jumps ? align_loops : align_jumps;        \
+                                                                       \
+      /* Also take possible .long constants / mova tables int account. */\
+      if (min_align < 4)                                               \
+       min_align = 4;                                                  \
+      if (align_functions < min_align)                                 \
+       align_functions = min_align;                                    \
+    }                                                                  \
+                                                                       \
+  if (sh_fixed_range_str)                                              \
+    sh_fix_range (sh_fixed_range_str);                                 \
 } while (0)
 \f
 /* Target machine storage layout.  */
 
-/* Define to use software floating point emulator for REAL_ARITHMETIC and
-   decimal <-> binary conversion.  */
-#define REAL_ARITHMETIC
-
 /* Define this if most significant bit is lowest numbered
    in instructions that operate on numbered bit-fields.  */
 
@@ -430,20 +785,10 @@ do {                                                                      \
 #define LIBGCC2_WORDS_BIG_ENDIAN 1
 #endif
 
-/* Number of bits in an addressable storage unit.  */
-#define BITS_PER_UNIT  8
-
-/* Width in bits of a "word", which is the contents of a machine register.
-   Note that this is not necessarily the width of data type `int';
-   if using 16-bit ints on a 68000, this would still be 32.
-   But on a machine with 16-bit registers, this would be 16.  */
-#define BITS_PER_WORD  (TARGET_SHMEDIA ? 64 : 32)
 #define MAX_BITS_PER_WORD 64
 
-#define MAX_LONG_TYPE_SIZE MAX_BITS_PER_WORD
-
 /* Width in bits of an `int'.  We want just 32-bits, even if words are
-   longer. */
+   longer.  */
 #define INT_TYPE_SIZE 32
 
 /* Width in bits of a `long'.  */
@@ -459,6 +804,13 @@ do {                                                                       \
 #define UNITS_PER_WORD (TARGET_SHMEDIA ? 8 : 4)
 #define MIN_UNITS_PER_WORD 4
 
+/* Scaling factor for Dwarf data offsets for CFI information.
+   The dwarf2out.c default would use -UNITS_PER_WORD, which is -8 for
+   SHmedia; however, since we do partial register saves for the registers
+   visible to SHcompact, and for target registers for SHMEDIA32, we have
+   to allow saves that are only 4-byte aligned.  */
+#define DWARF_CIE_DATA_ALIGNMENT -4
+
 /* Width in bits of a pointer.
    See also the macro `Pmode' defined below.  */
 #define POINTER_SIZE  (TARGET_SHMEDIA64 ? 64 : 32)
@@ -474,11 +826,9 @@ do {                                                                       \
    The SH2/3 have 16 byte cache lines, and the SH4 has a 32 byte cache line */
 #define CACHE_LOG (TARGET_CACHE32 ? 5 : TARGET_SH2 ? 4 : 2)
 
-/* Allocation boundary (in *bits*) for the code of a function.
-   32 bit alignment is faster, because instructions are always fetched as a
-   pair from a longword boundary.  */
-#define FUNCTION_BOUNDARY  \
-  (TARGET_SMALLCODE ? 16 << TARGET_SHMEDIA : (1 << CACHE_LOG) * 8)
+/* ABI given & required minimum allocation boundary (in *bits*) for the
+   code of a function.  */
+#define FUNCTION_BOUNDARY (16 << TARGET_SHMEDIA)
 
 /* On SH5, the lowest bit is used to indicate SHmedia functions, so
    the vbit must go into the delta field of
@@ -501,9 +851,16 @@ do {                                                                       \
     && (ALIGN) < FASTEST_ALIGNMENT)    \
     ? FASTEST_ALIGNMENT : (ALIGN))
 
-#ifndef MAX_OFILE_ALIGNMENT
-#define MAX_OFILE_ALIGNMENT 128
-#endif
+/* get_mode_alignment assumes complex values are always held in multiple
+   registers, but that is not the case on the SH; CQImode and CHImode are
+   held in a single integer register.  SH5 also holds CSImode and SCmode
+   values in integer registers.  This is relevant for argument passing on
+   SHcompact as we use a stack temp in order to pass CSImode by reference.  */
+#define LOCAL_ALIGNMENT(TYPE, ALIGN) \
+  ((GET_MODE_CLASS (TYPE_MODE (TYPE)) == MODE_COMPLEX_INT \
+    || GET_MODE_CLASS (TYPE_MODE (TYPE)) == MODE_COMPLEX_FLOAT) \
+   ? (unsigned) MIN (BIGGEST_ALIGNMENT, GET_MODE_BITSIZE (TYPE_MODE (TYPE))) \
+   : (unsigned) DATA_ALIGNMENT(TYPE, ALIGN))
 
 /* Make arrays of chars word-aligned for the same reasons.  */
 #define DATA_ALIGNMENT(TYPE, ALIGN)            \
@@ -525,7 +882,7 @@ do {                                                                        \
   barrier_align (LABEL_AFTER_BARRIER)
 
 #define LOOP_ALIGN(A_LABEL) \
-  ((! optimize || TARGET_HARVARD || TARGET_SMALLCODE) \
+  ((! optimize || TARGET_HARD_SH4 || TARGET_SMALLCODE) \
    ? 0 : sh_loop_align (A_LABEL))
 
 #define LABEL_ALIGN(A_LABEL) \
@@ -551,7 +908,7 @@ do {                                                                        \
 \f
 /* Standard register usage.  */
 
-/* Register allocation for the Hitachi calling convention:
+/* Register allocation for the Renesas calling convention:
 
         r0             arg return
        r1..r3          scratch
@@ -595,11 +952,9 @@ extern char sh_register_names[][MAX_REGISTER_NAME_LENGTH + 1];
   "tr0",  "tr1",  "tr2",  "tr3",  "tr4",  "tr5",  "tr6",  "tr7",       \
   "xd0",  "xd2",  "xd4",  "xd6",  "xd8",  "xd10", "xd12", "xd14",      \
   "gbr",  "ap",          "pr",   "t",    "mach", "macl", "fpul", "fpscr",      \
-  "rap"                                                                        \
+  "rap",  "sfp"                                                                \
 }
 
-#define DEBUG_REGISTER_NAMES SH_REGISTER_NAMES_INITIALIZER
-
 #define REGNAMES_ARR_INDEX_1(index) \
   (sh_register_names[index])
 #define REGNAMES_ARR_INDEX_2(index) \
@@ -622,7 +977,7 @@ extern char sh_register_names[][MAX_REGISTER_NAME_LENGTH + 1];
   REGNAMES_ARR_INDEX_8 (128), \
   REGNAMES_ARR_INDEX_8 (136), \
   REGNAMES_ARR_INDEX_8 (144), \
-  REGNAMES_ARR_INDEX_1 (152) \
+  REGNAMES_ARR_INDEX_2 (152) \
 }
 
 #define ADDREGNAMES_SIZE 32
@@ -672,23 +1027,36 @@ extern char sh_additional_register_names[ADDREGNAMES_SIZE] \
 #define LAST_GENERAL_REG (FIRST_GENERAL_REG + (TARGET_SHMEDIA ? 63 : 15))
 #define FIRST_FP_REG DR0_REG
 #define LAST_FP_REG  (FIRST_FP_REG + \
-                     (TARGET_SHMEDIA_FPU ? 63 : TARGET_SH3E ? 15 : -1))
+                     (TARGET_SHMEDIA_FPU ? 63 : TARGET_SH2E ? 15 : -1))
 #define FIRST_XD_REG XD0_REG
 #define LAST_XD_REG  (FIRST_XD_REG + ((TARGET_SH4 && TARGET_FMOVD) ? 7 : -1))
 #define FIRST_TARGET_REG TR0_REG
 #define LAST_TARGET_REG  (FIRST_TARGET_REG + (TARGET_SHMEDIA ? 7 : -1))
 
+/* Registers that can be accessed through bank0 or bank1 depending on sr.md.  */
+
+#define FIRST_BANKED_REG R0_REG
+#define LAST_BANKED_REG R7_REG
+
+#define BANKED_REGISTER_P(REGNO)                       \
+  IN_RANGE ((REGNO),                                   \
+           (unsigned HOST_WIDE_INT) FIRST_BANKED_REG, \
+           (unsigned HOST_WIDE_INT) LAST_BANKED_REG)
+
 #define GENERAL_REGISTER_P(REGNO) \
-  IN_RANGE ((REGNO), FIRST_GENERAL_REG, LAST_GENERAL_REG)
+  IN_RANGE ((REGNO), \
+           (unsigned HOST_WIDE_INT) FIRST_GENERAL_REG, \
+           (unsigned HOST_WIDE_INT) LAST_GENERAL_REG)
 
 #define GENERAL_OR_AP_REGISTER_P(REGNO) \
-  (GENERAL_REGISTER_P (REGNO) || ((REGNO) == AP_REG))
+  (GENERAL_REGISTER_P (REGNO) || ((REGNO) == AP_REG)   \
+   || ((REGNO) == FRAME_POINTER_REGNUM))
 
 #define FP_REGISTER_P(REGNO) \
-  ((REGNO) >= FIRST_FP_REG && (REGNO) <= LAST_FP_REG)
+  ((int) (REGNO) >= FIRST_FP_REG && (int) (REGNO) <= LAST_FP_REG)
 
 #define XD_REGISTER_P(REGNO) \
-  ((REGNO) >= FIRST_XD_REG && (REGNO) <= LAST_XD_REG)
+  ((int) (REGNO) >= FIRST_XD_REG && (int) (REGNO) <= LAST_XD_REG)
 
 #define FP_OR_XD_REGISTER_P(REGNO) \
   (FP_REGISTER_P (REGNO) || XD_REGISTER_P (REGNO))
@@ -701,7 +1069,7 @@ extern char sh_additional_register_names[ADDREGNAMES_SIZE] \
    || (REGNO) == MACH_REG || (REGNO) == MACL_REG)
 
 #define TARGET_REGISTER_P(REGNO) \
-  ((REGNO) >= FIRST_TARGET_REG && (REGNO) <= LAST_TARGET_REG)
+  ((int) (REGNO) >= FIRST_TARGET_REG && (int) (REGNO) <= LAST_TARGET_REG)
 
 #define SHMEDIA_REGISTER_P(REGNO) \
   (GENERAL_REGISTER_P (REGNO) || FP_REGISTER_P (REGNO) \
@@ -712,8 +1080,9 @@ extern char sh_additional_register_names[ADDREGNAMES_SIZE] \
 #define VALID_REGISTER_P(REGNO) \
   (SHMEDIA_REGISTER_P (REGNO) || XD_REGISTER_P (REGNO) \
    || (REGNO) == AP_REG || (REGNO) == RAP_REG \
+   || (REGNO) == FRAME_POINTER_REGNUM \
    || (TARGET_SH1 && (SPECIAL_REGISTER_P (REGNO) || (REGNO) == PR_REG)) \
-   || (TARGET_SH3E && (REGNO) == FPUL_REG))
+   || (TARGET_SH2E && (REGNO) == FPUL_REG))
 
 /* The mode that should be generally used to store a register by
    itself in the stack, or to load it back.  */
@@ -724,7 +1093,10 @@ extern char sh_additional_register_names[ADDREGNAMES_SIZE] \
    ? DImode \
    : SImode)
 
-#define FIRST_PSEUDO_REGISTER 153
+#define FIRST_PSEUDO_REGISTER 154
+
+/* Don't count soft frame pointer.  */
+#define DWARF_FRAME_REGISTERS (FIRST_PSEUDO_REGISTER - 1)
 
 /* 1 for registers that have pervasive standard uses
    and are not available for the register allocator.
@@ -761,8 +1133,8 @@ extern char sh_additional_register_names[ADDREGNAMES_SIZE] \
   0,      0,      0,      0,      0,      0,      0,      0,           \
 /*"gbr",  "ap",          "pr",   "t",    "mach", "macl", "fpul", "fpscr", */   \
   1,      1,      1,      1,      1,      1,      0,      1,           \
-/*"rap" */                                                             \
-  1,                                                                   \
+/*"rap",  "sfp" */                                                     \
+  1,     1,                                                            \
 }
 
 /* 1 for registers not available across function calls.
@@ -780,7 +1152,7 @@ extern char sh_additional_register_names[ADDREGNAMES_SIZE] \
      Only the lower 32bits of R10-R14 are guaranteed to be preserved   \
      across SH5 function calls.  */                                    \
   0,      0,      0,      0,      0,      0,      0,      1,           \
-  1,      1,      0,      1,      1,      1,      1,      1,           \
+  1,      1,      1,      1,      1,      1,      1,      1,           \
   1,      1,      1,      1,      0,      0,      0,      0,           \
   0,      0,      0,      0,      1,      1,      1,      1,           \
   1,      1,      1,      1,      0,      0,      0,      0,           \
@@ -800,11 +1172,15 @@ extern char sh_additional_register_names[ADDREGNAMES_SIZE] \
 /* XD registers.  */                                                   \
   1,      1,      1,      1,      1,      1,      0,      0,           \
 /*"gbr",  "ap",          "pr",   "t",    "mach", "macl", "fpul", "fpscr", */   \
-  1,      1,      0,      1,      1,      1,      1,      1,           \
-/*"rap" */                                                             \
-  1,                                                                   \
+  1,      1,      1,      1,      1,      1,      1,      1,           \
+/*"rap",  "sfp" */                                                     \
+  1,     1,                                                            \
 }
 
+/* CONDITIONAL_REGISTER_USAGE might want to make a register call-used, yet
+   fixed, like PIC_OFFSET_TABLE_REGNUM.  */
+#define CALL_REALLY_USED_REGISTERS CALL_USED_REGISTERS
+
 /* Only the lower 32-bits of R10-R14 are guaranteed to be preserved
    across SHcompact function calls.  We can't tell whether a called
    function is SHmedia or SHcompact, so we assume it may be when
@@ -814,7 +1190,8 @@ extern char sh_additional_register_names[ADDREGNAMES_SIZE] \
   (TARGET_SHMEDIA32 \
    && GET_MODE_SIZE (MODE) > 4 \
    && (((REGNO) >= FIRST_GENERAL_REG + 10 \
-        && (REGNO) <= FIRST_GENERAL_REG + 14) \
+        && (REGNO) <= FIRST_GENERAL_REG + 15) \
+       || TARGET_REGISTER_P (REGNO) \
        || (REGNO) == PR_MEDIA_REG))
 
 /* Return number of consecutive hard regs needed starting at reg REGNO
@@ -826,56 +1203,15 @@ extern char sh_additional_register_names[ADDREGNAMES_SIZE] \
 
 #define HARD_REGNO_NREGS(REGNO, MODE) \
    (XD_REGISTER_P (REGNO) \
-    ? (GET_MODE_SIZE (MODE) / (2 * UNITS_PER_WORD)) \
+    ? ((GET_MODE_SIZE (MODE) + (2*UNITS_PER_WORD - 1)) / (2*UNITS_PER_WORD)) \
     : (TARGET_SHMEDIA && FP_REGISTER_P (REGNO)) \
     ? ((GET_MODE_SIZE (MODE) + UNITS_PER_WORD/2 - 1) / (UNITS_PER_WORD/2)) \
-    : ((GET_MODE_SIZE (MODE) + UNITS_PER_WORD - 1) / UNITS_PER_WORD)) \
-
-/* Value is 1 if hard register REGNO can hold a value of machine-mode MODE.
-   We can allow any mode in any general register.  The special registers
-   only allow SImode.  Don't allow any mode in the PR.  */
-
-/* We cannot hold DCmode values in the XD registers because alter_reg
-   handles subregs of them incorrectly.  We could work around this by
-   spacing the XD registers like the DR registers, but this would require
-   additional memory in every compilation to hold larger register vectors.
-   We could hold SFmode / SCmode values in XD registers, but that
-   would require a tertiary reload when reloading from / to memory,
-   and a secondary reload to reload from / to general regs; that
-   seems to be a loosing proposition.  */
-#define HARD_REGNO_MODE_OK(REGNO, MODE)                \
-  (SPECIAL_REGISTER_P (REGNO) ? (MODE) == SImode \
-   : (REGNO) == FPUL_REG ? (MODE) == SImode || (MODE) == SFmode        \
-   : FP_REGISTER_P (REGNO) && (MODE) == SFmode \
-   ? 1 \
-   : (MODE) == V2SFmode \
-   ? (FP_REGISTER_P (REGNO) && ((REGNO) - FIRST_FP_REG) % 2 == 0) \
-   : (MODE) == V4SFmode \
-   ? (FP_REGISTER_P (REGNO) && ((REGNO) - FIRST_FP_REG) % 4 == 0) \
-   : (MODE) == V16SFmode \
-   ? (TARGET_SHMEDIA \
-      ? (FP_REGISTER_P (REGNO) && ((REGNO) - FIRST_FP_REG) % 16 == 0) \
-      : (REGNO) == FIRST_XD_REG) \
-   : FP_REGISTER_P (REGNO) \
-   ? ((MODE) == SFmode \
-      || (TARGET_SHMEDIA && (MODE) == SImode) \
-      || ((TARGET_SH3E || TARGET_SHMEDIA) && (MODE) == SCmode) \
-      || (((TARGET_SH4 && (MODE) == DFmode) || (MODE) == DCmode \
-          || (TARGET_SHMEDIA && ((MODE) == DFmode || (MODE) == DImode \
-                                 || (MODE) == V2SFmode))) \
-         && (((REGNO) - FIRST_FP_REG) & 1) == 0)) \
-   : XD_REGISTER_P (REGNO) \
-   ? (MODE) == DFmode \
-   : TARGET_REGISTER_P (REGNO) \
-   ? ((MODE) == DImode || (MODE) == SImode) \
-   : (REGNO) == PR_REG ? 0                     \
-   : (REGNO) == FPSCR_REG ? (MODE) == PSImode \
-   : 1)
+    : ((GET_MODE_SIZE (MODE) + UNITS_PER_WORD - 1) / UNITS_PER_WORD))
 
-/* Value is 1 if MODE is a supported vector mode.  */
-#define VECTOR_MODE_SUPPORTED_P(MODE) \
-  (TARGET_FPU_ANY \
-   && ((MODE) == V2SFmode || (MODE) == V4SFmode || (MODE) == V16SFmode))
+/* Value is 1 if hard register REGNO can hold a value of machine-mode MODE.  */
+
+#define HARD_REGNO_MODE_OK(REGNO, MODE)                \
+  sh_hard_regno_mode_ok ((REGNO), (MODE))
 
 /* Value is 1 if it is a good idea to tie two pseudo registers
    when one has mode MODE1 and one has mode MODE2.
@@ -887,11 +1223,20 @@ extern char sh_additional_register_names[ADDREGNAMES_SIZE] \
 
 #define MODES_TIEABLE_P(MODE1, MODE2) \
   ((MODE1) == (MODE2) \
+   || (TARGET_SHMEDIA \
+       && GET_MODE_SIZE (MODE1) == GET_MODE_SIZE (MODE2) \
+       && INTEGRAL_MODE_P (MODE1) && INTEGRAL_MODE_P (MODE2)) \
    || (GET_MODE_CLASS (MODE1) == GET_MODE_CLASS (MODE2) \
        && (TARGET_SHMEDIA ? ((GET_MODE_SIZE (MODE1) <= 4) \
                              && (GET_MODE_SIZE (MODE2) <= 4)) \
                          : ((MODE1) != SFmode && (MODE2) != SFmode))))
 
+/* A C expression that is nonzero if hard register NEW_REG can be
+   considered for use as a rename register for OLD_REG register */
+
+#define HARD_REGNO_RENAME_OK(OLD_REG, NEW_REG) \
+   sh_hard_regno_rename_ok (OLD_REG, NEW_REG)
+
 /* Specify the registers used for certain standard purposes.
    The values of these macros are register numbers.  */
 
@@ -902,7 +1247,10 @@ extern char sh_additional_register_names[ADDREGNAMES_SIZE] \
 #define STACK_POINTER_REGNUM   SP_REG
 
 /* Base register for access to local variables of the function.  */
-#define FRAME_POINTER_REGNUM   FP_REG
+#define HARD_FRAME_POINTER_REGNUM      FP_REG
+
+/* Base register for access to local variables of the function.  */
+#define FRAME_POINTER_REGNUM   153
 
 /* Fake register that holds the address on the stack of the
    current function's return address.  */
@@ -910,7 +1258,7 @@ extern char sh_additional_register_names[ADDREGNAMES_SIZE] \
 
 /* Register to hold the addressing base for position independent
    code access to data items.  */
-#define PIC_OFFSET_TABLE_REGNUM        PIC_REG
+#define PIC_OFFSET_TABLE_REGNUM        (flag_pic ? PIC_REG : INVALID_REGNUM)
 
 #define GOT_SYMBOL_NAME "*_GLOBAL_OFFSET_TABLE_"
 
@@ -944,16 +1292,18 @@ extern char sh_additional_register_names[ADDREGNAMES_SIZE] \
    of elimination fail.  */
 
 #define ELIMINABLE_REGS                                                \
-{{ FRAME_POINTER_REGNUM, STACK_POINTER_REGNUM},                        \
+{{ HARD_FRAME_POINTER_REGNUM, STACK_POINTER_REGNUM},           \
+ { FRAME_POINTER_REGNUM, STACK_POINTER_REGNUM},                        \
+ { FRAME_POINTER_REGNUM, HARD_FRAME_POINTER_REGNUM},           \
  { RETURN_ADDRESS_POINTER_REGNUM, STACK_POINTER_REGNUM},       \
- { RETURN_ADDRESS_POINTER_REGNUM, FRAME_POINTER_REGNUM},       \
+ { RETURN_ADDRESS_POINTER_REGNUM, HARD_FRAME_POINTER_REGNUM},  \
  { ARG_POINTER_REGNUM, STACK_POINTER_REGNUM},                  \
- { ARG_POINTER_REGNUM, FRAME_POINTER_REGNUM},}
+ { ARG_POINTER_REGNUM, HARD_FRAME_POINTER_REGNUM},}
 
 /* Given FROM and TO register numbers, say whether this elimination
    is allowed.  */
 #define CAN_ELIMINATE(FROM, TO) \
-  (!((FROM) == FRAME_POINTER_REGNUM && FRAME_POINTER_REQUIRED))
+  (!((FROM) == HARD_FRAME_POINTER_REGNUM && FRAME_POINTER_REQUIRED))
 
 /* Define the offset between two registers, one to be eliminated, and the other
    its replacement, at the start of a routine.  */
@@ -967,36 +1317,14 @@ extern char sh_additional_register_names[ADDREGNAMES_SIZE] \
 /* Register in which the static-chain is passed to a function.  */
 #define STATIC_CHAIN_REGNUM    (TARGET_SH5 ? 1 : 3)
 
-/* The register in which a struct value address is passed.  */
-
-#define STRUCT_VALUE_REGNUM 2
-
-/* If the structure value address is not passed in a register, define
-   `STRUCT_VALUE' as an expression returning an RTX for the place
-   where the address is passed.  If it returns 0, the address is
-   passed as an "invisible" first argument.  */
-
-/* The Hitachi calling convention doesn't quite fit into this scheme since
-   the address is passed like an invisible argument, but one that is always
-   passed in memory.  */
-#define STRUCT_VALUE \
-  (TARGET_HITACHI ? 0 : gen_rtx_REG (Pmode, STRUCT_VALUE_REGNUM))
-
-#define RETURN_IN_MEMORY(TYPE) \
-  (TARGET_SH5 \
-   ? ((TYPE_MODE (TYPE) == BLKmode \
-       ? int_size_in_bytes (TYPE) \
-       : GET_MODE_SIZE (TYPE_MODE (TYPE))) > 8) \
-   : (TYPE_MODE (TYPE) == BLKmode \
-      || TARGET_HITACHI && TREE_CODE (TYPE) == RECORD_TYPE))
-
 /* Don't default to pcc-struct-return, because we have already specified
-   exactly how to return structures in the RETURN_IN_MEMORY macro.  */
+   exactly how to return structures in the TARGET_RETURN_IN_MEMORY
+   target hook.  */
 
 #define DEFAULT_PCC_STRUCT_RETURN 0
 
 #define SHMEDIA_REGS_STACK_ADJUST() \
-  (TARGET_SHCOMPACT && current_function_has_nonlocal_label \
+  (TARGET_SHCOMPACT && crtl->saves_all_registers \
    ? (8 * (/* r28-r35 */ 8 + /* r44-r59 */ 16 + /* tr5-tr7 */ 3) \
       + (TARGET_FPU_ANY ? 4 * (/* fr36 - fr63 */ 28) : 0)) \
    : 0)
@@ -1047,9 +1375,11 @@ enum reg_class
   GENERAL_REGS,
   FP0_REGS,
   FP_REGS,
+  DF_HI_REGS,
   DF_REGS,
   FPSCR_REGS,
   GENERAL_FP_REGS,
+  GENERAL_DF_REGS,
   TARGET_REGS,
   ALL_REGS,
   LIM_REG_CLASSES
@@ -1070,9 +1400,11 @@ enum reg_class
   "GENERAL_REGS",      \
   "FP0_REGS",          \
   "FP_REGS",           \
+  "DF_HI_REGS",                \
   "DF_REGS",           \
   "FPSCR_REGS",                \
   "GENERAL_FP_REGS",   \
+  "GENERAL_DF_REGS",   \
   "TARGET_REGS",       \
   "ALL_REGS",          \
 }
@@ -1094,35 +1426,53 @@ enum reg_class
 /* MAC_REGS:  */                                                       \
   { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00300000 },      \
 /* FPUL_REGS:  */                                                      \
-  { 0x00000000, 0x00000000, 0x00000000, 0x00000001, 0x00400000 },      \
+  { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00400000 },      \
 /* SIBCALL_REGS: Initialized in CONDITIONAL_REGISTER_USAGE.  */        \
   { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 },      \
 /* GENERAL_REGS:  */                                                   \
-  { 0xffffffff, 0xffffffff, 0x00000000, 0x00000000, 0x01020000 },      \
+  { 0xffffffff, 0xffffffff, 0x00000000, 0x00000000, 0x03020000 },      \
 /* FP0_REGS:  */                                                       \
   { 0x00000000, 0x00000000, 0x00000001, 0x00000000, 0x00000000 },      \
 /* FP_REGS:  */                                                                \
   { 0x00000000, 0x00000000, 0xffffffff, 0xffffffff, 0x00000000 },      \
+/* DF_HI_REGS:  Initialized in CONDITIONAL_REGISTER_USAGE.  */         \
+  { 0x00000000, 0x00000000, 0xffffffff, 0xffffffff, 0x0000ff00 },      \
 /* DF_REGS:  */                                                                \
   { 0x00000000, 0x00000000, 0xffffffff, 0xffffffff, 0x0000ff00 },      \
 /* FPSCR_REGS:  */                                                     \
   { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00800000 },      \
 /* GENERAL_FP_REGS:  */                                                        \
-  { 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0x0102ff00 },      \
+  { 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0x03020000 },      \
+/* GENERAL_DF_REGS:  */                                                        \
+  { 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0x0302ff00 },      \
 /* TARGET_REGS:  */                                                    \
   { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x000000ff },      \
 /* ALL_REGS:  */                                                       \
-  { 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0x01ffffff },      \
-}                                                                       
+  { 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0x03ffffff },      \
+}
 
 /* The same information, inverted:
    Return the class number of the smallest class containing
    reg number REGNO.  This could be a conditional expression
    or could index an array.  */
 
-extern int regno_reg_class[FIRST_PSEUDO_REGISTER];
+extern enum reg_class regno_reg_class[FIRST_PSEUDO_REGISTER];
 #define REGNO_REG_CLASS(REGNO) regno_reg_class[(REGNO)]
 
+/* The following macro defines cover classes for Integrated Register
+   Allocator.  Cover classes is a set of non-intersected register
+   classes covering all hard registers used for register allocation
+   purpose.  Any move between two registers of a cover class should be
+   cheaper than load or store of the registers.  The macro value is
+   array of register classes with LIM_REG_CLASSES used as the end
+   marker.  */
+
+#define IRA_COVER_CLASSES                                                   \
+{                                                                           \
+  GENERAL_REGS, FP_REGS, PR_REGS, T_REGS, MAC_REGS, TARGET_REGS,            \
+  FPUL_REGS, LIM_REG_CLASSES                                                \
+}
+
 /* When defined, the compiler allows registers explicitly used in the
    rtl to be used as spill registers but prevents the compiler from
    extending the lifetime of these registers.  */
@@ -1134,84 +1484,58 @@ extern int regno_reg_class[FIRST_PSEUDO_REGISTER];
    and GENERAL_FP_REGS the alternate class.  Since FP0 is likely to be
    spilled or used otherwise, we better have the FP_REGS allocated first.  */
 #define REG_ALLOC_ORDER \
-  { 65, 66, 67, 68, 69, 70, 71, 64, \
-    72, 73, 74, 75, 76, 77, 78, 79, \
-   136,137,138,139,140,141,142,143, \
-    80, 81, 82, 83, 84, 85, 86, 87, \
-    88, 89, 90, 91, 92, 93, 94, 95, \
-    96, 97, 98, 99,100,101,102,103, \
+  {/* Caller-saved FPRs */ \
+    65, 66, 67, 68, 69, 70, 71, 64, \
+    72, 73, 74, 75, 80, 81, 82, 83, \
+    84, 85, 86, 87, 88, 89, 90, 91, \
+    92, 93, 94, 95, 96, 97, 98, 99, \
+   /* Callee-saved FPRs */ \
+    76, 77, 78, 79,100,101,102,103, \
    104,105,106,107,108,109,110,111, \
    112,113,114,115,116,117,118,119, \
    120,121,122,123,124,125,126,127, \
-   151,  1,  2,  3,  7,  6,  5,  4, \
-     0,  8,  9, 10, 11, 12, 13, 14, \
-    16, 17, 18, 19, 20, 21, 22, 23, \
-    24, 25, 26, 27, 28, 29, 30, 31, \
-    32, 33, 34, 35, 36, 37, 38, 39, \
-    40, 41, 42, 43, 44, 45, 46, 47, \
-    48, 49, 50, 51, 52, 53, 54, 55, \
-    56, 57, 58, 59, 60, 61, 62, 63, \
-   150, 15,145,146,147,144,148,149, \
+   136,137,138,139,140,141,142,143, \
+   /* FPSCR */ 151, \
+   /* Caller-saved GPRs (except 8/9 on SH1-4) */ \
+     1,  2,  3,  7,  6,  5,  4,  0, \
+     8,  9, 17, 19, 20, 21, 22, 23, \
+    36, 37, 38, 39, 40, 41, 42, 43, \
+    60, 61, 62, \
+   /* SH1-4 callee-saved saved GPRs / SH5 partially-saved GPRs */ \
+    10, 11, 12, 13, 14, 18, \
+    /* SH5 callee-saved GPRs */ \
+    28, 29, 30, 31, 32, 33, 34, 35, \
+    44, 45, 46, 47, 48, 49, 50, 51, \
+    52, 53, 54, 55, 56, 57, 58, 59, \
+   /* FPUL */ 150, \
+   /* SH5 branch target registers */ \
    128,129,130,131,132,133,134,135, \
-   152 }
+   /* Fixed registers */ \
+    15, 16, 24, 25, 26, 27, 63,144, \
+   145,146,147,148,149,152,153 }
 
 /* The class value for index registers, and the one for base regs.  */
-#define INDEX_REG_CLASS  (TARGET_SHMEDIA ? GENERAL_REGS : R0_REGS)
+#define INDEX_REG_CLASS \
+  (!ALLOW_INDEXED_ADDRESS ? NO_REGS : TARGET_SHMEDIA ? GENERAL_REGS : R0_REGS)
 #define BASE_REG_CLASS  GENERAL_REGS
+\f
+/* Defines for sh.md and constraints.md.  */
 
-/* Get reg_class from a letter such as appears in the machine
-   description.  */
-extern const enum reg_class reg_class_from_letter[];
+#define CONST_OK_FOR_I06(VALUE) (((HOST_WIDE_INT)(VALUE)) >= -32 \
+                                && ((HOST_WIDE_INT)(VALUE)) <= 31)
+#define CONST_OK_FOR_I08(VALUE) (((HOST_WIDE_INT)(VALUE))>= -128 \
+                                && ((HOST_WIDE_INT)(VALUE)) <= 127)
+#define CONST_OK_FOR_I10(VALUE) (((HOST_WIDE_INT)(VALUE)) >= -512 \
+                                && ((HOST_WIDE_INT)(VALUE)) <= 511)
+#define CONST_OK_FOR_I16(VALUE) (((HOST_WIDE_INT)(VALUE)) >= -32768 \
+                                && ((HOST_WIDE_INT)(VALUE)) <= 32767)
 
-#define REG_CLASS_FROM_LETTER(C) \
-   ( ISLOWER (C) ? reg_class_from_letter[(C)-'a'] : NO_REGS )
-\f
-/* The letters I, J, K, L and M in a register constraint string
-   can be used to stand for particular ranges of immediate operands.
-   This macro defines what the ranges are.
-   C is the letter, and VALUE is a constant value.
-   Return 1 if VALUE is in the range specified by C.
-       I: arithmetic operand -127..128, as used in add, sub, etc
-       J: arithmetic operand -32768..32767, as used in SHmedia movi and shori
-       K: shift operand 1,2,8 or 16
-       L: logical operand 0..255, as used in and, or, etc.
-       M: constant 1
-       N: constant 0
-       O: arithmetic operand -32..31, as used in SHmedia beqi, bnei and xori
-       P: arithmetic operand -512..511, as used in SHmedia andi, ori
-*/
-
-#define CONST_OK_FOR_I(VALUE) (((HOST_WIDE_INT)(VALUE))>= -128 \
-                              && ((HOST_WIDE_INT)(VALUE)) <= 127)
-#define CONST_OK_FOR_J(VALUE) (((HOST_WIDE_INT)(VALUE)) >= -32768 \
-                              && ((HOST_WIDE_INT)(VALUE)) <= 32767)
-#define CONST_OK_FOR_K(VALUE) ((VALUE)==1||(VALUE)==2||(VALUE)==8||(VALUE)==16)
-#define CONST_OK_FOR_L(VALUE) (((HOST_WIDE_INT)(VALUE))>= 0 \
-                              && ((HOST_WIDE_INT)(VALUE)) <= 255)
-#define CONST_OK_FOR_M(VALUE) ((VALUE)==1)
-#define CONST_OK_FOR_N(VALUE) ((VALUE)==0)
-#define CONST_OK_FOR_O(VALUE) (((HOST_WIDE_INT)(VALUE)) >= -32 \
-                              && ((HOST_WIDE_INT)(VALUE)) <= 31)
-#define CONST_OK_FOR_P(VALUE) (((HOST_WIDE_INT)(VALUE)) >= -512 \
-                              && ((HOST_WIDE_INT)(VALUE)) <= 511)
-#define CONST_OK_FOR_LETTER_P(VALUE, C)                \
-     ((C) == 'I' ? CONST_OK_FOR_I (VALUE)      \
-    : (C) == 'J' ? CONST_OK_FOR_J (VALUE)      \
-    : (C) == 'K' ? CONST_OK_FOR_K (VALUE)      \
-    : (C) == 'L' ? CONST_OK_FOR_L (VALUE)      \
-    : (C) == 'M' ? CONST_OK_FOR_M (VALUE)      \
-    : (C) == 'N' ? CONST_OK_FOR_N (VALUE)      \
-    : (C) == 'O' ? CONST_OK_FOR_O (VALUE)      \
-    : (C) == 'P' ? CONST_OK_FOR_P (VALUE)      \
-    : 0)
-
-/* Similar, but for floating constants, and defining letters G and H.
-   Here VALUE is the CONST_DOUBLE rtx itself.  */
-
-#define CONST_DOUBLE_OK_FOR_LETTER_P(VALUE, C)         \
-((C) == 'G' ? (fp_zero_operand (VALUE) && fldi_ok ())  \
- : (C) == 'H' ? (fp_one_operand (VALUE) && fldi_ok ()) \
- : (C) == 'F')
+#define CONST_OK_FOR_J16(VALUE) \
+  ((HOST_BITS_PER_WIDE_INT >= 64 && (VALUE) == (HOST_WIDE_INT) 0xffffffff) \
+   || (HOST_BITS_PER_WIDE_INT >= 64 && (VALUE) == (HOST_WIDE_INT) -1 << 32))
+
+#define CONST_OK_FOR_K08(VALUE) (((HOST_WIDE_INT)(VALUE))>= 0 \
+                                && ((HOST_WIDE_INT)(VALUE)) <= 255)
 
 /* Given an rtx X being reloaded into a reg required to be
    in class CLASS, return the class of reg to actually use.
@@ -1221,78 +1545,103 @@ extern const enum reg_class reg_class_from_letter[];
 #define PREFERRED_RELOAD_CLASS(X, CLASS) \
   ((CLASS) == NO_REGS && TARGET_SHMEDIA \
    && (GET_CODE (X) == CONST_DOUBLE \
-       || GET_CODE (X) == SYMBOL_REF) \
+       || GET_CODE (X) == SYMBOL_REF \
+       || PIC_ADDR_P (X)) \
    ? GENERAL_REGS \
    : (CLASS)) \
 
-#define SECONDARY_OUTPUT_RELOAD_CLASS(CLASS,MODE,X) \
-  ((((((CLASS) == FP_REGS || (CLASS) == FP0_REGS                       \
-       || (CLASS) == DF_REGS)                                          \
-      && (GET_CODE (X) == REG && GENERAL_OR_AP_REGISTER_P (REGNO (X))))        \
-     || (((CLASS) == GENERAL_REGS || (CLASS) == R0_REGS)               \
+#if 0
+#define SECONDARY_INOUT_RELOAD_CLASS(CLASS,MODE,X,ELSE) \
+  ((((REGCLASS_HAS_FP_REG (CLASS)                                      \
+      && (GET_CODE (X) == REG                                          \
+      && (GENERAL_OR_AP_REGISTER_P (REGNO (X))                         \
+         || (FP_REGISTER_P (REGNO (X)) && (MODE) == SImode             \
+             && TARGET_FMOVD))))                                       \
+     || (REGCLASS_HAS_GENERAL_REG (CLASS)                              \
         && GET_CODE (X) == REG                                         \
         && FP_REGISTER_P (REGNO (X))))                                 \
     && ! TARGET_SHMEDIA                                                        \
-    && MODE == SFmode)                                                 \
+    && ((MODE) == SFmode || (MODE) == SImode))                         \
    ? FPUL_REGS                                                         \
-   : ((CLASS) == FPUL_REGS                                             \
+   : (((CLASS) == FPUL_REGS                                            \
+       || (REGCLASS_HAS_FP_REG (CLASS)                                 \
+          && ! TARGET_SHMEDIA && MODE == SImode))                      \
       && (GET_CODE (X) == MEM                                          \
          || (GET_CODE (X) == REG                                       \
              && (REGNO (X) >= FIRST_PSEUDO_REGISTER                    \
                  || REGNO (X) == T_REG                                 \
                  || system_reg_operand (X, VOIDmode)))))               \
    ? GENERAL_REGS                                                      \
-   : (((CLASS) == FP_REGS || (CLASS) == DF_REGS) && TARGET_SHMEDIA     \
-      && immediate_operand ((X), (MODE)))                              \
+   : (((CLASS) == TARGET_REGS                                          \
+       || (TARGET_SHMEDIA && (CLASS) == SIBCALL_REGS))                 \
+      && !satisfies_constraint_Csy (X)                                 \
+      && (GET_CODE (X) != REG || ! GENERAL_REGISTER_P (REGNO (X))))    \
    ? GENERAL_REGS                                                      \
-   : ((CLASS) == TARGET_REGS                                           \
-      || (TARGET_SHMEDIA && (CLASS) == SIBCALL_REGS))                  \
-   ? ((target_operand ((X), (MODE))                                    \
-       && ! target_reg_operand ((X), (MODE)))                          \
-      ? NO_REGS : GENERAL_REGS)                                                \
    : (((CLASS) == MAC_REGS || (CLASS) == PR_REGS)                      \
       && GET_CODE (X) == REG && ! GENERAL_REGISTER_P (REGNO (X))       \
       && (CLASS) != REGNO_REG_CLASS (REGNO (X)))                       \
-   ? GENERAL_REGS : NO_REGS)
+   ? GENERAL_REGS                                                      \
+   : ((CLASS) != GENERAL_REGS && GET_CODE (X) == REG                   \
+      && TARGET_REGISTER_P (REGNO (X)))                                        \
+   ? GENERAL_REGS : (ELSE))
+
+#define SECONDARY_OUTPUT_RELOAD_CLASS(CLASS,MODE,X) \
+ SECONDARY_INOUT_RELOAD_CLASS(CLASS,MODE,X,NO_REGS)
 
 #define SECONDARY_INPUT_RELOAD_CLASS(CLASS,MODE,X)  \
-  ((((CLASS) == FP_REGS || (CLASS) == FP0_REGS || (CLASS) == DF_REGS)  \
+  ((REGCLASS_HAS_FP_REG (CLASS)                                        \
     && ! TARGET_SHMEDIA                                                        \
     && immediate_operand ((X), (MODE))                                 \
     && ! ((fp_zero_operand (X) || fp_one_operand (X))                  \
          && (MODE) == SFmode && fldi_ok ()))                           \
    ? R0_REGS                                                           \
-   : (CLASS == FPUL_REGS                                               \
+   : ((CLASS) == FPUL_REGS                                             \
       && ((GET_CODE (X) == REG                                         \
-          && (REGNO (X) == MACL_REG || REGNO (X) == MACH_REG           \
-             || REGNO (X) == T_REG))))                                 \
+          && (REGNO (X) == MACL_REG || REGNO (X) == MACH_REG           \
+              || REGNO (X) == T_REG))                                  \
+         || GET_CODE (X) == PLUS))                                     \
    ? GENERAL_REGS                                                      \
-   : CLASS == FPUL_REGS && immediate_operand ((X), (MODE))             \
-   ? (GET_CODE (X) == CONST_INT && CONST_OK_FOR_I (INTVAL (X))         \
+   : (CLASS) == FPUL_REGS && immediate_operand ((X), (MODE))           \
+   ? (satisfies_constraint_I08 (X)                                     \
       ? GENERAL_REGS                                                   \
       : R0_REGS)                                                       \
-   : (CLASS == FPSCR_REGS                                              \
+   : ((CLASS) == FPSCR_REGS                                            \
       && ((GET_CODE (X) == REG && REGNO (X) >= FIRST_PSEUDO_REGISTER)  \
          || (GET_CODE (X) == MEM && GET_CODE (XEXP ((X), 0)) == PLUS)))\
    ? GENERAL_REGS                                                      \
-   : SECONDARY_OUTPUT_RELOAD_CLASS((CLASS),(MODE),(X)))
+   : (REGCLASS_HAS_FP_REG (CLASS)                                      \
+      && TARGET_SHMEDIA                                                        \
+      && immediate_operand ((X), (MODE))                               \
+      && (X) != CONST0_RTX (GET_MODE (X))                              \
+      && GET_MODE (X) != V4SFmode)                                     \
+   ? GENERAL_REGS                                                      \
+   : (((MODE) == QImode || (MODE) == HImode)                           \
+      && TARGET_SHMEDIA && inqhi_operand ((X), (MODE)))                        \
+   ? GENERAL_REGS                                                      \
+   : (TARGET_SHMEDIA && (CLASS) == GENERAL_REGS                                \
+      && (GET_CODE (X) == LABEL_REF || PIC_ADDR_P (X)))                        \
+   ? TARGET_REGS                                                       \
+   : SECONDARY_INOUT_RELOAD_CLASS((CLASS),(MODE),(X), NO_REGS))
+#endif
 
 /* Return the maximum number of consecutive registers
    needed to represent mode MODE in a register of class CLASS.
 
-   On SH this is the size of MODE in words.  */
+   If TARGET_SHMEDIA, we need two FP registers per word.
+   Otherwise we will need at most one register per word.  */
 #define CLASS_MAX_NREGS(CLASS, MODE) \
-     ((GET_MODE_SIZE (MODE) + UNITS_PER_WORD - 1) / UNITS_PER_WORD)
+    (TARGET_SHMEDIA \
+     && TEST_HARD_REG_BIT (reg_class_contents[CLASS], FIRST_FP_REG) \
+     ? (GET_MODE_SIZE (MODE) + UNITS_PER_WORD/2 - 1) / (UNITS_PER_WORD/2) \
+     : (GET_MODE_SIZE (MODE) + UNITS_PER_WORD - 1) / UNITS_PER_WORD)
 
 /* If defined, gives a class of registers that cannot be used as the
    operand of a SUBREG that changes the mode of the object illegally.  */
+/* ??? We need to renumber the internal numbers for the frnn registers
+   when in little endian in order to allow mode size changes.  */
 
-#define CLASS_CANNOT_CHANGE_MODE        DF_REGS
-
-/* Defines illegal mode changes for CLASS_CANNOT_CHANGE_MODE.  */
-
-#define CLASS_CANNOT_CHANGE_MODE_P(FROM,TO) \
-  (GET_MODE_SIZE (FROM) != GET_MODE_SIZE (TO))
+#define CANNOT_CHANGE_MODE_CLASS(FROM, TO, CLASS)                          \
+  sh_cannot_change_mode_class (FROM, TO, CLASS)
 \f
 /* Stack layout; function entry, exit and calling.  */
 
@@ -1302,7 +1651,7 @@ extern const enum reg_class reg_class_from_letter[];
 #define NPARM_REGS(MODE) \
   (TARGET_FPU_ANY && (MODE) == SFmode \
    ? (TARGET_SH5 ? 12 : 8) \
-   : TARGET_SH4 && (GET_MODE_CLASS (MODE) == MODE_FLOAT \
+   : (TARGET_SH4 || TARGET_SH2A_DOUBLE) && (GET_MODE_CLASS (MODE) == MODE_FLOAT \
                    || GET_MODE_CLASS (MODE) == MODE_COMPLEX_FLOAT) \
    ? (TARGET_SH5 ? 12 : 8) \
    : (TARGET_SH5 ? 8 : 4))
@@ -1317,11 +1666,9 @@ extern const enum reg_class reg_class_from_letter[];
    makes the stack pointer a smaller address.  */
 #define STACK_GROWS_DOWNWARD
 
-/*  Define this macro if the addresses of local variable slots are at
-    negative offsets from the frame pointer.
-
-    The SH only has positive indexes, so grow the frame up.  */
-/* #define FRAME_GROWS_DOWNWARD */
+/*  Define this macro to nonzero if the addresses of local variable slots
+    are at negative offsets from the frame pointer.  */
+#define FRAME_GROWS_DOWNWARD 1
 
 /* Offset from the frame pointer to the first local variable slot to
    be allocated.  */
@@ -1357,14 +1704,6 @@ extern const enum reg_class reg_class_from_letter[];
    On SHcompact, the call trampoline pops arguments off the stack.  */
 #define CALL_POPS_ARGS(CUM) (TARGET_SHCOMPACT ? (CUM).stack_regs * 8 : 0)
 
-/* Nonzero if we do not know how to pass TYPE solely in registers.
-   Values that come in registers with inconvenient padding are stored
-   to memory at the function start.  */
-
-#define MUST_PASS_IN_STACK(MODE,TYPE)                  \
-  ((TYPE) != 0                                         \
-   && (TREE_CODE (TYPE_SIZE (TYPE)) != INTEGER_CST     \
-       || TREE_ADDRESSABLE (TYPE)))
 /* Some subroutine macros specific to this machine.  */
 
 #define BASE_RETURN_VALUE_REG(MODE) \
@@ -1379,9 +1718,9 @@ extern const enum reg_class reg_class_from_letter[];
    : FIRST_RET_REG)
 
 #define BASE_ARG_REG(MODE) \
-  ((TARGET_SH3E && ((MODE) == SFmode))                 \
+  ((TARGET_SH2E && ((MODE) == SFmode))                 \
    ? FIRST_FP_PARM_REG                                 \
-   : TARGET_SH4 && (GET_MODE_CLASS (MODE) == MODE_FLOAT        \
+   : (TARGET_SH4 || TARGET_SH2A_DOUBLE) && (GET_MODE_CLASS (MODE) == MODE_FLOAT        \
                    || GET_MODE_CLASS (MODE) == MODE_COMPLEX_FLOAT)\
    ? FIRST_FP_PARM_REG                                 \
    : FIRST_PARM_REG)
@@ -1396,18 +1735,18 @@ extern const enum reg_class reg_class_from_letter[];
    tested here has to be kept in sync with the one in explow.c:promote_mode.  */
 
 #define FUNCTION_VALUE(VALTYPE, FUNC)                                  \
-  gen_rtx (REG,                                                                \
+  gen_rtx_REG (                                                                \
           ((GET_MODE_CLASS (TYPE_MODE (VALTYPE)) == MODE_INT           \
-            && GET_MODE_SIZE (TYPE_MODE (VALTYPE)) < UNITS_PER_WORD    \
+            && GET_MODE_SIZE (TYPE_MODE (VALTYPE)) < 4                 \
             && (TREE_CODE (VALTYPE) == INTEGER_TYPE                    \
                 || TREE_CODE (VALTYPE) == ENUMERAL_TYPE                \
                 || TREE_CODE (VALTYPE) == BOOLEAN_TYPE                 \
-                || TREE_CODE (VALTYPE) == CHAR_TYPE                    \
                 || TREE_CODE (VALTYPE) == REAL_TYPE                    \
                 || TREE_CODE (VALTYPE) == OFFSET_TYPE))                \
-           ? (TARGET_SHMEDIA ? DImode : SImode) : TYPE_MODE (VALTYPE)), \
+             && sh_promote_prototypes (VALTYPE)                                \
+           ? (TARGET_SHMEDIA64 ? DImode : SImode) : TYPE_MODE (VALTYPE)), \
           BASE_RETURN_VALUE_REG (TYPE_MODE (VALTYPE)))
-     
+
 /* Define how to find the value returned by a library function
    assuming the value has mode MODE.  */
 #define LIBCALL_VALUE(MODE) \
@@ -1415,16 +1754,19 @@ extern const enum reg_class reg_class_from_letter[];
 
 /* 1 if N is a possible register number for a function value.  */
 #define FUNCTION_VALUE_REGNO_P(REGNO) \
-  ((REGNO) == FIRST_RET_REG || (TARGET_SH3E && (REGNO) == FIRST_FP_RET_REG) \
+  ((REGNO) == FIRST_RET_REG || (TARGET_SH2E && (REGNO) == FIRST_FP_RET_REG) \
    || (TARGET_SHMEDIA_FPU && (REGNO) == FIRST_FP_RET_REG))
 
 /* 1 if N is a possible register number for function argument passing.  */
+/* ??? There are some callers that pass REGNO as int, and others that pass
+   it as unsigned.  We get warnings unless we do casts everywhere.  */
 #define FUNCTION_ARG_REGNO_P(REGNO) \
-  (((REGNO) >= FIRST_PARM_REG && (REGNO) < (FIRST_PARM_REG             \
-                                           + NPARM_REGS (SImode)))     \
+  (((unsigned) (REGNO) >= (unsigned) FIRST_PARM_REG                    \
+    && (unsigned) (REGNO) < (unsigned) (FIRST_PARM_REG + NPARM_REGS (SImode)))\
    || (TARGET_FPU_ANY                                                   \
-       && (REGNO) >= FIRST_FP_PARM_REG && (REGNO) < (FIRST_FP_PARM_REG \
-                                                    + NPARM_REGS (SFmode))))
+       && (unsigned) (REGNO) >= (unsigned) FIRST_FP_PARM_REG           \
+       && (unsigned) (REGNO) < (unsigned) (FIRST_FP_PARM_REG           \
+                                          + NPARM_REGS (SFmode))))
 \f
 /* Define a data type for recording info about an argument list
    during the scan of that argument list.  This data type should
@@ -1441,7 +1783,7 @@ enum sh_arg_class { SH_ARG_INT = 0, SH_ARG_FLOAT = 1 };
 struct sh_args {
     int arg_count[2];
     int force_mem;
-  /* Non-zero if a prototype is available for the function.  */
+  /* Nonzero if a prototype is available for the function.  */
     int prototype_p;
   /* The number of an odd floating-point register, that should be used
      for the next argument of type float.  */
@@ -1462,8 +1804,8 @@ struct sh_args {
      used to pass arguments, if the arguments didn't have to be passed
      by reference.  */
     int byref_regs;
-  /* Set by SHCOMPACT_BYREF if the current argument is to be passed by
-     reference.  */
+  /* Set as by shcompact_byref if the current argument is to be passed
+     by reference.  */
     int byref;
 
   /* call_cookie is a bitmask used by call expanders, as well as
@@ -1521,6 +1863,13 @@ struct sh_args {
 
      - If T is set, a return trampoline will be set up for 64-bit
      return values to be split into 2 32-bit registers.  */
+    long call_cookie;
+
+  /* This is set to nonzero when the call in question must use the Renesas ABI,
+     even without the -mrenesas option.  */
+    int renesas_abi;
+};
+
 #define CALL_COOKIE_RET_TRAMP_SHIFT 0
 #define CALL_COOKIE_RET_TRAMP(VAL) ((VAL) << CALL_COOKIE_RET_TRAMP_SHIFT)
 #define CALL_COOKIE_STACKSEQ_SHIFT 1
@@ -1533,8 +1882,6 @@ struct sh_args {
   ((VAL) << CALL_COOKIE_INT_REG_SHIFT (REG))
 #define CALL_COOKIE_INT_REG_GET(COOKIE, REG) \
   (((COOKIE) >> CALL_COOKIE_INT_REG_SHIFT (REG)) & ((REG) < 4 ? 7 : 15))
-    long call_cookie;
-};
 
 #define CUMULATIVE_ARGS  struct sh_args
 
@@ -1560,7 +1907,7 @@ struct sh_args {
 
 #define ROUND_REG(CUM, MODE) \
    (((TARGET_ALIGN_DOUBLE                                      \
-      || (TARGET_SH4 && ((MODE) == DFmode || (MODE) == DCmode) \
+      || ((TARGET_SH4 || TARGET_SH2A_DOUBLE) && ((MODE) == DFmode || (MODE) == DCmode) \
          && (CUM).arg_count[(int) SH_ARG_FLOAT] < NPARM_REGS (MODE)))\
      && GET_MODE_UNIT_SIZE ((MODE)) > UNITS_PER_WORD)          \
     ? ((CUM).arg_count[(int) GET_SH_ARG_CLASS (MODE)]          \
@@ -1576,173 +1923,16 @@ struct sh_args {
 
    For TARGET_HITACHI, the structure value pointer is passed in memory.  */
 
-#define INIT_CUMULATIVE_ARGS(CUM, FNTYPE, LIBNAME, INDIRECT) \
-  do {                                                         \
-    (CUM).arg_count[(int) SH_ARG_INT] = 0;                     \
-    (CUM).arg_count[(int) SH_ARG_FLOAT] = 0;                   \
-    (CUM).force_mem                                            \
-      = (TARGET_HITACHI && FNTYPE                              \
-        && aggregate_value_p (TREE_TYPE (FNTYPE)));            \
-    (CUM).prototype_p = (FNTYPE) && TYPE_ARG_TYPES (FNTYPE);   \
-    (CUM).arg_count[(int) SH_ARG_INT]                          \
-      = (TARGET_SH5 && (FNTYPE)                                        \
-        && aggregate_value_p (TREE_TYPE (FNTYPE)));            \
-    (CUM).free_single_fp_reg = 0;                              \
-    (CUM).outgoing = 1;                                                \
-    (CUM).stack_regs = 0;                                      \
-    (CUM).byref_regs = 0;                                      \
-    (CUM).byref = 0;                                           \
-    (CUM).call_cookie                                          \
-      = (CALL_COOKIE_RET_TRAMP                                 \
-        (TARGET_SHCOMPACT && (FNTYPE)                          \
-         && (CUM).arg_count[(int) SH_ARG_INT] == 0             \
-         && (TYPE_MODE (TREE_TYPE (FNTYPE)) == BLKmode         \
-             ? int_size_in_bytes (TREE_TYPE (FNTYPE))          \
-             : GET_MODE_SIZE (TYPE_MODE (TREE_TYPE (FNTYPE)))) > 4 \
-         && (BASE_RETURN_VALUE_REG (TYPE_MODE (TREE_TYPE       \
-                                               (FNTYPE)))      \
-             == FIRST_RET_REG)));                              \
-  } while (0)
+#define INIT_CUMULATIVE_ARGS(CUM, FNTYPE, LIBNAME, FNDECL, N_NAMED_ARGS) \
+  sh_init_cumulative_args (& (CUM), (FNTYPE), (LIBNAME), (FNDECL), (N_NAMED_ARGS), VOIDmode)
 
 #define INIT_CUMULATIVE_LIBCALL_ARGS(CUM, MODE, LIBNAME) \
-  do {                                                         \
-    INIT_CUMULATIVE_ARGS ((CUM), NULL_TREE, (LIBNAME), 0);     \
-    (CUM).call_cookie                                          \
-      = (CALL_COOKIE_RET_TRAMP                                 \
-        (TARGET_SHCOMPACT && GET_MODE_SIZE (MODE) > 4          \
-         && BASE_RETURN_VALUE_REG (MODE) == FIRST_RET_REG));   \
-  } while (0)
-
-#define INIT_CUMULATIVE_INCOMING_ARGS(CUM, FNTYPE, LIBNAME) \
-  do {                                                         \
-    INIT_CUMULATIVE_ARGS ((CUM), (FNTYPE), (LIBNAME), 0);      \
-    (CUM).outgoing = 0;                                                \
-  } while (0)
-/* FIXME: This is overly conservative.  A SHcompact function that
-   receives arguments ``by reference'' will have them stored in its
-   own stack frame, so it must not pass pointers or references to
-   these arguments to other functions by means of sibling calls.  */
-#define FUNCTION_OK_FOR_SIBCALL(DECL) \
-  (! TARGET_SHCOMPACT || current_function_args_info.stack_regs == 0)
-
-/* Update the data in CUM to advance over an argument
-   of mode MODE and data type TYPE.
-   (TYPE is null for libcalls where that information may not be
-   available.)  */
+  sh_init_cumulative_args (& (CUM), NULL_TREE, (LIBNAME), NULL_TREE, 0, (MODE))
 
 #define FUNCTION_ARG_ADVANCE(CUM, MODE, TYPE, NAMED)   \
- if ((CUM).force_mem)                                  \
-   (CUM).force_mem = 0;                                        \
- else if (TARGET_SH5)                                  \
-   {                                                   \
-     tree TYPE_ = ((CUM).byref && (TYPE)               \
-                  ? TREE_TYPE (TYPE)                   \
-                  : (TYPE));                           \
-     enum machine_mode MODE_ = ((CUM).byref && (TYPE)  \
-                               ? TYPE_MODE (TYPE_)     \
-                               : (MODE));              \
-     int dwords = (((CUM).byref                                \
-                   ? (CUM).byref                       \
-                   : (MODE_) == BLKmode                \
-                   ? int_size_in_bytes (TYPE_)         \
-                   : GET_MODE_SIZE (MODE_)) + 7) / 8;  \
-     int numregs = MIN (dwords, NPARM_REGS (SImode)    \
-                       - (CUM).arg_count[(int) SH_ARG_INT]); \
-                                                       \
-     if (numregs)                                      \
-       {                                               \
-        (CUM).arg_count[(int) SH_ARG_INT] += numregs;  \
-        if (TARGET_SHCOMPACT                           \
-            && SHCOMPACT_FORCE_ON_STACK (MODE_, TYPE_)) \
-          (CUM).call_cookie                            \
-            |= CALL_COOKIE_INT_REG (((CUM).arg_count[(int) SH_ARG_INT] \
-                                     - numregs), 1);   \
-        else if ((CUM).byref)                          \
-          {                                            \
-            if (! (CUM).outgoing)                      \
-              (CUM).stack_regs += numregs;             \
-            (CUM).byref_regs += numregs;               \
-            (CUM).byref = 0;                           \
-            do                                         \
-              (CUM).call_cookie                        \
-                |= CALL_COOKIE_INT_REG (((CUM).arg_count[(int) SH_ARG_INT] \
-                                         - numregs), 2); \
-            while (--numregs);                         \
-            (CUM).call_cookie                          \
-              |= CALL_COOKIE_INT_REG (((CUM).arg_count[(int) SH_ARG_INT] \
-                                       - 1), 1); \
-          }                                            \
-        else if (dwords > numregs)                     \
-          {                                            \
-            int pushregs = numregs;                    \
-                                                       \
-            if (TARGET_SHCOMPACT)                      \
-              (CUM).stack_regs += numregs;             \
-            while (pushregs < NPARM_REGS (SImode) - 1  \
-                   && (CALL_COOKIE_INT_REG_GET         \
-                       ((CUM).call_cookie,             \
-                       NPARM_REGS (SImode) - pushregs) \
-                       == 1))                          \
-              {                                        \
-                (CUM).call_cookie                      \
-                  &= ~ CALL_COOKIE_INT_REG (NPARM_REGS (SImode) \
-                                            - pushregs, 1); \
-                pushregs++;                            \
-              }                                        \
-            if (numregs == NPARM_REGS (SImode))        \
-              (CUM).call_cookie                        \
-                |= CALL_COOKIE_INT_REG (0, 1)          \
-                   | CALL_COOKIE_STACKSEQ (numregs - 1); \
-            else                                       \
-              (CUM).call_cookie                        \
-                |= CALL_COOKIE_STACKSEQ (numregs);     \
-          }                                            \
-       }                                               \
-     if (GET_SH_ARG_CLASS (MODE_) == SH_ARG_FLOAT      \
-        && ((NAMED) || ! (CUM).prototype_p))           \
-       {                                               \
-        if ((MODE_) == SFmode && (CUM).free_single_fp_reg) \
-          (CUM).free_single_fp_reg = 0;                \
-        else if ((CUM).arg_count[(int) SH_ARG_FLOAT]   \
-                 < NPARM_REGS (SFmode))                \
-          {                                            \
-            int numfpregs                              \
-              = MIN ((GET_MODE_SIZE (MODE_) + 7) / 8 * 2, \
-                     NPARM_REGS (SFmode)               \
-                     - (CUM).arg_count[(int) SH_ARG_FLOAT]); \
-                                                       \
-            (CUM).arg_count[(int) SH_ARG_FLOAT] += numfpregs; \
-                                                       \
-            if (TARGET_SHCOMPACT && ! (CUM).prototype_p) \
-              {                                        \
-                if ((CUM).outgoing && numregs > 0)     \
-                  do                                   \
-                    {                                  \
-                      (CUM).call_cookie                \
-                        |= (CALL_COOKIE_INT_REG        \
-                            ((CUM).arg_count[(int) SH_ARG_INT] \
-                             - numregs + ((numfpregs - 2) / 2), \
-                             4 + ((CUM).arg_count[(int) SH_ARG_FLOAT] \
-                                  - numfpregs) / 2));  \
-                    }                                  \
-                  while (numfpregs -= 2);              \
-              }                                        \
-            else if ((MODE_) == SFmode && (NAMED)      \
-                     && ((CUM).arg_count[(int) SH_ARG_FLOAT] \
-                         < NPARM_REGS (SFmode)))       \
-              (CUM).free_single_fp_reg                 \
-                = FIRST_FP_PARM_REG - numfpregs        \
-                + (CUM).arg_count[(int) SH_ARG_FLOAT] + 1; \
-          }                                            \
-       }                                               \
-   }                                                   \
- else if (! TARGET_SH4 || PASS_IN_REG_P ((CUM), (MODE), (TYPE))) \
-   ((CUM).arg_count[(int) GET_SH_ARG_CLASS (MODE)]     \
-    = (ROUND_REG ((CUM), (MODE))                       \
-       + ((MODE) == BLKmode                            \
-         ? ROUND_ADVANCE (int_size_in_bytes (TYPE))    \
-         : ROUND_ADVANCE (GET_MODE_SIZE (MODE)))))
+       sh_function_arg_advance (&(CUM), (MODE), (TYPE), (NAMED))
+#define FUNCTION_ARG(CUM, MODE, TYPE, NAMED)   \
+       sh_function_arg (&(CUM), (MODE), (TYPE), (NAMED))
 
 /* Return boolean indicating arg of mode MODE will be passed in a reg.
    This macro is only used in this file.  */
@@ -1750,9 +1940,13 @@ struct sh_args {
 #define PASS_IN_REG_P(CUM, MODE, TYPE) \
   (((TYPE) == 0 \
     || (! TREE_ADDRESSABLE ((tree)(TYPE)) \
-       && (! TARGET_HITACHI || ! AGGREGATE_TYPE_P (TYPE)))) \
+       && (! (TARGET_HITACHI || (CUM).renesas_abi) \
+           || ! (AGGREGATE_TYPE_P (TYPE) \
+                 || (!TARGET_FPU_ANY \
+                     && (GET_MODE_CLASS (MODE) == MODE_FLOAT \
+                         && GET_MODE_SIZE (MODE) > GET_MODE_SIZE (SFmode))))))) \
    && ! (CUM).force_mem \
-   && (TARGET_SH3E \
+   && (TARGET_SH2E \
        ? ((MODE) == BLKmode \
          ? (((CUM).arg_count[(int) SH_ARG_INT] * UNITS_PER_WORD \
              + int_size_in_bytes (TYPE)) \
@@ -1762,82 +1956,23 @@ struct sh_args {
             <= NPARM_REGS (MODE))) \
        : ROUND_REG ((CUM), (MODE)) < NPARM_REGS (MODE)))
 
-/* Define where to put the arguments to a function.
-   Value is zero to push the argument on the stack,
-   or a hard register in which to store the argument.
-
-   MODE is the argument's machine mode.
-   TYPE is the data type of the argument (as a tree).
-    This is null for libcalls where that information may
-    not be available.
-   CUM is a variable of type CUMULATIVE_ARGS which gives info about
-    the preceding args and about the function being called.
-   NAMED is nonzero if this argument is a named parameter
-    (otherwise it is an extra parameter matching an ellipsis).
-
-   On SH the first args are normally in registers
-   and the rest are pushed.  Any arg that starts within the first
-   NPARM_REGS words is at least partially passed in a register unless
-   its data type forbids.  */
-
-#define FUNCTION_ARG(CUM, MODE, TYPE, NAMED) \
-  ((! TARGET_SH5 \
-    && PASS_IN_REG_P ((CUM), (MODE), (TYPE))                           \
-    && ((NAMED)                                                                \
-       || (! TARGET_HITACHI && (TARGET_SH3E || ! current_function_varargs)))) \
-   ? gen_rtx_REG ((MODE),                                              \
-                 ((BASE_ARG_REG (MODE) + ROUND_REG ((CUM), (MODE)))    \
-                  ^ ((MODE) == SFmode && TARGET_SH4                    \
-                     && TARGET_LITTLE_ENDIAN != 0)))                   \
-   : TARGET_SH5                                                                \
-   ? ((MODE) == VOIDmode && TARGET_SHCOMPACT                           \
-      ? GEN_INT ((CUM).call_cookie)                                    \
-      /* The following test assumes unnamed arguments are promoted to  \
-        DFmode.  */                                                    \
-      : (MODE) == SFmode && (CUM).free_single_fp_reg                   \
-      ? SH5_PROTOTYPED_FLOAT_ARG ((CUM), (MODE), (CUM).free_single_fp_reg) \
-      : (GET_SH_ARG_CLASS (MODE) == SH_ARG_FLOAT                       \
-         && ((NAMED) || ! (CUM).prototype_p)                           \
-         && (CUM).arg_count[(int) SH_ARG_FLOAT] < NPARM_REGS (SFmode)) \
-      ? ((! (CUM).prototype_p && TARGET_SHMEDIA)                       \
-        ? SH5_PROTOTYPELESS_FLOAT_ARG ((CUM), (MODE))                  \
-        : SH5_PROTOTYPED_FLOAT_ARG ((CUM), (MODE),                     \
-                                    FIRST_FP_PARM_REG                  \
-                                    + (CUM).arg_count[(int) SH_ARG_FLOAT])) \
-      : ((CUM).arg_count[(int) SH_ARG_INT] < NPARM_REGS (SImode)       \
-        && (! TARGET_SHCOMPACT                                         \
-            || (! SHCOMPACT_FORCE_ON_STACK ((MODE), (TYPE))            \
-                && ! SH5_WOULD_BE_PARTIAL_NREGS ((CUM), (MODE),        \
-                                                 (TYPE), (NAMED)))))   \
-      ? gen_rtx_REG ((MODE), (FIRST_PARM_REG                           \
-                             + (CUM).arg_count[(int) SH_ARG_INT]))     \
-      : 0)                                                             \
-   : 0)
-
-/* Whether an argument must be passed by reference.  On SHcompact, we
-   pretend arguments wider than 32-bits that would have been passed in
-   registers are passed by reference, so that an SHmedia trampoline
-   loads them into the full 64-bits registers.  */
-#define FUNCTION_ARG_PASS_BY_REFERENCE(CUM,MODE,TYPE,NAMED) \
-  (MUST_PASS_IN_STACK ((MODE), (TYPE)) \
-   || SHCOMPACT_BYREF ((CUM), (MODE), (TYPE), (NAMED)))
-
-#define SHCOMPACT_BYREF(CUM, MODE, TYPE, NAMED) \
-  ((CUM).byref                                                         \
-   = (TARGET_SHCOMPACT                                                 \
-      && (CUM).arg_count[(int) SH_ARG_INT] < NPARM_REGS (SImode)       \
-      && (! (NAMED) || GET_SH_ARG_CLASS (MODE) == SH_ARG_INT           \
-         || (GET_SH_ARG_CLASS (MODE) == SH_ARG_FLOAT                   \
-             && ((CUM).arg_count[(int) SH_ARG_FLOAT]                   \
-                 >= NPARM_REGS (SFmode))))                             \
-      && ((MODE) == BLKmode ? int_size_in_bytes (TYPE)                 \
-         : GET_MODE_SIZE (MODE)) > 4                                   \
-      && ! SHCOMPACT_FORCE_ON_STACK ((MODE), (TYPE))                   \
-      && ! SH5_WOULD_BE_PARTIAL_NREGS ((CUM), (MODE),                  \
-                                      (TYPE), (NAMED)))                \
-      ? ((MODE) == BLKmode ? int_size_in_bytes (TYPE)                  \
-        : GET_MODE_SIZE (MODE))                                        \
-      : 0)
+/* By accident we got stuck with passing SCmode on SH4 little endian
+   in two registers that are nominally successive - which is different from
+   two single SFmode values, where we take endianness translation into
+   account.  That does not work at all if an odd number of registers is
+   already in use, so that got fixed, but library functions are still more
+   likely to use complex numbers without mixing them with SFmode arguments
+   (which in C would have to be structures), so for the sake of ABI
+   compatibility the way SCmode values are passed when an even number of
+   FP registers is in use remains different from a pair of SFmode values for
+   now.
+   I.e.:
+   foo (double); a: fr5,fr4
+   foo (float a, float b); a: fr5 b: fr4
+   foo (__complex float a); a.real fr4 a.imag: fr5 - for consistency,
+                            this should be the other way round...
+   foo (float a, __complex float b); a: fr5 b.real: fr4 b.imag: fr7  */
+#define FUNCTION_ARG_SCmode_WART 1
 
 /* If an argument of size 5, 6 or 7 bytes is to be passed in a 64-bit
    register in SHcompact mode, it must be padded in the most
@@ -1857,12 +1992,6 @@ struct sh_args {
    boundaries, because they'll be loaded using quad loads.  */
 #define SH_MIN_ALIGN_FOR_CALLEE_COPY (8 * BITS_PER_UNIT)
 
-#define FUNCTION_ARG_CALLEE_COPIES(CUM,MODE,TYPE,NAMED) \
-  ((CUM).outgoing                                                      \
-   && (((MODE) == BLKmode ? TYPE_ALIGN (TYPE)                          \
-       : GET_MODE_ALIGNMENT (MODE))                                    \
-       % SH_MIN_ALIGN_FOR_CALLEE_COPY == 0))
-
 /* The SH5 ABI requires floating-point arguments to be passed to
    functions without a prototype in both an FP register and a regular
    register or the stack.  When passing the argument in both FP and
@@ -1908,61 +2037,18 @@ struct sh_args {
                                                          (REG)),       \
                                   const0_rtx))))
 
-#define STRICT_ARGUMENT_NAMING TARGET_SH5
-
-#define PRETEND_OUTGOING_VARARGS_NAMED (! TARGET_HITACHI && ! TARGET_SH5)
-
-/* For an arg passed partly in registers and partly in memory,
-   this is the number of registers used.
-   For args passed entirely in registers or entirely in memory, zero.
-
-   We sometimes split args.  */
-
-#define FUNCTION_ARG_PARTIAL_NREGS(CUM, MODE, TYPE, NAMED) \
-  ((! TARGET_SH5 \
-    && PASS_IN_REG_P ((CUM), (MODE), (TYPE))                   \
-    && ! TARGET_SH4                                            \
-    && (ROUND_REG ((CUM), (MODE))                              \
-       + ((MODE) != BLKmode                                    \
-          ? ROUND_ADVANCE (GET_MODE_SIZE (MODE))               \
-          : ROUND_ADVANCE (int_size_in_bytes (TYPE)))          \
-       > NPARM_REGS (MODE)))                                   \
-   ? NPARM_REGS (MODE) - ROUND_REG ((CUM), (MODE))             \
-   : (SH5_WOULD_BE_PARTIAL_NREGS ((CUM), (MODE), (TYPE), (NAMED)) \
-      && ! TARGET_SHCOMPACT)                                   \
-   ? NPARM_REGS (SImode) - (CUM).arg_count[(int) SH_ARG_INT]   \
-   : 0)
-
 #define SH5_WOULD_BE_PARTIAL_NREGS(CUM, MODE, TYPE, NAMED) \
-  (TARGET_SH5 && (MODE) == BLKmode                             \
+  (TARGET_SH5                                                  \
+   && ((MODE) == BLKmode || (MODE) == TImode || (MODE) == CDImode \
+       || (MODE) == DCmode) \
    && ((CUM).arg_count[(int) SH_ARG_INT]                       \
-       + (int_size_in_bytes (TYPE) + 7) / 8) > NPARM_REGS (SImode))
+       + (((MODE) == BLKmode ? int_size_in_bytes (TYPE)                \
+                            : GET_MODE_SIZE (MODE))            \
+         + 7) / 8) > NPARM_REGS (SImode))
 
 /* Perform any needed actions needed for a function that is receiving a
    variable number of arguments.  */
 
-/* We actually emit the code in sh_expand_prologue.  We used to use
-   a static variable to flag that we need to emit this code, but that
-   doesn't when inlining, when functions are deferred and then emitted
-   later.  Fortunately, we already have two flags that are part of struct
-   function that tell if a function uses varargs or stdarg.  */
-#define SETUP_INCOMING_VARARGS(ASF, MODE, TYPE, PAS, ST)  do \
-  if (! current_function_varargs && ! current_function_stdarg) \
-    abort (); \
-while (0)
-
-/* Define the `__builtin_va_list' type for the ABI.  */
-#define BUILD_VA_LIST_TYPE(VALIST) \
-  (VALIST) = sh_build_va_list ()
-
-/* Implement `va_start' for varargs and stdarg.  */
-#define EXPAND_BUILTIN_VA_START(stdarg, valist, nextarg) \
-  sh_va_start (stdarg, valist, nextarg)
-
-/* Implement `va_arg'.  */
-#define EXPAND_BUILTIN_VA_ARG(valist, type) \
-  sh_va_arg (valist, type)
-
 /* Call the function profiler with a given profile label.
    We use two .aligns, so as to make sure that both the .long is aligned
    on a 4 byte boundary, and that the .long is a fixed distance (2 bytes)
@@ -1970,10 +2056,19 @@ while (0)
 
 #define FUNCTION_PROFILER(STREAM,LABELNO)                      \
 {                                                              \
-       fprintf((STREAM), "\t.align\t2\n");                     \
-       fprintf((STREAM), "\ttrapa\t#33\n");                    \
-       fprintf((STREAM), "\t.align\t2\n");                     \
-       asm_fprintf((STREAM), "\t.long\t%LLP%d\n", (LABELNO));  \
+  if (TARGET_SHMEDIA)                                          \
+    {                                                          \
+      fprintf((STREAM), "\tmovi\t33,r0\n");                    \
+      fprintf((STREAM), "\ttrapa\tr0\n");                      \
+      asm_fprintf((STREAM), "\t.long\t%LLP%d\n", (LABELNO));   \
+    }                                                          \
+  else                                                         \
+    {                                                          \
+      fprintf((STREAM), "\t.align\t2\n");                      \
+      fprintf((STREAM), "\ttrapa\t#33\n");                     \
+      fprintf((STREAM), "\t.align\t2\n");                      \
+      asm_fprintf((STREAM), "\t.long\t%LLP%d\n", (LABELNO));   \
+    }                                                          \
 }
 
 /* Define this macro if the code for function profiling should come
@@ -1989,7 +2084,7 @@ while (0)
 
 #define EXIT_IGNORE_STACK 1
 
-/* 
+/*
    On the SH, the trampoline looks like
    2 0002 D202                 mov.l   l2,r2
    1 0000 D301                 mov.l   l1,r3
@@ -1999,65 +2094,26 @@ while (0)
    6 000c 00000000     l2:     .long   function  */
 
 /* Length in units of the trampoline for entering a nested function.  */
-#define TRAMPOLINE_SIZE  (TARGET_SHMEDIA64 ? 40 : TARGET_SH5 ? 32 : 16)
+#define TRAMPOLINE_SIZE  (TARGET_SHMEDIA64 ? 40 : TARGET_SH5 ? 24 : 16)
 
 /* Alignment required for a trampoline in bits .  */
 #define TRAMPOLINE_ALIGNMENT \
-  ((CACHE_LOG < 3 || (TARGET_SMALLCODE && ! TARGET_HARVARD)) ? 32 : 64)
+  ((CACHE_LOG < 3 || (TARGET_SMALLCODE && ! TARGET_HARVARD)) ? 32 \
+   : TARGET_SHMEDIA ? 256 : 64)
 
 /* Emit RTL insns to initialize the variable parts of a trampoline.
    FNADDR is an RTX for the address of the function's pure code.
    CXT is an RTX for the static chain value for the function.  */
 
-#define INITIALIZE_TRAMPOLINE(TRAMP, FNADDR, CXT) do                   \
-{                                                                      \
-  if (TARGET_SH5)                                                      \
-    {                                                                  \
-      rtx tramp_templ = gen_rtx_SYMBOL_REF (Pmode,                     \
-                                           "__GCC_nested_trampoline"); \
-      int fixed_len = TRAMPOLINE_SIZE - 2 * GET_MODE_SIZE (Pmode);     \
-                                                                       \
-      tramp_templ = gen_datalabel_ref (tramp_templ);                   \
-      emit_block_move (gen_rtx_MEM (BLKmode, (TRAMP)),                 \
-                      gen_rtx_MEM (BLKmode, tramp_templ),              \
-                      GEN_INT (fixed_len));                            \
-      emit_move_insn (gen_rtx_MEM (Pmode, plus_constant ((TRAMP),      \
-                                                        fixed_len)),   \
-                     (FNADDR));                                        \
-      emit_move_insn (gen_rtx_MEM (Pmode,                              \
-                                  plus_constant ((TRAMP),              \
-                                                 fixed_len             \
-                                                 + GET_MODE_SIZE (Pmode))), \
-                     (CXT));                                           \
-      emit_insn (gen_ic_invalidate_line (TRAMP));                      \
-      break;                                                           \
-    }                                                                  \
-  emit_move_insn (gen_rtx_MEM (SImode, (TRAMP)),                       \
-                  GEN_INT (trunc_int_for_mode                                  \
-                         (TARGET_LITTLE_ENDIAN ? 0xd301d202 : 0xd202d301,\
-                          SImode))); \
-  emit_move_insn (gen_rtx_MEM (SImode, plus_constant ((TRAMP), 4)),    \
-                 GEN_INT (TARGET_LITTLE_ENDIAN ? 0x0009422b : 0x422b0009));\
-  emit_move_insn (gen_rtx_MEM (SImode, plus_constant ((TRAMP), 8)),    \
-                 (CXT));                                               \
-  emit_move_insn (gen_rtx_MEM (SImode, plus_constant ((TRAMP), 12)),   \
-                 (FNADDR));                                            \
-  if (TARGET_HARVARD)                                                  \
-    {                                                                  \
-      if (TARGET_USERMODE)                                             \
-       emit_library_call (gen_rtx_SYMBOL_REF (Pmode, "__ic_invalidate"),\
-                          0, VOIDmode, 1, (TRAMP), SImode);            \
-      else                                                             \
-       emit_insn (gen_ic_invalidate_line (TRAMP));                     \
-    }                                                                  \
-} while (0)
+#define INITIALIZE_TRAMPOLINE(TRAMP, FNADDR, CXT) \
+  sh_initialize_trampoline ((TRAMP), (FNADDR), (CXT))
 
 /* On SH5, trampolines are SHmedia code, so add 1 to the address.  */
 
 #define TRAMPOLINE_ADJUST_ADDRESS(TRAMP) do                            \
 {                                                                      \
-  if (TARGET_SH5)                                                      \
-    (TRAMP) = expand_simple_binop (Pmode, PLUS, (TRAMP), GEN_INT (1),  \
+  if (TARGET_SHMEDIA)                                                  \
+    (TRAMP) = expand_simple_binop (Pmode, PLUS, (TRAMP), const1_rtx,   \
                                   gen_reg_rtx (Pmode), 0,              \
                                   OPTAB_LIB_WIDEN);                    \
 } while (0)
@@ -2068,17 +2124,18 @@ while (0)
    can ignore COUNT.  */
 
 #define RETURN_ADDR_RTX(COUNT, FRAME)  \
-  (((COUNT) == 0)                              \
-   ? get_hard_reg_initial_val (Pmode, PR_REG) \
-   : (rtx) 0)
-\f
-/* Generate necessary RTL for __builtin_saveregs().  */
-#define EXPAND_BUILTIN_SAVEREGS() sh_builtin_saveregs ()
+  (((COUNT) == 0) ? sh_get_pr_initial_val () : (rtx) 0)
+
+/* A C expression whose value is RTL representing the location of the
+   incoming return address at the beginning of any function, before the
+   prologue.  This RTL is either a REG, indicating that the return
+   value is saved in REG, or a MEM representing a location in
+   the stack.  */
+#define INCOMING_RETURN_ADDR_RTX \
+  gen_rtx_REG (Pmode, TARGET_SHMEDIA ? PR_MEDIA_REG : PR_REG)
 \f
 /* Addressing modes, and classification of registers for them.  */
 #define HAVE_POST_INCREMENT  TARGET_SH1
-/*#define HAVE_PRE_INCREMENT   1*/
-/*#define HAVE_POST_DECREMENT  1*/
 #define HAVE_PRE_DECREMENT   TARGET_SH1
 
 #define USE_LOAD_POST_INCREMENT(mode)    ((mode == SImode || mode == DImode) \
@@ -2088,9 +2145,15 @@ while (0)
 #define USE_STORE_PRE_DECREMENT(mode)    ((mode == SImode || mode == DImode) \
                                            ? 0 : TARGET_SH1)
 
-#define MOVE_BY_PIECES_P(SIZE, ALIGN)  (move_by_pieces_ninsns (SIZE, ALIGN) \
-                                        < (TARGET_SMALLCODE ? 2 :           \
-                                           ((ALIGN >= 32) ? 16 : 2)))
+#define MOVE_BY_PIECES_P(SIZE, ALIGN) \
+  (move_by_pieces_ninsns (SIZE, ALIGN, MOVE_MAX_PIECES + 1) \
+   < (TARGET_SMALLCODE ? 2 : ((ALIGN >= 32) ? 16 : 2)))
+
+#define STORE_BY_PIECES_P(SIZE, ALIGN) \
+  (move_by_pieces_ninsns (SIZE, ALIGN, STORE_MAX_PIECES + 1) \
+   < (TARGET_SMALLCODE ? 2 : ((ALIGN >= 32) ? 16 : 2)))
+
+#define SET_BY_PIECES_P(SIZE, ALIGN) STORE_BY_PIECES_P(SIZE, ALIGN)
 
 /* Macros to check register numbers against specific register classes.  */
 
@@ -2119,16 +2182,18 @@ while (0)
 #define CONSTANT_ADDRESS_P(X)  (GET_CODE (X) == LABEL_REF)
 
 /* Nonzero if the constant value X is a legitimate general operand.  */
+/* can_store_by_pieces constructs VOIDmode CONST_DOUBLEs.  */
 
 #define LEGITIMATE_CONSTANT_P(X) \
   (TARGET_SHMEDIA                                                      \
-   ? (GET_MODE (X) != DFmode                                           \
+   ? ((GET_MODE (X) != DFmode                                          \
+       && GET_MODE_CLASS (GET_MODE (X)) != MODE_VECTOR_FLOAT)          \
       || (X) == CONST0_RTX (GET_MODE (X))                              \
       || ! TARGET_SHMEDIA_FPU                                          \
       || TARGET_SHMEDIA64)                                             \
    : (GET_CODE (X) != CONST_DOUBLE                                     \
       || GET_MODE (X) == DFmode || GET_MODE (X) == SFmode              \
-      || (TARGET_SH3E && (fp_zero_operand (X) || fp_one_operand (X)))))
+      || GET_MODE (X) == DImode || GET_MODE (X) == VOIDmode))
 
 /* The macros REG_OK_FOR..._P assume that the arg is a REG rtx
    and check its validity for a certain class.
@@ -2172,42 +2237,30 @@ while (0)
 
 #endif
 
-/* The 'Q' constraint is a pc relative load operand.  */
-#define EXTRA_CONSTRAINT_Q(OP)                                         \
-  (GET_CODE (OP) == MEM                                                \
-   && ((GET_CODE (XEXP ((OP), 0)) == LABEL_REF)                                \
-       || (GET_CODE (XEXP ((OP), 0)) == CONST                          \
-          && GET_CODE (XEXP (XEXP ((OP), 0), 0)) == PLUS               \
-          && GET_CODE (XEXP (XEXP (XEXP ((OP), 0), 0), 0)) == LABEL_REF \
-          && GET_CODE (XEXP (XEXP (XEXP ((OP), 0), 0), 1)) == CONST_INT)))
-
-/* The `S' constraint is a 16-bit constant, literal or symbolic.  */
-#define EXTRA_CONSTRAINT_S(OP) \
-  (GET_CODE (OP) == CONST \
-   && GET_CODE (XEXP ((OP), 0)) == SIGN_EXTEND \
-   && GET_MODE (XEXP ((OP), 0)) == DImode \
-   && GET_CODE (XEXP (XEXP ((OP), 0), 0)) == TRUNCATE \
-   && GET_MODE (XEXP (XEXP ((OP), 0), 0)) == HImode \
-   && (MOVI_SHORI_BASE_OPERAND_P (XEXP (XEXP (XEXP ((OP), 0), 0), 0)) \
-       || (GET_CODE (XEXP (XEXP (XEXP ((OP), 0), 0), 0)) == ASHIFTRT \
-          && (MOVI_SHORI_BASE_OPERAND_P \
-              (XEXP (XEXP (XEXP (XEXP ((OP), 0), 0), 0), 0))) \
-          && GET_CODE (XEXP (XEXP (XEXP (XEXP ((OP), 0), 0), 0), \
-                             1)) == CONST_INT)))
+/* Macros for extra constraints.  */
+
+#define IS_PC_RELATIVE_LOAD_ADDR_P(OP)                                 \
+  ((GET_CODE ((OP)) == LABEL_REF)                                      \
+   || (GET_CODE ((OP)) == CONST                                                \
+       && GET_CODE (XEXP ((OP), 0)) == PLUS                            \
+       && GET_CODE (XEXP (XEXP ((OP), 0), 0)) == LABEL_REF             \
+       && GET_CODE (XEXP (XEXP ((OP), 0), 1)) == CONST_INT))
+
+#define IS_NON_EXPLICIT_CONSTANT_P(OP)                                 \
+  (CONSTANT_P (OP)                                                     \
+   && GET_CODE (OP) != CONST_INT                                       \
+   && GET_CODE (OP) != CONST_DOUBLE                                    \
+   && (!flag_pic                                                       \
+       || (LEGITIMATE_PIC_OPERAND_P (OP)                               \
+          && !PIC_ADDR_P (OP)                                          \
+          && GET_CODE (OP) != LABEL_REF)))
 
 /* Check whether OP is a datalabel unspec.  */
 #define DATALABEL_REF_NO_CONST_P(OP) \
   (GET_CODE (OP) == UNSPEC \
    && XINT ((OP), 1) == UNSPEC_DATALABEL \
    && XVECLEN ((OP), 0) == 1 \
-   && (GET_CODE (XVECEXP ((OP), 0, 0)) == SYMBOL_REF \
-       || GET_CODE (XVECEXP ((OP), 0, 0)) == LABEL_REF))
-
-/* Check whether OP is a datalabel unspec, possibly enclosed within a
-   CONST.  */
-#define DATALABEL_REF_P(OP) \
-  ((GET_CODE (OP) == CONST && DATALABEL_REF_NO_CONST_P (XEXP ((OP), 0))) \
-   || DATALABEL_REF_NO_CONST_P (OP))
+   && GET_CODE (XVECEXP ((OP), 0, 0)) == LABEL_REF)
 
 #define GOT_ENTRY_P(OP) \
   (GET_CODE (OP) == CONST && GET_CODE (XEXP ((OP), 0)) == UNSPEC \
@@ -2217,20 +2270,35 @@ while (0)
   (GET_CODE (OP) == CONST && GET_CODE (XEXP ((OP), 0)) == UNSPEC \
    && XINT (XEXP ((OP), 0), 1) == UNSPEC_GOTPLT)
 
+#define UNSPEC_GOTOFF_P(OP) \
+  (GET_CODE (OP) == UNSPEC && XINT ((OP), 1) == UNSPEC_GOTOFF)
+
 #define GOTOFF_P(OP) \
-  (GET_CODE (OP) == CONST && GET_CODE (XEXP ((OP), 0)) == UNSPEC \
-   && XINT (XEXP ((OP), 0), 1) == UNSPEC_GOTOFF)
+  (GET_CODE (OP) == CONST \
+   && (UNSPEC_GOTOFF_P (XEXP ((OP), 0)) \
+       || (GET_CODE (XEXP ((OP), 0)) == PLUS \
+           && UNSPEC_GOTOFF_P (XEXP (XEXP ((OP), 0), 0)) \
+          && GET_CODE (XEXP (XEXP ((OP), 0), 1)) == CONST_INT)))
 
 #define PIC_ADDR_P(OP) \
   (GET_CODE (OP) == CONST && GET_CODE (XEXP ((OP), 0)) == UNSPEC \
    && XINT (XEXP ((OP), 0), 1) == UNSPEC_PIC)
 
+#define PCREL_SYMOFF_P(OP) \
+  (GET_CODE (OP) == CONST \
+   && GET_CODE (XEXP ((OP), 0)) == UNSPEC \
+   && XINT (XEXP ((OP), 0), 1) == UNSPEC_PCREL_SYMOFF)
+
 #define NON_PIC_REFERENCE_P(OP) \
   (GET_CODE (OP) == LABEL_REF || GET_CODE (OP) == SYMBOL_REF \
-   || DATALABEL_REF_P (OP) \
+   || (GET_CODE (OP) == CONST \
+       && (GET_CODE (XEXP ((OP), 0)) == LABEL_REF \
+          || GET_CODE (XEXP ((OP), 0)) == SYMBOL_REF \
+          || DATALABEL_REF_NO_CONST_P (XEXP ((OP), 0)))) \
    || (GET_CODE (OP) == CONST && GET_CODE (XEXP ((OP), 0)) == PLUS \
        && (GET_CODE (XEXP (XEXP ((OP), 0), 0)) == SYMBOL_REF \
-          || DATALABEL_REF_P (XEXP (XEXP ((OP), 0), 0))) \
+          || GET_CODE (XEXP (XEXP ((OP), 0), 0)) == LABEL_REF \
+          || DATALABEL_REF_NO_CONST_P (XEXP (XEXP ((OP), 0), 0))) \
        && GET_CODE (XEXP (XEXP ((OP), 0), 1)) == CONST_INT))
 
 #define PIC_REFERENCE_P(OP) \
@@ -2238,17 +2306,10 @@ while (0)
    || GOTOFF_P (OP) || PIC_ADDR_P (OP))
 
 #define MOVI_SHORI_BASE_OPERAND_P(OP) \
-  (flag_pic ? PIC_REFERENCE_P (OP) : NON_PIC_REFERENCE_P (OP))
-
-/* The `T' constraint is a label or a symbol.  */
-#define EXTRA_CONSTRAINT_T(OP) \
-  (NON_PIC_REFERENCE_P (OP))
-
-#define EXTRA_CONSTRAINT(OP, C)                \
-  ((C) == 'Q' ? EXTRA_CONSTRAINT_Q (OP)        \
-   : (C) == 'S' ? EXTRA_CONSTRAINT_S (OP) \
-   : (C) == 'T' ? EXTRA_CONSTRAINT_T (OP) \
-   : 0)
+  (flag_pic \
+   ? (GOT_ENTRY_P (OP) || GOTPLT_ENTRY_P (OP)  || GOTOFF_P (OP) \
+      || PCREL_SYMOFF_P (OP)) \
+   : NON_PIC_REFERENCE_P (OP))
 \f
 /* GO_IF_LEGITIMATE_ADDRESS recognizes an RTL expression
    that is a valid memory address for an instruction.
@@ -2257,15 +2318,31 @@ while (0)
 
 #define MODE_DISP_OK_4(X,MODE) \
 (GET_MODE_SIZE (MODE) == 4 && (unsigned) INTVAL (X) < 64       \
- && ! (INTVAL (X) & 3) && ! (TARGET_SH3E && (MODE) == SFmode))
+ && ! (INTVAL (X) & 3) && ! (TARGET_SH2E && (MODE) == SFmode))
 
 #define MODE_DISP_OK_8(X,MODE) \
 ((GET_MODE_SIZE(MODE)==8) && ((unsigned)INTVAL(X)<60)  \
  && ! (INTVAL(X) & 3) && ! (TARGET_SH4 && (MODE) == DFmode))
 
+#undef MODE_DISP_OK_4
+#define MODE_DISP_OK_4(X,MODE) \
+((GET_MODE_SIZE (MODE) == 4 && (unsigned) INTVAL (X) < 64      \
+  && ! (INTVAL (X) & 3) && ! (TARGET_SH2E && (MODE) == SFmode)) \
+  || ((GET_MODE_SIZE(MODE)==4) && ((unsigned)INTVAL(X)<16383)  \
+  && ! (INTVAL(X) & 3) && TARGET_SH2A))
+
+#undef MODE_DISP_OK_8
+#define MODE_DISP_OK_8(X,MODE) \
+(((GET_MODE_SIZE(MODE)==8) && ((unsigned)INTVAL(X)<60) \
+  && ! (INTVAL(X) & 3) && ! ((TARGET_SH4 || TARGET_SH2A) && (MODE) == DFmode)) \
+ || ((GET_MODE_SIZE(MODE)==8) && ((unsigned)INTVAL(X)<8192)    \
+  && ! (INTVAL(X) & (TARGET_SH2A_DOUBLE ? 7 : 3)) && (TARGET_SH2A && (MODE) == DFmode)))
+
 #define BASE_REGISTER_RTX_P(X)                         \
   ((GET_CODE (X) == REG && REG_OK_FOR_BASE_P (X))      \
    || (GET_CODE (X) == SUBREG                          \
+       && TRULY_NOOP_TRUNCATION (GET_MODE_BITSIZE (GET_MODE ((X))), \
+                                GET_MODE_BITSIZE (GET_MODE (SUBREG_REG (X)))) \
        && GET_CODE (SUBREG_REG (X)) == REG             \
        && REG_OK_FOR_BASE_P (SUBREG_REG (X))))
 
@@ -2275,6 +2352,8 @@ while (0)
 #define INDEX_REGISTER_RTX_P(X)                                \
   ((GET_CODE (X) == REG && REG_OK_FOR_INDEX_P (X))     \
    || (GET_CODE (X) == SUBREG                          \
+       && TRULY_NOOP_TRUNCATION (GET_MODE_BITSIZE (GET_MODE ((X))), \
+                                GET_MODE_BITSIZE (GET_MODE (SUBREG_REG (X)))) \
        && GET_CODE (SUBREG_REG (X)) == REG             \
        && SUBREG_OK_FOR_INDEX_P (SUBREG_REG (X), SUBREG_BYTE (X))))
 
@@ -2288,7 +2367,7 @@ while (0)
          REG++
          --REG  */
 
-/* ??? The SH3e does not have the REG+disp addressing mode when loading values
+/* ??? The SH2e does not have the REG+disp addressing mode when loading values
    into the FRx registers.  We implement this by setting the maximum offset
    to zero when the value is SFmode.  This also restricts loading of SFmode
    values into the integer registers, but that can't be helped.  */
@@ -2306,7 +2385,15 @@ while (0)
       {                                                                        \
        if (TARGET_SHMEDIA)                                             \
          {                                                             \
-           int MODE_SIZE = GET_MODE_SIZE (MODE);                       \
+           int MODE_SIZE;                                              \
+           /* Check if this the address of an unaligned load / store.  */\
+           if ((MODE) == VOIDmode)                                     \
+             {                                                         \
+               if (CONST_OK_FOR_I06 (INTVAL (OP)))                     \
+                 goto LABEL;                                           \
+               break;                                                  \
+             }                                                         \
+           MODE_SIZE = GET_MODE_SIZE (MODE);                           \
            if (! (INTVAL (OP) & (MODE_SIZE - 1))                       \
                && INTVAL (OP) >= -512 * MODE_SIZE                      \
                && INTVAL (OP) < 512 * MODE_SIZE)                       \
@@ -2314,11 +2401,20 @@ while (0)
            else                                                        \
              break;                                                    \
          }                                                             \
+       if (TARGET_SH2A)                                                \
+         {                                                             \
+           if (GET_MODE_SIZE (MODE) == 1                               \
+               && (unsigned) INTVAL (OP) < 4096)                       \
+           goto LABEL;                                                 \
+         }                                                             \
        if (MODE_DISP_OK_4 ((OP), (MODE)))  goto LABEL;                 \
        if (MODE_DISP_OK_8 ((OP), (MODE)))  goto LABEL;                 \
       }                                                                        \
   } while(0)
 
+#define ALLOW_INDEXED_ADDRESS \
+  ((!TARGET_SHMEDIA32 && !TARGET_SHCOMPACT) || TARGET_ALLOW_INDEXED_ADDRESS)
+
 #define GO_IF_LEGITIMATE_ADDRESS(MODE, X, LABEL)                       \
 {                                                                      \
   if (BASE_REGISTER_RTX_P (X))                                         \
@@ -2334,9 +2430,17 @@ while (0)
       rtx xop1 = XEXP ((X), 1);                                                \
       if (GET_MODE_SIZE (MODE) <= 8 && BASE_REGISTER_RTX_P (xop0))     \
        GO_IF_LEGITIMATE_INDEX ((MODE), xop1, LABEL);                   \
-      if (GET_MODE_SIZE (MODE) <= 4                                    \
-         || (TARGET_SHMEDIA && GET_MODE_SIZE (MODE) <= 8)              \
-         || (TARGET_SH4 && TARGET_FMOVD && MODE == DFmode))            \
+      if ((ALLOW_INDEXED_ADDRESS || GET_MODE (X) == DImode             \
+          || ((xop0 == stack_pointer_rtx                               \
+               || xop0 == hard_frame_pointer_rtx)                      \
+              && REG_P (xop1) && REGNO (xop1) == R0_REG)               \
+          || ((xop1 == stack_pointer_rtx                               \
+               || xop1 == hard_frame_pointer_rtx)                      \
+              && REG_P (xop0) && REGNO (xop0) == R0_REG))              \
+         && ((!TARGET_SHMEDIA && GET_MODE_SIZE (MODE) <= 4)            \
+             || (TARGET_SHMEDIA && GET_MODE_SIZE (MODE) <= 8)          \
+             || ((TARGET_SH4 || TARGET_SH2A_DOUBLE)                    \
+                 && TARGET_FMOVD && MODE == DFmode)))                  \
        {                                                               \
          if (BASE_REGISTER_RTX_P (xop1) && INDEX_REGISTER_RTX_P (xop0))\
            goto LABEL;                                                 \
@@ -2373,8 +2477,8 @@ while (0)
       && GET_CODE (XEXP ((X), 1)) == CONST_INT                 \
       && BASE_REGISTER_RTX_P (XEXP ((X), 0))                   \
       && ! TARGET_SHMEDIA                                      \
-      && ! (TARGET_SH4 && (MODE) == DFmode)                    \
-      && ! (TARGET_SH3E && (MODE) == SFmode))                  \
+      && ! ((TARGET_SH4 || TARGET_SH2A_DOUBLE) && (MODE) == DFmode)                    \
+      && ! (TARGET_SH2E && (MODE) == SFmode))                  \
     {                                                          \
       rtx index_rtx = XEXP ((X), 1);                           \
       HOST_WIDE_INT offset = INTVAL (index_rtx), offset_base;  \
@@ -2423,17 +2527,27 @@ while (0)
       && BASE_REGISTER_RTX_P (XEXP (X, 0))                             \
       && ! TARGET_SHMEDIA                                              \
       && ! (TARGET_SH4 && (MODE) == DFmode)                            \
-      && ! ((MODE) == PSImode && (TYPE) == RELOAD_FOR_INPUT_ADDRESS))  \
+      && ! ((MODE) == PSImode && (TYPE) == RELOAD_FOR_INPUT_ADDRESS)   \
+      && (ALLOW_INDEXED_ADDRESS                                                \
+         || XEXP ((X), 0) == stack_pointer_rtx                         \
+         || XEXP ((X), 0) == hard_frame_pointer_rtx))                  \
     {                                                                  \
       rtx index_rtx = XEXP (X, 1);                                     \
       HOST_WIDE_INT offset = INTVAL (index_rtx), offset_base;          \
       rtx sum;                                                         \
                                                                        \
-      if (TARGET_SH3E && MODE == SFmode)                               \
+      if (TARGET_SH2A && (MODE) == DFmode && (offset & 0x7))           \
+       {                                                               \
+         push_reload (X, NULL_RTX, &X, NULL,                           \
+                      BASE_REG_CLASS, Pmode, VOIDmode, 0, 0, (OPNUM),  \
+                      (TYPE));                                         \
+         goto WIN;                                                     \
+       }                                                               \
+      if (TARGET_SH2E && MODE == SFmode)                               \
        {                                                               \
          X = copy_rtx (X);                                             \
-         push_reload (index_rtx, NULL_RTX, &XEXP (X, 1), NULL,         \
-                      INDEX_REG_CLASS, Pmode, VOIDmode, 0, 0, (OPNUM), \
+         push_reload (X, NULL_RTX, &X, NULL,                           \
+                      BASE_REG_CLASS, Pmode, VOIDmode, 0, 0, (OPNUM),  \
                       (TYPE));                                         \
          goto WIN;                                                     \
        }                                                               \
@@ -2451,9 +2565,9 @@ while (0)
         prevalent.  */                                                 \
       if (GET_MODE_SIZE (MODE) + offset - offset_base <= 64)           \
        {                                                               \
-         sum = gen_rtx (PLUS, Pmode, XEXP (X, 0),                      \
+         sum = gen_rtx_PLUS (Pmode, XEXP (X, 0),                       \
                         GEN_INT (offset_base));                        \
-         X = gen_rtx (PLUS, Pmode, sum, GEN_INT (offset - offset_base));\
+         X = gen_rtx_PLUS (Pmode, sum, GEN_INT (offset - offset_base));\
          push_reload (sum, NULL_RTX, &XEXP (X, 0), NULL,               \
                       BASE_REG_CLASS, Pmode, VOIDmode, 0, 0, (OPNUM),  \
                       (TYPE));                                         \
@@ -2468,7 +2582,7 @@ while (0)
           && BASE_REGISTER_RTX_P (XEXP (XEXP (X, 0), 0))               \
           && GET_CODE (XEXP (X, 1)) == CONST_INT                       \
           && ! TARGET_SHMEDIA                                          \
-          && ! (TARGET_SH3E && MODE == SFmode))                        \
+          && ! (TARGET_SH2E && MODE == SFmode))                        \
     {                                                                  \
       /* Because this address is so complex, we know it must have      \
         been created by LEGITIMIZE_RELOAD_ADDRESS before; thus,        \
@@ -2485,17 +2599,15 @@ while (0)
    ??? Strictly speaking, we should also include all indexed addressing,
    because the index scale factor is the length of the operand.
    However, the impact of GO_IF_MODE_DEPENDENT_ADDRESS would be to
-   high if we did that.  So we rely on reload to fix things up.  */
+   high if we did that.  So we rely on reload to fix things up.
 
-#define GO_IF_MODE_DEPENDENT_ADDRESS(ADDR,LABEL)                       \
-{                                                                      \
-  if (GET_CODE(ADDR) == PRE_DEC || GET_CODE(ADDR) == POST_INC)         \
-    goto LABEL;                                                                \
-}
+   Auto-increment addressing is now treated in recog.c.  */
+
+#define GO_IF_MODE_DEPENDENT_ADDRESS(ADDR,LABEL)
 \f
 /* Specify the machine mode that this machine uses
    for the index in the tablejump instruction.  */
-#define CASE_VECTOR_MODE (TARGET_BIGTABLE ? SImode : HImode)
+#define CASE_VECTOR_MODE ((! optimize || TARGET_BIGTABLE) ? SImode : HImode)
 
 #define CASE_VECTOR_SHORTEN_MODE(MIN_OFFSET, MAX_OFFSET, BODY) \
 ((MIN_OFFSET) >= 0 && (MAX_OFFSET) <= 127 \
@@ -2514,29 +2626,29 @@ while (0)
 /* Define it here, so that it doesn't get bumped to 64-bits on SHmedia.  */
 #define FLOAT_TYPE_SIZE 32
 
-/* Since the SH3e has only `float' support, it is desirable to make all
+/* Since the SH2e has only `float' support, it is desirable to make all
    floating point types equivalent to `float'.  */
-#define DOUBLE_TYPE_SIZE ((TARGET_SH3E && ! TARGET_SH4) ? 32 : 64)
+#define DOUBLE_TYPE_SIZE ((TARGET_SH2E && ! TARGET_SH4 && ! TARGET_SH2A_DOUBLE) ? 32 : 64)
+
+#if defined(__SH2E__) || defined(__SH3E__) || defined( __SH4_SINGLE_ONLY__)
+#define LIBGCC2_DOUBLE_TYPE_SIZE 32
+#else
+#define LIBGCC2_DOUBLE_TYPE_SIZE 64
+#endif
 
 /* 'char' is signed by default.  */
 #define DEFAULT_SIGNED_CHAR  1
 
-/* We -Define SIZE_TYPE in CPP_SPEC.  */
-#define NO_BUILTIN_SIZE_TYPE 1
-
 /* The type of size_t unsigned int.  */
 #define SIZE_TYPE (TARGET_SH5 ? "long unsigned int" : "unsigned int")
 
-#define NO_BUILTIN_PTRDIFF_TYPE 1
-
 #undef  PTRDIFF_TYPE
 #define PTRDIFF_TYPE (TARGET_SH5 ? "long int" : "int")
 
 #define WCHAR_TYPE "short unsigned int"
 #define WCHAR_TYPE_SIZE 16
 
-/* Don't cse the address of the function being compiled.  */
-/*#define NO_RECURSIVE_FUNCTION_CSE 1*/
+#define SH_ELF_WCHAR_TYPE "long int"
 
 /* Max number of bytes we can move from memory to memory
    in one reasonably fast instruction.  */
@@ -2557,8 +2669,13 @@ while (0)
 /* Define if loading in MODE, an integral mode narrower than BITS_PER_WORD
    will either zero-extend or sign-extend.  The value of this macro should
    be the code that says which one of the two operations is implicitly
-   done, NIL if none.  */
-#define LOAD_EXTEND_OP(MODE) SIGN_EXTEND
+   done, UNKNOWN if none.  */
+/* For SHmedia, we can truncate to QImode easier using zero extension.  */
+/* FP registers can load SImode values, but don't implicitly sign-extend
+   them to DImode.  */
+#define LOAD_EXTEND_OP(MODE) \
+ (((MODE) == QImode  && TARGET_SHMEDIA) ? ZERO_EXTEND \
+  : (MODE) != SImode ? SIGN_EXTEND : UNKNOWN)
 
 /* Define if loading short immediate values into registers sign extends.  */
 #define SHORT_IMMEDIATES_SIGN_EXTEND
@@ -2566,11 +2683,6 @@ while (0)
 /* Nonzero if access to memory by bytes is no faster than for words.  */
 #define SLOW_BYTE_ACCESS 1
 
-/* We assume that the store-condition-codes instructions store 0 for false
-   and some other value for true.  This is the value stored for true.  */
-
-#define STORE_FLAG_VALUE 1
-
 /* Immediate shift counts are truncated by the output routines (or was it
    the assembler?).  Shift counts in a register are truncated by SH.  Note
    that the native compiler puts too large (> 32) immediate shift counts
@@ -2580,10 +2692,12 @@ while (0)
    However, the SH3 has hardware shifts that do not truncate exactly as gcc
    expects - the sign bit is significant - so it appears that we need to
    leave this zero for correct SH3 code.  */
-#define SHIFT_COUNT_TRUNCATED (! TARGET_SH3)
+#define SHIFT_COUNT_TRUNCATED (! TARGET_SH3 && ! TARGET_SH2A)
 
 /* All integers have the same format so truncation is easy.  */
-#define TRULY_NOOP_TRUNCATION(OUTPREC,INPREC)  1
+/* But SHmedia must sign-extend DImode when truncating to SImode.  */
+#define TRULY_NOOP_TRUNCATION(OUTPREC,INPREC) \
+ (!TARGET_SHMEDIA || (INPREC) < 64 || (OUTPREC) >= 64)
 
 /* Define this if addresses of constant functions
    shouldn't be put through pseudo regs where they can be cse'd.
@@ -2591,69 +2705,10 @@ while (0)
    but a CALL with constant address is cheap.  */
 /*#define NO_FUNCTION_CSE 1*/
 
-/* Chars and shorts should be passed as ints.  */
-#define PROMOTE_PROTOTYPES 1
-
 /* The machine modes of pointers and functions.  */
 #define Pmode  (TARGET_SHMEDIA64 ? DImode : SImode)
 #define FUNCTION_MODE  Pmode
 
-/* The relative costs of various types of constants.  */
-
-#define CONST_COSTS(RTX, CODE, OUTER_CODE)     \
-  case CONST_INT:                              \
-    if (TARGET_SHMEDIA)                                \
-      {                                                \
-       if (CONST_OK_FOR_J (INTVAL (RTX)))      \
-          return COSTS_N_INSNS (1);            \
-       else if (CONST_OK_FOR_J (INTVAL (RTX) >> 16)) \
-         return COSTS_N_INSNS (2);             \
-       else if (CONST_OK_FOR_J ((INTVAL (RTX) >> 16) >> 16)) \
-         return COSTS_N_INSNS (3);             \
-        else                                   \
-         return COSTS_N_INSNS (4);             \
-      }                                                \
-    if (CONST_OK_FOR_I (INTVAL (RTX)))         \
-      return 0;                                        \
-    else if (((OUTER_CODE) == AND || (OUTER_CODE) == IOR || (OUTER_CODE) == XOR) \
-            && CONST_OK_FOR_L (INTVAL (RTX)))  \
-      return 1;                                        \
-    else                                       \
-      return 8;                                        \
-  case CONST:                                  \
-  case LABEL_REF:                              \
-  case SYMBOL_REF:                             \
-    if (TARGET_SHMEDIA64)                      \
-      return COSTS_N_INSNS (4);                        \
-    if (TARGET_SHMEDIA32)                      \
-      return COSTS_N_INSNS (2);                        \
-    return 5;                                  \
-  case CONST_DOUBLE:                           \
-    if (TARGET_SHMEDIA)                                \
-      return COSTS_N_INSNS (4);                        \
-    else                                       \
-      return 10;
-
-#define RTX_COSTS(X, CODE, OUTER_CODE)                 \
-  case PLUS:                                           \
-    return COSTS_N_INSNS (addsubcosts (X));            \
-  case AND:                                            \
-    return COSTS_N_INSNS (andcosts (X));               \
-  case MULT:                                           \
-    return COSTS_N_INSNS (multcosts (X));              \
-  case ASHIFT:                                         \
-  case ASHIFTRT:                                       \
-  case LSHIFTRT:                                       \
-    return COSTS_N_INSNS (shiftcosts (X));             \
-  case DIV:                                            \
-  case UDIV:                                           \
-  case MOD:                                            \
-  case UMOD:                                           \
-    return COSTS_N_INSNS (20);                         \
-  case FLOAT:                                          \
-  case FIX:                                            \
-    return 100;
-
 /* The multiply insn on the SH1 and the divide insns on the SH1 and SH2
    are actually function calls with some special constraints on arguments
    and register usage.
@@ -2684,111 +2739,37 @@ while (0)
 
 \f
 /* Position Independent Code.  */
-/* Define this macro if references to a symbol must be treated
-   differently depending on something about the variable or function
-   named by the symbol (such as what section it is in).
-
-   On SH, if using PIC, mark a SYMBOL_REF for a non-global symbol
-   so that we may access it using GOTOFF instead of GOT.  */
-
-#define ENCODE_SECTION_INFO(DECL) \
-do                                                                     \
-  {                                                                    \
-    if (flag_pic)                                                      \
-      {                                                                        \
-       rtx rtl = (TREE_CODE_CLASS (TREE_CODE (DECL)) != 'd'            \
-                  ? TREE_CST_RTL (DECL) : DECL_RTL (DECL));            \
-                                                                       \
-       SYMBOL_REF_FLAG (XEXP (rtl, 0)) =                               \
-         (TREE_CODE_CLASS (TREE_CODE (DECL)) != 'd'                    \
-          || ! TREE_PUBLIC (DECL));                                    \
-      }                                                                        \
-    if (TARGET_SH5)                                                    \
-      {                                                                        \
-       rtx rtl = (TREE_CODE_CLASS (TREE_CODE (DECL)) != 'd'            \
-                  ? TREE_CST_RTL (DECL)                                \
-                  : TREE_CODE (DECL) != VAR_DECL                       \
-                  ? NULL_RTX                                           \
-                  : DECL_RTL (DECL));                                  \
-                                                                       \
-        if (rtl && GET_CODE (rtl) == MEM                               \
-           && GET_CODE (XEXP (rtl, 0)) == SYMBOL_REF)                  \
-         XEXP (rtl, 0) = gen_datalabel_ref (XEXP (rtl, 0));            \
-      }                                                                        \
-  }                                                                    \
-while (0)
-
-/* The prefix used to mark SYMBOL_REFs that refer to data symbols.  */
-#define SH_DATALABEL_ENCODING "#"
-
-/* Return true if SYM_NAME starts with SH_DATALABEL_ENCODING.  */
-#define DATALABEL_SYMNAME_P(SYM_NAME) \
-  (SH_DATALABEL_ENCODING[1] ? (abort (), 0) : \
-   (SYM_NAME)[0] == SH_DATALABEL_ENCODING[0])
-
-/* Skip an optional SH_DATALABEL_ENCODING in the beginning of
-   SYM_NAME.  Then, remove a leading *, like the default definition in
-   output.h.  */
-#define STRIP_DATALABEL_ENCODING(VAR, SYM_NAME) \
-  (VAR) = (SYM_NAME) + (DATALABEL_SYMNAME_P (SYM_NAME) \
-                       ? strlen (SH_DATALABEL_ENCODING) : 0)
-#define STRIP_NAME_ENCODING(VAR, SYM_NAME) \
-  STRIP_DATALABEL_ENCODING((VAR), (SYM_NAME)), \
-  (VAR) += (*(VAR) == '*')
 
 /* We can't directly access anything that contains a symbol,
    nor can we indirect via the constant pool.  */
 #define LEGITIMATE_PIC_OPERAND_P(X)                            \
-       (! nonpic_symbol_mentioned_p (X)                        \
-        && (! CONSTANT_POOL_ADDRESS_P (X)                      \
-            || ! nonpic_symbol_mentioned_p (get_pool_constant (X))))
+       ((! nonpic_symbol_mentioned_p (X)                       \
+         && (GET_CODE (X) != SYMBOL_REF                        \
+             || ! CONSTANT_POOL_ADDRESS_P (X)                  \
+             || ! nonpic_symbol_mentioned_p (get_pool_constant (X)))) \
+        || (TARGET_SHMEDIA && GET_CODE (X) == LABEL_REF))
 
 #define SYMBOLIC_CONST_P(X)    \
 ((GET_CODE (X) == SYMBOL_REF || GET_CODE (X) == LABEL_REF)     \
   && nonpic_symbol_mentioned_p (X))
 \f
-/* Compute the cost of an address.  For the SH, all valid addresses are
-   the same cost.  Use a slightly higher cost for reg + reg addressing,
-   since it increases pressure on r0.  */
-
-#define ADDRESS_COST(X) (GET_CODE (X) == PLUS && ! CONSTANT_P (XEXP (X, 1)) \
-                        && ! TARGET_SHMEDIA \
-                        ? 1 : 0)
-
 /* Compute extra cost of moving data between one register class
    and another.  */
 
-/* Regclass always uses 2 for moves in the same register class;
-   If SECONDARY*_RELOAD_CLASS says something about the src/dst pair,
-   it uses this information.  Hence, the general register <-> floating point
+/* If SECONDARY*_RELOAD_CLASS says something about the src/dst pair, regclass
+   uses this information.  Hence, the general register <-> floating point
    register information here is not used for SFmode.  */
+
+#define REGCLASS_HAS_GENERAL_REG(CLASS) \
+  ((CLASS) == GENERAL_REGS || (CLASS) == R0_REGS \
+    || (! TARGET_SHMEDIA && (CLASS) == SIBCALL_REGS))
+
+#define REGCLASS_HAS_FP_REG(CLASS) \
+  ((CLASS) == FP0_REGS || (CLASS) == FP_REGS \
+   || (CLASS) == DF_REGS || (CLASS) == DF_HI_REGS)
+
 #define REGISTER_MOVE_COST(MODE, SRCCLASS, DSTCLASS) \
- (((((DSTCLASS) == T_REGS) || ((DSTCLASS) == PR_REGS)) ? 10            \
-   : ((((DSTCLASS) == FP0_REGS || (DSTCLASS) == FP_REGS || (DSTCLASS) == DF_REGS) \
-       && ((SRCCLASS) == GENERAL_REGS || (SRCCLASS) == R0_REGS))       \
-      || (((DSTCLASS) == GENERAL_REGS || (DSTCLASS) == R0_REGS)                \
-         && ((SRCCLASS) == FP0_REGS || (SRCCLASS) == FP_REGS           \
-             || (SRCCLASS) == DF_REGS)))                               \
-   ? (TARGET_SHMEDIA ? 2                                               \
-      : TARGET_FMOVD ? 8 : 12)                                         \
-   : (((DSTCLASS) == FPUL_REGS                                         \
-       && ((SRCCLASS) == GENERAL_REGS || (SRCCLASS) == R0_REGS))       \
-      || (SRCCLASS == FPUL_REGS                                                \
-         && ((DSTCLASS) == GENERAL_REGS || (DSTCLASS) == R0_REGS)))    \
-   ? 5                                                                 \
-   : (((DSTCLASS) == FPUL_REGS                                         \
-       && ((SRCCLASS) == PR_REGS || (SRCCLASS) == MAC_REGS             \
-           || (SRCCLASS) == T_REGS))                                   \
-      || ((SRCCLASS) == FPUL_REGS                                      \
-         && ((DSTCLASS) == PR_REGS || (DSTCLASS) == MAC_REGS)))        \
-   ? 7                                                                 \
-   : (((SRCCLASS) == TARGET_REGS && (DSTCLASS) != GENERAL_REGS)                \
-      || ((DSTCLASS) == TARGET_REGS && (SRCCLASS) != GENERAL_REGS))    \
-   ? 20                                                                        \
-   : (((SRCCLASS) == FPSCR_REGS && (DSTCLASS) != GENERAL_REGS)         \
-      || ((DSTCLASS) == FPSCR_REGS && (SRCCLASS) != GENERAL_REGS))     \
-   ? 4                                                                 \
-   : 2) * ((MODE) == V16SFmode ? 8 : (MODE) == V4SFmode ? 2 : 1))
+  sh_register_move_cost ((MODE), (SRCCLASS), (DSTCLASS))
 
 /* ??? Perhaps make MEMORY_MOVE_COST depend on compiler option?  This
    would be so that people with slow memory systems could generate
@@ -2799,7 +2780,8 @@ while (0)
    The SH1 does not have delay slots, hence we get a pipeline stall
    at every branch.  The SH4 is superscalar, so the single delay slot
    is not sufficient to keep both pipelines filled.  */
-#define BRANCH_COST (TARGET_SH5 ? 1 : ! TARGET_SH2 || TARGET_HARD_SH4 ? 2 : 1)
+#define BRANCH_COST(speed_p, predictable_p) \
+       (TARGET_SH5 ? 1 : ! TARGET_SH2 || TARGET_HARD_SH4 ? 2 : 1)
 \f
 /* Assembler output control.  */
 
@@ -2808,16 +2790,9 @@ while (0)
    the end of the line.  */
 #define ASM_COMMENT_START "!"
 
-/* The text to go at the start of the assembler file.  */
-#define ASM_FILE_START(STREAM) \
-  output_file_start (STREAM)
-
-#define ASM_FILE_END(STREAM)
-
 #define ASM_APP_ON             ""
 #define ASM_APP_OFF            ""
 #define FILE_ASM_OP            "\t.file\n"
-#define IDENT_ASM_OP           "\t.ident\t"
 #define SET_ASM_OP             "\t.set\t"
 
 /* How to change between sections.  */
@@ -2864,13 +2839,10 @@ while (0)
    which could be text or it could be a user defined section.  */
 #define JUMP_TABLES_IN_TEXT_SECTION 1
 
-/* Switch into a generic section.  */
-#define TARGET_ASM_NAMED_SECTION  sh_asm_named_section
-
 #undef DO_GLOBAL_CTORS_BODY
 #define DO_GLOBAL_CTORS_BODY                   \
 {                                              \
-  typedef (*pfunc)();                          \
+  typedef void (*pfunc) (void);                        \
   extern pfunc __ctors[];                      \
   extern pfunc __ctors_end[];                  \
   pfunc *p;                                    \
@@ -2883,7 +2855,7 @@ while (0)
 #undef DO_GLOBAL_DTORS_BODY
 #define DO_GLOBAL_DTORS_BODY                   \
 {                                              \
-  typedef (*pfunc)();                          \
+  typedef void (*pfunc) (void);                        \
   extern pfunc __dtors[];                      \
   extern pfunc __dtors_end[];                  \
   pfunc *p;                                    \
@@ -2894,70 +2866,87 @@ while (0)
 }
 
 #define ASM_OUTPUT_REG_PUSH(file, v) \
-  fprintf ((file), "\tmov.l\tr%d,@-r15\n", (v));
+{                                                      \
+  if (TARGET_SHMEDIA)                                  \
+    {                                                  \
+      fprintf ((file), "\taddi.l\tr15,-8,r15\n");      \
+      fprintf ((file), "\tst.q\tr15,0,r%d\n", (v));    \
+    }                                                  \
+  else                                                 \
+    fprintf ((file), "\tmov.l\tr%d,@-r15\n", (v));     \
+}
 
 #define ASM_OUTPUT_REG_POP(file, v) \
-  fprintf ((file), "\tmov.l\t@r15+,r%d\n", (v));
+{                                                      \
+  if (TARGET_SHMEDIA)                                  \
+    {                                                  \
+      fprintf ((file), "\tld.q\tr15,0,r%d\n", (v));    \
+      fprintf ((file), "\taddi.l\tr15,8,r15\n");       \
+    }                                                  \
+  else                                                 \
+    fprintf ((file), "\tmov.l\t@r15+,r%d\n", (v));     \
+}
 
 /* DBX register number for a given compiler register number.  */
 /* GDB has FPUL at 23 and FP0 at 25, so we must add one to all FP registers
    to match gdb.  */
-/* If you change this macro, make sure you update it in elf.h too.  */
-#define DBX_REGISTER_NUMBER(REGNO) \
-  (GENERAL_REGISTER_P (REGNO) \
-   ? ((REGNO) - FIRST_GENERAL_REG) \
-   : FP_REGISTER_P (REGNO) \
-   ? ((REGNO) - FIRST_FP_REG + (TARGET_SH5 ? (TARGET_SHCOMPACT ? 245 \
-                                             : 77) : 25)) \
+/* svr4.h undefines this macro, yet we really want to use the same numbers
+   for coff as for elf, so we go via another macro: SH_DBX_REGISTER_NUMBER.  */
+/* expand_builtin_init_dwarf_reg_sizes uses this to test if a
+   register exists, so we should return -1 for invalid register numbers.  */
+#define DBX_REGISTER_NUMBER(REGNO) SH_DBX_REGISTER_NUMBER (REGNO)
+
+/* SHcompact PR_REG used to use the encoding 241, and SHcompact FP registers
+   used to use the encodings 245..260, but that doesn't make sense:
+   PR_REG and PR_MEDIA_REG are actually the same register, and likewise
+   the FP registers stay the same when switching between compact and media
+   mode.  Hence, we also need to use the same dwarf frame columns.
+   Likewise, we need to support unwind information for SHmedia registers
+   even in compact code.  */
+#define SH_DBX_REGISTER_NUMBER(REGNO) \
+  (IN_RANGE ((REGNO), \
+            (unsigned HOST_WIDE_INT) FIRST_GENERAL_REG, \
+            FIRST_GENERAL_REG + (TARGET_SH5 ? 63U :15U)) \
+   ? ((unsigned) (REGNO) - FIRST_GENERAL_REG) \
+  : ((int) (REGNO) >= FIRST_FP_REG \
+     && ((int) (REGNO) \
+        <= (FIRST_FP_REG + \
+            ((TARGET_SH5 && TARGET_FPU_ANY) ? 63 : TARGET_SH2E ? 15 : -1)))) \
+   ? ((unsigned) (REGNO) - FIRST_FP_REG \
+      + (TARGET_SH5 ? 77 : 25)) \
    : XD_REGISTER_P (REGNO) \
-   ? ((REGNO) - FIRST_XD_REG + (TARGET_SH5 ? 289 : 87)) \
+   ? ((unsigned) (REGNO) - FIRST_XD_REG + (TARGET_SH5 ? 289 : 87)) \
    : TARGET_REGISTER_P (REGNO) \
-   ? ((REGNO) - FIRST_TARGET_REG + 68) \
+   ? ((unsigned) (REGNO) - FIRST_TARGET_REG + 68) \
    : (REGNO) == PR_REG \
-   ? (TARGET_SH5 ? 241 : 17) \
-   : (REGNO) == T_REG \
-   ? (TARGET_SH5 ? 242 : 18) \
+   ? (TARGET_SH5 ? 18 : 17) \
+   : (REGNO) == PR_MEDIA_REG \
+   ? (TARGET_SH5 ? 18 : (unsigned) -1) \
    : (REGNO) == GBR_REG \
-   ? (TARGET_SH5 ? 238 : 19) \
+   ? (TARGET_SH5 ? 238 : 18) \
    : (REGNO) == MACH_REG \
    ? (TARGET_SH5 ? 239 : 20) \
    : (REGNO) == MACL_REG \
    ? (TARGET_SH5 ? 240 : 21) \
+   : (REGNO) == T_REG \
+   ? (TARGET_SH5 ? 242 : 22) \
    : (REGNO) == FPUL_REG \
    ? (TARGET_SH5 ? 244 : 23) \
-   : (abort(), -1))
-
-/* This is how to output a reference to a user-level label named NAME.  */
-#define ASM_OUTPUT_LABELREF(FILE, NAME)                        \
-  do                                                   \
-    {                                                  \
-      char * lname;                                    \
-                                                       \
-      STRIP_DATALABEL_ENCODING (lname, (NAME));                \
-      if (lname[0] == '*')                             \
-       fputs (lname + 1, (FILE));                      \
-      else                                             \
-       asm_fprintf ((FILE), "%U%s", lname);            \
-    }                                                  \
-  while (0)
+   : (REGNO) == FPSCR_REG \
+   ? (TARGET_SH5 ? 243 : 24) \
+   : (unsigned) -1)
 
 /* This is how to output a reference to a symbol_ref.  On SH5,
    references to non-code symbols must be preceded by `datalabel'.  */
 #define ASM_OUTPUT_SYMBOL_REF(FILE,SYM)                        \
   do                                                   \
     {                                                  \
-      if (TARGET_SH5                                   \
-         && (DATALABEL_SYMNAME_P (XSTR ((SYM), 0))     \
-             || CONSTANT_POOL_ADDRESS_P (SYM)))        \
+      if (TARGET_SH5 && !SYMBOL_REF_FUNCTION_P (SYM))  \
        fputs ("datalabel ", (FILE));                   \
       assemble_name ((FILE), XSTR ((SYM), 0));         \
     }                                                  \
   while (0)
 
-/* Output a label definition.  */
-#define ASM_OUTPUT_LABEL(FILE,NAME) \
-  do { assemble_name ((FILE), (NAME)); fputs (":\n", (FILE)); } while (0)
-
 /* This is how to output an assembler line
    that says to advance the location counter
    to a multiple of 2**LOG bytes.  */
@@ -2966,39 +2955,11 @@ while (0)
   if ((LOG) != 0)                      \
     fprintf ((FILE), "\t.align %d\n", (LOG))
 
-/* Output a function label definition.  */
-#define ASM_DECLARE_FUNCTION_NAME(STREAM,NAME,DECL) \
-    ASM_OUTPUT_LABEL((STREAM), (NAME))
-
-/* Output a globalising directive for a label.  */
-#define ASM_GLOBALIZE_LABEL(STREAM,NAME)       \
-  (fprintf ((STREAM), "\t.global\t"),          \
-   assemble_name ((STREAM), (NAME)),           \
-   fputc ('\n', (STREAM)))
-
-/* The prefix to add to user-visible assembler symbols.  */
-
-#define USER_LABEL_PREFIX "_"
-
-/* The prefix to add to an internally generated label.  */
-
-#define LOCAL_LABEL_PREFIX ""
-
-/* Make an internal label into a string.  */
-#define ASM_GENERATE_INTERNAL_LABEL(STRING, PREFIX, NUM) \
-  sprintf ((STRING), "*%s%s%ld", LOCAL_LABEL_PREFIX, (PREFIX), (long)(NUM))
-
-/* Output an internal label definition.  */
-#define ASM_OUTPUT_INTERNAL_LABEL(FILE,PREFIX,NUM) \
-  asm_fprintf ((FILE), "%L%s%d:\n", (PREFIX), (NUM))
+/* Globalizing directive for a label.  */
+#define GLOBAL_ASM_OP "\t.global\t"
 
 /* #define ASM_OUTPUT_CASE_END(STREAM,NUM,TABLE)           */
 
-/* Construct a private name.  */
-#define ASM_FORMAT_PRIVATE_NAME(OUTVAR,NAME,NUMBER)    \
-  ((OUTVAR) = (char *) alloca (strlen (NAME) + 10),    \
-   sprintf ((OUTVAR), "%s.%d", (NAME), (NUMBER)))
-
 /* Output a relative address table.  */
 
 #define ASM_OUTPUT_ADDR_DIFF_ELT(STREAM,BODY,VALUE,REL)                \
@@ -3038,37 +2999,11 @@ while (0)
 /* Output an absolute table element.  */
 
 #define ASM_OUTPUT_ADDR_VEC_ELT(STREAM,VALUE)                                  \
-  if (TARGET_BIGTABLE)                                                         \
-    asm_fprintf ((STREAM), "\t.long\t%LL%d\n", (VALUE));                       \
+  if (! optimize || TARGET_BIGTABLE)                                   \
+    asm_fprintf ((STREAM), "\t.long\t%LL%d\n", (VALUE));               \
   else                                                                 \
-    asm_fprintf ((STREAM), "\t.word\t%LL%d\n", (VALUE));                       \
-
-/* Output various types of constants.  */
-
-/* Loop alignment is now done in machine_dependent_reorg, so that
-   branch shortening can know about it.  */
-
-/* This is how to output an assembler line
-   that says to advance the location counter by SIZE bytes.  */
-
-#define ASM_OUTPUT_SKIP(FILE,SIZE) \
-  fprintf ((FILE), "\t.space %d\n", (SIZE))
+    asm_fprintf ((STREAM), "\t.word\t%LL%d\n", (VALUE));
 
-/* This says how to output an assembler line
-   to define a global common symbol.  */
-
-#define ASM_OUTPUT_COMMON(FILE, NAME, SIZE, ROUNDED)   \
-( fputs ("\t.comm ", (FILE)),                  \
-  assemble_name ((FILE), (NAME)),              \
-  fprintf ((FILE), ",%d\n", (SIZE)))
-
-/* This says how to output an assembler line
-   to define a local common symbol.  */
-
-#define ASM_OUTPUT_LOCAL(FILE, NAME, SIZE, ROUNDED)    \
-( fputs ("\t.lcomm ", (FILE)),                         \
-  assemble_name ((FILE), (NAME)),                      \
-  fprintf ((FILE), ",%d\n", (SIZE)))
 \f
 /* A C statement to be executed just prior to the output of
    assembler code for INSN, to modify the extracted operands so
@@ -3096,13 +3031,13 @@ while (0)
 
 #define PRINT_OPERAND_PUNCT_VALID_P(CHAR) \
   ((CHAR) == '.' || (CHAR) == '#' || (CHAR) == '@' || (CHAR) == ','    \
-   || (CHAR) == '$')
+   || (CHAR) == '$' || (CHAR) == '\'' || (CHAR) == '>')
 
 /* Recognize machine-specific patterns that may appear within
    constants.  Used for PIC-specific UNSPECs.  */
 #define OUTPUT_ADDR_CONST_EXTRA(STREAM, X, FAIL) \
   do                                                                   \
-    if (GET_CODE (X) == UNSPEC && XVECLEN ((X), 0) == 1)       \
+    if (GET_CODE (X) == UNSPEC)                                                \
       {                                                                        \
        switch (XINT ((X), 1))                                          \
          {                                                             \
@@ -3130,6 +3065,18 @@ while (0)
            output_addr_const ((STREAM), XVECEXP ((X), 0, 0));          \
            fputs ("@GOTPLT", (STREAM));                                \
            break;                                                      \
+         case UNSPEC_DTPOFF:                                           \
+           output_addr_const ((STREAM), XVECEXP ((X), 0, 0));          \
+           fputs ("@DTPOFF", (STREAM));                                \
+           break;                                                      \
+         case UNSPEC_GOTTPOFF:                                         \
+           output_addr_const ((STREAM), XVECEXP ((X), 0, 0));          \
+           fputs ("@GOTTPOFF", (STREAM));                              \
+           break;                                                      \
+         case UNSPEC_TPOFF:                                            \
+           output_addr_const ((STREAM), XVECEXP ((X), 0, 0));          \
+           fputs ("@TPOFF", (STREAM));                                 \
+           break;                                                      \
          case UNSPEC_CALLER:                                           \
            {                                                           \
              char name[32];                                            \
@@ -3139,6 +3086,52 @@ while (0)
              assemble_name ((STREAM), name);                           \
            }                                                           \
            break;                                                      \
+         case UNSPEC_EXTRACT_S16:                                      \
+         case UNSPEC_EXTRACT_U16:                                      \
+           {                                                           \
+             rtx val, shift;                                           \
+                                                                       \
+             val = XVECEXP (X, 0, 0);                                  \
+             shift = XVECEXP (X, 0, 1);                                \
+             fputc ('(', STREAM);                                      \
+             if (shift != const0_rtx)                                  \
+               fputc ('(', STREAM);                                    \
+             if (GET_CODE (val) == CONST                               \
+                 || GET_RTX_CLASS (GET_CODE (val)) != RTX_OBJ)         \
+               {                                                       \
+                 fputc ('(', STREAM);                                  \
+                 output_addr_const (STREAM, val);                      \
+                 fputc (')', STREAM);                                  \
+               }                                                       \
+             else                                                      \
+               output_addr_const (STREAM, val);                        \
+             if (shift != const0_rtx)                                  \
+               {                                                       \
+                 fputs (" >> ", STREAM);                               \
+                 output_addr_const (STREAM, shift);                    \
+                 fputc (')', STREAM);                                  \
+               }                                                       \
+             fputs (" & 65535)", STREAM);                              \
+           }                                                           \
+           break;                                                      \
+         case UNSPEC_SYMOFF:                                           \
+           output_addr_const (STREAM, XVECEXP (X, 0, 0));              \
+           fputc ('-', STREAM);                                        \
+           if (GET_CODE (XVECEXP (X, 0, 1)) == CONST)                  \
+             {                                                         \
+               fputc ('(', STREAM);                                    \
+               output_addr_const (STREAM, XVECEXP (X, 0, 1));          \
+               fputc (')', STREAM);                                    \
+             }                                                         \
+           else                                                        \
+             output_addr_const (STREAM, XVECEXP (X, 0, 1));            \
+           break;                                                      \
+         case UNSPEC_PCREL_SYMOFF:                                     \
+           output_addr_const (STREAM, XVECEXP (X, 0, 0));              \
+           fputs ("-(", STREAM);                                       \
+           output_addr_const (STREAM, XVECEXP (X, 0, 1));              \
+           fputs ("-.)", STREAM);                                      \
+           break;                                                      \
          default:                                                      \
            goto FAIL;                                                  \
          }                                                             \
@@ -3158,9 +3151,12 @@ extern struct rtx_def *sh_compare_op1;
 enum processor_type {
   PROCESSOR_SH1,
   PROCESSOR_SH2,
+  PROCESSOR_SH2E,
+  PROCESSOR_SH2A,
   PROCESSOR_SH3,
   PROCESSOR_SH3E,
   PROCESSOR_SH4,
+  PROCESSOR_SH4A,
   PROCESSOR_SH5
 };
 
@@ -3181,34 +3177,20 @@ enum mdep_reorg_phase_e
 
 extern enum mdep_reorg_phase_e mdep_reorg_phase;
 
-#define MACHINE_DEPENDENT_REORG(X) machine_dependent_reorg(X)
-
-/* Generate calls to memcpy, memcmp and memset.  */
-
-#define TARGET_MEM_FUNCTIONS
-
-/* Handle Hitachi compiler's pragmas.  */
-#define REGISTER_TARGET_PRAGMAS(PFILE) do {                                \
-  cpp_register_pragma (PFILE, 0, "interrupt", sh_pr_interrupt);                    \
-  cpp_register_pragma (PFILE, 0, "trapa", sh_pr_trapa);                            \
-  cpp_register_pragma (PFILE, 0, "nosave_low_regs", sh_pr_nosave_low_regs); \
+/* Handle Renesas compiler's pragmas.  */
+#define REGISTER_TARGET_PRAGMAS() do {                                 \
+  c_register_pragma (0, "interrupt", sh_pr_interrupt);                 \
+  c_register_pragma (0, "trapa", sh_pr_trapa);                         \
+  c_register_pragma (0, "nosave_low_regs", sh_pr_nosave_low_regs);     \
 } while (0)
 
-/* Set when processing a function with pragma interrupt turned on.  */
-
-extern int pragma_interrupt;
+extern tree sh_deferred_function_attributes;
+extern tree *sh_deferred_function_attributes_tail;
 
 /* Set when processing a function with interrupt attribute.  */
 
 extern int current_function_interrupt;
 
-/* Set to an RTX containing the address of the stack to switch to
-   for interrupt functions.  */
-extern struct rtx_def *sp_switch;
-
-extern int rtx_equal_function_value_matters;
-extern struct rtx_def *fpscr_rtx;
-
 \f
 /* Instructions with unfilled delay slots take up an
    extra two bytes for the nop in the delay slot.
@@ -3217,28 +3199,8 @@ extern struct rtx_def *fpscr_rtx;
 #define ADJUST_INSN_LENGTH(X, LENGTH)                          \
   (LENGTH) += sh_insn_length_adjustment (X);
 \f
-/* Define the codes that are matched by predicates in sh.c.  */
-#define PREDICATE_CODES \
-  {"arith_operand", {SUBREG, REG, CONST_INT}},                         \
-  {"arith_reg_operand", {SUBREG, REG}},                                        \
-  {"arith_reg_or_0_operand", {SUBREG, REG, CONST_INT}},                        \
-  {"binary_float_operator", {PLUS, MULT}},                             \
-  {"commutative_float_operator", {PLUS, MULT}},                                \
-  {"fp_arith_reg_operand", {SUBREG, REG}},                             \
-  {"fpscr_operand", {REG}},                                            \
-  {"fpul_operand", {REG}},                                             \
-  {"general_movsrc_operand", {SUBREG, REG, CONST_INT, CONST_DOUBLE, MEM}}, \
-  {"general_movdst_operand", {SUBREG, REG, MEM}},                      \
-  {"logical_operand", {SUBREG, REG, CONST_INT}},                       \
-  {"noncommutative_float_operator", {MINUS, DIV}},                     \
-  {"shmedia_6bit_operand", {SUBREG, REG, CONST_INT}},                  \
-  {"target_reg_operand", {SUBREG, REG}},                               \
-  {"target_operand", {SUBREG, REG, LABEL_REF, SYMBOL_REF}},            \
-  {"register_operand", {SUBREG, REG}},                                 \
-  {"symbol_ref_operand", {SYMBOL_REF}},
-
 /* Define this macro if it is advisable to hold scalars in registers
-   in a wider mode than that declared by the program.  In such cases, 
+   in a wider mode than that declared by the program.  In such cases,
    the value is constrained to be within the bounds of the declared
    type, but kept valid in the wider mode.  The signedness of the
    extension may differ from that of the type.
@@ -3248,19 +3210,17 @@ extern struct rtx_def *fpscr_rtx;
    load instructions.  */
 #define PROMOTE_MODE(MODE, UNSIGNEDP, TYPE) \
   if (GET_MODE_CLASS (MODE) == MODE_INT                        \
-      && GET_MODE_SIZE (MODE) < UNITS_PER_WORD)                \
+      && GET_MODE_SIZE (MODE) < 4/* ! UNITS_PER_WORD */)\
     (UNSIGNEDP) = ((MODE) == SImode ? 0 : (UNSIGNEDP)),        \
-    (MODE) = (TARGET_SH1 ? SImode : DImode);
+    (MODE) = (TARGET_SH1 ? SImode \
+             : TARGET_SHMEDIA32 ? SImode : DImode);
 
-/* Defining PROMOTE_FUNCTION_ARGS eliminates some unnecessary zero/sign
-   extensions applied to char/short functions arguments.  Defining
-   PROMOTE_FUNCTION_RETURN does the same for function returns.  */
+#define MAX_FIXED_MODE_SIZE (TARGET_SH5 ? 128 : 64)
 
-#define PROMOTE_FUNCTION_ARGS
-#define PROMOTE_FUNCTION_RETURN
+#define SIDI_OFF (TARGET_LITTLE_ENDIAN ? 0 : 4)
 
 /* ??? Define ACCUMULATE_OUTGOING_ARGS?  This is more efficient than pushing
-   and poping arguments.  However, we do have push/pop instructions, and
+   and popping arguments.  However, we do have push/pop instructions, and
    rather limited offsets (4 bits) in load/store instructions, so it isn't
    clear if this would give better code.  If implemented, should check for
    compatibility problems.  */
@@ -3271,12 +3231,22 @@ extern struct rtx_def *fpscr_rtx;
 
 #define NUM_MODES_FOR_MODE_SWITCHING { FP_MODE_NONE }
 
-#define OPTIMIZE_MODE_SWITCHING(ENTITY) TARGET_SH4
+#define OPTIMIZE_MODE_SWITCHING(ENTITY) (TARGET_SH4 || TARGET_SH2A_DOUBLE)
+
+#define ACTUAL_NORMAL_MODE(ENTITY) \
+  (TARGET_FPU_SINGLE ? FP_MODE_SINGLE : FP_MODE_DOUBLE)
 
 #define NORMAL_MODE(ENTITY) \
-   (TARGET_FPU_SINGLE ? FP_MODE_SINGLE : FP_MODE_DOUBLE) 
+  (sh_cfun_interrupt_handler_p () \
+   ? (TARGET_FMOVD ? FP_MODE_DOUBLE : FP_MODE_NONE) \
+   : ACTUAL_NORMAL_MODE (ENTITY))
+
+#define MODE_ENTRY(ENTITY) NORMAL_MODE (ENTITY)
 
-#define EPILOGUE_USES(REGNO)       ((TARGET_SH3E || TARGET_SH4)                \
+#define MODE_EXIT(ENTITY) \
+  (sh_cfun_attr_renesas_p () ? FP_MODE_NONE : NORMAL_MODE (ENTITY))
+
+#define EPILOGUE_USES(REGNO)       ((TARGET_SH2E || TARGET_SH4)                \
                                    && (REGNO) == FPSCR_REG)
 
 #define MODE_NEEDED(ENTITY, INSN)                                      \
@@ -3284,6 +3254,13 @@ extern struct rtx_def *fpscr_rtx;
    ? get_attr_fp_mode (INSN)                                           \
    : FP_MODE_NONE)
 
+#define MODE_AFTER(MODE, INSN)                  \
+     (TARGET_HITACHI                           \
+      && recog_memoized (INSN) >= 0            \
+      && get_attr_fp_set (INSN) != FP_SET_NONE  \
+      ? (int) get_attr_fp_set (INSN)            \
+      : (MODE))
+
 #define MODE_PRIORITY_TO_MODE(ENTITY, N) \
   ((TARGET_FPU_SINGLE != 0) ^ (N) ? FP_MODE_SINGLE : FP_MODE_DOUBLE)
 
@@ -3293,6 +3270,35 @@ extern struct rtx_def *fpscr_rtx;
 #define MD_CAN_REDIRECT_BRANCH(INSN, SEQ) \
   sh_can_redirect_branch ((INSN), (SEQ))
 
+#define DWARF_FRAME_RETURN_COLUMN \
+  (TARGET_SH5 ? DWARF_FRAME_REGNUM (PR_MEDIA_REG) : DWARF_FRAME_REGNUM (PR_REG))
+
+#define EH_RETURN_DATA_REGNO(N)        \
+  ((N) < 4 ? (N) + (TARGET_SH5 ? 2U : 4U) : INVALID_REGNUM)
+
+#define EH_RETURN_STACKADJ_REGNO STATIC_CHAIN_REGNUM
+#define EH_RETURN_STACKADJ_RTX gen_rtx_REG (Pmode, EH_RETURN_STACKADJ_REGNO)
+
+/* We have to distinguish between code and data, so that we apply
+   datalabel where and only where appropriate.  Use sdataN for data.  */
+#define ASM_PREFERRED_EH_DATA_FORMAT(CODE, GLOBAL) \
+ ((flag_pic && (GLOBAL) ? DW_EH_PE_indirect : 0) \
+  | (flag_pic ? DW_EH_PE_pcrel : DW_EH_PE_absptr) \
+  | ((CODE) ? 0 : (TARGET_SHMEDIA64 ? DW_EH_PE_sdata8 : DW_EH_PE_sdata4)))
+
+/* Handle special EH pointer encodings.  Absolute, pc-relative, and
+   indirect are handled automatically.  */
+#define ASM_MAYBE_OUTPUT_ENCODED_ADDR_RTX(FILE, ENCODING, SIZE, ADDR, DONE) \
+  do { \
+    if (((ENCODING) & 0xf) != DW_EH_PE_sdata4 \
+       && ((ENCODING) & 0xf) != DW_EH_PE_sdata8) \
+      { \
+       gcc_assert (GET_CODE (ADDR) == SYMBOL_REF); \
+       SYMBOL_REF_FLAGS (ADDR) |= SYMBOL_FLAG_FUNCTION; \
+       if (0) goto DONE; \
+      } \
+  } while (0)
+
 #if (defined CRT_BEGIN || defined CRT_END) && ! __SHMEDIA__
 /* SH constant pool breaks the devices in crtstuff.c to control section
    in where code resides.  We have to write it as asm code.  */
@@ -3307,11 +3313,7 @@ extern struct rtx_def *fpscr_rtx;
 2:\n" TEXT_SECTION_ASM_OP);
 #endif /* (defined CRT_BEGIN || defined CRT_END) && ! __SHMEDIA__ */
 
-#define ALLOCATE_INITIAL_VALUE(hard_reg) \
-  (REGNO (hard_reg) == PR_REG \
-   ? (current_function_is_leaf && ! sh_pr_n_sets () \
-      ? (hard_reg) \
-      : gen_rtx_MEM (Pmode, arg_pointer_rtx)) \
-   : NULL_RTX)
+/* FIXME: middle-end support for highpart optimizations is missing.  */
+#define high_life_started reload_in_progress
 
 #endif /* ! GCC_SH_H */