OSDN Git Service

Fix for proprietary testcase that fails at -m5-compact
[pf3gnuchains/gcc-fork.git] / gcc / config / sh / sh.h
index 3002c3e..c2f3160 100644 (file)
@@ -1,6 +1,6 @@
 /* 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.
+   Copyright (C) 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
+   2003 Free Software Foundation, Inc.
    Contributed by Steve Chamberlain (sac@cygnus.com).
    Improved by Jim Wilson (wilson@cygnus.com).
 
@@ -28,7 +28,7 @@ Boston, MA 02111-1307, USA.  */
   fputs (" (Hitachi SH)", stderr);
 
 /* Unfortunately, insn-attrtab.c doesn't include insn-codes.h.  We can't
-   include it here, because hconfig.h is also included by gencodes.c .  */
+   include it here, because bconfig.h is also included by gencodes.c .  */
 /* ??? No longer true.  */
 extern int code_for_indirect_jump_scratch;
 
@@ -45,6 +45,9 @@ do { \
     case PROCESSOR_SH2: \
       builtin_define ("__sh2__"); \
       break; \
+    case PROCESSOR_SH2E: \
+      builtin_define ("__SH2E__"); \
+      break; \
     case PROCESSOR_SH3: \
       builtin_define ("__sh3__"); \
       builtin_define ("__SH3__"); \
@@ -132,7 +135,7 @@ extern int target_flags;
 #define SH1_BIT                (1<<8)
 #define SH2_BIT                (1<<9)
 #define SH3_BIT                (1<<10)
-#define SH3E_BIT       (1<<11)
+#define SH_E_BIT       (1<<11)
 #define HARD_SH4_BIT   (1<<5)
 #define FPU_SINGLE_BIT (1<<7)
 #define SH4_BIT                (1<<12)
@@ -161,11 +164,14 @@ extern int target_flags;
 /* Nonzero if we should generate code using type 2 insns.  */
 #define TARGET_SH2 (target_flags & SH2_BIT)
 
+/* Nonzero if we should generate code using type 2E insns.  */
+#define TARGET_SH2E ((target_flags & SH_E_BIT) && TARGET_SH2)
+
 /* Nonzero if we should generate code using type 3 insns.  */
 #define TARGET_SH3 (target_flags & SH3_BIT)
 
 /* Nonzero if we should generate code using type 3E insns.  */
-#define TARGET_SH3E ((target_flags & SH3E_BIT) && (target_flags & SH1_BIT))
+#define TARGET_SH3E ((target_flags & SH_E_BIT) && TARGET_SH3)
 
 /* Nonzero if the cache line size is 32.  */
 #define TARGET_CACHE32 (target_flags & HARD_SH4_BIT || TARGET_SH5)
@@ -186,7 +192,7 @@ extern int target_flags;
 #define TARGET_FPU_DOUBLE (target_flags & SH4_BIT)
 
 /* Nonzero if an FPU is available.  */
-#define TARGET_FPU_ANY (TARGET_SH3E || TARGET_FPU_DOUBLE)
+#define TARGET_FPU_ANY (TARGET_SH2E || TARGET_FPU_DOUBLE)
 
 /* Nonzero if we should generate code using type 4 insns.  */
 #define TARGET_SH4 ((target_flags & SH4_BIT) && (target_flags & SH1_BIT))
@@ -205,12 +211,12 @@ extern int target_flags;
 /* Nonzero if we should generate code using the SHmedia ISA and 32-bit
    ABI.  */
 #define TARGET_SHMEDIA32 (TARGET_SH5 && ! TARGET_SH1 \
-                         && (target_flags & SH3E_BIT))
+                         && (target_flags & SH_E_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))
+                         && ! (target_flags & SH_E_BIT))
 
 /* Nonzero if we should generate code using SHmedia FPU instructions.  */
 #define TARGET_SHMEDIA_FPU (TARGET_SHMEDIA && TARGET_FPU_DOUBLE)
@@ -252,42 +258,45 @@ extern int target_flags;
 /* 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_SH1               (SH1_BIT)
+#define SELECT_SH2               (SH2_BIT | SELECT_SH1)
+#define SELECT_SH2E              (SH_E_BIT | SH2_BIT | SH1_BIT | FPU_SINGLE_BIT)
+#define SELECT_SH3               (SH3_BIT | SELECT_SH2)
+#define SELECT_SH3E              (SH_E_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 | SH_E_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 | SH_E_BIT)
+#define SELECT_SH5_32_NOFPU      (SH5_BIT | SH_E_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 \
+#define TARGET_NONE -(SH1_BIT | SH2_BIT | SH3_BIT | SH_E_BIT | SH4_BIT \
                      | HARD_SH4_BIT | FPU_SINGLE_BIT | SH5_BIT)
 
 #define TARGET_SWITCHES                        \
 { {"1",                TARGET_NONE, "" },              \
-  {"1",                SELECT_SH1, "" },                       \
+  {"1",                SELECT_SH1, "" },               \
   {"2",                TARGET_NONE, "" },              \
   {"2",                SELECT_SH2, "" },               \
+  {"2e",        TARGET_NONE, "" },             \
+  {"2e",        SELECT_SH2E, "" },             \
   {"3",                TARGET_NONE, "" },              \
-  {"3",                SELECT_SH3, "" },       \
+  {"3",                SELECT_SH3, "" },               \
   {"3e",       TARGET_NONE, "" },              \
-  {"3e",       SELECT_SH3E, "" },      \
+  {"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-single", SELECT_SH4_SINGLE, "" },        \
   {"4-nofpu",  TARGET_NONE, "" },              \
-  {"4-nofpu",  SELECT_SH4_NOFPU, "" },\
+  {"4-nofpu",  SELECT_SH4_NOFPU, "" },         \
   {"4",                TARGET_NONE, "" },              \
-  {"4",                SELECT_SH4, "" }, \
+  {"4",                SELECT_SH4, "" },               \
   {"5-64media",        TARGET_NONE, "" },              \
   {"5-64media", SELECT_SH5_64, "Generate 64-bit SHmedia code" }, \
   {"5-64media-nofpu", TARGET_NONE, "" },       \
@@ -350,9 +359,21 @@ extern int target_flags;
   { "subtarget_link_emul_suffix", SUBTARGET_LINK_EMUL_SUFFIX },        \
   { "subtarget_link_spec", SUBTARGET_LINK_SPEC },              \
   { "subtarget_asm_endian_spec", SUBTARGET_ASM_ENDIAN_SPEC },  \
+  { "subtarget_asm_relax_spec", SUBTARGET_ASM_RELAX_SPEC },    \
+  { "subtarget_asm_isa_spec", SUBTARGET_ASM_ISA_SPEC },        \
   SUBTARGET_EXTRA_SPECS
 
-#define ASM_SPEC  "%(subtarget_asm_endian_spec) %{mrelax:-relax}"
+#if TARGET_CPU_DEFAULT & HARD_SH4_BIT
+#define SUBTARGET_ASM_RELAX_SPEC "%{!m[1235]*:-isa=sh4}"
+#else
+#define SUBTARGET_ASM_RELAX_SPEC "%{m4*:-isa=sh4}"
+#endif
+
+#define SH_ASM_SPEC \
+ "%(subtarget_asm_endian_spec) %{mrelax:-relax %(subtarget_asm_relax_spec)}\
+%(subtarget_asm_isa_spec)"
+
+#define ASM_SPEC SH_ASM_SPEC
 
 #ifndef SUBTARGET_ASM_ENDIAN_SPEC
 #if TARGET_ENDIAN_DEFAULT == LITTLE_ENDIAN_BIT
@@ -362,14 +383,16 @@ extern int target_flags;
 #endif
 #endif
 
+#define SUBTARGET_ASM_ISA_SPEC ""
+
 #define LINK_EMUL_PREFIX "sh%{ml:l}"
 
 #if TARGET_CPU_DEFAULT & SH5_BIT
-#if TARGET_CPU_DEFAULT & SH3E_BIT
+#if TARGET_CPU_DEFAULT & SH_E_BIT
 #define LINK_DEFAULT_CPU_EMUL "32"
 #else
 #define LINK_DEFAULT_CPU_EMUL "64"
-#endif /* SH3E_BIT */
+#endif /* SH_E_BIT */
 #else
 #define LINK_DEFAULT_CPU_EMUL ""
 #endif /* SH5_BIT */
@@ -409,6 +432,8 @@ do {                                                                        \
   assembler_dialect = 0;                                               \
   if (TARGET_SH2)                                                      \
     sh_cpu = CPU_SH2;                                                  \
+  if (TARGET_SH2E)                                                     \
+    sh_cpu = CPU_SH2E;                                                 \
   if (TARGET_SH3)                                                      \
     sh_cpu = CPU_SH3;                                                  \
   if (TARGET_SH3E)                                                     \
@@ -444,6 +469,8 @@ do {                                                                        \
        targetm.asm_out.aligned_op.di = NULL;                           \
        targetm.asm_out.unaligned_op.di = NULL;                         \
     }                                                                  \
+  if (TARGET_FMOVD)                                                    \
+    reg_class_from_letter['e' - 'a'] = NO_REGS;                                \
                                                                        \
   for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)              \
     if (! VALID_REGISTER_P (regno))                                    \
@@ -468,10 +495,42 @@ do {                                                                      \
   if (flag_pic && ! TARGET_PREFERGOT)                                  \
     flag_no_function_cse = 1;                                          \
                                                                        \
-  /* Never run scheduling before reload, since that can                        \
-     break global alloc, and generates slower code anyway due          \
-     to the pressure on R0.  */                                                \
-  flag_schedule_insns = 0;                                             \
+  if (SMALL_REGISTER_CLASSES)                                          \
+    {                                                                  \
+      /* Never run scheduling before reload, since that can            \
+        break global alloc, and generates slower code anyway due       \
+        to the pressure on R0.  */                                     \
+      flag_schedule_insns = 0;                                         \
+    }                                                                  \
+                                                                       \
+  if (align_loops == 0)                                                        \
+    align_loops =  1 << (TARGET_SH5 ? 3 : 2);                          \
+  if (align_jumps == 0)                                                        \
+    align_jumps = 1 << CACHE_LOG;                                      \
+  else if (align_jumps < (TARGET_SHMEDIA ? 4 : 2))                     \
+    align_jumps = TARGET_SHMEDIA ? 4 : 2;                              \
+                                                                       \
+  /* Allocation boundary (in *bytes*) for the code of a function.      \
+     SH1: 32 bit alignment is faster, because instructions are always  \
+     fetched as a pair from a longword boundary.                       \
+     SH2 .. SH5 : align to cache line start.  */                       \
+  if (align_functions == 0)                                            \
+    align_functions                                                    \
+      = TARGET_SMALLCODE ? FUNCTION_BOUNDARY/8 : (1 << CACHE_LOG);     \
+  /* The linker relaxation code breaks when a function contains                \
+     alignments that are larger than that at the start of a            \
+     compilation unit.  */                                             \
+  if (TARGET_RELAX)                                                    \
+    {                                                                  \
+      int min_align                                                    \
+       = align_loops > align_jumps ? align_loops : align_jumps;        \
+                                                                       \
+      /* Also take possible .long constants / mova tables int account. */\
+      if (min_align < 4)                                               \
+       min_align = 4;                                                  \
+      if (align_functions < min_align)                                 \
+       align_functions = min_align;                                    \
+    }                                                                  \
 } while (0)
 \f
 /* Target machine storage layout.  */
@@ -532,11 +591,9 @@ do {                                                                       \
    The SH2/3 have 16 byte cache lines, and the SH4 has a 32 byte cache line */
 #define CACHE_LOG (TARGET_CACHE32 ? 5 : TARGET_SH2 ? 4 : 2)
 
-/* Allocation boundary (in *bits*) for the code of a function.
-   32 bit alignment is faster, because instructions are always fetched as a
-   pair from a longword boundary.  */
-#define FUNCTION_BOUNDARY  \
-  (TARGET_SMALLCODE ? 16 << TARGET_SHMEDIA : (1 << CACHE_LOG) * 8)
+/* ABI given & required minimum allocation boundary (in *bits*) for the
+   code of a function.  */
+#define FUNCTION_BOUNDARY (16 << TARGET_SHMEDIA)
 
 /* On SH5, the lowest bit is used to indicate SHmedia functions, so
    the vbit must go into the delta field of
@@ -726,7 +783,7 @@ extern char sh_additional_register_names[ADDREGNAMES_SIZE] \
 #define LAST_GENERAL_REG (FIRST_GENERAL_REG + (TARGET_SHMEDIA ? 63 : 15))
 #define FIRST_FP_REG DR0_REG
 #define LAST_FP_REG  (FIRST_FP_REG + \
-                     (TARGET_SHMEDIA_FPU ? 63 : TARGET_SH3E ? 15 : -1))
+                     (TARGET_SHMEDIA_FPU ? 63 : TARGET_SH2E ? 15 : -1))
 #define FIRST_XD_REG XD0_REG
 #define LAST_XD_REG  (FIRST_XD_REG + ((TARGET_SH4 && TARGET_FMOVD) ? 7 : -1))
 #define FIRST_TARGET_REG TR0_REG
@@ -767,7 +824,7 @@ extern char sh_additional_register_names[ADDREGNAMES_SIZE] \
   (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))
+   || (TARGET_SH2E && (REGNO) == FPUL_REG))
 
 /* The mode that should be generally used to store a register by
    itself in the stack, or to load it back.  */
@@ -880,10 +937,10 @@ extern char sh_additional_register_names[ADDREGNAMES_SIZE] \
 
 #define HARD_REGNO_NREGS(REGNO, MODE) \
    (XD_REGISTER_P (REGNO) \
-    ? (GET_MODE_SIZE (MODE) / (2 * UNITS_PER_WORD)) \
+    ? ((GET_MODE_SIZE (MODE) + (2*UNITS_PER_WORD - 1)) / (2*UNITS_PER_WORD)) \
     : (TARGET_SHMEDIA && FP_REGISTER_P (REGNO)) \
     ? ((GET_MODE_SIZE (MODE) + UNITS_PER_WORD/2 - 1) / (UNITS_PER_WORD/2)) \
-    : ((GET_MODE_SIZE (MODE) + UNITS_PER_WORD - 1) / UNITS_PER_WORD)) \
+    : ((GET_MODE_SIZE (MODE) + UNITS_PER_WORD - 1) / UNITS_PER_WORD))
 
 /* Value is 1 if hard register REGNO can hold a value of machine-mode MODE.
    We can allow any mode in any general register.  The special registers
@@ -906,17 +963,17 @@ extern char sh_additional_register_names[ADDREGNAMES_SIZE] \
    ? 1 \
    : (MODE) == V2SFmode \
    ? ((FP_REGISTER_P (REGNO) && ((REGNO) - FIRST_FP_REG) % 2 == 0) \
-      || (TARGET_SHMEDIA && GENERAL_REGISTER_P (REGNO))) \
+      || GENERAL_REGISTER_P (REGNO)) \
    : (MODE) == V4SFmode \
-   ? (FP_REGISTER_P (REGNO) && ((REGNO) - FIRST_FP_REG) % 4 == 0) \
+   ? ((FP_REGISTER_P (REGNO) && ((REGNO) - FIRST_FP_REG) % 4 == 0) \
+      || (! TARGET_SHMEDIA && GENERAL_REGISTER_P (REGNO))) \
    : (MODE) == V16SFmode \
    ? (TARGET_SHMEDIA \
       ? (FP_REGISTER_P (REGNO) && ((REGNO) - FIRST_FP_REG) % 16 == 0) \
       : (REGNO) == FIRST_XD_REG) \
    : FP_REGISTER_P (REGNO) \
-   ? ((MODE) == SFmode \
-      || (TARGET_SHMEDIA && (MODE) == SImode) \
-      || ((TARGET_SH3E || TARGET_SHMEDIA) && (MODE) == SCmode) \
+   ? ((MODE) == SFmode || (MODE) == SImode \
+      || ((TARGET_SH2E || TARGET_SHMEDIA) && (MODE) == SCmode) \
       || (((TARGET_SH4 && (MODE) == DFmode) || (MODE) == DCmode \
           || (TARGET_SHMEDIA && ((MODE) == DFmode || (MODE) == DImode \
                                  || (MODE) == V2SFmode || (MODE) == TImode))) \
@@ -1231,7 +1288,7 @@ extern int regno_reg_class[FIRST_PSEUDO_REGISTER];
 
 /* Get reg_class from a letter such as appears in the machine
    description.  */
-extern const enum reg_class reg_class_from_letter[];
+extern enum reg_class reg_class_from_letter[];
 
 #define REG_CLASS_FROM_LETTER(C) \
    ( ISLOWER (C) ? reg_class_from_letter[(C)-'a'] : NO_REGS )
@@ -1296,16 +1353,20 @@ extern const enum reg_class reg_class_from_letter[];
    : (CLASS)) \
 
 #define SECONDARY_OUTPUT_RELOAD_CLASS(CLASS,MODE,X) \
-  ((((((CLASS) == FP_REGS || (CLASS) == FP0_REGS                       \
-       || (CLASS) == DF_REGS || (CLASS) == DF_HI_REGS)                 \
-      && (GET_CODE (X) == REG && GENERAL_OR_AP_REGISTER_P (REGNO (X))))        \
-     || (((CLASS) == GENERAL_REGS || (CLASS) == R0_REGS)               \
+  ((((REGCLASS_HAS_FP_REG (CLASS)                                      \
+      && (GET_CODE (X) == REG                                          \
+      && (GENERAL_OR_AP_REGISTER_P (REGNO (X))                         \
+         || (FP_REGISTER_P (REGNO (X)) && (MODE) == SImode             \
+             && TARGET_FMOVD))))                                       \
+     || (REGCLASS_HAS_GENERAL_REG (CLASS)                              \
         && GET_CODE (X) == REG                                         \
         && FP_REGISTER_P (REGNO (X))))                                 \
     && ! TARGET_SHMEDIA                                                        \
-    && MODE == SFmode)                                                 \
+    && ((MODE) == SFmode || (MODE) == SImode))                         \
    ? FPUL_REGS                                                         \
-   : ((CLASS) == FPUL_REGS                                             \
+   : (((CLASS) == FPUL_REGS                                            \
+       || (REGCLASS_HAS_FP_REG (CLASS)                                 \
+          && ! TARGET_SHMEDIA && MODE == SImode))                      \
       && (GET_CODE (X) == MEM                                          \
          || (GET_CODE (X) == REG                                       \
              && (REGNO (X) >= FIRST_PSEUDO_REGISTER                    \
@@ -1326,8 +1387,7 @@ extern const enum reg_class reg_class_from_letter[];
    ? GENERAL_REGS : NO_REGS)
 
 #define SECONDARY_INPUT_RELOAD_CLASS(CLASS,MODE,X)  \
-  ((((CLASS) == FP_REGS || (CLASS) == FP0_REGS || (CLASS) == DF_REGS   \
-     || (CLASS) == DF_HI_REGS)                                         \
+  ((REGCLASS_HAS_FP_REG (CLASS)                                        \
     && ! TARGET_SHMEDIA                                                        \
     && immediate_operand ((X), (MODE))                                 \
     && ! ((fp_zero_operand (X) || fp_one_operand (X))                  \
@@ -1335,8 +1395,9 @@ extern const enum reg_class reg_class_from_letter[];
    ? R0_REGS                                                           \
    : (CLASS == FPUL_REGS                                               \
       && ((GET_CODE (X) == REG                                         \
-          && (REGNO (X) == MACL_REG || REGNO (X) == MACH_REG           \
-             || REGNO (X) == T_REG))))                                 \
+          && (REGNO (X) == MACL_REG || REGNO (X) == MACH_REG           \
+              || REGNO (X) == T_REG))                                  \
+         || GET_CODE (X) == PLUS))                                     \
    ? GENERAL_REGS                                                      \
    : CLASS == FPUL_REGS && immediate_operand ((X), (MODE))             \
    ? (GET_CODE (X) == CONST_INT && CONST_OK_FOR_I (INTVAL (X))         \
@@ -1346,7 +1407,7 @@ extern const enum reg_class reg_class_from_letter[];
       && ((GET_CODE (X) == REG && REGNO (X) >= FIRST_PSEUDO_REGISTER)  \
          || (GET_CODE (X) == MEM && GET_CODE (XEXP ((X), 0)) == PLUS)))\
    ? GENERAL_REGS                                                      \
-   : (((CLASS) == FP_REGS || (CLASS) == DF_REGS || (CLASS) == DF_HI_REGS)\
+   : (REGCLASS_HAS_FP_REG (CLASS)                                      \
       && TARGET_SHMEDIA                                                        \
       && immediate_operand ((X), (MODE))                               \
       && (X) != CONST0_RTX (GET_MODE (X))                              \
@@ -1357,23 +1418,21 @@ extern const enum reg_class reg_class_from_letter[];
 /* Return the maximum number of consecutive registers
    needed to represent mode MODE in a register of class CLASS.
 
-   On SH this is the size of MODE in words.  */
+   If TARGET_SHMEDIA, we need two FP registers per word.
+   Otherwise we will need at most one register per word.  */
 #define CLASS_MAX_NREGS(CLASS, MODE) \
-     ((GET_MODE_SIZE (MODE) + UNITS_PER_WORD - 1) / UNITS_PER_WORD)
+    (TARGET_SHMEDIA \
+     && TEST_HARD_REG_BIT (reg_class_contents[CLASS], FIRST_FP_REG) \
+     ? (GET_MODE_SIZE (MODE) + UNITS_PER_WORD/2 - 1) / (UNITS_PER_WORD/2) \
+     : (GET_MODE_SIZE (MODE) + UNITS_PER_WORD - 1) / UNITS_PER_WORD)
 
 /* If defined, gives a class of registers that cannot be used as the
    operand of a SUBREG that changes the mode of the object illegally.  */
 /* ??? We need to renumber the internal numbers for the frnn registers
    when in little endian in order to allow mode size changes.  */
 
-#define CLASS_CANNOT_CHANGE_MODE (TARGET_LITTLE_ENDIAN ? DF_REGS : DF_HI_REGS)
-
-/* Defines illegal mode changes for CLASS_CANNOT_CHANGE_MODE.  */
-
-#define CLASS_CANNOT_CHANGE_MODE_P(FROM,TO) \
-  (GET_MODE_SIZE (FROM) != GET_MODE_SIZE (TO) \
-   && ((TARGET_LITTLE_ENDIAN  && GET_MODE_SIZE (TO) < 8) \
-       || GET_MODE_SIZE (FROM) < 8))
+#define CANNOT_CHANGE_MODE_CLASS(FROM, TO, CLASS)                          \
+  sh_cannot_change_mode_class (FROM, TO, CLASS)
 \f
 /* Stack layout; function entry, exit and calling.  */
 
@@ -1460,7 +1519,7 @@ extern const enum reg_class reg_class_from_letter[];
    : FIRST_RET_REG)
 
 #define BASE_ARG_REG(MODE) \
-  ((TARGET_SH3E && ((MODE) == SFmode))                 \
+  ((TARGET_SH2E && ((MODE) == SFmode))                 \
    ? FIRST_FP_PARM_REG                                 \
    : TARGET_SH4 && (GET_MODE_CLASS (MODE) == MODE_FLOAT        \
                    || GET_MODE_CLASS (MODE) == MODE_COMPLEX_FLOAT)\
@@ -1496,7 +1555,7 @@ extern const enum reg_class reg_class_from_letter[];
 
 /* 1 if N is a possible register number for a function value.  */
 #define FUNCTION_VALUE_REGNO_P(REGNO) \
-  ((REGNO) == FIRST_RET_REG || (TARGET_SH3E && (REGNO) == FIRST_FP_RET_REG) \
+  ((REGNO) == FIRST_RET_REG || (TARGET_SH2E && (REGNO) == FIRST_FP_RET_REG) \
    || (TARGET_SHMEDIA_FPU && (REGNO) == FIRST_FP_RET_REG))
 
 /* 1 if N is a possible register number for function argument passing.  */
@@ -1522,7 +1581,7 @@ enum sh_arg_class { SH_ARG_INT = 0, SH_ARG_FLOAT = 1 };
 struct sh_args {
     int arg_count[2];
     int force_mem;
-  /* Non-zero if a prototype is available for the function.  */
+  /* Nonzero if a prototype is available for the function.  */
     int prototype_p;
   /* The number of an odd floating-point register, that should be used
      for the next argument of type float.  */
@@ -1700,13 +1759,6 @@ struct sh_args {
     (CUM).outgoing = 0;                                                \
   } while (0)
  
-/* FIXME: This is overly conservative.  A SHcompact function that
-   receives arguments ``by reference'' will have them stored in its
-   own stack frame, so it must not pass pointers or references to
-   these arguments to other functions by means of sibling calls.  */
-#define FUNCTION_OK_FOR_SIBCALL(DECL) \
-  (! TARGET_SHCOMPACT || current_function_args_info.stack_regs == 0)
-
 /* Update the data in CUM to advance over an argument
    of mode MODE and data type TYPE.
    (TYPE is null for libcalls where that information may not be
@@ -1837,7 +1889,7 @@ struct sh_args {
     || (! TREE_ADDRESSABLE ((tree)(TYPE)) \
        && (! TARGET_HITACHI || ! AGGREGATE_TYPE_P (TYPE)))) \
    && ! (CUM).force_mem \
-   && (TARGET_SH3E \
+   && (TARGET_SH2E \
        ? ((MODE) == BLKmode \
          ? (((CUM).arg_count[(int) SH_ARG_INT] * UNITS_PER_WORD \
              + int_size_in_bytes (TYPE)) \
@@ -2018,7 +2070,7 @@ struct sh_args {
    : 0)
 
 #define SH5_WOULD_BE_PARTIAL_NREGS(CUM, MODE, TYPE, NAMED) \
-  (TARGET_SH5 && (MODE) == BLKmode                             \
+  (TARGET_SH5 && ((MODE) == BLKmode || (MODE) == TImode)       \
    && ((CUM).arg_count[(int) SH_ARG_INT]                       \
        + (int_size_in_bytes (TYPE) + 7) / 8) > NPARM_REGS (SImode))
 
@@ -2130,8 +2182,6 @@ while (0)
 \f
 /* Addressing modes, and classification of registers for them.  */
 #define HAVE_POST_INCREMENT  TARGET_SH1
-/*#define HAVE_PRE_INCREMENT   1*/
-/*#define HAVE_POST_DECREMENT  1*/
 #define HAVE_PRE_DECREMENT   TARGET_SH1
 
 #define USE_LOAD_POST_INCREMENT(mode)    ((mode == SImode || mode == DImode) \
@@ -2182,7 +2232,7 @@ while (0)
       || 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)))))
+      || (TARGET_SH2E && (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.
@@ -2271,9 +2321,15 @@ while (0)
   (GET_CODE (OP) == CONST && GET_CODE (XEXP ((OP), 0)) == UNSPEC \
    && XINT (XEXP ((OP), 0), 1) == UNSPEC_GOTPLT)
 
+#define UNSPEC_GOTOFF_P(OP) \
+  (GET_CODE (OP) == UNSPEC && XINT ((OP), 1) == UNSPEC_GOTOFF)
+
 #define GOTOFF_P(OP) \
-  (GET_CODE (OP) == CONST && GET_CODE (XEXP ((OP), 0)) == UNSPEC \
-   && XINT (XEXP ((OP), 0), 1) == UNSPEC_GOTOFF)
+  (GET_CODE (OP) == CONST \
+   && (UNSPEC_GOTOFF_P (XEXP ((OP), 0)) \
+       || (GET_CODE (XEXP ((OP), 0)) == PLUS \
+           && UNSPEC_GOTOFF_P (XEXP (XEXP ((OP), 0), 0)) \
+          && GET_CODE (XEXP (XEXP ((OP), 0), 1)) == CONST_INT)))
 
 #define PIC_ADDR_P(OP) \
   (GET_CODE (OP) == CONST && GET_CODE (XEXP ((OP), 0)) == UNSPEC \
@@ -2310,12 +2366,18 @@ while (0)
           ? sh_const_vec ((OP), VOIDmode) \
           : sh_1el_vec ((OP), VOIDmode))))
 
+#define EXTRA_CONSTRAINT_Z(OP) \
+  (GET_CODE (OP) == CONST_INT \
+   && (INTVAL (OP) == (unsigned) 0xffffffff \
+       || INTVAL (OP) == (HOST_WIDE_INT) -1 << 32))
+
 #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) \
+   : (C) == 'Z' ? EXTRA_CONSTRAINT_Z (OP) \
    : 0)
 \f
 /* GO_IF_LEGITIMATE_ADDRESS recognizes an RTL expression
@@ -2325,7 +2387,7 @@ while (0)
 
 #define MODE_DISP_OK_4(X,MODE) \
 (GET_MODE_SIZE (MODE) == 4 && (unsigned) INTVAL (X) < 64       \
- && ! (INTVAL (X) & 3) && ! (TARGET_SH3E && (MODE) == SFmode))
+ && ! (INTVAL (X) & 3) && ! (TARGET_SH2E && (MODE) == SFmode))
 
 #define MODE_DISP_OK_8(X,MODE) \
 ((GET_MODE_SIZE(MODE)==8) && ((unsigned)INTVAL(X)<60)  \
@@ -2356,7 +2418,7 @@ while (0)
          REG++
          --REG  */
 
-/* ??? The SH3e does not have the REG+disp addressing mode when loading values
+/* ??? The SH2e does not have the REG+disp addressing mode when loading values
    into the FRx registers.  We implement this by setting the maximum offset
    to zero when the value is SFmode.  This also restricts loading of SFmode
    values into the integer registers, but that can't be helped.  */
@@ -2442,7 +2504,7 @@ while (0)
       && BASE_REGISTER_RTX_P (XEXP ((X), 0))                   \
       && ! TARGET_SHMEDIA                                      \
       && ! (TARGET_SH4 && (MODE) == DFmode)                    \
-      && ! (TARGET_SH3E && (MODE) == SFmode))                  \
+      && ! (TARGET_SH2E && (MODE) == SFmode))                  \
     {                                                          \
       rtx index_rtx = XEXP ((X), 1);                           \
       HOST_WIDE_INT offset = INTVAL (index_rtx), offset_base;  \
@@ -2497,7 +2559,7 @@ while (0)
       HOST_WIDE_INT offset = INTVAL (index_rtx), offset_base;          \
       rtx sum;                                                         \
                                                                        \
-      if (TARGET_SH3E && MODE == SFmode)                               \
+      if (TARGET_SH2E && MODE == SFmode)                               \
        {                                                               \
          X = copy_rtx (X);                                             \
          push_reload (index_rtx, NULL_RTX, &XEXP (X, 1), NULL,         \
@@ -2536,7 +2598,7 @@ while (0)
           && BASE_REGISTER_RTX_P (XEXP (XEXP (X, 0), 0))               \
           && GET_CODE (XEXP (X, 1)) == CONST_INT                       \
           && ! TARGET_SHMEDIA                                          \
-          && ! (TARGET_SH3E && MODE == SFmode))                        \
+          && ! (TARGET_SH2E && MODE == SFmode))                        \
     {                                                                  \
       /* Because this address is so complex, we know it must have      \
         been created by LEGITIMIZE_RELOAD_ADDRESS before; thus,        \
@@ -2563,7 +2625,7 @@ while (0)
 \f
 /* Specify the machine mode that this machine uses
    for the index in the tablejump instruction.  */
-#define CASE_VECTOR_MODE (TARGET_BIGTABLE ? SImode : HImode)
+#define CASE_VECTOR_MODE ((! optimize || TARGET_BIGTABLE) ? SImode : HImode)
 
 #define CASE_VECTOR_SHORTEN_MODE(MIN_OFFSET, MAX_OFFSET, BODY) \
 ((MIN_OFFSET) >= 0 && (MAX_OFFSET) <= 127 \
@@ -2582,9 +2644,9 @@ while (0)
 /* Define it here, so that it doesn't get bumped to 64-bits on SHmedia.  */
 #define FLOAT_TYPE_SIZE 32
 
-/* Since the SH3e has only `float' support, it is desirable to make all
+/* Since the SH2e has only `float' support, it is desirable to make all
    floating point types equivalent to `float'.  */
-#define DOUBLE_TYPE_SIZE ((TARGET_SH3E && ! TARGET_SH4) ? 32 : 64)
+#define DOUBLE_TYPE_SIZE ((TARGET_SH2E && ! TARGET_SH4) ? 32 : 64)
 
 /* 'char' is signed by default.  */
 #define DEFAULT_SIGNED_CHAR  1
@@ -2668,70 +2730,6 @@ while (0)
 #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) \
-            && CONST_OK_FOR_L (INTVAL (RTX)))  \
-      return 1;                                        \
-    else                                       \
-      return 8;                                        \
-  case CONST:                                  \
-  case LABEL_REF:                              \
-  case SYMBOL_REF:                             \
-    if (TARGET_SHMEDIA64)                      \
-      return COSTS_N_INSNS (4);                        \
-    if (TARGET_SHMEDIA32)                      \
-      return COSTS_N_INSNS (2);                        \
-    return 5;                                  \
-  case CONST_DOUBLE:                           \
-    if (TARGET_SHMEDIA)                                \
-      return COSTS_N_INSNS (4);                        \
-    else                                       \
-      return 10;
-
-#define RTX_COSTS(X, CODE, OUTER_CODE)                 \
-  case PLUS:                                           \
-    return COSTS_N_INSNS (addsubcosts (X));            \
-  case AND:                                            \
-    return COSTS_N_INSNS (andcosts (X));               \
-  case MULT:                                           \
-    return COSTS_N_INSNS (multcosts (X));              \
-  case ASHIFT:                                         \
-  case ASHIFTRT:                                       \
-  case LSHIFTRT:                                       \
-    return COSTS_N_INSNS (shiftcosts (X));             \
-  case DIV:                                            \
-  case UDIV:                                           \
-  case MOD:                                            \
-  case UMOD:                                           \
-    return COSTS_N_INSNS (20);                         \
-  case FLOAT:                                          \
-  case FIX:                                            \
-    return 100;
-
 /* The multiply insn on the SH1 and the divide insns on the SH1 and SH2
    are actually function calls with some special constraints on arguments
    and register usage.
@@ -2790,49 +2788,37 @@ while (0)
 ((GET_CODE (X) == SYMBOL_REF || GET_CODE (X) == LABEL_REF)     \
   && nonpic_symbol_mentioned_p (X))
 \f
-/* Compute the cost of an address.  For the SH, all valid addresses are
-   the same cost.  Use a slightly higher cost for reg + reg addressing,
-   since it increases pressure on r0.  */
+/* TLS.  */
 
-#define ADDRESS_COST(X) (GET_CODE (X) == PLUS && ! CONSTANT_P (XEXP (X, 1)) \
-                        && ! TARGET_SHMEDIA \
-                        ? 1 : 0)
+/* The prefix used to mark SYMBOL_REFs that refer to TLS symbols.  */
+#define SH_TLS_ENCODING "@"
 
+/* Return true if SYM_NAME starts with SH_TLS_ENCODING.  */
+#define TLS_SYMNAME_P(SYM_NAME) \
+  ((SYM_NAME)[0] == SH_TLS_ENCODING[0])
+
+/* Skip an optional SH_TLS_ENCODING in the beginning of SYM_NAME.  */
+#define STRIP_TLS_ENCODING(VAR, SYM_NAME) \
+  (VAR) = (SYM_NAME) + (TLS_SYMNAME_P (SYM_NAME) \
+                       ? strlen (SH_TLS_ENCODING) + 1 : 0)
+\f
 /* Compute extra cost of moving data between one register class
    and another.  */
 
-/* Regclass always uses 2 for moves in the same register class;
-   If SECONDARY*_RELOAD_CLASS says something about the src/dst pair,
-   it uses this information.  Hence, the general register <-> floating point
+/* If SECONDARY*_RELOAD_CLASS says something about the src/dst pair, regclass
+   uses this information.  Hence, the general register <-> floating point
    register information here is not used for SFmode.  */
+
+#define REGCLASS_HAS_GENERAL_REG(CLASS) \
+  ((CLASS) == GENERAL_REGS || (CLASS) == R0_REGS \
+    || (! TARGET_SHMEDIA && (CLASS) == SIBCALL_REGS))
+
+#define REGCLASS_HAS_FP_REG(CLASS) \
+  ((CLASS) == FP0_REGS || (CLASS) == FP_REGS \
+   || (CLASS) == DF_REGS || (CLASS) == DF_HI_REGS)
+
 #define REGISTER_MOVE_COST(MODE, SRCCLASS, DSTCLASS) \
- (((((DSTCLASS) == T_REGS) || ((DSTCLASS) == PR_REGS)) ? 10            \
-   : ((((DSTCLASS) == FP0_REGS || (DSTCLASS) == FP_REGS                        \
-       || (DSTCLASS) == DF_REGS || (DSTCLASS) == DF_HI_REGS)           \
-       && ((SRCCLASS) == GENERAL_REGS || (SRCCLASS) == R0_REGS))       \
-      || (((DSTCLASS) == GENERAL_REGS || (DSTCLASS) == R0_REGS)                \
-         && ((SRCCLASS) == FP0_REGS || (SRCCLASS) == FP_REGS           \
-             || (SRCCLASS) == DF_REGS || (SRCCLASS) == DF_HI_REGS)))   \
-   ? (TARGET_SHMEDIA ? 4                                               \
-      : TARGET_FMOVD ? 8 : 12)                                         \
-   : (((DSTCLASS) == FPUL_REGS                                         \
-       && ((SRCCLASS) == GENERAL_REGS || (SRCCLASS) == R0_REGS))       \
-      || (SRCCLASS == FPUL_REGS                                                \
-         && ((DSTCLASS) == GENERAL_REGS || (DSTCLASS) == R0_REGS)))    \
-   ? 5                                                                 \
-   : (((DSTCLASS) == FPUL_REGS                                         \
-       && ((SRCCLASS) == PR_REGS || (SRCCLASS) == MAC_REGS             \
-           || (SRCCLASS) == T_REGS))                                   \
-      || ((SRCCLASS) == FPUL_REGS                                      \
-         && ((DSTCLASS) == PR_REGS || (DSTCLASS) == MAC_REGS)))        \
-   ? 7                                                                 \
-   : (((SRCCLASS) == TARGET_REGS && (DSTCLASS) != GENERAL_REGS)                \
-      || ((DSTCLASS) == TARGET_REGS && (SRCCLASS) != GENERAL_REGS))    \
-   ? 20                                                                        \
-   : (((SRCCLASS) == FPSCR_REGS && (DSTCLASS) != GENERAL_REGS)         \
-      || ((DSTCLASS) == FPSCR_REGS && (SRCCLASS) != GENERAL_REGS))     \
-   ? 4                                                                 \
-   : 2) * ((MODE) == V16SFmode ? 8 : (MODE) == V4SFmode ? 2 : 1))
+  sh_register_move_cost ((MODE), (SRCCLASS), (DSTCLASS))
 
 /* ??? Perhaps make MEMORY_MOVE_COST depend on compiler option?  This
    would be so that people with slow memory systems could generate
@@ -2942,6 +2928,8 @@ while (0)
    to match gdb.  */
 /* svr4.h undefines this macro, yet we really want to use the same numbers
    for coff as for elf, so we go via another macro: SH_DBX_REGISTER_NUMBER.  */
+/* expand_builtin_init_dwarf_reg_sizes uses this to test if a
+   register exists, so we should return -1 for invalid register numbers.  */
 #define DBX_REGISTER_NUMBER(REGNO) SH_DBX_REGISTER_NUMBER (REGNO)
 
 #define SH_DBX_REGISTER_NUMBER(REGNO) \
@@ -2956,6 +2944,8 @@ while (0)
    ? ((REGNO) - FIRST_TARGET_REG + 68) \
    : (REGNO) == PR_REG \
    ? (TARGET_SH5 ? 241 : 17) \
+   : (REGNO) == PR_MEDIA_REG \
+   ? (TARGET_SH5 ? 18 : -1) \
    : (REGNO) == T_REG \
    ? (TARGET_SH5 ? 242 : 18) \
    : (REGNO) == GBR_REG \
@@ -2966,15 +2956,16 @@ while (0)
    ? (TARGET_SH5 ? 240 : 21) \
    : (REGNO) == FPUL_REG \
    ? (TARGET_SH5 ? 244 : 23) \
-   : (abort(), -1))
+   : -1)
 
 /* This is how to output a reference to a user-level label named NAME.  */
 #define ASM_OUTPUT_LABELREF(FILE, NAME)                        \
   do                                                   \
     {                                                  \
-      char * lname;                                    \
+      const char * lname;                              \
                                                        \
       STRIP_DATALABEL_ENCODING (lname, (NAME));                \
+      STRIP_TLS_ENCODING (lname, lname);               \
       if (lname[0] == '*')                             \
        fputs (lname + 1, (FILE));                      \
       else                                             \
@@ -2995,10 +2986,6 @@ while (0)
     }                                                  \
   while (0)
 
-/* Output a label definition.  */
-#define ASM_OUTPUT_LABEL(FILE,NAME) \
-  do { assemble_name ((FILE), (NAME)); fputs (":\n", (FILE)); } while (0)
-
 /* This is how to output an assembler line
    that says to advance the location counter
    to a multiple of 2**LOG bytes.  */
@@ -3007,19 +2994,11 @@ while (0)
   if ((LOG) != 0)                      \
     fprintf ((FILE), "\t.align %d\n", (LOG))
 
-/* 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)))
+/* Globalizing directive for a label.  */
+#define GLOBAL_ASM_OP "\t.global\t"
 
 /* #define ASM_OUTPUT_CASE_END(STREAM,NUM,TABLE)           */
 
-/* Construct a private name.  */
-#define ASM_FORMAT_PRIVATE_NAME(OUTVAR,NAME,NUMBER)    \
-  ((OUTVAR) = (char *) alloca (strlen (NAME) + 10),    \
-   sprintf ((OUTVAR), "%s.%d", (NAME), (NUMBER)))
-
 /* Output a relative address table.  */
 
 #define ASM_OUTPUT_ADDR_DIFF_ELT(STREAM,BODY,VALUE,REL)                \
@@ -3059,7 +3038,7 @@ while (0)
 /* Output an absolute table element.  */
 
 #define ASM_OUTPUT_ADDR_VEC_ELT(STREAM,VALUE)                                  \
-  if (TARGET_BIGTABLE)                                                         \
+  if (! optimize || TARGET_BIGTABLE)                                   \
     asm_fprintf ((STREAM), "\t.long\t%LL%d\n", (VALUE));               \
   else                                                                 \
     asm_fprintf ((STREAM), "\t.word\t%LL%d\n", (VALUE));
@@ -3125,6 +3104,18 @@ while (0)
            output_addr_const ((STREAM), XVECEXP ((X), 0, 0));          \
            fputs ("@GOTPLT", (STREAM));                                \
            break;                                                      \
+         case UNSPEC_DTPOFF:                                           \
+           output_addr_const ((STREAM), XVECEXP ((X), 0, 0));          \
+           fputs ("@DTPOFF", (STREAM));                                \
+           break;                                                      \
+         case UNSPEC_GOTTPOFF:                                         \
+           output_addr_const ((STREAM), XVECEXP ((X), 0, 0));          \
+           fputs ("@GOTTPOFF", (STREAM));                              \
+           break;                                                      \
+         case UNSPEC_TPOFF:                                            \
+           output_addr_const ((STREAM), XVECEXP ((X), 0, 0));          \
+           fputs ("@TPOFF", (STREAM));                                 \
+           break;                                                      \
          case UNSPEC_CALLER:                                           \
            {                                                           \
              char name[32];                                            \
@@ -3153,6 +3144,7 @@ extern struct rtx_def *sh_compare_op1;
 enum processor_type {
   PROCESSOR_SH1,
   PROCESSOR_SH2,
+  PROCESSOR_SH2E,
   PROCESSOR_SH3,
   PROCESSOR_SH3E,
   PROCESSOR_SH4,
@@ -3183,10 +3175,10 @@ extern enum mdep_reorg_phase_e mdep_reorg_phase;
 #define TARGET_MEM_FUNCTIONS
 
 /* Handle Hitachi compiler's pragmas.  */
-#define REGISTER_TARGET_PRAGMAS(PFILE) do {                                \
-  cpp_register_pragma (PFILE, 0, "interrupt", sh_pr_interrupt);                    \
-  cpp_register_pragma (PFILE, 0, "trapa", sh_pr_trapa);                            \
-  cpp_register_pragma (PFILE, 0, "nosave_low_regs", sh_pr_nosave_low_regs); \
+#define REGISTER_TARGET_PRAGMAS() do {                                 \
+  c_register_pragma (0, "interrupt", sh_pr_interrupt);                 \
+  c_register_pragma (0, "trapa", sh_pr_trapa);                         \
+  c_register_pragma (0, "nosave_low_regs", sh_pr_nosave_low_regs);     \
 } while (0)
 
 /* Set when processing a function with pragma interrupt turned on.  */
@@ -3220,6 +3212,7 @@ extern int rtx_equal_function_value_matters;
   {"arith_reg_operand", {SUBREG, REG}},                                        \
   {"arith_reg_or_0_operand", {SUBREG, REG, CONST_INT, CONST_VECTOR}},  \
   {"binary_float_operator", {PLUS, MINUS, MULT, DIV}},                 \
+  {"binary_logical_operator", {AND, IOR, XOR}},                                \
   {"commutative_float_operator", {PLUS, MULT}},                                \
   {"equality_comparison_operator", {EQ,NE}},                           \
   {"extend_reg_operand", {SUBREG, REG, TRUNCATE}},                     \
@@ -3238,6 +3231,7 @@ extern int rtx_equal_function_value_matters;
   {"mextr_bit_offset", {CONST_INT}},                                   \
   {"noncommutative_float_operator", {MINUS, DIV}},                     \
   {"shmedia_6bit_operand", {SUBREG, REG, CONST_INT}},                  \
+  {"sh_register_operand", {REG, SUBREG, CONST_INT}},                   \
   {"target_reg_operand", {SUBREG, REG}},                               \
   {"target_operand", {SUBREG, REG, LABEL_REF, SYMBOL_REF, CONST, UNSPEC}},\
   {"trunc_hi_operand", {SUBREG, REG, TRUNCATE}},                       \
@@ -3278,6 +3272,8 @@ extern int rtx_equal_function_value_matters;
 #define PROMOTE_FUNCTION_ARGS
 #define PROMOTE_FUNCTION_RETURN
 
+#define MAX_FIXED_MODE_SIZE (TARGET_SH5 ? 128 : 64)
+
 /* ??? Define ACCUMULATE_OUTGOING_ARGS?  This is more efficient than pushing
    and poping arguments.  However, we do have push/pop instructions, and
    rather limited offsets (4 bits) in load/store instructions, so it isn't
@@ -3297,7 +3293,7 @@ extern int rtx_equal_function_value_matters;
    : TARGET_FPU_SINGLE ? FP_MODE_SINGLE \
    : FP_MODE_DOUBLE)
 
-#define EPILOGUE_USES(REGNO)       ((TARGET_SH3E || TARGET_SH4)                \
+#define EPILOGUE_USES(REGNO)       ((TARGET_SH2E || TARGET_SH4)                \
                                    && (REGNO) == FPSCR_REG)
 
 #define MODE_NEEDED(ENTITY, INSN)                                      \
@@ -3314,7 +3310,13 @@ extern int rtx_equal_function_value_matters;
 #define MD_CAN_REDIRECT_BRANCH(INSN, SEQ) \
   sh_can_redirect_branch ((INSN), (SEQ))
 
-#define DWARF_FRAME_RETURN_COLUMN (TARGET_SH5 ? PR_MEDIA_REG : PR_REG)
+#define DWARF_FRAME_RETURN_COLUMN \
+  (TARGET_SH5 ? DWARF_FRAME_REGNUM (PR_MEDIA_REG) : DWARF_FRAME_REGNUM (PR_REG))
+
+#define EH_RETURN_DATA_REGNO(N)        \
+  ((N) < 4 ? (N) + (TARGET_SH5 ? 2 : 4) : INVALID_REGNUM)
+
+#define EH_RETURN_STACKADJ_RTX gen_rtx_REG (Pmode, STATIC_CHAIN_REGNUM)
 
 #if (defined CRT_BEGIN || defined CRT_END) && ! __SHMEDIA__
 /* SH constant pool breaks the devices in crtstuff.c to control section