builtins.c (std_expand_builtin_va_start): Remove unused first argument.
[gcc.git] / gcc / config / sh / sh.h
index 6e73788e22ec12663d29604b21928bb8dfce131a..9d15fcf74182a28415ed309646d51d4d89ff0a94 100644 (file)
@@ -1,5 +1,5 @@
-/* Definitions of target machine for GNU compiler for Hitachi Super-H.
-   Copyright (C) 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000
+/* 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.
    Contributed by Steve Chamberlain (sac@cygnus.com).
    Improved by Jim Wilson (wilson@cygnus.com).
@@ -21,74 +21,102 @@ 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.  */
 
+#ifndef GCC_SH_H
+#define GCC_SH_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 hconfig.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 "%{ml:-D__LITTLE_ENDIAN__} \
-%{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__} \
-%{m4:-D__SH4__} \
-%{!m1:%{!m2:%{!m3:%{!m3e:%{!m4:%{!m4-single:%{!m4-single-only:%{!m4-nofpu:-D__sh1__}}}}}}}} \
-%{mnomacsave:-D__NOMACSAVE__} \
-%{mhitachi:-D__HITACHI__}"
-
-#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_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_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_HITACHI) \
+    builtin_define ("__HITACHI__"); \
+  builtin_define (TARGET_LITTLE_ENDIAN \
+                 ? "__LITTLE_ENDIAN__" : "__BIG_ENDIAN__"); \
+  if (flag_pic) \
+    { \
+      builtin_define ("__pic__"); \
+      builtin_define ("__PIC__"); \
+    } \
+  TARGET_OBJFMT_CPP_BUILTINS (); \
+} while (0)
 
 /* We can not debug without a frame pointer.  */
 /* #define CAN_DEBUG_WITHOUT_FP */
 
-#define CONDITIONAL_REGISTER_USAGE                                     \
-  if (! TARGET_SH4 || ! TARGET_FMOVD)                                  \
+#define CONDITIONAL_REGISTER_USAGE do                                  \
+{                                                                      \
+  int regno;                                                           \
+  for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno ++)             \
+    if (! VALID_REGISTER_P (regno))                                    \
+      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;                     \
+  if (TARGET_SHMEDIA)                                                  \
     {                                                                  \
-      int regno;                                                       \
-      for (regno = FIRST_XD_REG; regno <= LAST_XD_REG; regno++)                \
-       fixed_regs[regno] = call_used_regs[regno] = 1;                  \
-      if (! TARGET_SH4)                                                        \
-       {                                                               \
-         if (! TARGET_SH3E)                                            \
-           {                                                           \
-             int regno;                                                \
-             for (regno = FIRST_FP_REG; regno <= LAST_FP_REG; regno++) \
-               fixed_regs[regno] = call_used_regs[regno] = 1;          \
-             fixed_regs[FPUL_REG] = call_used_regs[FPUL_REG] = 1;      \
-           }                                                           \
-       }                                                               \
+      regno_reg_class[FIRST_GENERAL_REG] = GENERAL_REGS;               \
+      CLEAR_HARD_REG_SET (reg_class_contents[FP0_REGS]);               \
+      regno_reg_class[FIRST_FP_REG] = FP_REGS;                         \
     }                                                                  \
   if (flag_pic)                                                                \
-    {                                                                  \
-      fixed_regs[PIC_OFFSET_TABLE_REGNUM] = 1;                         \
-      call_used_regs[PIC_OFFSET_TABLE_REGNUM] = 1;                     \
-    }                                                                  \
+    fixed_regs[PIC_OFFSET_TABLE_REGNUM] = 1;                           \
   /* Hitachi saves and restores mac registers on call.  */             \
   if (TARGET_HITACHI && ! TARGET_NOMACSAVE)                            \
     {                                                                  \
       call_used_regs[MACH_REG] = 0;                                    \
       call_used_regs[MACL_REG] = 0;                                    \
-    }
+    }                                                                  \
+  if (TARGET_SHMEDIA)                                                  \
+    {                                                                  \
+      for (regno = FIRST_TARGET_REG; regno <= LAST_TARGET_REG; regno ++)\
+       if (! fixed_regs[regno] && call_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])                        \
+       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.  */
@@ -106,9 +134,11 @@ extern int target_flags;
 #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)
@@ -132,12 +162,12 @@ extern int target_flags;
 #define TARGET_SH3 (target_flags & SH3_BIT)
 
 /* Nonzero if we should generate code using type 3E insns.  */
-#define TARGET_SH3E (target_flags & SH3E_BIT)
+#define TARGET_SH3E ((target_flags & SH3E_BIT) && (target_flags & SH1_BIT))
 
-/* Nonzero if the cache line size is 32. */
-#define TARGET_CACHE32 (target_flags & HARD_SH4_BIT)
+/* Nonzero if the cache line size is 32.  */
+#define TARGET_CACHE32 (target_flags & HARD_SH4_BIT || TARGET_SH5)
 
-/* Nonzero if we schedule for a superscalar implementation. */
+/* Nonzero if we schedule for a superscalar implementation.  */
 #define TARGET_SUPERSCALAR (target_flags & HARD_SH4_BIT)
 
 /* Nonzero if the target has separate instruction and data caches.  */
@@ -149,9 +179,38 @@ extern int target_flags;
 /* Nonzero if the default precision of th FPU is single */
 #define TARGET_FPU_SINGLE (target_flags & FPU_SINGLE_BIT)
 
+/* Nonzero if a double-precision FPU is available.  */
+#define TARGET_FPU_DOUBLE (target_flags & SH4_BIT)
+
+/* Nonzero if an FPU is available.  */
+#define TARGET_FPU_ANY (TARGET_SH3E || TARGET_FPU_DOUBLE)
+
 /* Nonzero if we should generate code using type 4 insns.  */
-#define TARGET_SH4 (target_flags & SH4_BIT)
+#define TARGET_SH4 ((target_flags & SH4_BIT) && (target_flags & SH1_BIT))
+
+/* Nonzero if we should generate code for a SH5 CPU (either ISA).  */
+#define TARGET_SH5 (target_flags & SH5_BIT)
+
+/* Nonzero if we should generate code using the SHcompact instruction
+   set and 32-bit ABI.  */
+#define TARGET_SHCOMPACT (TARGET_SH5 && TARGET_SH1)
+
+/* Nonzero if we should generate code using the SHmedia instruction
+   set and ABI.  */
+#define TARGET_SHMEDIA (TARGET_SH5 && ! TARGET_SH1)
+
+/* 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))
 
+/* 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))
+
+/* 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)
 
@@ -184,40 +243,148 @@ extern int target_flags;
 /* Nonzero if generating code for a little endian SH.  */
 #define TARGET_LITTLE_ENDIAN     (target_flags & LITTLE_ENDIAN_BIT)
 
+/* Nonzero if we should do everything in userland.  */
+#define TARGET_USERMODE                (target_flags & USERMODE_BIT)
+
 /* Nonzero if we should prefer @GOT calls when generating PIC.  */
 #define TARGET_PREFERGOT       (target_flags & PREFERGOT_BIT)
 
+#define SELECT_SH1 (SH1_BIT)
+#define SELECT_SH2 (SH2_BIT | SELECT_SH1)
+#define SELECT_SH3 (SH3_BIT | SELECT_SH2)
+#define SELECT_SH3E (SH3E_BIT | FPU_SINGLE_BIT | SELECT_SH3)
+#define SELECT_SH4_NOFPU (HARD_SH4_BIT | SELECT_SH3)
+#define SELECT_SH4_SINGLE_ONLY (HARD_SH4_BIT | SELECT_SH3E)
+#define SELECT_SH4 (SH4_BIT|SH3E_BIT|HARD_SH4_BIT | SELECT_SH3)
+#define SELECT_SH4_SINGLE (FPU_SINGLE_BIT | SELECT_SH4)
+#define SELECT_SH5_64 (SH5_BIT | SH4_BIT)
+#define SELECT_SH5_64_NOFPU (SH5_BIT)
+#define SELECT_SH5_32 (SH5_BIT | SH4_BIT | SH3E_BIT)
+#define SELECT_SH5_32_NOFPU (SH5_BIT | SH3E_BIT)
+#define SELECT_SH5_COMPACT (SH5_BIT | SH4_BIT | SELECT_SH3E)
+#define SELECT_SH5_COMPACT_NOFPU (SH5_BIT | SELECT_SH3)
+
+/* 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",                SH1_BIT},                       \
-  {"2",                SH2_BIT},                       \
-  {"3",                SH3_BIT|SH2_BIT},               \
-  {"3e",       SH3E_BIT|SH3_BIT|SH2_BIT|FPU_SINGLE_BIT},       \
-  {"4-single-only",    SH3E_BIT|SH3_BIT|SH2_BIT|HARD_SH4_BIT|FPU_SINGLE_BIT},  \
-  {"4-single", SH4_BIT|SH3E_BIT|SH3_BIT|SH2_BIT|HARD_SH4_BIT|FPU_SINGLE_BIT},\
-  {"4-nofpu",  SH3_BIT|SH2_BIT|HARD_SH4_BIT},\
-  {"4",                SH4_BIT|SH3E_BIT|SH3_BIT|SH2_BIT|HARD_SH4_BIT}, \
-  {"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},                     \
+{ {"1",                TARGET_NONE, "" },              \
+  {"1",                SELECT_SH1, "" },                       \
+  {"2",                TARGET_NONE, "" },              \
+  {"2",                SELECT_SH2, "" },               \
+  {"3",                TARGET_NONE, "" },              \
+  {"3",                SELECT_SH3, "" },       \
+  {"3e",       TARGET_NONE, "" },              \
+  {"3e",       SELECT_SH3E, "" },      \
+  {"4-single-only",    TARGET_NONE, "" },      \
+  {"4-single-only",    SELECT_SH4_SINGLE_ONLY, "" },   \
+  {"4-single", TARGET_NONE, "" },              \
+  {"4-single", SELECT_SH4_SINGLE, "" },\
+  {"4-nofpu",  TARGET_NONE, "" },              \
+  {"4-nofpu",  SELECT_SH4_NOFPU, "" },\
+  {"4",                TARGET_NONE, "" },              \
+  {"4",                SELECT_SH4, "" }, \
+  {"5-64media",        TARGET_NONE, "" },              \
+  {"5-64media", SELECT_SH5_64, "Generate 64-bit SHmedia code" }, \
+  {"5-64media-nofpu", TARGET_NONE, "" },       \
+  {"5-64media-nofpu", SELECT_SH5_64_NOFPU, "Generate 64-bit FPU-less SHmedia code" }, \
+  {"5-32media",        TARGET_NONE, "" },              \
+  {"5-32media", SELECT_SH5_32, "Generate 32-bit SHmedia code" }, \
+  {"5-32media-nofpu", TARGET_NONE, "" },       \
+  {"5-32media-nofpu", SELECT_SH5_32_NOFPU, "Generate 32-bit FPU-less SHmedia code" }, \
+  {"5-compact",        TARGET_NONE, "" },              \
+  {"5-compact",        SELECT_SH5_COMPACT, "Generate SHcompact code" }, \
+  {"5-compact-nofpu", TARGET_NONE, "" },       \
+  {"5-compact-nofpu", SELECT_SH5_COMPACT_NOFPU, "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}                 \
+  {"",         TARGET_DEFAULT, "" }            \
 }
 
 /* This are meant to be redefined in the host dependent files */
 #define SUBTARGET_SWITCHES
 
-#define TARGET_DEFAULT  (0)
+/* This defaults us to big-endian.  */
+#ifndef TARGET_ENDIAN_DEFAULT
+#define TARGET_ENDIAN_DEFAULT 0
+#endif
+
+#ifndef TARGET_CPU_DEFAULT
+#define TARGET_CPU_DEFAULT SELECT_SH1
+#endif
+
+#define TARGET_DEFAULT  (TARGET_CPU_DEFAULT|TARGET_ENDIAN_DEFAULT)
+
+#define CPP_SPEC " %(subtarget_cpp_spec) "
+
+#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_EXTRA_SPECS
+
+#define ASM_SPEC  "%(subtarget_asm_endian_spec) %{mrelax:-relax}"
+
+#ifndef SUBTARGET_ASM_ENDIAN_SPEC
+#if TARGET_ENDIAN_DEFAULT == LITTLE_ENDIAN_BIT
+#define SUBTARGET_ASM_ENDIAN_SPEC "%{mb:-big} %{!mb:-little}"
+#else
+#define SUBTARGET_ASM_ENDIAN_SPEC "%{ml:-little} %{!ml:-big}"
+#endif
+#endif
+
+#define LINK_EMUL_PREFIX "sh%{ml:l}"
+
+#if TARGET_CPU_DEFAULT & SH5_BIT
+#if TARGET_CPU_DEFAULT & SH3E_BIT
+#define LINK_DEFAULT_CPU_EMUL "32"
+#else
+#define LINK_DEFAULT_CPU_EMUL "64"
+#endif /* SH3E_BIT */
+#else
+#define LINK_DEFAULT_CPU_EMUL ""
+#endif /* SH5_BIT */
+
+#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)"
 
 #define OPTIMIZATION_OPTIONS(LEVEL,SIZE)                               \
 do {                                                                   \
@@ -233,6 +400,8 @@ extern int assembler_dialect;
 
 #define OVERRIDE_OPTIONS                                               \
 do {                                                                   \
+  int regno;                                                           \
+                                                                       \
   sh_cpu = CPU_SH1;                                                    \
   assembler_dialect = 0;                                               \
   if (TARGET_SH2)                                                      \
@@ -246,25 +415,51 @@ do {                                                                      \
       assembler_dialect = 1;                                           \
       sh_cpu = CPU_SH4;                                                        \
     }                                                                  \
-  if (! TARGET_SH4 || ! TARGET_FMOVD)                                  \
+  if (TARGET_SH5)                                                      \
     {                                                                  \
-      /* Prevent usage of explicit register names for variables                \
-        for registers not present / not addressable in the             \
-        target architecture.  */                                       \
-      int regno;                                                       \
-      for (regno = (TARGET_SH3E) ? 17 : 0;                             \
-          regno <= 24; regno++)                                        \
-       fp_reg_names[regno][0] = 0;                                     \
+      sh_cpu = CPU_SH5;                                                        \
+      target_flags |= DALIGN_BIT;                                      \
+      if (TARGET_FPU_ANY)                                              \
+       target_flags |= FMOVD_BIT;                                      \
+      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;                          \
+       }                                                               \
     }                                                                  \
+  else                                                                 \
+    {                                                                  \
+       /* Only the sh64-elf assembler fully supports .quad properly.  */\
+       targetm.asm_out.aligned_op.di = NULL;                           \
+       targetm.asm_out.unaligned_op.di = NULL;                         \
+    }                                                                  \
+                                                                       \
+  for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)              \
+    if (! VALID_REGISTER_P (regno))                                    \
+      sh_register_names[regno][0] = '\0';                              \
+                                                                       \
+  for (regno = 0; regno < ADDREGNAMES_SIZE; regno++)                   \
+    if (! VALID_REGISTER_P (ADDREGNAMES_REGNO (regno)))                        \
+      sh_additional_register_names[regno][0] = '\0';                   \
+                                                                       \
   if (flag_omit_frame_pointer < 0)                                     \
-   /* 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);                  \
-   else                                                                        \
-    flag_omit_frame_pointer = 0;                                       \
+   {                                                                   \
+     /* 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);                \
+     else                                                              \
+      flag_omit_frame_pointer = 0;                                     \
+   }                                                                   \
                                                                        \
   if (flag_pic && ! TARGET_PREFERGOT)                                  \
     flag_no_function_cse = 1;                                          \
@@ -277,10 +472,6 @@ do {                                                                       \
 \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.  */
 
@@ -301,25 +492,33 @@ do {                                                                      \
 #define LIBGCC2_WORDS_BIG_ENDIAN 1
 #endif
 
-/* Number of bits in an addressable storage unit.  */
-#define BITS_PER_UNIT  8
+#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. */
+#define INT_TYPE_SIZE 32
+
+/* Width in bits of a `long'.  */
+#define LONG_TYPE_SIZE (TARGET_SHMEDIA64 ? 64 : 32)
+
+/* Width in bits of a `long long'.  */
+#define LONG_LONG_TYPE_SIZE 64
 
-/* 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  32
-#define MAX_BITS_PER_WORD 32
+/* Width in bits of a `long double'.  */
+#define LONG_DOUBLE_TYPE_SIZE 64
 
 /* Width of a word, in units (bytes).  */
-#define UNITS_PER_WORD 4
+#define UNITS_PER_WORD (TARGET_SHMEDIA ? 8 : 4)
+#define MIN_UNITS_PER_WORD 4
 
 /* Width in bits of a pointer.
    See also the macro `Pmode' defined below.  */
-#define POINTER_SIZE  32
+#define POINTER_SIZE  (TARGET_SHMEDIA64 ? 64 : 32)
 
 /* Allocation boundary (in *bits*) for storing arguments in argument list.  */
-#define PARM_BOUNDARY          32
+#define PARM_BOUNDARY          (TARGET_SH5 ? 64 : 32)
 
 /* Boundary (in *bits*) on which stack pointer should be aligned.  */
 #define STACK_BOUNDARY  BIGGEST_ALIGNMENT
@@ -332,7 +531,14 @@ do {                                                                       \
 /* 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 : (1 << CACHE_LOG) * 8)
+#define FUNCTION_BOUNDARY  \
+  (TARGET_SMALLCODE ? 16 << TARGET_SHMEDIA : (1 << CACHE_LOG) * 8)
+
+/* On SH5, the lowest bit is used to indicate SHmedia functions, so
+   the vbit must go into the delta field of
+   pointers-to-member-functions.  */
+#define TARGET_PTRMEMFUNC_VBIT_LOCATION \
+  (TARGET_SH5 ? ptrmemfunc_vbit_in_delta : ptrmemfunc_vbit_in_pfn)
 
 /* Alignment of field after `int : 0' in a structure.  */
 #define EMPTY_FIELD_BOUNDARY  32
@@ -341,7 +547,7 @@ do {                                                                        \
 #define BIGGEST_ALIGNMENT  (TARGET_ALIGN_DOUBLE ? 64 : 32)
 
 /* The best alignment to use in cases where we have a choice.  */
-#define FASTEST_ALIGNMENT 32
+#define FASTEST_ALIGNMENT (TARGET_SH5 ? 64 : 32)
 
 /* Make strings word-aligned so strcpy from constants will be faster.  */
 #define CONSTANT_ALIGNMENT(EXP, ALIGN) \
@@ -349,10 +555,6 @@ do {                                                                       \
     && (ALIGN) < FASTEST_ALIGNMENT)    \
     ? FASTEST_ALIGNMENT : (ALIGN))
 
-#ifndef MAX_OFILE_ALIGNMENT
-#define MAX_OFILE_ALIGNMENT 128
-#endif
-
 /* Make arrays of chars word-aligned for the same reasons.  */
 #define DATA_ALIGNMENT(TYPE, ALIGN)            \
   (TREE_CODE (TYPE) == ARRAY_TYPE              \
@@ -381,8 +583,8 @@ do {                                                                        \
   (PREV_INSN (A_LABEL)                                                 \
    && GET_CODE (PREV_INSN (A_LABEL)) == INSN                           \
    && GET_CODE (PATTERN (PREV_INSN (A_LABEL))) == UNSPEC_VOLATILE      \
-   && XINT (PATTERN (PREV_INSN (A_LABEL)), 1) == 1)                    \
-   /* explicit alignment insn in constant tables. */                   \
+   && XINT (PATTERN (PREV_INSN (A_LABEL)), 1) == UNSPECV_ALIGN)                \
+   /* explicit alignment insn in constant tables.  */                  \
   ? INTVAL (XVECEXP (PATTERN (PREV_INSN (A_LABEL)), 0, 0))             \
   : 0)
 
@@ -392,9 +594,9 @@ do {                                                                        \
 /* The base two logarithm of the known minimum alignment of an insn length.  */
 #define INSN_LENGTH_ALIGNMENT(A_INSN)                                  \
   (GET_CODE (A_INSN) == INSN                                           \
-   ? 1                                                                 \
+   ? 1 << TARGET_SHMEDIA                                               \
    : GET_CODE (A_INSN) == JUMP_INSN || GET_CODE (A_INSN) == CALL_INSN  \
-   ? 1                                                                 \
+   ? 1 << TARGET_SHMEDIA                                               \
    : CACHE_LOG)
 \f
 /* Standard register usage.  */
@@ -419,28 +621,160 @@ do {                                                                     \
        fr4..fr11       fp args in
        fr12..fr15      call saved floating point registers  */
 
+#define MAX_REGISTER_NAME_LENGTH 5
+extern char sh_register_names[][MAX_REGISTER_NAME_LENGTH + 1];
+
+#define SH_REGISTER_NAMES_INITIALIZER                                  \
+{                                                                      \
+  "r0",   "r1",   "r2",   "r3",   "r4",   "r5",   "r6",   "r7",        \
+  "r8",   "r9",   "r10",  "r11",  "r12",  "r13",  "r14",  "r15",       \
+  "r16",  "r17",  "r18",  "r19",  "r20",  "r21",  "r22",  "r23",       \
+  "r24",  "r25",  "r26",  "r27",  "r28",  "r29",  "r30",  "r31",       \
+  "r32",  "r33",  "r34",  "r35",  "r36",  "r37",  "r38",  "r39",       \
+  "r40",  "r41",  "r42",  "r43",  "r44",  "r45",  "r46",  "r47",       \
+  "r48",  "r49",  "r50",  "r51",  "r52",  "r53",  "r54",  "r55",       \
+  "r56",  "r57",  "r58",  "r59",  "r60",  "r61",  "r62",  "r63",       \
+  "fr0",  "fr1",  "fr2",  "fr3",  "fr4",  "fr5",  "fr6",  "fr7",       \
+  "fr8",  "fr9",  "fr10", "fr11", "fr12", "fr13", "fr14", "fr15",      \
+  "fr16", "fr17", "fr18", "fr19", "fr20", "fr21", "fr22", "fr23",      \
+  "fr24", "fr25", "fr26", "fr27", "fr28", "fr29", "fr30", "fr31",      \
+  "fr32", "fr33", "fr34", "fr35", "fr36", "fr37", "fr38", "fr39",      \
+  "fr40", "fr41", "fr42", "fr43", "fr44", "fr45", "fr46", "fr47",      \
+  "fr48", "fr49", "fr50", "fr51", "fr52", "fr53", "fr54", "fr55",      \
+  "fr56", "fr57", "fr58", "fr59", "fr60", "fr61", "fr62", "fr63",      \
+  "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"                                                                        \
+}
+
+#define DEBUG_REGISTER_NAMES SH_REGISTER_NAMES_INITIALIZER
+
+#define REGNAMES_ARR_INDEX_1(index) \
+  (sh_register_names[index])
+#define REGNAMES_ARR_INDEX_2(index) \
+  REGNAMES_ARR_INDEX_1 ((index)), REGNAMES_ARR_INDEX_1 ((index)+1)
+#define REGNAMES_ARR_INDEX_4(index) \
+  REGNAMES_ARR_INDEX_2 ((index)), REGNAMES_ARR_INDEX_2 ((index)+2)
+#define REGNAMES_ARR_INDEX_8(index) \
+  REGNAMES_ARR_INDEX_4 ((index)), REGNAMES_ARR_INDEX_4 ((index)+4)
+#define REGNAMES_ARR_INDEX_16(index) \
+  REGNAMES_ARR_INDEX_8 ((index)), REGNAMES_ARR_INDEX_8 ((index)+8)
+#define REGNAMES_ARR_INDEX_32(index) \
+  REGNAMES_ARR_INDEX_16 ((index)), REGNAMES_ARR_INDEX_16 ((index)+16)
+#define REGNAMES_ARR_INDEX_64(index) \
+  REGNAMES_ARR_INDEX_32 ((index)), REGNAMES_ARR_INDEX_32 ((index)+32)
+
+#define REGISTER_NAMES \
+{ \
+  REGNAMES_ARR_INDEX_64 (0), \
+  REGNAMES_ARR_INDEX_64 (64), \
+  REGNAMES_ARR_INDEX_8 (128), \
+  REGNAMES_ARR_INDEX_8 (136), \
+  REGNAMES_ARR_INDEX_8 (144), \
+  REGNAMES_ARR_INDEX_1 (152) \
+}
+
+#define ADDREGNAMES_SIZE 32
+#define MAX_ADDITIONAL_REGISTER_NAME_LENGTH 4
+extern char sh_additional_register_names[ADDREGNAMES_SIZE] \
+  [MAX_ADDITIONAL_REGISTER_NAME_LENGTH + 1];
+
+#define SH_ADDITIONAL_REGISTER_NAMES_INITIALIZER                       \
+{                                                                      \
+  "dr0",  "dr2",  "dr4",  "dr6",  "dr8",  "dr10", "dr12", "dr14",      \
+  "dr16", "dr18", "dr20", "dr22", "dr24", "dr26", "dr28", "dr30",      \
+  "dr32", "dr34", "dr36", "dr38", "dr40", "dr42", "dr44", "dr46",      \
+  "dr48", "dr50", "dr52", "dr54", "dr56", "dr58", "dr60", "dr62"       \
+}
+
+#define ADDREGNAMES_REGNO(index) \
+  ((index < 32) ? (FIRST_FP_REG + (index) * 2) \
+   : (-1))
+
+#define ADDREGNAMES_ARR_INDEX_1(index) \
+  { (sh_additional_register_names[index]), ADDREGNAMES_REGNO (index) }
+#define ADDREGNAMES_ARR_INDEX_2(index) \
+  ADDREGNAMES_ARR_INDEX_1 ((index)), ADDREGNAMES_ARR_INDEX_1 ((index)+1)
+#define ADDREGNAMES_ARR_INDEX_4(index) \
+  ADDREGNAMES_ARR_INDEX_2 ((index)), ADDREGNAMES_ARR_INDEX_2 ((index)+2)
+#define ADDREGNAMES_ARR_INDEX_8(index) \
+  ADDREGNAMES_ARR_INDEX_4 ((index)), ADDREGNAMES_ARR_INDEX_4 ((index)+4)
+#define ADDREGNAMES_ARR_INDEX_16(index) \
+  ADDREGNAMES_ARR_INDEX_8 ((index)), ADDREGNAMES_ARR_INDEX_8 ((index)+8)
+#define ADDREGNAMES_ARR_INDEX_32(index) \
+  ADDREGNAMES_ARR_INDEX_16 ((index)), ADDREGNAMES_ARR_INDEX_16 ((index)+16)
+
+#define ADDITIONAL_REGISTER_NAMES \
+{                                      \
+  ADDREGNAMES_ARR_INDEX_32 (0)         \
+}
+
 /* Number of actual hardware registers.
    The hardware registers are assigned numbers for the compiler
    from 0 to just below FIRST_PSEUDO_REGISTER.
    All registers that the compiler knows about must be given numbers,
    even those that are not normally considered general registers.  */
 
-#define AP_REG   16
-#define PR_REG   17
-#define T_REG    18
-#define GBR_REG  19
-#define MACH_REG 20
-#define MACL_REG 21
-#define SPECIAL_REG(REGNO) ((REGNO) >= 18 && (REGNO) <= 21)
-#define FPUL_REG 22
-#define RAP_REG 23
-#define FIRST_FP_REG 24
-#define LAST_FP_REG 39
-#define FIRST_XD_REG 40
-#define LAST_XD_REG 47
-#define FPSCR_REG 48
-
-#define FIRST_PSEUDO_REGISTER 49
+/* There are many other relevant definitions in sh.md's md_constants.  */
+
+#define FIRST_GENERAL_REG R0_REG
+#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))
+#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))
+
+#define GENERAL_REGISTER_P(REGNO) \
+  IN_RANGE ((REGNO), FIRST_GENERAL_REG, LAST_GENERAL_REG)
+
+#define GENERAL_OR_AP_REGISTER_P(REGNO) \
+  (GENERAL_REGISTER_P (REGNO) || ((REGNO) == AP_REG))
+
+#define FP_REGISTER_P(REGNO) \
+  ((REGNO) >= FIRST_FP_REG && (REGNO) <= LAST_FP_REG)
+
+#define XD_REGISTER_P(REGNO) \
+  ((REGNO) >= FIRST_XD_REG && (REGNO) <= LAST_XD_REG)
+
+#define FP_OR_XD_REGISTER_P(REGNO) \
+  (FP_REGISTER_P (REGNO) || XD_REGISTER_P (REGNO))
+
+#define FP_ANY_REGISTER_P(REGNO) \
+  (FP_REGISTER_P (REGNO) || XD_REGISTER_P (REGNO) || (REGNO) == FPUL_REG)
+
+#define SPECIAL_REGISTER_P(REGNO) \
+  ((REGNO) == GBR_REG || (REGNO) == T_REG \
+   || (REGNO) == MACH_REG || (REGNO) == MACL_REG)
+
+#define TARGET_REGISTER_P(REGNO) \
+  ((REGNO) >= FIRST_TARGET_REG && (REGNO) <= LAST_TARGET_REG)
+
+#define SHMEDIA_REGISTER_P(REGNO) \
+  (GENERAL_REGISTER_P (REGNO) || FP_REGISTER_P (REGNO) \
+   || TARGET_REGISTER_P (REGNO))
+
+/* This is to be used in CONDITIONAL_REGISTER_USAGE, to mark registers
+   that should be fixed.  */
+#define VALID_REGISTER_P(REGNO) \
+  (SHMEDIA_REGISTER_P (REGNO) || XD_REGISTER_P (REGNO) \
+   || (REGNO) == AP_REG || (REGNO) == RAP_REG \
+   || (TARGET_SH1 && (SPECIAL_REGISTER_P (REGNO) || (REGNO) == PR_REG)) \
+   || (TARGET_SH3E && (REGNO) == FPUL_REG))
+
+/* The mode that should be generally used to store a register by
+   itself in the stack, or to load it back.  */
+#define REGISTER_NATURAL_MODE(REGNO) \
+  (FP_REGISTER_P (REGNO) ? SFmode \
+   : XD_REGISTER_P (REGNO) ? DFmode \
+   : TARGET_SHMEDIA && ! HARD_REGNO_CALL_PART_CLOBBERED ((REGNO), DImode) \
+   ? DImode \
+   : SImode)
+
+#define FIRST_PSEUDO_REGISTER 153
 
 /* 1 for registers that have pervasive standard uses
    and are not available for the register allocator.
@@ -448,20 +782,37 @@ do {                                                                      \
    Mach register is fixed 'cause it's only 10 bits wide for SH1.
    It is 32 bits wide for SH2.  */
 
-#define FIXED_REGISTERS        \
-  { 0,  0,  0,  0,             \
-    0,  0,  0,  0,             \
-    0,  0,  0,  0,             \
-    0,  0,  0,  1,             \
-    1,  1,  1,  1,             \
-    1,  1,  0,  1,             \
-    0,  0,  0,  0,             \
-    0,  0,  0,  0,             \
-    0,  0,  0,  0,             \
-    0,  0,  0,  0,             \
-    0,  0,  0,  0,             \
-    0,  0,  0,  0,             \
-    1,                         \
+#define FIXED_REGISTERS                                                \
+{                                                                      \
+/* Regular registers.  */                                              \
+  0,      0,      0,      0,      0,      0,      0,      0,           \
+  0,      0,      0,      0,      0,      0,      0,      1,           \
+  /* r16 is reserved, r18 is the former pr.  */                                \
+  1,      0,      0,      0,      0,      0,      0,      0,           \
+  /* r24 is reserved for the OS; r25, for the assembler or linker.  */ \
+  /* r26 is a global variable data pointer; r27 is for constants.  */  \
+  1,      1,      1,      1,      0,      0,      0,      0,           \
+  0,      0,      0,      0,      0,      0,      0,      0,           \
+  0,      0,      0,      0,      0,      0,      0,      0,           \
+  0,      0,      0,      0,      0,      0,      0,      0,           \
+  0,      0,      0,      0,      0,      0,      0,      1,           \
+/* FP registers.  */                                                   \
+  0,      0,      0,      0,      0,      0,      0,      0,           \
+  0,      0,      0,      0,      0,      0,      0,      0,           \
+  0,      0,      0,      0,      0,      0,      0,      0,           \
+  0,      0,      0,      0,      0,      0,      0,      0,           \
+  0,      0,      0,      0,      0,      0,      0,      0,           \
+  0,      0,      0,      0,      0,      0,      0,      0,           \
+  0,      0,      0,      0,      0,      0,      0,      0,           \
+  0,      0,      0,      0,      0,      0,      0,      0,           \
+/* Branch target registers.  */                                                \
+  0,      0,      0,      0,      0,      0,      0,      0,           \
+/* XD registers.  */                                                   \
+  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,                                                                   \
 }
 
 /* 1 for registers not available across function calls.
@@ -471,22 +822,51 @@ do {                                                                      \
    and the register where structure-value addresses are passed.
    Aside from that, you can include as many other registers as you like.  */
 
-#define CALL_USED_REGISTERS    \
-  { 1,  1,  1,  1,             \
-    1,  1,  1,  1,             \
-    0,  0,  0,  0,             \
-    0,  0,  0,  1,             \
-    1,  0,  1,  1,             \
-    1,  1,  1,  1,             \
-    1,  1,  1,  1,             \
-    1,  1,  1,  1,             \
-    1,  1,  1,  1,             \
-    0,  0,  0,  0,             \
-    1,  1,  1,  1,             \
-    1,  1,  0,  0,             \
-    1,                         \
+#define CALL_USED_REGISTERS                                            \
+{                                                                      \
+/* Regular registers.  */                                              \
+  1,      1,      1,      1,      1,      1,      1,      1,           \
+  /* R8 and R9 are call-clobbered on SH5, but not on earlier SH ABIs.  \
+     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,      0,      0,      0,      0,           \
+  0,      0,      0,      0,      1,      1,      1,      1,           \
+  1,      1,      1,      1,      0,      0,      0,      0,           \
+  0,      0,      0,      0,      0,      0,      0,      0,           \
+  0,      0,      0,      0,      1,      1,      1,      1,           \
+/* FP registers.  */                                                   \
+  1,      1,      1,      1,      1,      1,      1,      1,           \
+  1,      1,      1,      1,      0,      0,      0,      0,           \
+  1,      1,      1,      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,      0,      0,      0,      0,           \
+  0,      0,      0,      0,      0,      0,      0,      0,           \
+  0,      0,      0,      0,      0,      0,      0,      0,           \
+/* Branch target registers.  */                                                \
+  1,      1,      1,      1,      1,      0,      0,      0,           \
+/* 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,                                                                   \
 }
 
+/* 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
+   compiling SHmedia code with the 32-bit ABI, since that's the only
+   ABI that can be linked with SHcompact code.  */
+#define HARD_REGNO_CALL_PART_CLOBBERED(REGNO,MODE) \
+  (TARGET_SHMEDIA32 \
+   && GET_MODE_SIZE (MODE) > 4 \
+   && (((REGNO) >= FIRST_GENERAL_REG + 10 \
+        && (REGNO) <= FIRST_GENERAL_REG + 14) \
+       || (REGNO) == PR_MEDIA_REG))
+
 /* Return number of consecutive hard regs needed starting at reg REGNO
    to hold something of mode MODE.
    This is ordinarily the length in words of a value of mode MODE
@@ -495,8 +875,10 @@ do {                                                                       \
    On the SH all but the XD regs are UNITS_PER_WORD bits wide.  */
 
 #define HARD_REGNO_NREGS(REGNO, MODE) \
-   ((REGNO) >= FIRST_XD_REG && (REGNO) <= LAST_XD_REG \
+   (XD_REGISTER_P (REGNO) \
     ? (GET_MODE_SIZE (MODE) / (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.
@@ -512,28 +894,62 @@ do {                                                                      \
    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_REG (REGNO) ? (MODE) == SImode      \
+  (SPECIAL_REGISTER_P (REGNO) ? (MODE) == SImode \
    : (REGNO) == FPUL_REG ? (MODE) == SImode || (MODE) == SFmode        \
-   : (REGNO) >= FIRST_FP_REG && (REGNO) <= LAST_FP_REG && (MODE) == SFmode \
+   : FP_REGISTER_P (REGNO) && (MODE) == SFmode \
    ? 1 \
-   : (REGNO) >= FIRST_FP_REG && (REGNO) <= LAST_FP_REG \
+   : (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_SH3E && (MODE) == SCmode) \
-      || (((TARGET_SH4 && (MODE) == DFmode) || (MODE) == DCmode) \
+      || (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)) \
-   : (REGNO) >= FIRST_XD_REG && (REGNO) <= LAST_XD_REG \
+   : XD_REGISTER_P (REGNO) \
    ? (MODE) == DFmode \
+   : TARGET_REGISTER_P (REGNO) \
+   ? ((MODE) == DImode || (MODE) == SImode) \
    : (REGNO) == PR_REG ? 0                     \
    : (REGNO) == FPSCR_REG ? (MODE) == PSImode \
    : 1)
 
+/* 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)) \
+   || (TARGET_SHMEDIA \
+       && ((MODE) == V8QImode || (MODE) == V2HImode || (MODE) == V4HImode \
+          || (MODE) == V2SImode)))
+
 /* Value is 1 if it is a good idea to tie two pseudo registers
    when one has mode MODE1 and one has mode MODE2.
    If HARD_REGNO_MODE_OK could produce different values for MODE1 and MODE2,
-   for any hard reg, then this must be 0 for correct output.  */
+   for any hard reg, then this must be 0 for correct output.
+   That's the case for xd registers: we don't hold SFmode values in
+   them, so we can't tie an SFmode pseudos with one in another
+   floating-point mode.  */
 
 #define MODES_TIEABLE_P(MODE1, MODE2) \
-  ((MODE1) == (MODE2) || GET_MODE_CLASS (MODE1) == GET_MODE_CLASS (MODE2))
+  ((MODE1) == (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.  */
@@ -542,18 +958,18 @@ do {                                                                      \
 /* #define PC_REGNUM           15*/
 
 /* Register to use for pushing function arguments.  */
-#define STACK_POINTER_REGNUM   15
+#define STACK_POINTER_REGNUM   SP_REG
 
 /* Base register for access to local variables of the function.  */
-#define FRAME_POINTER_REGNUM   14
+#define FRAME_POINTER_REGNUM   FP_REG
 
 /* Fake register that holds the address on the stack of the
    current function's return address.  */
-#define RETURN_ADDRESS_POINTER_REGNUM 23
+#define RETURN_ADDRESS_POINTER_REGNUM RAP_REG
 
 /* Register to hold the addressing base for position independent
    code access to data items.  */
-#define PIC_OFFSET_TABLE_REGNUM        12
+#define PIC_OFFSET_TABLE_REGNUM        (flag_pic ? PIC_REG : INVALID_REGNUM)
 
 #define GOT_SYMBOL_NAME "*_GLOBAL_OFFSET_TABLE_"
 
@@ -605,10 +1021,10 @@ do {                                                                     \
   OFFSET = initial_elimination_offset ((FROM), (TO))
 
 /* Base register for access to arguments of the function.  */
-#define ARG_POINTER_REGNUM     16
+#define ARG_POINTER_REGNUM     AP_REG
 
 /* Register in which the static-chain is passed to a function.  */
-#define STATIC_CHAIN_REGNUM    13
+#define STATIC_CHAIN_REGNUM    (TARGET_SH5 ? 1 : 3)
 
 /* The register in which a struct value address is passed.  */
 
@@ -626,13 +1042,24 @@ do {                                                                     \
   (TARGET_HITACHI ? 0 : gen_rtx_REG (Pmode, STRUCT_VALUE_REGNUM))
 
 #define RETURN_IN_MEMORY(TYPE) \
-  (TYPE_MODE (TYPE) == BLKmode \
-   || TARGET_HITACHI && TREE_CODE (TYPE) == RECORD_TYPE)
+  (TARGET_SH5 \
+   ? ((TYPE_MODE (TYPE) == BLKmode \
+       ? (unsigned HOST_WIDE_INT) 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.  */
 
 #define DEFAULT_PCC_STRUCT_RETURN 0
+
+#define SHMEDIA_REGS_STACK_ADJUST() \
+  (TARGET_SHCOMPACT && current_function_has_nonlocal_label \
+   ? (8 * (/* r28-r35 */ 8 + /* r44-r59 */ 16 + /* tr5-tr7 */ 3) \
+      + (TARGET_FPU_ANY ? 4 * (/* fr36 - fr63 */ 28) : 0)) \
+   : 0)
+
 \f
 /* Define the classes of registers for register constraints in the
    machine description.  Also define ranges of constants.
@@ -675,12 +1102,14 @@ enum reg_class
   T_REGS,
   MAC_REGS,
   FPUL_REGS,
+  SIBCALL_REGS,
   GENERAL_REGS,
   FP0_REGS,
   FP_REGS,
   DF_REGS,
   FPSCR_REGS,
   GENERAL_FP_REGS,
+  TARGET_REGS,
   ALL_REGS,
   LIM_REG_CLASSES
 };
@@ -696,12 +1125,14 @@ enum reg_class
   "T_REGS",            \
   "MAC_REGS",          \
   "FPUL_REGS",         \
+  "SIBCALL_REGS",      \
   "GENERAL_REGS",      \
   "FP0_REGS",          \
   "FP_REGS",           \
   "DF_REGS",           \
   "FPSCR_REGS",                \
   "GENERAL_FP_REGS",   \
+  "TARGET_REGS",       \
   "ALL_REGS",          \
 }
 
@@ -709,57 +1140,90 @@ enum reg_class
    This is an initializer for a vector of HARD_REG_SET
    of length N_REG_CLASSES.  */
 
-#define REG_CLASS_CONTENTS                             \
-{                                                      \
-  { 0x00000000, 0x00000000 }, /* NO_REGS       */      \
-  { 0x00000001, 0x00000000 }, /* R0_REGS       */      \
-  { 0x00020000, 0x00000000 }, /* PR_REGS       */      \
-  { 0x00040000, 0x00000000 }, /* T_REGS                */      \
-  { 0x00300000, 0x00000000 }, /* MAC_REGS      */      \
-  { 0x00400000, 0x00000000 }, /* FPUL_REGS     */      \
-  { 0x0081FFFF, 0x00000000 }, /* GENERAL_REGS  */      \
-  { 0x01000000, 0x00000000 }, /* FP0_REGS      */      \
-  { 0xFF000000, 0x000000FF }, /* FP_REGS       */      \
-  { 0xFF000000, 0x0000FFFF }, /* DF_REGS       */      \
-  { 0x00000000, 0x00010000 }, /* FPSCR_REGS    */      \
-  { 0xFF81FFFF, 0x0000FFFF }, /* GENERAL_FP_REGS */    \
-  { 0xFFFFFFFF, 0x0001FFFF }, /* ALL_REGS      */      \
-}
+#define REG_CLASS_CONTENTS                                             \
+{                                                                      \
+/* NO_REGS:  */                                                                \
+  { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 },      \
+/* R0_REGS:  */                                                                \
+  { 0x00000001, 0x00000000, 0x00000000, 0x00000000, 0x00000000 },      \
+/* PR_REGS:  */                                                                \
+  { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00040000 },      \
+/* T_REGS:  */                                                         \
+  { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00080000 },      \
+/* MAC_REGS:  */                                                       \
+  { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00300000 },      \
+/* FPUL_REGS:  */                                                      \
+  { 0x00000000, 0x00000000, 0x00000000, 0x00000001, 0x00400000 },      \
+/* SIBCALL_REGS: Initialized in CONDITIONAL_REGISTER_USAGE.  */        \
+  { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 },      \
+/* GENERAL_REGS:  */                                                   \
+  { 0xffffffff, 0xffffffff, 0x00000000, 0x00000000, 0x01020000 },      \
+/* FP0_REGS:  */                                                       \
+  { 0x00000000, 0x00000000, 0x00000001, 0x00000000, 0x00000000 },      \
+/* FP_REGS:  */                                                                \
+  { 0x00000000, 0x00000000, 0xffffffff, 0xffffffff, 0x00000000 },      \
+/* DF_REGS:  */                                                                \
+  { 0x00000000, 0x00000000, 0xffffffff, 0xffffffff, 0x0000ff00 },      \
+/* FPSCR_REGS:  */                                                     \
+  { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00800000 },      \
+/* GENERAL_FP_REGS:  */                                                        \
+  { 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0x0102ff00 },      \
+/* TARGET_REGS:  */                                                    \
+  { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x000000ff },      \
+/* ALL_REGS:  */                                                       \
+  { 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0x01ffffff },      \
+}                                                                       
 
 /* 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[];
+extern int regno_reg_class[FIRST_PSEUDO_REGISTER];
 #define REGNO_REG_CLASS(REGNO) regno_reg_class[(REGNO)]
 
 /* 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.  */
 
-#define SMALL_REGISTER_CLASSES 1
+#define SMALL_REGISTER_CLASSES (! TARGET_SHMEDIA)
 
 /* The order in which register should be allocated.  */
 /* Sometimes FP0_REGS becomes the preferred class of a floating point pseudo,
    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 \
-  { 25,26,27,28,29,30,31,24,32,33,34,35,36,37,38,39,   \
-    40,41,42,43,44,45,46,47,48,                                \
-    1,2,3,7,6,5,4,0,8,9,10,11,12,13,14,                        \
-    22,15,16,17,18,19,20,21,23 }
+  { 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, \
+   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, \
+   128,129,130,131,132,133,134,135, \
+   152 }
 
 /* The class value for index registers, and the one for base regs.  */
-#define INDEX_REG_CLASS  R0_REGS
+#define INDEX_REG_CLASS  (TARGET_SHMEDIA ? GENERAL_REGS : R0_REGS)
 #define BASE_REG_CLASS  GENERAL_REGS
 
 /* Get reg_class from a letter such as appears in the machine
    description.  */
-extern enum reg_class reg_class_from_letter[];
+extern const enum reg_class reg_class_from_letter[];
 
 #define REG_CLASS_FROM_LETTER(C) \
-   ( (C) >= 'a' && (C) <= 'z' ? reg_class_from_letter[(C)-'a'] : NO_REGS )
+   ( 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.
@@ -767,24 +1231,37 @@ extern enum reg_class reg_class_from_letter[];
    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  */
+       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.
@@ -800,34 +1277,55 @@ extern enum reg_class reg_class_from_letter[];
    In general this is just CLASS; but on some machines
    in some cases it is preferable to use a more restrictive class.  */
 
-#define PREFERRED_RELOAD_CLASS(X, CLASS) (CLASS)
+#define PREFERRED_RELOAD_CLASS(X, CLASS) \
+  ((CLASS) == NO_REGS && TARGET_SHMEDIA \
+   && (GET_CODE (X) == CONST_DOUBLE \
+       || GET_CODE (X) == SYMBOL_REF) \
+   ? GENERAL_REGS \
+   : (CLASS)) \
 
 #define SECONDARY_OUTPUT_RELOAD_CLASS(CLASS,MODE,X) \
   ((((((CLASS) == FP_REGS || (CLASS) == FP0_REGS                       \
        || (CLASS) == DF_REGS)                                          \
-      && (GET_CODE (X) == REG && REGNO (X) <= AP_REG))                 \
+      && (GET_CODE (X) == REG && GENERAL_OR_AP_REGISTER_P (REGNO (X))))        \
      || (((CLASS) == GENERAL_REGS || (CLASS) == R0_REGS)               \
         && GET_CODE (X) == REG                                         \
-        && REGNO (X) >= FIRST_FP_REG && REGNO (X) <= LAST_FP_REG))     \
+        && FP_REGISTER_P (REGNO (X))))                                 \
+    && ! TARGET_SHMEDIA                                                        \
     && MODE == SFmode)                                                 \
    ? FPUL_REGS                                                         \
    : ((CLASS) == FPUL_REGS                                             \
       && (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)))                              \
+   ? 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 && REGNO (X) > 15                         \
+      && GET_CODE (X) == REG && ! GENERAL_REGISTER_P (REGNO (X))       \
       && (CLASS) != REGNO_REG_CLASS (REGNO (X)))                       \
    ? GENERAL_REGS : NO_REGS)
 
 #define SECONDARY_INPUT_RELOAD_CLASS(CLASS,MODE,X)  \
   ((((CLASS) == FP_REGS || (CLASS) == FP0_REGS || (CLASS) == DF_REGS)  \
+    && ! TARGET_SHMEDIA                                                        \
     && immediate_operand ((X), (MODE))                                 \
     && ! ((fp_zero_operand (X) || fp_one_operand (X))                  \
          && (MODE) == SFmode && fldi_ok ()))                           \
    ? R0_REGS                                                           \
+   : (CLASS == FPUL_REGS                                               \
+      && ((GET_CODE (X) == REG                                         \
+          && (REGNO (X) == MACL_REG || REGNO (X) == MACH_REG           \
+             || REGNO (X) == T_REG))))                                 \
+   ? GENERAL_REGS                                                      \
    : CLASS == FPUL_REGS && immediate_operand ((X), (MODE))             \
    ? (GET_CODE (X) == CONST_INT && CONST_OK_FOR_I (INTVAL (X))         \
       ? GENERAL_REGS                                                   \
@@ -861,17 +1359,17 @@ extern enum reg_class reg_class_from_letter[];
    These macros are used only in other macro definitions below.  */
 
 #define NPARM_REGS(MODE) \
-  (TARGET_SH3E && (MODE) == SFmode \
-   ? 8 \
+  (TARGET_FPU_ANY && (MODE) == SFmode \
+   ? (TARGET_SH5 ? 12 : 8) \
    : TARGET_SH4 && (GET_MODE_CLASS (MODE) == MODE_FLOAT \
                    || GET_MODE_CLASS (MODE) == MODE_COMPLEX_FLOAT) \
-   ? 8 \
-   : 4)
+   ? (TARGET_SH5 ? 12 : 8) \
+   : (TARGET_SH5 ? 8 : 4))
 
-#define FIRST_PARM_REG 4
-#define FIRST_RET_REG  0
+#define FIRST_PARM_REG (FIRST_GENERAL_REG + (TARGET_SH5 ? 2 : 4))
+#define FIRST_RET_REG  (FIRST_GENERAL_REG + (TARGET_SH5 ? 2 : 0))
 
-#define FIRST_FP_PARM_REG (FIRST_FP_REG + 4)
+#define FIRST_FP_PARM_REG (FIRST_FP_REG + (TARGET_SH5 ? 0 : 4))
 #define FIRST_FP_RET_REG FIRST_FP_REG
 
 /* Define this if pushing a word on the stack
@@ -911,6 +1409,13 @@ extern enum reg_class reg_class_from_letter[];
    on the stack.  */
 #define RETURN_POPS_ARGS(FUNDECL,FUNTYPE,SIZE)  0
 
+/* Value is the number of bytes of arguments automatically popped when
+   calling a subroutine.
+   CUM is the accumulated argument list.
+
+   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.  */
@@ -919,14 +1424,14 @@ extern enum reg_class reg_class_from_letter[];
   ((TYPE) != 0                                         \
    && (TREE_CODE (TYPE_SIZE (TYPE)) != INTEGER_CST     \
        || TREE_ADDRESSABLE (TYPE)))
-/* Some subroutine macros specific to this machine. */
+/* Some subroutine macros specific to this machine.  */
 
 #define BASE_RETURN_VALUE_REG(MODE) \
-  ((TARGET_SH3E && ((MODE) == SFmode))                 \
+  ((TARGET_FPU_ANY && ((MODE) == SFmode))                      \
    ? FIRST_FP_RET_REG                                  \
-   : TARGET_SH3E && (MODE) == SCmode           \
+   : TARGET_FPU_ANY && (MODE) == SCmode                \
    ? FIRST_FP_RET_REG                                  \
-   : (TARGET_SH4                                       \
+   : (TARGET_FPU_DOUBLE                                        \
       && ((MODE) == DFmode || (MODE) == SFmode         \
          || (MODE) == DCmode || (MODE) == SCmode ))    \
    ? FIRST_FP_RET_REG                                  \
@@ -959,7 +1464,7 @@ extern enum reg_class reg_class_from_letter[];
                 || TREE_CODE (VALTYPE) == CHAR_TYPE                    \
                 || TREE_CODE (VALTYPE) == REAL_TYPE                    \
                 || TREE_CODE (VALTYPE) == OFFSET_TYPE))                \
-           ? SImode : TYPE_MODE (VALTYPE)),                            \
+           ? (TARGET_SHMEDIA ? DImode : SImode) : TYPE_MODE (VALTYPE)), \
           BASE_RETURN_VALUE_REG (TYPE_MODE (VALTYPE)))
      
 /* Define how to find the value returned by a library function
@@ -967,15 +1472,18 @@ extern enum reg_class reg_class_from_letter[];
 #define LIBCALL_VALUE(MODE) \
   gen_rtx_REG ((MODE), BASE_RETURN_VALUE_REG (MODE));
 
-/* 1 if N is a possible register number for a function value. */
+/* 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_SH3E && (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.  */
 #define FUNCTION_ARG_REGNO_P(REGNO) \
-  (((REGNO) >= FIRST_PARM_REG && (REGNO) < (FIRST_PARM_REG + 4))        \
-   || (TARGET_SH3E                                                      \
-       && (REGNO) >= FIRST_FP_PARM_REG && (REGNO) < (FIRST_FP_PARM_REG + 8)))
+  (((REGNO) >= FIRST_PARM_REG && (REGNO) < (FIRST_PARM_REG             \
+                                           + NPARM_REGS (SImode)))     \
+   || (TARGET_FPU_ANY                                                   \
+       && (REGNO) >= FIRST_FP_PARM_REG && (REGNO) < (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
@@ -992,15 +1500,112 @@ 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.  */
+    int prototype_p;
+  /* The number of an odd floating-point register, that should be used
+     for the next argument of type float.  */
+    int free_single_fp_reg;
+  /* Whether we're processing an outgoing function call.  */
+    int outgoing;
+  /* The number of general-purpose registers that should have been
+     used to pass partial arguments, that are passed totally on the
+     stack.  On SHcompact, a call trampoline will pop them off the
+     stack before calling the actual function, and, if the called
+     function is implemented in SHcompact mode, the incoming arguments
+     decoder will push such arguments back onto the stack.  For
+     incoming arguments, STACK_REGS also takes into account other
+     arguments passed by reference, that the decoder will also push
+     onto the stack.  */
+    int stack_regs;
+  /* The number of general-purpose registers that should have been
+     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.  */
+    int byref;
+
+  /* call_cookie is a bitmask used by call expanders, as well as
+     function prologue and epilogues, to allow SHcompact to comply
+     with the SH5 32-bit ABI, that requires 64-bit registers to be
+     used even though only the lower 32-bit half is visible in
+     SHcompact mode.  The strategy is to call SHmedia trampolines.
+
+     The alternatives for each of the argument-passing registers are
+     (a) leave it unchanged; (b) pop it off the stack; (c) load its
+     contents from the address in it; (d) add 8 to it, storing the
+     result in the next register, then (c); (e) copy it from some
+     floating-point register,
+
+     Regarding copies from floating-point registers, r2 may only be
+     copied from dr0.  r3 may be copied from dr0 or dr2.  r4 maybe
+     copied from dr0, dr2 or dr4.  r5 maybe copied from dr0, dr2,
+     dr4 or dr6.  r6 may be copied from dr0, dr2, dr4, dr6 or dr8.
+     r7 through to r9 may be copied from dr0, dr2, dr4, dr8, dr8 or
+     dr10.
+
+     The bit mask is structured as follows:
+
+     - 1 bit to tell whether to set up a return trampoline.
+
+     - 3 bits to count the number consecutive registers to pop off the
+       stack.
+
+     - 4 bits for each of r9, r8, r7 and r6.
+
+     - 3 bits for each of r5, r4, r3 and r2.
+
+     - 3 bits set to 0 (the most significant ones)
+
+        3           2            1           0
+       1098 7654 3210 9876 5432 1098 7654 3210
+       FLPF LPFL PFLP FFLP FFLP FFLP FFLP SSST
+       2223 3344 4555 6666 7777 8888 9999 SSS-
+
+     - If F is set, the register must be copied from an FP register,
+       whose number is encoded in the remaining bits.
+
+     - Else, if L is set, the register must be loaded from the address
+       contained in it.  If the P bit is *not* set, the address of the
+       following dword should be computed first, and stored in the
+       following register.
+
+     - Else, if P is set, the register alone should be popped off the
+       stack.
+
+     - After all this processing, the number of registers represented
+       in SSS will be popped off the stack.  This is an optimization
+       for pushing/popping consecutive registers, typically used for
+       varargs and large arguments partially passed in registers.
+
+     - If T is set, a return trampoline will be set up for 64-bit
+     return values to be split into 2 32-bit registers.  */
+#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
+#define CALL_COOKIE_STACKSEQ(VAL) ((VAL) << CALL_COOKIE_STACKSEQ_SHIFT)
+#define CALL_COOKIE_STACKSEQ_GET(COOKIE) \
+  (((COOKIE) >> CALL_COOKIE_STACKSEQ_SHIFT) & 7)
+#define CALL_COOKIE_INT_REG_SHIFT(REG) \
+  (4 * (7 - (REG)) + (((REG) <= 2) ? ((REG) - 2) : 1) + 3)
+#define CALL_COOKIE_INT_REG(REG, VAL) \
+  ((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
 
 #define GET_SH_ARG_CLASS(MODE) \
-  ((TARGET_SH3E && (MODE) == SFmode) \
+  ((TARGET_FPU_ANY && (MODE) == SFmode) \
    ? SH_ARG_FLOAT \
-   : TARGET_SH4 && (GET_MODE_CLASS (MODE) == MODE_FLOAT \
-                   || GET_MODE_CLASS (MODE) == MODE_COMPLEX_FLOAT) \
+   /* There's no mention of complex float types in the SH5 ABI, so we
+      should presumably handle them as aggregate types.  */ \
+   : TARGET_SH5 && GET_MODE_CLASS (MODE) == MODE_COMPLEX_FLOAT \
+   ? SH_ARG_INT \
+   : TARGET_FPU_DOUBLE && (GET_MODE_CLASS (MODE) == MODE_FLOAT \
+                          || GET_MODE_CLASS (MODE) == MODE_COMPLEX_FLOAT) \
    ? SH_ARG_FLOAT : SH_ARG_INT)
 
 #define ROUND_ADVANCE(SIZE) \
@@ -1037,7 +1642,48 @@ struct sh_args {
     (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_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.
@@ -1047,6 +1693,113 @@ struct sh_args {
 #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); \
+            /* N.B. We want this also for outgoing.   */\
+            (CUM).stack_regs += numregs;               \
+          }                                            \
+        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))                       \
@@ -1055,7 +1808,7 @@ struct sh_args {
          : ROUND_ADVANCE (GET_MODE_SIZE (MODE)))))
 
 /* Return boolean indicating arg of mode MODE will be passed in a reg.
-   This macro is only used in this file. */
+   This macro is only used in this file.  */
 
 #define PASS_IN_REG_P(CUM, MODE, TYPE) \
   (((TYPE) == 0 \
@@ -1091,16 +1844,135 @@ struct sh_args {
    its data type forbids.  */
 
 #define FUNCTION_ARG(CUM, MODE, TYPE, NAMED) \
-  ((PASS_IN_REG_P ((CUM), (MODE), (TYPE))                              \
-    && ((NAMED)                                                                \
-       || (! TARGET_HITACHI && (TARGET_SH3E || ! current_function_varargs)))) \
+  ((! TARGET_SH5 \
+    && PASS_IN_REG_P ((CUM), (MODE), (TYPE))                           \
+    && ((NAMED) || !TARGET_HITACHI))                                   \
    ? 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)
 
-#define PRETEND_OUTGOING_VARARGS_NAMED (! TARGET_HITACHI)
+/* 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)
+
+/* 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
+   significant end.  This means that passing it by reference wouldn't
+   pad properly on a big-endian machine.  In this particular case, we
+   pass this argument on the stack, in a way that the call trampoline
+   will load its value into the appropriate register.  */
+#define SHCOMPACT_FORCE_ON_STACK(MODE,TYPE) \
+  ((MODE) == BLKmode \
+   && TARGET_SHCOMPACT \
+   && ! TARGET_LITTLE_ENDIAN \
+   && int_size_in_bytes (TYPE) > 4 \
+   && int_size_in_bytes (TYPE) < 8)
+
+/* Minimum alignment for an argument to be passed by callee-copy
+   reference.  We need such arguments to be aligned to 8 byte
+   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
+   general-purpose registers, list the FP register first.  */
+#define SH5_PROTOTYPELESS_FLOAT_ARG(CUM,MODE) \
+  (gen_rtx_PARALLEL                                                    \
+   ((MODE),                                                            \
+    gen_rtvec (2,                                                      \
+              gen_rtx_EXPR_LIST                                        \
+              (VOIDmode,                                               \
+               ((CUM).arg_count[(int) SH_ARG_INT] < NPARM_REGS (SImode) \
+                ? gen_rtx_REG ((MODE), FIRST_FP_PARM_REG               \
+                               + (CUM).arg_count[(int) SH_ARG_FLOAT])  \
+                : NULL_RTX),                                           \
+               const0_rtx),                                            \
+              gen_rtx_EXPR_LIST                                        \
+              (VOIDmode,                                               \
+               ((CUM).arg_count[(int) SH_ARG_INT] < NPARM_REGS (SImode) \
+                ? gen_rtx_REG ((MODE), FIRST_PARM_REG                  \
+                               + (CUM).arg_count[(int) SH_ARG_INT])    \
+                : gen_rtx_REG ((MODE), FIRST_FP_PARM_REG               \
+                               + (CUM).arg_count[(int) SH_ARG_FLOAT])), \
+               const0_rtx))))
+
+/* The SH5 ABI requires regular registers or stack slots to be
+   reserved for floating-point arguments.  Registers are taken care of
+   in FUNCTION_ARG_ADVANCE, but stack slots must be reserved here.
+   Unfortunately, there's no way to just reserve a stack slot, so
+   we'll end up needlessly storing a copy of the argument in the
+   stack.  For incoming arguments, however, the PARALLEL will be
+   optimized to the register-only form, and the value in the stack
+   slot won't be used at all.  */
+#define SH5_PROTOTYPED_FLOAT_ARG(CUM,MODE,REG) \
+  ((CUM).arg_count[(int) SH_ARG_INT] < NPARM_REGS (SImode)             \
+   ? gen_rtx_REG ((MODE), (REG))                                       \
+   : gen_rtx_PARALLEL ((MODE),                                         \
+                      gen_rtvec (2,                                    \
+                                 gen_rtx_EXPR_LIST                     \
+                                 (VOIDmode, NULL_RTX,                  \
+                                  const0_rtx),                         \
+                                 gen_rtx_EXPR_LIST                     \
+                                 (VOIDmode, gen_rtx_REG ((MODE),       \
+                                                         (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.
@@ -1109,7 +1981,8 @@ struct sh_args {
    We sometimes split args.  */
 
 #define FUNCTION_ARG_PARTIAL_NREGS(CUM, MODE, TYPE, NAMED) \
-  ((PASS_IN_REG_P ((CUM), (MODE), (TYPE))                      \
+  ((! TARGET_SH5 \
+    && PASS_IN_REG_P ((CUM), (MODE), (TYPE))                   \
     && ! TARGET_SH4                                            \
     && (ROUND_REG ((CUM), (MODE))                              \
        + ((MODE) != BLKmode                                    \
@@ -1117,23 +1990,36 @@ struct sh_args {
           : 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)
 
-extern int current_function_anonymous_args;
+#define SH5_WOULD_BE_PARTIAL_NREGS(CUM, MODE, TYPE, NAMED) \
+  (TARGET_SH5 && (MODE) == BLKmode                             \
+   && ((CUM).arg_count[(int) SH_ARG_INT]                       \
+       + (int_size_in_bytes (TYPE) + 7) / 8) > NPARM_REGS (SImode))
 
 /* Perform any needed actions needed for a function that is receiving a
    variable number of arguments.  */
 
-#define SETUP_INCOMING_VARARGS(ASF, MODE, TYPE, PAS, ST) \
-  current_function_anonymous_args = 1;
+/* 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_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)
+#define EXPAND_BUILTIN_VA_START(valist, nextarg) \
+  sh_va_start (valist, nextarg)
 
 /* Implement `va_arg'.  */
 #define EXPAND_BUILTIN_VA_ARG(valist, type) \
@@ -1165,22 +2051,17 @@ extern int current_function_anonymous_args;
 
 #define EXIT_IGNORE_STACK 1
 
-/* Generate the assembly code for function exit
-   Just dump out any accumulated constant table.  */
-
-#define FUNCTION_EPILOGUE(STREAM, SIZE)  function_epilogue ((STREAM), (SIZE))
-
 /* 
    On the SH, the trampoline looks like
-   2 0002 DD02                 mov.l   l2,r13
+   2 0002 D202                 mov.l   l2,r2
    1 0000 D301                 mov.l   l1,r3
-   3 0004 4D2B                 jmp     @r13
+   3 0004 422B                 jmp     @r2
    4 0006 0009                 nop
-   5 0008 00000000     l1:     .long   function
-   6 000c 00000000     l2:     .long   area  */
+   5 0008 00000000     l1:     .long   area
+   6 000c 00000000     l2:     .long   function  */
 
 /* Length in units of the trampoline for entering a nested function.  */
-#define TRAMPOLINE_SIZE  16
+#define TRAMPOLINE_SIZE  (TARGET_SHMEDIA64 ? 40 : TARGET_SH5 ? 32 : 16)
 
 /* Alignment required for a trampoline in bits .  */
 #define TRAMPOLINE_ALIGNMENT \
@@ -1190,19 +2071,58 @@ extern int current_function_anonymous_args;
    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)                      \
+#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 (TARGET_LITTLE_ENDIAN ? 0xd301dd02 : 0xdd02d301));\
+                  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 ? 0x00094d2b : 0x4d2b0009));\
+                 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)                                                  \
-    emit_insn (gen_ic_invalidate_line (TRAMP));                                \
-}
+    {                                                                  \
+      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)
+
+/* 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),  \
+                                  gen_reg_rtx (Pmode), 0,              \
+                                  OPTAB_LIB_WIDEN);                    \
+} while (0)
 
 /* A C expression whose value is RTL representing the value of the return
    address for the frame COUNT steps up from the current frame.
@@ -1211,24 +2131,32 @@ extern int current_function_anonymous_args;
 
 #define RETURN_ADDR_RTX(COUNT, FRAME)  \
   (((COUNT) == 0)                              \
-   ? gen_rtx_MEM (Pmode, gen_rtx_REG (Pmode, RETURN_ADDRESS_POINTER_REGNUM)) \
+   ? get_hard_reg_initial_val (Pmode, TARGET_SHMEDIA ? PR_MEDIA_REG : PR_REG) \
    : (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
 /* Generate necessary RTL for __builtin_saveregs().  */
 #define EXPAND_BUILTIN_SAVEREGS() sh_builtin_saveregs ()
 \f
 /* Addressing modes, and classification of registers for them.  */
-#define HAVE_POST_INCREMENT  1
+#define HAVE_POST_INCREMENT  TARGET_SH1
 /*#define HAVE_PRE_INCREMENT   1*/
 /*#define HAVE_POST_DECREMENT  1*/
-#define HAVE_PRE_DECREMENT   1
+#define HAVE_PRE_DECREMENT   TARGET_SH1
 
 #define USE_LOAD_POST_INCREMENT(mode)    ((mode == SImode || mode == DImode) \
-                                           ? 0 : 1)
+                                           ? 0 : TARGET_SH1)
 #define USE_LOAD_PRE_DECREMENT(mode)     0
 #define USE_STORE_POST_INCREMENT(mode)   0
 #define USE_STORE_PRE_DECREMENT(mode)    ((mode == SImode || mode == DImode) \
-                                           ? 0 : 1)
+                                           ? 0 : TARGET_SH1)
 
 #define MOVE_BY_PIECES_P(SIZE, ALIGN)  (move_by_pieces_ninsns (SIZE, ALIGN) \
                                         < (TARGET_SMALLCODE ? 2 :           \
@@ -1243,9 +2171,13 @@ extern int current_function_anonymous_args;
    has been allocated, which happens in local-alloc.c.  */
 
 #define REGNO_OK_FOR_BASE_P(REGNO) \
-  ((REGNO) < PR_REG || (unsigned) reg_renumber[(REGNO)] < PR_REG)
+  (GENERAL_OR_AP_REGISTER_P (REGNO) \
+   || GENERAL_OR_AP_REGISTER_P (reg_renumber[(REGNO)]))
 #define REGNO_OK_FOR_INDEX_P(REGNO) \
-  ((REGNO) == 0 || (unsigned) reg_renumber[(REGNO)] == 0)
+  (TARGET_SHMEDIA \
+   ? (GENERAL_REGISTER_P (REGNO) \
+      || GENERAL_REGISTER_P ((unsigned) reg_renumber[(REGNO)])) \
+   : (REGNO) == R0_REG || (unsigned) reg_renumber[(REGNO)] == R0_REG)
 
 /* Maximum number of registers that can appear in a valid memory
    address.  */
@@ -1259,9 +2191,14 @@ extern int current_function_anonymous_args;
 /* Nonzero if the constant value X is a legitimate general operand.  */
 
 #define LEGITIMATE_CONSTANT_P(X) \
-  (GET_CODE (X) != CONST_DOUBLE                                                \
-   || GET_MODE (X) == DFmode || GET_MODE (X) == SFmode                 \
-   || (TARGET_SH3E && (fp_zero_operand (X) || fp_one_operand (X))))
+  (TARGET_SHMEDIA                                                      \
+   ? (GET_MODE (X) != DFmode                                           \
+      || (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)))))
 
 /* The macros REG_OK_FOR..._P assume that the arg is a REG rtx
    and check its validity for a certain class.
@@ -1275,17 +2212,19 @@ extern int current_function_anonymous_args;
 /* Nonzero if X is a hard reg that can be used as a base reg
    or if it is a pseudo reg.  */
 #define REG_OK_FOR_BASE_P(X) \
-  (REGNO (X) <= 16 || REGNO (X) >= FIRST_PSEUDO_REGISTER)
+  (GENERAL_OR_AP_REGISTER_P (REGNO (X)) || REGNO (X) >= FIRST_PSEUDO_REGISTER)
 
 /* Nonzero if X is a hard reg that can be used as an index
    or if it is a pseudo reg.  */
 #define REG_OK_FOR_INDEX_P(X) \
-  (REGNO (X) == 0 || REGNO (X) >= FIRST_PSEUDO_REGISTER)
+  ((TARGET_SHMEDIA ? GENERAL_REGISTER_P (REGNO (X)) \
+    : REGNO (X) == R0_REG) || REGNO (X) >= FIRST_PSEUDO_REGISTER)
 
 /* Nonzero if X/OFFSET is a hard reg that can be used as an index
    or if X is a pseudo reg.  */
 #define SUBREG_OK_FOR_INDEX_P(X, OFFSET) \
-  ((REGNO (X) == 0 && OFFSET == 0) || REGNO (X) >= FIRST_PSEUDO_REGISTER)
+  ((TARGET_SHMEDIA ? GENERAL_REGISTER_P (REGNO (X)) \
+    : REGNO (X) == R0_REG && OFFSET == 0) || REGNO (X) >= FIRST_PSEUDO_REGISTER)
 
 #else
 
@@ -1312,8 +2251,90 @@ extern int current_function_anonymous_args;
           && 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)))
+
+/* 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))
+
+#define GOT_ENTRY_P(OP) \
+  (GET_CODE (OP) == CONST && GET_CODE (XEXP ((OP), 0)) == UNSPEC \
+   && XINT (XEXP ((OP), 0), 1) == UNSPEC_GOT)
+
+#define GOTPLT_ENTRY_P(OP) \
+  (GET_CODE (OP) == CONST && GET_CODE (XEXP ((OP), 0)) == UNSPEC \
+   && XINT (XEXP ((OP), 0), 1) == UNSPEC_GOTPLT)
+
+#define GOTOFF_P(OP) \
+  (GET_CODE (OP) == CONST && GET_CODE (XEXP ((OP), 0)) == UNSPEC \
+   && XINT (XEXP ((OP), 0), 1) == UNSPEC_GOTOFF)
+
+#define PIC_ADDR_P(OP) \
+  (GET_CODE (OP) == CONST && GET_CODE (XEXP ((OP), 0)) == UNSPEC \
+   && XINT (XEXP ((OP), 0), 1) == UNSPEC_PIC)
+
+#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)) == PLUS \
+       && (GET_CODE (XEXP (XEXP ((OP), 0), 0)) == SYMBOL_REF \
+          || DATALABEL_REF_P (XEXP (XEXP ((OP), 0), 0))) \
+       && GET_CODE (XEXP (XEXP ((OP), 0), 1)) == CONST_INT))
+
+#define PIC_REFERENCE_P(OP) \
+  (GOT_ENTRY_P (OP) || GOTPLT_ENTRY_P (OP) \
+   || 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))
+
+/* A zero in any shape or form.  */
+#define EXTRA_CONSTRAINT_U(OP) \
+  ((OP) == const0_rtx \
+   || (GET_CODE (OP) == SUBREG && VECTOR_MODE_SUPPORTED_P(GET_MODE (OP)) \
+       && SUBREG_REG (OP) == const0_rtx && SUBREG_BYTE (OP) == 0) \
+   || GET_CODE (OP) == CONST_VECTOR && zero_vec_operand ((OP), VOIDmode))
+
+/* Any vector constant we can handle.  */
+#define EXTRA_CONSTRAINT_W(OP) \
+  (GET_CODE (OP) == CONST_VECTOR \
+   && (sh_rep_vec ((OP), VOIDmode) \
+       || (HOST_BITS_PER_WIDE_INT >= 64 \
+          ? sh_const_vec ((OP), VOIDmode) \
+          : sh_1el_vec ((OP), VOIDmode))))
+
 #define EXTRA_CONSTRAINT(OP, C)                \
   ((C) == 'Q' ? EXTRA_CONSTRAINT_Q (OP)        \
+   : (C) == 'S' ? EXTRA_CONSTRAINT_S (OP) \
+   : (C) == 'T' ? EXTRA_CONSTRAINT_T (OP) \
+   : (C) == 'U' ? EXTRA_CONSTRAINT_U (OP) \
+   : (C) == 'W' ? EXTRA_CONSTRAINT_W (OP) \
    : 0)
 \f
 /* GO_IF_LEGITIMATE_ADDRESS recognizes an RTL expression
@@ -1342,7 +2363,7 @@ extern int current_function_anonymous_args;
   ((GET_CODE (X) == REG && REG_OK_FOR_INDEX_P (X))     \
    || (GET_CODE (X) == SUBREG                          \
        && GET_CODE (SUBREG_REG (X)) == REG             \
-       && SUBREG_OK_FOR_INDEX_P (SUBREG_REG (X), SUBREG_WORD (X))))
+       && SUBREG_OK_FOR_INDEX_P (SUBREG_REG (X), SUBREG_BYTE (X))))
 
 /* Jump to LABEL if X is a valid address RTX.  This must also take
    REG_OK_STRICT into account when deciding about valid registers, but it uses
@@ -1370,6 +2391,16 @@ extern int current_function_anonymous_args;
   do {                                                                 \
     if (GET_CODE (OP) == CONST_INT)                                    \
       {                                                                        \
+       if (TARGET_SHMEDIA)                                             \
+         {                                                             \
+           int MODE_SIZE = GET_MODE_SIZE (MODE);                       \
+           if (! (INTVAL (OP) & (MODE_SIZE - 1))                       \
+               && INTVAL (OP) >= -512 * MODE_SIZE                      \
+               && INTVAL (OP) < 512 * MODE_SIZE)                       \
+             goto LABEL;                                               \
+           else                                                        \
+             break;                                                    \
+         }                                                             \
        if (MODE_DISP_OK_4 ((OP), (MODE)))  goto LABEL;                 \
        if (MODE_DISP_OK_8 ((OP), (MODE)))  goto LABEL;                 \
       }                                                                        \
@@ -1380,6 +2411,7 @@ extern int current_function_anonymous_args;
   if (BASE_REGISTER_RTX_P (X))                                         \
     goto LABEL;                                                                \
   else if ((GET_CODE (X) == POST_INC || GET_CODE (X) == PRE_DEC)       \
+          && ! TARGET_SHMEDIA                                          \
           && BASE_REGISTER_RTX_P (XEXP ((X), 0)))                      \
     goto LABEL;                                                                \
   else if (GET_CODE (X) == PLUS                                                \
@@ -1390,6 +2422,7 @@ extern int current_function_anonymous_args;
       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 (BASE_REGISTER_RTX_P (xop1) && INDEX_REGISTER_RTX_P (xop0))\
@@ -1426,6 +2459,7 @@ extern int current_function_anonymous_args;
          || GET_MODE_SIZE (MODE) == 8)                         \
       && GET_CODE (XEXP ((X), 1)) == CONST_INT                 \
       && BASE_REGISTER_RTX_P (XEXP ((X), 0))                   \
+      && ! TARGET_SHMEDIA                                      \
       && ! (TARGET_SH4 && (MODE) == DFmode)                    \
       && ! (TARGET_SH3E && (MODE) == SFmode))                  \
     {                                                          \
@@ -1474,6 +2508,7 @@ extern int current_function_anonymous_args;
       && (GET_MODE_SIZE (MODE) == 4 || GET_MODE_SIZE (MODE) == 8)      \
       && GET_CODE (XEXP (X, 1)) == CONST_INT                           \
       && BASE_REGISTER_RTX_P (XEXP (X, 0))                             \
+      && ! TARGET_SHMEDIA                                              \
       && ! (TARGET_SH4 && (MODE) == DFmode)                            \
       && ! ((MODE) == PSImode && (TYPE) == RELOAD_FOR_INPUT_ADDRESS))  \
     {                                                                  \
@@ -1484,7 +2519,7 @@ extern int current_function_anonymous_args;
       if (TARGET_SH3E && MODE == SFmode)                               \
        {                                                               \
          X = copy_rtx (X);                                             \
-         push_reload (index_rtx, NULL_RTX, &XEXP (X, 1), NULL_PTR,     \
+         push_reload (index_rtx, NULL_RTX, &XEXP (X, 1), NULL,         \
                       INDEX_REG_CLASS, Pmode, VOIDmode, 0, 0, (OPNUM), \
                       (TYPE));                                         \
          goto WIN;                                                     \
@@ -1506,7 +2541,7 @@ extern int current_function_anonymous_args;
          sum = gen_rtx (PLUS, Pmode, XEXP (X, 0),                      \
                         GEN_INT (offset_base));                        \
          X = gen_rtx (PLUS, Pmode, sum, GEN_INT (offset - offset_base));\
-         push_reload (sum, NULL_RTX, &XEXP (X, 0), NULL_PTR,   \
+         push_reload (sum, NULL_RTX, &XEXP (X, 0), NULL,               \
                       BASE_REG_CLASS, Pmode, VOIDmode, 0, 0, (OPNUM),  \
                       (TYPE));                                         \
          goto WIN;                                                     \
@@ -1519,12 +2554,13 @@ extern int current_function_anonymous_args;
           && GET_CODE (XEXP (XEXP (X, 0), 1)) == CONST_INT             \
           && BASE_REGISTER_RTX_P (XEXP (XEXP (X, 0), 0))               \
           && GET_CODE (XEXP (X, 1)) == CONST_INT                       \
+          && ! TARGET_SHMEDIA                                          \
           && ! (TARGET_SH3E && MODE == SFmode))                        \
     {                                                                  \
       /* Because this address is so complex, we know it must have      \
         been created by LEGITIMIZE_RELOAD_ADDRESS before; thus,        \
         it is already unshared, and needs no further unsharing.  */    \
-      push_reload (XEXP ((X), 0), NULL_RTX, &XEXP ((X), 0), NULL_PTR,  \
+      push_reload (XEXP ((X), 0), NULL_RTX, &XEXP ((X), 0), NULL,      \
                   BASE_REG_CLASS, Pmode, VOIDmode, 0, 0, (OPNUM), (TYPE));\
       goto WIN;                                                                \
     }                                                                  \
@@ -1559,14 +2595,11 @@ extern int current_function_anonymous_args;
 /* Define as C expression which evaluates to nonzero if the tablejump
    instruction expects the table to contain offsets from the address of the
    table.
-   Do not define this if the table should contain absolute addresses. */
+   Do not define this if the table should contain absolute addresses.  */
 #define CASE_VECTOR_PC_RELATIVE 1
 
-/* Specify the tree operation to be used to convert reals to integers.  */
-#define IMPLICIT_FIX_EXPR  FIX_ROUND_EXPR
-
-/* This is the kind of divide that is easiest to do in the general case.  */
-#define EASY_DIV_EXPR  TRUNC_DIV_EXPR
+/* 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
    floating point types equivalent to `float'.  */
@@ -1576,21 +2609,30 @@ extern int current_function_anonymous_args;
 #define DEFAULT_SIGNED_CHAR  1
 
 /* The type of size_t unsigned int.  */
-#define SIZE_TYPE "unsigned int"
+#define SIZE_TYPE (TARGET_SH5 ? "long unsigned int" : "unsigned int")
+
+#undef  PTRDIFF_TYPE
+#define PTRDIFF_TYPE (TARGET_SH5 ? "long int" : "int")
 
 #define WCHAR_TYPE "short unsigned int"
 #define WCHAR_TYPE_SIZE 16
 
+#define SH_ELF_WCHAR_TYPE "long int"
+
 /* Don't cse the address of the function being compiled.  */
 /*#define NO_RECURSIVE_FUNCTION_CSE 1*/
 
 /* Max number of bytes we can move from memory to memory
    in one reasonably fast instruction.  */
-#define MOVE_MAX 4
+#define MOVE_MAX (TARGET_SHMEDIA ? 8 : 4)
+
+/* Maximum value possibly taken by MOVE_MAX.  Must be defined whenever
+   MOVE_MAX is not a compile-time constant.  */
+#define MAX_MOVE_MAX 8
 
 /* Max number of bytes we want move_by_pieces to be able to copy
    efficiently.  */
-#define MOVE_MAX_PIECES (TARGET_SH4 ? 8 : 4)
+#define MOVE_MAX_PIECES (TARGET_SH4 || TARGET_SHMEDIA ? 8 : 4)
 
 /* Define if operations between registers always perform the operation
    on the full register even if a narrower mode is specified.  */
@@ -1605,20 +2647,9 @@ extern int current_function_anonymous_args;
 /* Define if loading short immediate values into registers sign extends.  */
 #define SHORT_IMMEDIATES_SIGN_EXTEND
 
-/* Define this if zero-extension is slow (more than one real instruction).
-   On the SH, it's only one instruction.  */
-/* #define SLOW_ZERO_EXTEND */
-
 /* Nonzero if access to memory by bytes is no faster than for words.  */
 #define SLOW_BYTE_ACCESS 1
 
-/* Force sizeof(bool) == 1 to maintain binary compatibility; otherwise, the
-   change in SLOW_BYTE_ACCESS would have changed it to 4.  */
-
-/* This used to use INT_TYPE_SIZE / CHAR_TYPE_SIZE, but these are
-   not guaranteed to be defined when BOOL_TYPE_SIZE is used.  */
-#define BOOL_TYPE_SIZE (flag_new_abi ? BITS_PER_WORD : BITS_PER_UNIT)
-
 /* 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.  */
 
@@ -1648,13 +2679,32 @@ extern int current_function_anonymous_args;
 #define PROMOTE_PROTOTYPES 1
 
 /* The machine modes of pointers and functions.  */
-#define Pmode  SImode
+#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 (INTVAL (RTX) == 0)                  \
+         return 0;                             \
+       if ((OUTER_CODE) == AND && and_operand ((RTX), DImode)) \
+         return 0;                             \
+       if (((OUTER_CODE) == IOR || (OUTER_CODE) == XOR \
+            || (OUTER_CODE) == PLUS) \
+           && CONST_OK_FOR_P (INTVAL (RTX)))   \
+         return 0;                             \
+       if (CONST_OK_FOR_J (INTVAL (RTX)))      \
+          return COSTS_N_INSNS ((OUTER_CODE) != SET);          \
+       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) \
@@ -1665,8 +2715,15 @@ extern int current_function_anonymous_args;
   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)                 \
@@ -1719,36 +2776,28 @@ extern int current_function_anonymous_args;
 
 \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.  */
+/* The prefix used to mark SYMBOL_REFs that refer to data symbols.  */
+#define SH_DATALABEL_ENCODING "#"
 
-#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));                                    \
-      }                                                                        \
-  }                                                                    \
-while (0)
+/* 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])
 
-#define FINALIZE_PIC                                                   \
-  current_function_uses_pic_offset_table |= profile_flag | profile_block_flag
+/* 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)
 
 /* 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)                      \
+        && (GET_CODE (X) != SYMBOL_REF                         \
+            || ! CONSTANT_POOL_ADDRESS_P (X)                   \
             || ! nonpic_symbol_mentioned_p (get_pool_constant (X))))
 
 #define SYMBOLIC_CONST_P(X)    \
@@ -1760,6 +2809,7 @@ while (0)
    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
@@ -1769,14 +2819,15 @@ while (0)
    If SECONDARY*_RELOAD_CLASS says something about the src/dst pair,
    it uses this information.  Hence, the general register <-> floating point
    register information here is not used for SFmode.  */
-#define REGISTER_MOVE_COST(SRCCLASS, DSTCLASS) \
 ((((DSTCLASS) == T_REGS) || ((DSTCLASS) == PR_REGS)) ? 10            \
+#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_FMOVD ? 8 : 12                                             \
+   ? (TARGET_SHMEDIA ? 2                                               \
+      : TARGET_FMOVD ? 8 : 12)                                         \
    : (((DSTCLASS) == FPUL_REGS                                         \
        && ((SRCCLASS) == GENERAL_REGS || (SRCCLASS) == R0_REGS))       \
       || (SRCCLASS == FPUL_REGS                                                \
@@ -1788,7 +2839,13 @@ while (0)
       || ((SRCCLASS) == FPUL_REGS                                      \
          && ((DSTCLASS) == PR_REGS || (DSTCLASS) == MAC_REGS)))        \
    ? 7                                                                 \
-   : 2)
+   : (((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))
 
 /* ??? Perhaps make MEMORY_MOVE_COST depend on compiler option?  This
    would be so that people with slow memory systems could generate
@@ -1799,7 +2856,7 @@ 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_SH2 || TARGET_HARD_SH4 ? 2 : 1)
+#define BRANCH_COST (TARGET_SH5 ? 1 : ! TARGET_SH2 || TARGET_HARD_SH4 ? 2 : 1)
 \f
 /* Assembler output control.  */
 
@@ -1812,40 +2869,26 @@ while (0)
 #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\n"
-#define SET_ASM_OP             ".set"
+#define SET_ASM_OP             "\t.set\t"
 
 /* How to change between sections.  */
 
-#define TEXT_SECTION_ASM_OP            "\t.text"
+#define TEXT_SECTION_ASM_OP            (TARGET_SHMEDIA32 ? "\t.section\t.text..SHmedia32,\"ax\"" : "\t.text")
 #define DATA_SECTION_ASM_OP            "\t.data"
-#define CTORS_SECTION_ASM_OP           "\t.section\t.ctors\n"
-#define DTORS_SECTION_ASM_OP           "\t.section\t.dtors\n"
-#define EXTRA_SECTIONS                         in_ctors, in_dtors
-#define EXTRA_SECTION_FUNCTIONS                                        \
-void                                                           \
-ctors_section()                                                        \
-{                                                              \
-  if (in_section != in_ctors)                                  \
-    {                                                          \
-      fprintf (asm_out_file, "%s\n", CTORS_SECTION_ASM_OP);    \
-      in_section = in_ctors;                                   \
-    }                                                          \
-}                                                              \
-void                                                           \
-dtors_section()                                                        \
-{                                                              \
-  if (in_section != in_dtors)                                  \
-    {                                                          \
-      fprintf (asm_out_file, "%s\n", DTORS_SECTION_ASM_OP);    \
-      in_section = in_dtors;                                   \
-    }                                                          \
-}
+
+#if defined CRT_BEGIN || defined CRT_END
+/* Arrange for TEXT_SECTION_ASM_OP to be a compile-time constant.  */
+# undef TEXT_SECTION_ASM_OP
+# if __SHMEDIA__ == 1 && __SH5__ == 32
+#  define TEXT_SECTION_ASM_OP "\t.section\t.text..SHmedia32,\"ax\""
+# else
+#  define TEXT_SECTION_ASM_OP "\t.text"
+# endif
+#endif
+
 
 /* If defined, a C expression whose value is a string containing the
    assembler operation to identify the following data as
@@ -1855,7 +2898,7 @@ dtors_section()                                                   \
    `-fno-common' is passed, otherwise `ASM_OUTPUT_COMMON' will be
    used.  */
 #ifndef BSS_SECTION_ASM_OP
-#define BSS_SECTION_ASM_OP     ".section\t.bss"
+#define BSS_SECTION_ASM_OP     "\t.section\t.bss"
 #endif
 
 /* Like `ASM_OUTPUT_BSS' except takes the required alignment as a
@@ -1865,7 +2908,7 @@ dtors_section()                                                   \
    specified as the number of bits.
 
    Try to use function `asm_output_aligned_bss' defined in file
-   `varasm.c' when defining this macro. */
+   `varasm.c' when defining this macro.  */
 #ifndef ASM_OUTPUT_ALIGNED_BSS
 #define ASM_OUTPUT_ALIGNED_BSS(FILE, DECL, NAME, SIZE, ALIGN) \
   asm_output_aligned_bss (FILE, DECL, NAME, SIZE, ALIGN)
@@ -1875,22 +2918,7 @@ dtors_section()                                                  \
    which could be text or it could be a user defined section.  */
 #define JUMP_TABLES_IN_TEXT_SECTION 1
 
-/* A C statement to output something to the assembler file to switch to section
-   NAME for object DECL which is either a FUNCTION_DECL, a VAR_DECL or
-   NULL_TREE.  Some target formats do not support arbitrary sections.  Do not
-   define this macro in such cases.  */
-
-#define ASM_OUTPUT_SECTION_NAME(FILE, DECL, NAME, RELOC) \
-   do { fprintf (FILE, ".section\t%s\n", NAME); } while (0)
-
-#define ASM_OUTPUT_CONSTRUCTOR(FILE,NAME) \
-   do { ctors_section();  asm_fprintf((FILE),"\t.long\t%U%s\n", (NAME)); } while (0)
-
-#define ASM_OUTPUT_DESTRUCTOR(FILE,NAME) \
-   do {  dtors_section();  asm_fprintf((FILE),"\t.long\t%U%s\n", (NAME)); } while (0)
-
 #undef DO_GLOBAL_CTORS_BODY
-
 #define DO_GLOBAL_CTORS_BODY                   \
 {                                              \
   typedef (*pfunc)();                          \
@@ -1922,43 +2950,63 @@ dtors_section()                                                 \
 #define ASM_OUTPUT_REG_POP(file, v) \
   fprintf ((file), "\tmov.l\t@r15+,r%d\n", (v));
 
-/* The assembler's names for the registers.  RFP need not always be used as
-   the Real framepointer; it can also be used as a normal general register.
-   Note that the name `fp' is horribly misleading since `fp' is in fact only
-   the argument-and-return-context pointer.  */
-
-extern char fp_reg_names[][5];
-
-#define REGISTER_NAMES                                 \
-{                                                      \
-  "r0", "r1", "r2",  "r3",  "r4",  "r5",  "r6",  "r7",         \
-  "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15",        \
-  "ap", "pr", "t",   "gbr", "mach","macl", fp_reg_names[16], "rap", \
-  fp_reg_names[0],  fp_reg_names[1] , fp_reg_names[2],  fp_reg_names[3], \
-  fp_reg_names[4],  fp_reg_names[5],  fp_reg_names[6],  fp_reg_names[7], \
-  fp_reg_names[8],  fp_reg_names[9],  fp_reg_names[10], fp_reg_names[11], \
-  fp_reg_names[12], fp_reg_names[13], fp_reg_names[14], fp_reg_names[15], \
-  fp_reg_names[17], fp_reg_names[18], fp_reg_names[19], fp_reg_names[20], \
-  fp_reg_names[21], fp_reg_names[22], fp_reg_names[23], fp_reg_names[24], \
-  "fpscr", \
-}
-
-#define DEBUG_REGISTER_NAMES                           \
-{                                                      \
-  "r0", "r1", "r2",  "r3",  "r4",  "r5",  "r6",  "r7",         \
-  "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15",        \
-  "ap", "pr", "t",  "gbr", "mach","macl", "fpul","rap", \
-  "fr0","fr1","fr2", "fr3", "fr4", "fr5", "fr6", "fr7", \
-  "fr8","fr9","fr10","fr11","fr12","fr13","fr14","fr15",\
-  "xd0","xd2","xd4", "xd6", "xd8", "xd10","xd12","xd14", \
-  "fpscr", \
-}
-
 /* 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.  */
-#define DBX_REGISTER_NUMBER(REGNO)     \
-  (((REGNO) >= 22 && (REGNO) <= 39) ? ((REGNO) + 1) : (REGNO))
+/* 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.  */
+#define DBX_REGISTER_NUMBER(REGNO) SH_DBX_REGISTER_NUMBER (REGNO)
+
+#define SH_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)) \
+   : XD_REGISTER_P (REGNO) \
+   ? ((REGNO) - FIRST_XD_REG + (TARGET_SH5 ? 289 : 87)) \
+   : TARGET_REGISTER_P (REGNO) \
+   ? ((REGNO) - FIRST_TARGET_REG + 68) \
+   : (REGNO) == PR_REG \
+   ? (TARGET_SH5 ? 241 : 17) \
+   : (REGNO) == T_REG \
+   ? (TARGET_SH5 ? 242 : 18) \
+   : (REGNO) == GBR_REG \
+   ? (TARGET_SH5 ? 238 : 19) \
+   : (REGNO) == MACH_REG \
+   ? (TARGET_SH5 ? 239 : 20) \
+   : (REGNO) == MACL_REG \
+   ? (TARGET_SH5 ? 240 : 21) \
+   : (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)
+
+/* 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)))        \
+       fputs ("datalabel ", (FILE));                   \
+      assemble_name ((FILE), XSTR ((SYM), 0));         \
+    }                                                  \
+  while (0)
 
 /* Output a label definition.  */
 #define ASM_OUTPUT_LABEL(FILE,NAME) \
@@ -1972,32 +3020,12 @@ extern char fp_reg_names[][5];
   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))
-
 /* #define ASM_OUTPUT_CASE_END(STREAM,NUM,TABLE)           */
 
 /* Construct a private name.  */
@@ -2011,12 +3039,30 @@ extern char fp_reg_names[][5];
   switch (GET_MODE (BODY))                                             \
     {                                                                  \
     case SImode:                                                       \
+      if (TARGET_SH5)                                                  \
+       {                                                               \
+         asm_fprintf ((STREAM), "\t.long\t%LL%d-datalabel %LL%d\n",    \
+                      (VALUE), (REL));                                 \
+         break;                                                        \
+       }                                                               \
       asm_fprintf ((STREAM), "\t.long\t%LL%d-%LL%d\n", (VALUE),(REL)); \
       break;                                                           \
     case HImode:                                                       \
+      if (TARGET_SH5)                                                  \
+       {                                                               \
+         asm_fprintf ((STREAM), "\t.word\t%LL%d-datalabel %LL%d\n",    \
+                      (VALUE), (REL));                                 \
+         break;                                                        \
+       }                                                               \
       asm_fprintf ((STREAM), "\t.word\t%LL%d-%LL%d\n", (VALUE),(REL)); \
       break;                                                           \
     case QImode:                                                       \
+      if (TARGET_SH5)                                                  \
+       {                                                               \
+         asm_fprintf ((STREAM), "\t.byte\t%LL%d-datalabel %LL%d\n",    \
+                      (VALUE), (REL));                                 \
+         break;                                                        \
+       }                                                               \
       asm_fprintf ((STREAM), "\t.byte\t%LL%d-%LL%d\n", (VALUE),(REL)); \
       break;                                                           \
     default:                                                           \
@@ -2027,86 +3073,10 @@ extern char fp_reg_names[][5];
 
 #define ASM_OUTPUT_ADDR_VEC_ELT(STREAM,VALUE)                                  \
   if (TARGET_BIGTABLE)                                                         \
-    asm_fprintf ((STREAM), "\t.long\t%LL%d\n", (VALUE));                       \
+    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.  */
-
-/* This is how to output an assembler line defining a `double'.  */
-
-#define ASM_OUTPUT_DOUBLE(FILE,VALUE)                  \
-do { char dstr[30];                                    \
-     REAL_VALUE_TO_DECIMAL ((VALUE), "%.20e", dstr);   \
-     fprintf ((FILE), "\t.double %s\n", dstr);         \
-   } while (0)
-
-/* This is how to output an assembler line defining a `float' constant.  */
-#define ASM_OUTPUT_FLOAT(FILE,VALUE)                   \
-do { char dstr[30];                                    \
-     REAL_VALUE_TO_DECIMAL ((VALUE), "%.20e", dstr);   \
-     fprintf ((FILE), "\t.float %s\n", dstr);          \
-   } while (0)
-
-#define ASM_OUTPUT_INT(STREAM, EXP)            \
-  (fprintf ((STREAM), "\t.long\t"),            \
-   output_pic_addr_const ((STREAM), (EXP)),    \
-   fputc ('\n', (STREAM)))
-
-#define ASM_OUTPUT_SHORT(STREAM, EXP)  \
-  (fprintf ((STREAM), "\t.short\t"),   \
-   output_pic_addr_const ((STREAM), (EXP)),    \
-   fputc ('\n', (STREAM)))
-
-#define ASM_OUTPUT_CHAR(STREAM, EXP)           \
-  (fprintf ((STREAM), "\t.byte\t"),            \
-   output_addr_const ((STREAM), (EXP)),        \
-   fputc ('\n', (STREAM)))
-
-#define ASM_OUTPUT_BYTE(STREAM, VALUE)         \
-  fprintf ((STREAM), "\t.byte\t%d\n", (VALUE))         \
-
-/* The next two are used for debug info when compiling with -gdwarf.  */
-#define UNALIGNED_SHORT_ASM_OP ".uaword"
-#define UNALIGNED_INT_ASM_OP   ".ualong"
-
-/* Loop alignment is now done in machine_dependent_reorg, so that
-   branch shortening can know about it.  */
+    asm_fprintf ((STREAM), "\t.word\t%LL%d\n", (VALUE));
 
-/* 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))
-
-/* 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)))
-
-/* The assembler's parentheses characters.  */
-#define ASM_OPEN_PAREN "("
-#define ASM_CLOSE_PAREN ")"
-
-/* Target characters.  */
-#define TARGET_BELL    007
-#define TARGET_BS      010
-#define TARGET_TAB     011
-#define TARGET_NEWLINE 012
-#define TARGET_VT      013
-#define TARGET_FF      014
-#define TARGET_CR      015
 \f
 /* A C statement to be executed just prior to the output of
    assembler code for INSN, to modify the extracted operands so
@@ -2134,7 +3104,58 @@ do { char dstr[30];                                      \
 
 #define PRINT_OPERAND_PUNCT_VALID_P(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)       \
+      {                                                                        \
+       switch (XINT ((X), 1))                                          \
+         {                                                             \
+         case UNSPEC_DATALABEL:                                        \
+           fputs ("datalabel ", (STREAM));                             \
+           output_addr_const ((STREAM), XVECEXP ((X), 0, 0));          \
+           break;                                                      \
+         case UNSPEC_PIC:                                              \
+           /* GLOBAL_OFFSET_TABLE or local symbols, no suffix.  */     \
+           output_addr_const ((STREAM), XVECEXP ((X), 0, 0));          \
+           break;                                                      \
+         case UNSPEC_GOT:                                              \
+           output_addr_const ((STREAM), XVECEXP ((X), 0, 0));          \
+           fputs ("@GOT", (STREAM));                                   \
+           break;                                                      \
+         case UNSPEC_GOTOFF:                                           \
+           output_addr_const ((STREAM), XVECEXP ((X), 0, 0));          \
+           fputs ("@GOTOFF", (STREAM));                                \
+           break;                                                      \
+         case UNSPEC_PLT:                                              \
+           output_addr_const ((STREAM), XVECEXP ((X), 0, 0));          \
+           fputs ("@PLT", (STREAM));                                   \
+           break;                                                      \
+         case UNSPEC_GOTPLT:                                           \
+           output_addr_const ((STREAM), XVECEXP ((X), 0, 0));          \
+           fputs ("@GOTPLT", (STREAM));                                \
+           break;                                                      \
+         case UNSPEC_CALLER:                                           \
+           {                                                           \
+             char name[32];                                            \
+             /* LPCS stands for Label for PIC Call Site.  */           \
+             ASM_GENERATE_INTERNAL_LABEL                               \
+               (name, "LPCS", INTVAL (XVECEXP ((X), 0, 0)));           \
+             assemble_name ((STREAM), name);                           \
+           }                                                           \
+           break;                                                      \
+         default:                                                      \
+           goto FAIL;                                                  \
+         }                                                             \
+       break;                                                          \
+      }                                                                        \
+    else                                                               \
+      goto FAIL;                                                       \
+  while (0)
+
 \f
 extern struct rtx_def *sh_compare_op0;
 extern struct rtx_def *sh_compare_op1;
@@ -2147,7 +3168,8 @@ enum processor_type {
   PROCESSOR_SH2,
   PROCESSOR_SH3,
   PROCESSOR_SH3E,
-  PROCESSOR_SH4
+  PROCESSOR_SH4,
+  PROCESSOR_SH5
 };
 
 #define sh_cpu_attr ((enum attr_cpu)sh_cpu)
@@ -2173,30 +3195,26 @@ extern enum mdep_reorg_phase_e mdep_reorg_phase;
 
 #define TARGET_MEM_FUNCTIONS
 
-/* Define this macro if you want to implement any pragmas.  If defined, it
-   is a C expression whose value is 1 if the pragma was handled by the
-   macro, zero otherwise.  */
-#define HANDLE_PRAGMA(GETC, UNGETC, NODE) sh_handle_pragma (GETC, UNGETC, NODE)
+/* 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); \
+} while (0)
 
 /* Set when processing a function with pragma interrupt turned on.  */
 
 extern int pragma_interrupt;
 
+/* 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;
 
-/* A C expression whose value is nonzero if IDENTIFIER with arguments ARGS
-   is a valid machine specific attribute for DECL.
-   The attributes in ATTRIBUTES have previously been assigned to DECL.  */
-#define VALID_MACHINE_DECL_ATTRIBUTE(DECL, ATTRIBUTES, IDENTIFIER, ARGS) \
-sh_valid_machine_decl_attribute (DECL, ATTRIBUTES, IDENTIFIER, ARGS)
-
-#define PRAGMA_INSERT_ATTRIBUTES(node, pattr, prefix_attr) \
-  sh_pragma_insert_attributes (node, pattr, prefix_attr)
-
 extern int rtx_equal_function_value_matters;
-extern struct rtx_def *fpscr_rtx;
 
 \f
 /* Instructions with unfilled delay slots take up an
@@ -2208,19 +3226,37 @@ extern struct rtx_def *fpscr_rtx;
 \f
 /* Define the codes that are matched by predicates in sh.c.  */
 #define PREDICATE_CODES \
+  {"and_operand", {SUBREG, REG, CONST_INT}},                           \
   {"arith_operand", {SUBREG, REG, CONST_INT}},                         \
+  {"arith_reg_dest", {SUBREG, REG}},                                   \
   {"arith_reg_operand", {SUBREG, REG}},                                        \
-  {"arith_reg_or_0_operand", {SUBREG, REG, CONST_INT}},                        \
+  {"arith_reg_or_0_operand", {SUBREG, REG, CONST_INT, CONST_VECTOR}},  \
   {"binary_float_operator", {PLUS, MULT}},                             \
   {"commutative_float_operator", {PLUS, MULT}},                                \
+  {"equality_comparison_operator", {EQ,NE}},                           \
+  {"extend_reg_operand", {SUBREG, REG, TRUNCATE}},                     \
+  {"extend_reg_or_0_operand", {SUBREG, REG, TRUNCATE, CONST_INT}},     \
   {"fp_arith_reg_operand", {SUBREG, REG}},                             \
-  {"fp_extended_operand", {SUBREG, REG, FLOAT_EXTEND}},                        \
   {"fpscr_operand", {REG}},                                            \
-  {"general_movsrc_operand", {SUBREG, REG, CONST_INT, MEM}},           \
-  {"general_movdst_operand", {SUBREG, REG, CONST_INT, MEM}},           \
+  {"fpul_operand", {REG}},                                             \
+  {"general_extend_operand", {SUBREG, REG, MEM, TRUNCATE}},            \
+  {"general_movsrc_operand", {SUBREG, REG, CONST_INT, CONST_DOUBLE, MEM}}, \
+  {"general_movdst_operand", {SUBREG, REG, MEM}},                      \
+  {"greater_comparison_operator", {GT,GE,GTU,GEU}},                    \
+  {"inqhi_operand", {TRUNCATE}},                                       \
+  {"less_comparison_operator", {LT,LE,LTU,LEU}},                       \
   {"logical_operand", {SUBREG, REG, CONST_INT}},                       \
+  {"mextr_bit_offset", {CONST_INT}},                                   \
   {"noncommutative_float_operator", {MINUS, DIV}},                     \
-  {"register_operand", {SUBREG, REG}},
+  {"shmedia_6bit_operand", {SUBREG, REG, CONST_INT}},                  \
+  {"target_reg_operand", {SUBREG, REG}},                               \
+  {"target_operand", {SUBREG, REG, LABEL_REF, SYMBOL_REF, CONST, UNSPEC}},\
+  {"register_operand", {SUBREG, REG}},                                 \
+  {"sh_const_vec", {CONST_VECTOR}},                                    \
+  {"sh_1el_vec", {CONST_VECTOR, PARALLEL}},                            \
+  {"sh_rep_vec", {CONST_VECTOR, PARALLEL}},                            \
+  {"symbol_ref_operand", {SYMBOL_REF}},                                        \
+  {"zero_vec_operand", {CONST_VECTOR}},
 
 /* 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, 
@@ -2234,7 +3270,8 @@ extern struct rtx_def *fpscr_rtx;
 #define PROMOTE_MODE(MODE, UNSIGNEDP, TYPE) \
   if (GET_MODE_CLASS (MODE) == MODE_INT                        \
       && GET_MODE_SIZE (MODE) < UNITS_PER_WORD)                \
-    (MODE) = SImode;
+    (UNSIGNEDP) = ((MODE) == SImode ? 0 : (UNSIGNEDP)),        \
+    (MODE) = (TARGET_SH1 ? SImode : DImode);
 
 /* Defining PROMOTE_FUNCTION_ARGS eliminates some unnecessary zero/sign
    extensions applied to char/short functions arguments.  Defining
@@ -2249,58 +3286,6 @@ extern struct rtx_def *fpscr_rtx;
    clear if this would give better code.  If implemented, should check for
    compatibility problems.  */
 
-/* A C statement (sans semicolon) to update the integer variable COST
-   based on the relationship between INSN that is dependent on
-   DEP_INSN through the dependence LINK.  The default is to make no
-   adjustment to COST.  This can be used for example to specify to
-   the scheduler that an output- or anti-dependence does not incur
-   the same cost as a data-dependence.  */
-
-#define ADJUST_COST(insn,link,dep_insn,cost)                           \
-do {                                                                   \
-  rtx reg;                                                             \
-                                                                       \
-  if (GET_CODE(insn) == CALL_INSN)                                     \
-    {                                                                  \
-      /* The only input for a call that is timing-critical is the      \
-        function's address.  */                                        \
-      rtx call = PATTERN (insn);                                       \
-                                                                       \
-      if (GET_CODE (call) == PARALLEL)                                 \
-       call = XVECEXP (call, 0 ,0);                                    \
-      if (GET_CODE (call) == SET)                                      \
-       call = SET_SRC (call);                                          \
-      if (GET_CODE (call) == CALL && GET_CODE (XEXP (call, 0)) == MEM  \
-         && ! reg_set_p (XEXP (XEXP (call, 0), 0), dep_insn))          \
-       (cost) = 0;                                                     \
-    }                                                                  \
-  /* All sfunc calls are parallels with at least four components.      \
-     Exploit this to avoid unnecessary calls to sfunc_uses_reg.  */    \
-  else if (GET_CODE (PATTERN (insn)) == PARALLEL                       \
-          && XVECLEN (PATTERN (insn), 0) >= 4                          \
-          && (reg = sfunc_uses_reg (insn)))                            \
-    {                                                                  \
-      /* Likewise, the most timing critical input for an sfuncs call   \
-        is the function address.  However, sfuncs typically start      \
-        using their arguments pretty quickly.                          \
-        Assume a four cycle delay before they are needed.  */          \
-      if (! reg_set_p (reg, dep_insn))                                 \
-       cost -= TARGET_SUPERSCALAR ? 40 : 4;                            \
-    }                                                                  \
-  /* Adjust load_si / pcload_si type insns latency.  Use the known     \
-     nominal latency and form of the insn to speed up the check.  */   \
-  else if (cost == 3                                                   \
-          && GET_CODE (PATTERN (dep_insn)) == SET                      \
-          /* Latency for dmpy type insns is also 3, so check the that  \
-             it's actually a move insn.  */                            \
-          && general_movsrc_operand (SET_SRC (PATTERN (dep_insn)), SImode))\
-    cost = 2;                                                          \
-  else if (cost == 30                                                  \
-          && GET_CODE (PATTERN (dep_insn)) == SET                      \
-          && GET_MODE (SET_SRC (PATTERN (dep_insn))) == SImode)        \
-    cost = 20;                                                         \
-} while (0)                                                            \
-
 #define SH_DYNAMIC_SHIFT_COST \
   (TARGET_HARD_SH4 ? 1 : TARGET_SH3 ? (TARGET_SMALLCODE ? 1 : 2) : 20)
 
@@ -2310,9 +3295,12 @@ do {                                                                     \
 #define OPTIMIZE_MODE_SWITCHING(ENTITY) TARGET_SH4
 
 #define NORMAL_MODE(ENTITY) \
-   (TARGET_FPU_SINGLE ? FP_MODE_SINGLE : FP_MODE_DOUBLE) 
+  (sh_cfun_interrupt_handler_p () ? FP_MODE_NONE \
+   : TARGET_FPU_SINGLE ? FP_MODE_SINGLE \
+   : FP_MODE_DOUBLE)
 
-#define EPILOGUE_USES(REGNO)       (TARGET_SH4 && (REGNO) == FPSCR_REG)
+#define EPILOGUE_USES(REGNO)       ((TARGET_SH3E || TARGET_SH4)                \
+                                   && (REGNO) == FPSCR_REG)
 
 #define MODE_NEEDED(ENTITY, INSN)                                      \
   (recog_memoized (INSN) >= 0                                          \
@@ -2325,35 +3313,33 @@ do {                                                                    \
 #define EMIT_MODE_SET(ENTITY, MODE, HARD_REGS_LIVE) \
   fpscr_set_from_mem ((MODE), (HARD_REGS_LIVE))
 
-#define DWARF_LINE_MIN_INSTR_LENGTH 2
-
-#undef INIT_SECTION_ASM_OP
-#define INIT_SECTION_ASM_OP    ".section\t.init"
-#undef FINI_SECTION_ASM_OP
-#define FINI_SECTION_ASM_OP    ".section\t.fini"
-
-#undef STARTFILE_SPEC
-#define STARTFILE_SPEC \
-  "crt1.o%s crti.o%s crtbegin.o%s"
+#define MD_CAN_REDIRECT_BRANCH(INSN, SEQ) \
+  sh_can_redirect_branch ((INSN), (SEQ))
 
-#undef ENDFILE_SPEC
-#define ENDFILE_SPEC \
-  "crtend.o%s crtn.o%s"
+#define DWARF_FRAME_RETURN_COLUMN (TARGET_SH5 ? PR_MEDIA_REG : PR_REG)
 
+#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.  */
-#define CRT_CALL_STATIC_FUNCTION(func) \
-  if (0) \
-     /* This avoids warnings about the static function being unused.  */ \
-     func (); \
-  else \
-    /* We should be passing FUNC to the asm statement as an asm input  \
-       operand, but this breaks with -fPIC.  FIXME.  */                        \
-    asm \
-      ("mov.l  1f,r1\n\
+#define CRT_CALL_STATIC_FUNCTION(SECTION_OP, FUNC) \
+   asm (SECTION_OP "\n\
+       mov.l   1f,r1\n\
        mova    2f,r0\n\
        braf    r1\n\
        lds     r0,pr\n\
 0:     .p2align 2\n\
-1:     .long   " USER_LABEL_PREFIX #func " - 0b\n\
-2:")
+1:     .long   " USER_LABEL_PREFIX #FUNC " - 0b\n\
+2:\n" TEXT_SECTION_ASM_OP);
+#endif /* (defined CRT_BEGIN || defined CRT_END) && ! __SHMEDIA__ */
+
+#define ALLOCATE_INITIAL_VALUE(hard_reg) \
+  (REGNO (hard_reg) == (TARGET_SH5 ? PR_MEDIA_REG : PR_REG) \
+   ? (current_function_is_leaf && ! sh_pr_n_sets () \
+      ? (hard_reg) \
+      : gen_rtx_MEM (Pmode, TARGET_SH5 \
+                           ? (plus_constant (arg_pointer_rtx, \
+                                             TARGET_SHMEDIA64 ? -8 : -4)) \
+                           : frame_pointer_rtx)) \
+   : NULL_RTX)
+
+#endif /* ! GCC_SH_H */