OSDN Git Service

* config/sh/sh-protos.h (sh_optimization_options): Declare.
[pf3gnuchains/gcc-fork.git] / gcc / config / sh / sh.h
index a6652df..7f90147 100644 (file)
@@ -1,6 +1,6 @@
 /* Definitions of target machine for GNU compiler for Renesas / SuperH SH.
    Copyright (C) 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
-   2003, 2004, 2005 Free Software Foundation, Inc.
+   2003, 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation, Inc.
    Contributed by Steve Chamberlain (sac@cygnus.com).
    Improved by Jim Wilson (wilson@cygnus.com).
 
@@ -8,7 +8,7 @@ This file is part of GCC.
 
 GCC is free software; you can redistribute it and/or modify
 it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2, or (at your option)
+the Free Software Foundation; either version 3, or (at your option)
 any later version.
 
 GCC is distributed in the hope that it will be useful,
@@ -17,13 +17,14 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 GNU General Public License for more details.
 
 You should have received a copy of the GNU General Public License
-along with GCC; see the file COPYING.  If not, write to
-the Free Software Foundation, 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA.  */
+along with GCC; see the file COPYING3.  If not see
+<http://www.gnu.org/licenses/>.  */
 
 #ifndef GCC_SH_H
 #define GCC_SH_H
 
+#include "config/vxworks-dummy.h"
+
 #define TARGET_VERSION \
   fputs (" (Hitachi SH)", stderr);
 
@@ -92,11 +93,6 @@ do { \
     builtin_define ("__HITACHI__"); \
   builtin_define (TARGET_LITTLE_ENDIAN \
                  ? "__LITTLE_ENDIAN__" : "__BIG_ENDIAN__"); \
-  if (flag_pic) \
-    { \
-      builtin_define ("__pic__"); \
-      builtin_define ("__PIC__"); \
-    } \
 } while (0)
 
 /* We can not debug without a frame pointer.  */
@@ -174,7 +170,8 @@ do { \
 #define TARGET_HARVARD (TARGET_HARD_SH4 || TARGET_SH5)
 
 /* Nonzero if a double-precision FPU is available.  */
-#define TARGET_FPU_DOUBLE (TARGET_SH4 || TARGET_SH2A_DOUBLE)
+#define TARGET_FPU_DOUBLE \
+  ((target_flags & MASK_SH4) != 0 || TARGET_SH2A_DOUBLE)
 
 /* Nonzero if an FPU is available.  */
 #define TARGET_FPU_ANY (TARGET_SH2E || TARGET_FPU_DOUBLE)
@@ -238,6 +235,9 @@ do { \
 #define TARGET_DIVIDE_INV20L (sh_div_strategy == SH_DIV_INV20L)
 #define TARGET_DIVIDE_INV_CALL (sh_div_strategy == SH_DIV_INV_CALL)
 #define TARGET_DIVIDE_INV_CALL2 (sh_div_strategy == SH_DIV_INV_CALL2)
+#define TARGET_DIVIDE_CALL_DIV1 (sh_div_strategy == SH_DIV_CALL_DIV1)
+#define TARGET_DIVIDE_CALL_FP (sh_div_strategy == SH_DIV_CALL_FP)
+#define TARGET_DIVIDE_CALL_TABLE (sh_div_strategy == SH_DIV_CALL_TABLE)
 
 #define SELECT_SH1               (MASK_SH1)
 #define SELECT_SH2               (MASK_SH2 | SELECT_SH1)
@@ -275,6 +275,7 @@ do { \
 #endif
 #if SUPPORT_SH2
 #define SUPPORT_SH3 1
+#define SUPPORT_SH2A_NOFPU 1
 #endif
 #if SUPPORT_SH3
 #define SUPPORT_SH4_NOFPU 1
@@ -282,16 +283,17 @@ do { \
 #if SUPPORT_SH4_NOFPU
 #define SUPPORT_SH4A_NOFPU 1
 #define SUPPORT_SH4AL 1
-#define SUPPORT_SH2A_NOFPU 1
 #endif
 
 #if SUPPORT_SH2E
 #define SUPPORT_SH3E 1
+#define SUPPORT_SH2A_SINGLE_ONLY 1
 #endif
 #if SUPPORT_SH3E
 #define SUPPORT_SH4_SINGLE_ONLY 1
+#endif
+#if SUPPORT_SH4_SINGLE_ONLY
 #define SUPPORT_SH4A_SINGLE_ONLY 1
-#define SUPPORT_SH2A_SINGLE_ONLY 1
 #endif
 
 #if SUPPORT_SH4
@@ -367,9 +369,9 @@ do { \
   SUBTARGET_EXTRA_SPECS
 
 #if TARGET_CPU_DEFAULT & MASK_HARD_SH4
-#define SUBTARGET_ASM_RELAX_SPEC "%{!m1:%{!m2:%{!m3*:%{!m5*:-isa=sh4}}}}"
+#define SUBTARGET_ASM_RELAX_SPEC "%{!m1:%{!m2:%{!m3*:%{!m5*:-isa=sh4-up}}}}"
 #else
-#define SUBTARGET_ASM_RELAX_SPEC "%{m4*:-isa=sh4}"
+#define SUBTARGET_ASM_RELAX_SPEC "%{m4*:-isa=sh4-up}"
 #endif
 
 #define SH_ASM_SPEC \
@@ -457,51 +459,32 @@ do { \
 #endif
 
 #define DRIVER_SELF_SPECS "%{m2a:%{ml:%eSH2a does not support little-endian}}"
-#define OPTIMIZATION_OPTIONS(LEVEL,SIZE)                               \
-do {                                                                   \
-  if (LEVEL)                                                           \
-    {                                                                  \
-      flag_omit_frame_pointer = -1;                                    \
-      if (! SIZE)                                                      \
-       sh_div_str = "inv:minlat";                                      \
-    }                                                                  \
-  if (SIZE)                                                            \
-    {                                                                  \
-      target_flags |= MASK_SMALLCODE;                                  \
-      sh_div_str = SH_DIV_STR_FOR_SIZE ;                               \
-    }                                                                  \
-  /* We can't meaningfully test TARGET_SHMEDIA here, because -m options        \
-     haven't been parsed yet, hence we';d read only the default.       \
-     sh_target_reg_class will return NO_REGS if this is not SHMEDIA, so        \
-     it's OK to always set flag_branch_target_load_optimize.  */       \
-  if (LEVEL > 1)                                                       \
-    {                                                                  \
-      flag_branch_target_load_optimize = 1;                            \
-      if (! (SIZE))                                                    \
-       target_flags |= MASK_SAVE_ALL_TARGET_REGS;                      \
-    }                                                                  \
-  /* Likewise, we can't meaningfully test TARGET_SH2E / TARGET_IEEE    \
-     here, so leave it to OVERRIDE_OPTIONS to set                      \
-    flag_finite_math_only.  We set it to 2 here so we know if the user \
-    explicitly requested this to be on or off.  */                     \
-  flag_finite_math_only = 2;                                           \
-} while (0)
+
+#define OPTIMIZATION_OPTIONS(LEVEL,SIZE) sh_optimization_options (LEVEL, SIZE)
 
 #define ASSEMBLER_DIALECT assembler_dialect
 
 extern int assembler_dialect;
 
 enum sh_divide_strategy_e {
+  /* SH5 strategies.  */
   SH_DIV_CALL,
   SH_DIV_CALL2,
-  SH_DIV_FP,
+  SH_DIV_FP, /* We could do this also for SH4.  */
   SH_DIV_INV,
   SH_DIV_INV_MINLAT,
   SH_DIV_INV20U,
   SH_DIV_INV20L,
   SH_DIV_INV_CALL,
   SH_DIV_INV_CALL2,
-  SH_DIV_INV_FP
+  SH_DIV_INV_FP,
+  /* SH1 .. SH4 strategies.  Because of the small number of registers
+     available, the compiler uses knowledge of the actual set of registers
+     being clobbered by the different functions called.  */
+  SH_DIV_CALL_DIV1, /* No FPU, medium size, highest latency.  */
+  SH_DIV_CALL_FP,     /* FPU needed, small size, high latency.  */
+  SH_DIV_CALL_TABLE,  /* No FPU, large size, medium latency. */
+  SH_DIV_INTRINSIC
 };
 
 extern enum sh_divide_strategy_e sh_div_strategy;
@@ -510,187 +493,12 @@ extern enum sh_divide_strategy_e sh_div_strategy;
 #define SH_DIV_STRATEGY_DEFAULT SH_DIV_CALL
 #endif
 
-#define OVERRIDE_OPTIONS                                               \
-do {                                                                   \
-  int regno;                                                           \
-                                                                       \
-  if (flag_finite_math_only == 2)                                      \
-    flag_finite_math_only                                              \
-      = !flag_signaling_nans && TARGET_SH2E && ! TARGET_IEEE;          \
-  if (TARGET_SH2E && !flag_finite_math_only)                           \
-    target_flags |= MASK_IEEE;                                         \
-  sh_cpu = CPU_SH1;                                                    \
-  assembler_dialect = 0;                                               \
-  if (TARGET_SH2)                                                      \
-    sh_cpu = CPU_SH2;                                                  \
-  if (TARGET_SH2E)                                                     \
-    sh_cpu = CPU_SH2E;                                                 \
-  if (TARGET_SH2A)                                                     \
-    {                                                                  \
-      sh_cpu = CPU_SH2A;                                               \
-      if (TARGET_SH2A_DOUBLE)                                          \
-        target_flags |= MASK_FMOVD;                                    \
-    }                                                                  \
-  if (TARGET_SH3)                                                      \
-    sh_cpu = CPU_SH3;                                                  \
-  if (TARGET_SH3E)                                                     \
-    sh_cpu = CPU_SH3E;                                                 \
-  if (TARGET_SH4)                                                      \
-    {                                                                  \
-      assembler_dialect = 1;                                           \
-      sh_cpu = CPU_SH4;                                                        \
-    }                                                                  \
-  if (TARGET_SH4A_ARCH)                                                        \
-    {                                                                  \
-      assembler_dialect = 1;                                           \
-      sh_cpu = CPU_SH4A;                                               \
-    }                                                                  \
-  if (TARGET_SH5)                                                      \
-    {                                                                  \
-      sh_cpu = CPU_SH5;                                                        \
-      target_flags |= MASK_ALIGN_DOUBLE;                               \
-      if (TARGET_SHMEDIA_FPU)                                          \
-       target_flags |= MASK_FMOVD;                                     \
-      if (TARGET_SHMEDIA)                                              \
-       {                                                               \
-         /* There are no delay slots on SHmedia.  */                   \
-         flag_delayed_branch = 0;                                      \
-         /* Relaxation isn't yet supported for SHmedia */              \
-         target_flags &= ~MASK_RELAX;                                  \
-         /* After reload, if conversion does little good but can cause \
-            ICEs:                                                      \
-            - find_if_block doesn't do anything for SH because we don't\
-              have conditional execution patterns.  (We use conditional\
-              move patterns, which are handled differently, and only   \
-              before reload).                                          \
-            - find_cond_trap doesn't do anything for the SH because we \       
-              don't have conditional traps.                            \
-            - find_if_case_1 uses redirect_edge_and_branch_force in    \
-              the only path that does an optimization, and this causes \
-              an ICE when branch targets are in registers.             \
-            - find_if_case_2 doesn't do anything for the SHmedia after \
-              reload except when it can redirect a tablejump - and     \
-              that's rather rare.  */                                  \
-         flag_if_conversion2 = 0;                                      \
-         if (! strcmp (sh_div_str, "call"))                            \
-           sh_div_strategy = SH_DIV_CALL;                              \
-         else if (! strcmp (sh_div_str, "call2"))                      \
-           sh_div_strategy = SH_DIV_CALL2;                             \
-         if (! strcmp (sh_div_str, "fp") && TARGET_FPU_ANY)            \
-           sh_div_strategy = SH_DIV_FP;                                \
-         else if (! strcmp (sh_div_str, "inv"))                        \
-           sh_div_strategy = SH_DIV_INV;                               \
-         else if (! strcmp (sh_div_str, "inv:minlat"))                 \
-           sh_div_strategy = SH_DIV_INV_MINLAT;                        \
-         else if (! strcmp (sh_div_str, "inv20u"))                     \
-           sh_div_strategy = SH_DIV_INV20U;                            \
-         else if (! strcmp (sh_div_str, "inv20l"))                     \
-           sh_div_strategy = SH_DIV_INV20L;                            \
-         else if (! strcmp (sh_div_str, "inv:call2"))                  \
-           sh_div_strategy = SH_DIV_INV_CALL2;                         \
-         else if (! strcmp (sh_div_str, "inv:call"))                   \
-           sh_div_strategy = SH_DIV_INV_CALL;                          \
-         else if (! strcmp (sh_div_str, "inv:fp"))                     \
-           {                                                           \
-             if (TARGET_FPU_ANY)                                       \
-               sh_div_strategy = SH_DIV_INV_FP;                        \
-             else                                                      \
-               sh_div_strategy = SH_DIV_INV;                           \
-           }                                                           \
-       }                                                               \
-      /* -fprofile-arcs needs a working libgcov .  In unified tree     \
-        configurations with newlib, this requires to configure with    \
-        --with-newlib --with-headers.  But there is no way to check    \
-        here we have a working libgcov, so just assume that we have.  */\
-      if (profile_flag)                                                        \
-       warning (0, "Profiling is still experimental for this target.");\
-    }                                                                  \
-  else                                                                 \
-    {                                                                  \
-       /* Only the sh64-elf assembler fully supports .quad properly.  */\
-       targetm.asm_out.aligned_op.di = NULL;                           \
-       targetm.asm_out.unaligned_op.di = NULL;                         \
-    }                                                                  \
-  if (sh_divsi3_libfunc[0])                                            \
-    ; /* User supplied - leave it alone.  */                           \
-  else if (TARGET_HARD_SH4 && TARGET_SH2E)                             \
-    sh_divsi3_libfunc = "__sdivsi3_i4";                                        \
-  else if (TARGET_SH5)                                                 \
-    {                                                                  \
-      if (TARGET_FPU_ANY && TARGET_SH1)                                        \
-       sh_divsi3_libfunc = "__sdivsi3_i4";                             \
-      else                                                             \
-       sh_divsi3_libfunc = "__sdivsi3_1";                              \
-    }                                                                  \
-  else                                                                 \
-    sh_divsi3_libfunc = "__sdivsi3";                                   \
-  if (TARGET_FMOVD)                                                    \
-    reg_class_from_letter['e' - 'a'] = NO_REGS;                                \
-                                                                       \
-  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 == DWARF2_DEBUG);                  \
-     else                                                              \
-      flag_omit_frame_pointer = 0;                                     \
-   }                                                                   \
-                                                                       \
-  if ((flag_pic && ! TARGET_PREFERGOT)                                 \
-      || (TARGET_SHMEDIA && !TARGET_PT_FIXED))                         \
-    flag_no_function_cse = 1;                                          \
-                                                                       \
-  if (SMALL_REGISTER_CLASSES)                                          \
-    {                                                                  \
-      /* Never run scheduling before reload, since that can            \
-        break global alloc, and generates slower code anyway due       \
-        to the pressure on R0.  */                                     \
-      /* Enable sched1 for SH4; ready queue will be reordered by       \
-        the target hooks when pressure is high. We can not do this for \
-        SH3 and lower as they give spill failures for R0.  */          \
-      if (!TARGET_HARD_SH4)                                            \
-        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)
+#define SUBTARGET_OVERRIDE_OPTIONS (void) 0
+
+extern const char *sh_fixed_range_str;
+
+#define OVERRIDE_OPTIONS sh_override_options ()
+
 \f
 /* Target machine storage layout.  */
 
@@ -789,7 +597,7 @@ do {                                                                        \
   ((GET_MODE_CLASS (TYPE_MODE (TYPE)) == MODE_COMPLEX_INT \
     || GET_MODE_CLASS (TYPE_MODE (TYPE)) == MODE_COMPLEX_FLOAT) \
    ? (unsigned) MIN (BIGGEST_ALIGNMENT, GET_MODE_BITSIZE (TYPE_MODE (TYPE))) \
-   : (unsigned) ALIGN)
+   : (unsigned) DATA_ALIGNMENT(TYPE, ALIGN))
 
 /* Make arrays of chars word-aligned for the same reasons.  */
 #define DATA_ALIGNMENT(TYPE, ALIGN)            \
@@ -817,7 +625,7 @@ do {                                                                        \
 #define LABEL_ALIGN(A_LABEL) \
 (                                                                      \
   (PREV_INSN (A_LABEL)                                                 \
-   && GET_CODE (PREV_INSN (A_LABEL)) == INSN                           \
+   && NONJUMP_INSN_P (PREV_INSN (A_LABEL))                             \
    && GET_CODE (PATTERN (PREV_INSN (A_LABEL))) == UNSPEC_VOLATILE      \
    && XINT (PATTERN (PREV_INSN (A_LABEL)), 1) == UNSPECV_ALIGN)                \
    /* explicit alignment insn in constant tables.  */                  \
@@ -829,9 +637,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                                           \
+  (NONJUMP_INSN_P (A_INSN)                                             \
    ? 1 << TARGET_SHMEDIA                                               \
-   : GET_CODE (A_INSN) == JUMP_INSN || GET_CODE (A_INSN) == CALL_INSN  \
+   : JUMP_P (A_INSN) || CALL_P (A_INSN)                                        \
    ? 1 << TARGET_SHMEDIA                                               \
    : CACHE_LOG)
 \f
@@ -881,7 +689,7 @@ extern char sh_register_names[][MAX_REGISTER_NAME_LENGTH + 1];
   "tr0",  "tr1",  "tr2",  "tr3",  "tr4",  "tr5",  "tr6",  "tr7",       \
   "xd0",  "xd2",  "xd4",  "xd6",  "xd8",  "xd10", "xd12", "xd14",      \
   "gbr",  "ap",          "pr",   "t",    "mach", "macl", "fpul", "fpscr",      \
-  "rap"                                                                        \
+  "rap",  "sfp"                                                                \
 }
 
 #define REGNAMES_ARR_INDEX_1(index) \
@@ -906,7 +714,7 @@ extern char sh_register_names[][MAX_REGISTER_NAME_LENGTH + 1];
   REGNAMES_ARR_INDEX_8 (128), \
   REGNAMES_ARR_INDEX_8 (136), \
   REGNAMES_ARR_INDEX_8 (144), \
-  REGNAMES_ARR_INDEX_1 (152) \
+  REGNAMES_ARR_INDEX_2 (152) \
 }
 
 #define ADDREGNAMES_SIZE 32
@@ -962,13 +770,24 @@ extern char sh_additional_register_names[ADDREGNAMES_SIZE] \
 #define FIRST_TARGET_REG TR0_REG
 #define LAST_TARGET_REG  (FIRST_TARGET_REG + (TARGET_SHMEDIA ? 7 : -1))
 
+/* Registers that can be accessed through bank0 or bank1 depending on sr.md.  */
+
+#define FIRST_BANKED_REG R0_REG
+#define LAST_BANKED_REG R7_REG
+
+#define BANKED_REGISTER_P(REGNO)                       \
+  IN_RANGE ((REGNO),                                   \
+           (unsigned HOST_WIDE_INT) FIRST_BANKED_REG, \
+           (unsigned HOST_WIDE_INT) LAST_BANKED_REG)
+
 #define GENERAL_REGISTER_P(REGNO) \
   IN_RANGE ((REGNO), \
            (unsigned HOST_WIDE_INT) FIRST_GENERAL_REG, \
            (unsigned HOST_WIDE_INT) LAST_GENERAL_REG)
 
 #define GENERAL_OR_AP_REGISTER_P(REGNO) \
-  (GENERAL_REGISTER_P (REGNO) || ((REGNO) == AP_REG))
+  (GENERAL_REGISTER_P (REGNO) || ((REGNO) == AP_REG)   \
+   || ((REGNO) == FRAME_POINTER_REGNUM))
 
 #define FP_REGISTER_P(REGNO) \
   ((int) (REGNO) >= FIRST_FP_REG && (int) (REGNO) <= LAST_FP_REG)
@@ -998,6 +817,7 @@ extern char sh_additional_register_names[ADDREGNAMES_SIZE] \
 #define VALID_REGISTER_P(REGNO) \
   (SHMEDIA_REGISTER_P (REGNO) || XD_REGISTER_P (REGNO) \
    || (REGNO) == AP_REG || (REGNO) == RAP_REG \
+   || (REGNO) == FRAME_POINTER_REGNUM \
    || (TARGET_SH1 && (SPECIAL_REGISTER_P (REGNO) || (REGNO) == PR_REG)) \
    || (TARGET_SH2E && (REGNO) == FPUL_REG))
 
@@ -1010,7 +830,10 @@ extern char sh_additional_register_names[ADDREGNAMES_SIZE] \
    ? DImode \
    : SImode)
 
-#define FIRST_PSEUDO_REGISTER 153
+#define FIRST_PSEUDO_REGISTER 154
+
+/* Don't count soft frame pointer.  */
+#define DWARF_FRAME_REGISTERS (FIRST_PSEUDO_REGISTER - 1)
 
 /* 1 for registers that have pervasive standard uses
    and are not available for the register allocator.
@@ -1047,8 +870,8 @@ extern char sh_additional_register_names[ADDREGNAMES_SIZE] \
   0,      0,      0,      0,      0,      0,      0,      0,           \
 /*"gbr",  "ap",          "pr",   "t",    "mach", "macl", "fpul", "fpscr", */   \
   1,      1,      1,      1,      1,      1,      0,      1,           \
-/*"rap" */                                                             \
-  1,                                                                   \
+/*"rap",  "sfp" */                                                     \
+  1,     1,                                                            \
 }
 
 /* 1 for registers not available across function calls.
@@ -1087,8 +910,8 @@ extern char sh_additional_register_names[ADDREGNAMES_SIZE] \
   1,      1,      1,      1,      1,      1,      0,      0,           \
 /*"gbr",  "ap",          "pr",   "t",    "mach", "macl", "fpul", "fpscr", */   \
   1,      1,      1,      1,      1,      1,      1,      1,           \
-/*"rap" */                                                             \
-  1,                                                                   \
+/*"rap",  "sfp" */                                                     \
+  1,     1,                                                            \
 }
 
 /* CONDITIONAL_REGISTER_USAGE might want to make a register call-used, yet
@@ -1122,52 +945,10 @@ extern char sh_additional_register_names[ADDREGNAMES_SIZE] \
     ? ((GET_MODE_SIZE (MODE) + UNITS_PER_WORD/2 - 1) / (UNITS_PER_WORD/2)) \
     : ((GET_MODE_SIZE (MODE) + UNITS_PER_WORD - 1) / UNITS_PER_WORD))
 
-/* Value is 1 if hard register REGNO can hold a value of machine-mode MODE.
-   We can allow any mode in any general register.  The special registers
-   only allow SImode.  Don't allow any mode in the PR.  */
-
-/* We cannot hold DCmode values in the XD registers because alter_reg
-   handles subregs of them incorrectly.  We could work around this by
-   spacing the XD registers like the DR registers, but this would require
-   additional memory in every compilation to hold larger register vectors.
-   We could hold SFmode / SCmode values in XD registers, but that
-   would require a tertiary reload when reloading from / to memory,
-   and a secondary reload to reload from / to general regs; that
-   seems to be a loosing proposition.  */
-/* We want to allow TImode FP regs so that when V4SFmode is loaded as TImode,
-   it won't be ferried through GP registers first.  */
+/* Value is 1 if hard register REGNO can hold a value of machine-mode MODE.  */
+
 #define HARD_REGNO_MODE_OK(REGNO, MODE)                \
-  (SPECIAL_REGISTER_P (REGNO) ? (MODE) == SImode \
-   : (REGNO) == FPUL_REG ? (MODE) == SImode || (MODE) == SFmode        \
-   : FP_REGISTER_P (REGNO) && (MODE) == SFmode \
-   ? 1 \
-   : (MODE) == V2SFmode \
-   ? ((FP_REGISTER_P (REGNO) && ((REGNO) - FIRST_FP_REG) % 2 == 0) \
-      || GENERAL_REGISTER_P (REGNO)) \
-   : (MODE) == V4SFmode \
-   ? ((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 || (MODE) == SImode \
-      || ((TARGET_SH2E || TARGET_SHMEDIA) && (MODE) == SCmode) \
-      || ((((TARGET_SH4 || TARGET_SH2A_DOUBLE) && (MODE) == DFmode) || (MODE) == DCmode \
-          || (TARGET_SHMEDIA && ((MODE) == DFmode || (MODE) == DImode \
-                                 || (MODE) == V2SFmode || (MODE) == TImode))) \
-         && (((REGNO) - FIRST_FP_REG) & 1) == 0) \
-      || ((TARGET_SH4 || TARGET_SHMEDIA) \
-         && (MODE) == TImode \
-         && (((REGNO) - FIRST_FP_REG) & 3) == 0)) \
-   : XD_REGISTER_P (REGNO) \
-   ? (MODE) == DFmode \
-   : TARGET_REGISTER_P (REGNO) \
-   ? ((MODE) == DImode || (MODE) == SImode || (MODE) == PDImode) \
-   : (REGNO) == PR_REG ? (MODE) == SImode \
-   : (REGNO) == FPSCR_REG ? (MODE) == PSImode \
-   : 1)
+  sh_hard_regno_mode_ok ((REGNO), (MODE))
 
 /* Value is 1 if it is a good idea to tie two pseudo registers
    when one has mode MODE1 and one has mode MODE2.
@@ -1203,7 +984,10 @@ extern char sh_additional_register_names[ADDREGNAMES_SIZE] \
 #define STACK_POINTER_REGNUM   SP_REG
 
 /* Base register for access to local variables of the function.  */
-#define FRAME_POINTER_REGNUM   FP_REG
+#define HARD_FRAME_POINTER_REGNUM      FP_REG
+
+/* Base register for access to local variables of the function.  */
+#define FRAME_POINTER_REGNUM   153
 
 /* Fake register that holds the address on the stack of the
    current function's return address.  */
@@ -1215,12 +999,6 @@ extern char sh_additional_register_names[ADDREGNAMES_SIZE] \
 
 #define GOT_SYMBOL_NAME "*_GLOBAL_OFFSET_TABLE_"
 
-/* Value should be nonzero if functions must have frame pointers.
-   Zero means the frame pointer need not be set up (and parms may be accessed
-   via the stack pointer) in functions that seem suitable.  */
-
-#define FRAME_POINTER_REQUIRED 0
-
 /* Definitions for register eliminations.
 
    We have three registers that can be eliminated on the SH.  First, the
@@ -1245,16 +1023,18 @@ extern char sh_additional_register_names[ADDREGNAMES_SIZE] \
    of elimination fail.  */
 
 #define ELIMINABLE_REGS                                                \
-{{ FRAME_POINTER_REGNUM, STACK_POINTER_REGNUM},                        \
+{{ HARD_FRAME_POINTER_REGNUM, STACK_POINTER_REGNUM},           \
+ { FRAME_POINTER_REGNUM, STACK_POINTER_REGNUM},                        \
+ { FRAME_POINTER_REGNUM, HARD_FRAME_POINTER_REGNUM},           \
  { RETURN_ADDRESS_POINTER_REGNUM, STACK_POINTER_REGNUM},       \
- { RETURN_ADDRESS_POINTER_REGNUM, FRAME_POINTER_REGNUM},       \
+ { RETURN_ADDRESS_POINTER_REGNUM, HARD_FRAME_POINTER_REGNUM},  \
  { ARG_POINTER_REGNUM, STACK_POINTER_REGNUM},                  \
- { ARG_POINTER_REGNUM, FRAME_POINTER_REGNUM},}
+ { ARG_POINTER_REGNUM, HARD_FRAME_POINTER_REGNUM},}
 
 /* Given FROM and TO register numbers, say whether this elimination
    is allowed.  */
 #define CAN_ELIMINATE(FROM, TO) \
-  (!((FROM) == FRAME_POINTER_REGNUM && FRAME_POINTER_REQUIRED))
+  (!((FROM) == HARD_FRAME_POINTER_REGNUM && FRAME_POINTER_REQUIRED))
 
 /* Define the offset between two registers, one to be eliminated, and the other
    its replacement, at the start of a routine.  */
@@ -1275,7 +1055,7 @@ extern char sh_additional_register_names[ADDREGNAMES_SIZE] \
 #define DEFAULT_PCC_STRUCT_RETURN 0
 
 #define SHMEDIA_REGS_STACK_ADJUST() \
-  (TARGET_SHCOMPACT && current_function_has_nonlocal_label \
+  (TARGET_SHCOMPACT && crtl->saves_all_registers \
    ? (8 * (/* r28-r35 */ 8 + /* r44-r59 */ 16 + /* tr5-tr7 */ 3) \
       + (TARGET_FPU_ANY ? 4 * (/* fr36 - fr63 */ 28) : 0)) \
    : 0)
@@ -1330,6 +1110,7 @@ enum reg_class
   DF_REGS,
   FPSCR_REGS,
   GENERAL_FP_REGS,
+  GENERAL_DF_REGS,
   TARGET_REGS,
   ALL_REGS,
   LIM_REG_CLASSES
@@ -1354,6 +1135,7 @@ enum reg_class
   "DF_REGS",           \
   "FPSCR_REGS",                \
   "GENERAL_FP_REGS",   \
+  "GENERAL_DF_REGS",   \
   "TARGET_REGS",       \
   "ALL_REGS",          \
 }
@@ -1375,11 +1157,11 @@ enum reg_class
 /* MAC_REGS:  */                                                       \
   { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00300000 },      \
 /* FPUL_REGS:  */                                                      \
-  { 0x00000000, 0x00000000, 0x00000000, 0x00000001, 0x00400000 },      \
+  { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00400000 },      \
 /* SIBCALL_REGS: Initialized in CONDITIONAL_REGISTER_USAGE.  */        \
   { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 },      \
 /* GENERAL_REGS:  */                                                   \
-  { 0xffffffff, 0xffffffff, 0x00000000, 0x00000000, 0x01020000 },      \
+  { 0xffffffff, 0xffffffff, 0x00000000, 0x00000000, 0x03020000 },      \
 /* FP0_REGS:  */                                                       \
   { 0x00000000, 0x00000000, 0x00000001, 0x00000000, 0x00000000 },      \
 /* FP_REGS:  */                                                                \
@@ -1391,11 +1173,13 @@ enum reg_class
 /* FPSCR_REGS:  */                                                     \
   { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00800000 },      \
 /* GENERAL_FP_REGS:  */                                                        \
-  { 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0x0102ff00 },      \
+  { 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0x03020000 },      \
+/* GENERAL_DF_REGS:  */                                                        \
+  { 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0x0302ff00 },      \
 /* TARGET_REGS:  */                                                    \
   { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x000000ff },      \
 /* ALL_REGS:  */                                                       \
-  { 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0x01ffffff },      \
+  { 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0x03ffffff },      \
 }
 
 /* The same information, inverted:
@@ -1406,6 +1190,20 @@ enum reg_class
 extern enum reg_class regno_reg_class[FIRST_PSEUDO_REGISTER];
 #define REGNO_REG_CLASS(REGNO) regno_reg_class[(REGNO)]
 
+/* The following macro defines cover classes for Integrated Register
+   Allocator.  Cover classes is a set of non-intersected register
+   classes covering all hard registers used for register allocation
+   purpose.  Any move between two registers of a cover class should be
+   cheaper than load or store of the registers.  The macro value is
+   array of register classes with LIM_REG_CLASSES used as the end
+   marker.  */
+
+#define IRA_COVER_CLASSES                                                   \
+{                                                                           \
+  GENERAL_REGS, FP_REGS, PR_REGS, T_REGS, MAC_REGS, TARGET_REGS,            \
+  FPUL_REGS, LIM_REG_CLASSES                                                \
+}
+
 /* When defined, the compiler allows registers explicitly used in the
    rtl to be used as spill registers but prevents the compiler from
    extending the lifetime of these registers.  */
@@ -1445,71 +1243,14 @@ extern enum reg_class regno_reg_class[FIRST_PSEUDO_REGISTER];
    128,129,130,131,132,133,134,135, \
    /* Fixed registers */ \
     15, 16, 24, 25, 26, 27, 63,144, \
-   145,146,147,148,149,152 }
+   145,146,147,148,149,152,153 }
 
 /* The class value for index registers, and the one for base regs.  */
 #define INDEX_REG_CLASS \
   (!ALLOW_INDEXED_ADDRESS ? NO_REGS : 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[];
-
-/* We might use 'Rxx' constraints in the future for exotic reg classes.*/
-#define REG_CLASS_FROM_CONSTRAINT(C, STR) \
-  (ISLOWER (C) ? reg_class_from_letter[(C)-'a'] : NO_REGS )
 \f
-/* Overview of uppercase letter constraints:
-   A: Addresses (constraint len == 3)
-    Ac4: sh4 cache operations
-    Ac5: sh5 cache operations
-   Bxx: miscellaneous constraints
-    Bsc: SCRATCH - for the scratch register in movsi_ie in the
-        fldi0 / fldi0 cases
-   C: Constants other than only CONST_INT (constraint len == 3)
-    C16: 16 bit constant, literal or symbolic
-    Csy: label or symbol
-    Cpg: non-explicit constants that can be directly loaded into a general
-        purpose register in PIC code.  like 's' except we don't allow
-        PIC_DIRECT_ADDR_P
-   IJKLMNOP: CONT_INT constants
-    Ixx: signed xx bit
-    J16: 0xffffffff00000000 | 0x00000000ffffffff
-    Kxx: unsigned xx bit
-    M: 1
-    N: 0
-    P27: 1 | 2 | 8 | 16
-   Q: pc relative load operand
-   Rxx: reserved for exotic register classes.
-   S: extra memory (storage) constraints (constraint len == 3)
-    Sua: unaligned memory operations
-   W: vector
-   Z: zero in any mode
-
-   unused CONST_INT constraint letters: LO
-   unused EXTRA_CONSTRAINT letters: D T U Y */
-
-#define CONSTRAINT_LEN(C,STR) \
-  (((C) == 'A' || (C) == 'B' || (C) == 'C' \
-    || (C) == 'I' || (C) == 'J' || (C) == 'K' || (C) == 'P' \
-    || (C) == 'R' || (C) == 'S') \
-   ? 3 : DEFAULT_CONSTRAINT_LEN ((C), (STR)))
-
-/* The letters I, J, K, L and M in a register constraint string
-   can be used to stand for particular ranges of immediate operands.
-   This macro defines what the ranges are.
-   C is the letter, and VALUE is a constant value.
-   Return 1 if VALUE is in the range specified by C.
-       I08: arithmetic operand -127..128, as used in add, sub, etc
-       I16: arithmetic operand -32768..32767, as used in SHmedia movi and shori
-       P27: shift operand 1,2,8 or 16
-       K08: logical operand 0..255, as used in and, or, etc.
-       M: constant 1
-       N: constant 0
-       I06: arithmetic operand -32..31, as used in SHmedia beqi, bnei and xori
-       I10: arithmetic operand -512..511, as used in SHmedia andi, ori
-*/
+/* Defines for sh.md and constraints.md.  */
 
 #define CONST_OK_FOR_I06(VALUE) (((HOST_WIDE_INT)(VALUE)) >= -32 \
                                 && ((HOST_WIDE_INT)(VALUE)) <= 31)
@@ -1519,52 +1260,13 @@ extern enum reg_class reg_class_from_letter[];
                                 && ((HOST_WIDE_INT)(VALUE)) <= 511)
 #define CONST_OK_FOR_I16(VALUE) (((HOST_WIDE_INT)(VALUE)) >= -32768 \
                                 && ((HOST_WIDE_INT)(VALUE)) <= 32767)
-#define CONST_OK_FOR_I20(VALUE) (((HOST_WIDE_INT)(VALUE)) >= -524288 \
-                                && ((HOST_WIDE_INT)(VALUE)) <= 524287 \
-                                && TARGET_SH2A)
-#define CONST_OK_FOR_I(VALUE, STR) \
-  ((STR)[1] == '0' && (STR)[2] == '6' ? CONST_OK_FOR_I06 (VALUE) \
-   : (STR)[1] == '0' && (STR)[2] == '8' ? CONST_OK_FOR_I08 (VALUE) \
-   : (STR)[1] == '1' && (STR)[2] == '0' ? CONST_OK_FOR_I10 (VALUE) \
-   : (STR)[1] == '1' && (STR)[2] == '6' ? CONST_OK_FOR_I16 (VALUE) \
-   : (STR)[1] == '2' && (STR)[2] == '0' ? CONST_OK_FOR_I20 (VALUE) \
-   : 0)
 
 #define CONST_OK_FOR_J16(VALUE) \
   ((HOST_BITS_PER_WIDE_INT >= 64 && (VALUE) == (HOST_WIDE_INT) 0xffffffff) \
    || (HOST_BITS_PER_WIDE_INT >= 64 && (VALUE) == (HOST_WIDE_INT) -1 << 32))
-#define CONST_OK_FOR_J(VALUE, STR) \
-  ((STR)[1] == '1' && (STR)[2] == '6' ? CONST_OK_FOR_J16 (VALUE) \
-   : 0)
 
 #define CONST_OK_FOR_K08(VALUE) (((HOST_WIDE_INT)(VALUE))>= 0 \
                                 && ((HOST_WIDE_INT)(VALUE)) <= 255)
-#define CONST_OK_FOR_K(VALUE, STR) \
-  ((STR)[1] == '0' && (STR)[2] == '8' ? CONST_OK_FOR_K08 (VALUE) \
-   : 0)
-#define CONST_OK_FOR_P27(VALUE) \
-  ((VALUE)==1||(VALUE)==2||(VALUE)==8||(VALUE)==16)
-#define CONST_OK_FOR_P(VALUE, STR) \
-  ((STR)[1] == '2' && (STR)[2] == '7' ? CONST_OK_FOR_P27 (VALUE) \
-   : 0)
-#define CONST_OK_FOR_M(VALUE) ((VALUE)==1)
-#define CONST_OK_FOR_N(VALUE) ((VALUE)==0)
-#define CONST_OK_FOR_CONSTRAINT_P(VALUE, C, STR)       \
-     ((C) == 'I' ? CONST_OK_FOR_I ((VALUE), (STR))     \
-    : (C) == 'J' ? CONST_OK_FOR_J ((VALUE), (STR))     \
-    : (C) == 'K' ? CONST_OK_FOR_K ((VALUE), (STR))     \
-    : (C) == 'M' ? CONST_OK_FOR_M (VALUE)              \
-    : (C) == 'N' ? CONST_OK_FOR_N (VALUE)              \
-    : (C) == 'P' ? CONST_OK_FOR_P ((VALUE), (STR))     \
-    : 0)
-
-/* Similar, but for floating constants, and defining letters G and H.
-   Here VALUE is the CONST_DOUBLE rtx itself.  */
-
-#define CONST_DOUBLE_OK_FOR_LETTER_P(VALUE, C)         \
-((C) == 'G' ? (fp_zero_operand (VALUE) && fldi_ok ())  \
- : (C) == 'H' ? (fp_one_operand (VALUE) && fldi_ok ()) \
- : (C) == 'F')
 
 /* Given an rtx X being reloaded into a reg required to be
    in class CLASS, return the class of reg to actually use.
@@ -1575,18 +1277,19 @@ extern enum reg_class reg_class_from_letter[];
   ((CLASS) == NO_REGS && TARGET_SHMEDIA \
    && (GET_CODE (X) == CONST_DOUBLE \
        || GET_CODE (X) == SYMBOL_REF \
-       || PIC_DIRECT_ADDR_P (X)) \
+       || PIC_ADDR_P (X)) \
    ? GENERAL_REGS \
    : (CLASS)) \
 
+#if 0
 #define SECONDARY_INOUT_RELOAD_CLASS(CLASS,MODE,X,ELSE) \
   ((((REGCLASS_HAS_FP_REG (CLASS)                                      \
-      && (GET_CODE (X) == REG                                          \
+      && (REG_P (X)                                                    \
       && (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                                         \
+        && REG_P (X)                                                   \
         && FP_REGISTER_P (REGNO (X))))                                 \
     && ! TARGET_SHMEDIA                                                        \
     && ((MODE) == SFmode || (MODE) == SImode))                         \
@@ -1594,22 +1297,22 @@ extern enum reg_class reg_class_from_letter[];
    : (((CLASS) == FPUL_REGS                                            \
        || (REGCLASS_HAS_FP_REG (CLASS)                                 \
           && ! TARGET_SHMEDIA && MODE == SImode))                      \
-      && (GET_CODE (X) == MEM                                          \
-         || (GET_CODE (X) == REG                                       \
+      && (MEM_P (X)                                                    \
+         || (REG_P (X)                                                 \
              && (REGNO (X) >= FIRST_PSEUDO_REGISTER                    \
                  || REGNO (X) == T_REG                                 \
                  || system_reg_operand (X, VOIDmode)))))               \
    ? GENERAL_REGS                                                      \
    : (((CLASS) == TARGET_REGS                                          \
        || (TARGET_SHMEDIA && (CLASS) == SIBCALL_REGS))                 \
-      && !EXTRA_CONSTRAINT_Csy (X)                                     \
-      && (GET_CODE (X) != REG || ! GENERAL_REGISTER_P (REGNO (X))))    \
+      && !satisfies_constraint_Csy (X)                                 \
+      && (!REG_P (X) || ! GENERAL_REGISTER_P (REGNO (X))))             \
    ? GENERAL_REGS                                                      \
    : (((CLASS) == MAC_REGS || (CLASS) == PR_REGS)                      \
-      && GET_CODE (X) == REG && ! GENERAL_REGISTER_P (REGNO (X))       \
+      && REG_P (X) && ! GENERAL_REGISTER_P (REGNO (X))                 \
       && (CLASS) != REGNO_REG_CLASS (REGNO (X)))                       \
    ? GENERAL_REGS                                                      \
-   : ((CLASS) != GENERAL_REGS && GET_CODE (X) == REG                   \
+   : ((CLASS) != GENERAL_REGS && REG_P (X)                             \
       && TARGET_REGISTER_P (REGNO (X)))                                        \
    ? GENERAL_REGS : (ELSE))
 
@@ -1624,18 +1327,18 @@ extern enum reg_class reg_class_from_letter[];
          && (MODE) == SFmode && fldi_ok ()))                           \
    ? R0_REGS                                                           \
    : ((CLASS) == FPUL_REGS                                             \
-      && ((GET_CODE (X) == REG                                         \
+      && ((REG_P (X)                                                   \
           && (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_I08 (INTVAL (X))       \
+   ? (satisfies_constraint_I08 (X)                                     \
       ? GENERAL_REGS                                                   \
       : R0_REGS)                                                       \
    : ((CLASS) == FPSCR_REGS                                            \
-      && ((GET_CODE (X) == REG && REGNO (X) >= FIRST_PSEUDO_REGISTER)  \
-         || (GET_CODE (X) == MEM && GET_CODE (XEXP ((X), 0)) == PLUS)))\
+      && ((REG_P (X) && REGNO (X) >= FIRST_PSEUDO_REGISTER)            \
+         || (MEM_P (X) && GET_CODE (XEXP ((X), 0)) == PLUS)))          \
    ? GENERAL_REGS                                                      \
    : (REGCLASS_HAS_FP_REG (CLASS)                                      \
       && TARGET_SHMEDIA                                                        \
@@ -1647,9 +1350,10 @@ extern enum reg_class reg_class_from_letter[];
       && TARGET_SHMEDIA && inqhi_operand ((X), (MODE)))                        \
    ? GENERAL_REGS                                                      \
    : (TARGET_SHMEDIA && (CLASS) == GENERAL_REGS                                \
-      && (GET_CODE (X) == LABEL_REF || PIC_DIRECT_ADDR_P (X)))         \
+      && (GET_CODE (X) == LABEL_REF || PIC_ADDR_P (X)))                        \
    ? TARGET_REGS                                                       \
    : SECONDARY_INOUT_RELOAD_CLASS((CLASS),(MODE),(X), NO_REGS))
+#endif
 
 /* Return the maximum number of consecutive registers
    needed to represent mode MODE in a register of class CLASS.
@@ -1693,11 +1397,9 @@ extern enum reg_class reg_class_from_letter[];
    makes the stack pointer a smaller address.  */
 #define STACK_GROWS_DOWNWARD
 
-/*  Define this macro if the addresses of local variable slots are at
-    negative offsets from the frame pointer.
-
-    The SH only has positive indexes, so grow the frame up.  */
-/* #define FRAME_GROWS_DOWNWARD */
+/*  Define this macro to nonzero if the addresses of local variable slots
+    are at negative offsets from the frame pointer.  */
+#define FRAME_GROWS_DOWNWARD 1
 
 /* Offset from the frame pointer to the first local variable slot to
    be allocated.  */
@@ -1770,10 +1472,9 @@ extern enum reg_class reg_class_from_letter[];
             && (TREE_CODE (VALTYPE) == INTEGER_TYPE                    \
                 || TREE_CODE (VALTYPE) == ENUMERAL_TYPE                \
                 || TREE_CODE (VALTYPE) == BOOLEAN_TYPE                 \
-                || TREE_CODE (VALTYPE) == CHAR_TYPE                    \
                 || TREE_CODE (VALTYPE) == REAL_TYPE                    \
                 || TREE_CODE (VALTYPE) == OFFSET_TYPE))                \
-             && sh_promote_prototypes (VALTYPE)                                \
+             && sh_promote_prototypes (FUNC)                           \
            ? (TARGET_SHMEDIA64 ? DImode : SImode) : TYPE_MODE (VALTYPE)), \
           BASE_RETURN_VALUE_REG (TYPE_MODE (VALTYPE)))
 
@@ -1893,6 +1594,13 @@ struct sh_args {
 
      - If T is set, a return trampoline will be set up for 64-bit
      return values to be split into 2 32-bit registers.  */
+    long call_cookie;
+
+  /* This is set to nonzero when the call in question must use the Renesas ABI,
+     even without the -mrenesas option.  */
+    int renesas_abi;
+};
+
 #define CALL_COOKIE_RET_TRAMP_SHIFT 0
 #define CALL_COOKIE_RET_TRAMP(VAL) ((VAL) << CALL_COOKIE_RET_TRAMP_SHIFT)
 #define CALL_COOKIE_STACKSEQ_SHIFT 1
@@ -1905,12 +1613,6 @@ struct sh_args {
   ((VAL) << CALL_COOKIE_INT_REG_SHIFT (REG))
 #define CALL_COOKIE_INT_REG_GET(COOKIE, REG) \
   (((COOKIE) >> CALL_COOKIE_INT_REG_SHIFT (REG)) & ((REG) < 4 ? 7 : 15))
-    long call_cookie;
-
-  /* This is set to nonzero when the call in question must use the Renesas ABI,
-     even without the -mrenesas option.  */
-    int renesas_abi;
-};
 
 #define CUMULATIVE_ARGS  struct sh_args
 
@@ -2071,15 +1773,13 @@ struct sh_args {
    && ((MODE) == BLKmode || (MODE) == TImode || (MODE) == CDImode \
        || (MODE) == DCmode) \
    && ((CUM).arg_count[(int) SH_ARG_INT]                       \
-       + (int_size_in_bytes (TYPE) + 7) / 8) > NPARM_REGS (SImode))
+       + (((MODE) == BLKmode ? int_size_in_bytes (TYPE)                \
+                            : GET_MODE_SIZE (MODE))            \
+         + 7) / 8) > NPARM_REGS (SImode))
 
 /* Perform any needed actions needed for a function that is receiving a
    variable number of arguments.  */
 
-/* Implement `va_start' for varargs and stdarg.  */
-#define EXPAND_BUILTIN_VA_START(valist, nextarg) \
-  sh_va_start (valist, nextarg)
-
 /* Call the function profiler with a given profile label.
    We use two .aligns, so as to make sure that both the .long is aligned
    on a 4 byte boundary, and that the .long is a fixed distance (2 bytes)
@@ -2184,6 +1884,8 @@ struct sh_args {
   (move_by_pieces_ninsns (SIZE, ALIGN, STORE_MAX_PIECES + 1) \
    < (TARGET_SMALLCODE ? 2 : ((ALIGN >= 32) ? 16 : 2)))
 
+#define SET_BY_PIECES_P(SIZE, ALIGN) STORE_BY_PIECES_P(SIZE, ALIGN)
+
 /* Macros to check register numbers against specific register classes.  */
 
 /* These assume that REGNO is a hard or pseudo reg number.
@@ -2211,6 +1913,7 @@ struct sh_args {
 #define CONSTANT_ADDRESS_P(X)  (GET_CODE (X) == LABEL_REF)
 
 /* Nonzero if the constant value X is a legitimate general operand.  */
+/* can_store_by_pieces constructs VOIDmode CONST_DOUBLEs.  */
 
 #define LEGITIMATE_CONSTANT_P(X) \
   (TARGET_SHMEDIA                                                      \
@@ -2221,84 +1924,47 @@ struct sh_args {
       || TARGET_SHMEDIA64)                                             \
    : (GET_CODE (X) != CONST_DOUBLE                                     \
       || GET_MODE (X) == DFmode || GET_MODE (X) == SFmode              \
-      || (TARGET_SH2E && (fp_zero_operand (X) || fp_one_operand (X)))))
+      || GET_MODE (X) == DImode || GET_MODE (X) == VOIDmode))
 
 /* The macros REG_OK_FOR..._P assume that the arg is a REG rtx
    and check its validity for a certain class.
-   We have two alternate definitions for each of them.
-   The usual definition accepts all pseudo regs; the other rejects
-   them unless they have been allocated suitable hard regs.
-   The symbol REG_OK_STRICT causes the latter definition to be used.  */
-
-#ifndef REG_OK_STRICT
-
-/* 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) \
-  (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) \
-  ((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) \
-  ((TARGET_SHMEDIA ? GENERAL_REGISTER_P (REGNO (X)) \
-    : REGNO (X) == R0_REG && OFFSET == 0) || REGNO (X) >= FIRST_PSEUDO_REGISTER)
-
-#else
-
-/* Nonzero if X is a hard reg that can be used as a base reg.  */
-#define REG_OK_FOR_BASE_P(X) \
-  REGNO_OK_FOR_BASE_P (REGNO (X))
-
-/* Nonzero if X is a hard reg that can be used as an index.  */
-#define REG_OK_FOR_INDEX_P(X) \
-  REGNO_OK_FOR_INDEX_P (REGNO (X))
-
-/* Nonzero if X/OFFSET is a hard reg that can be used as an index.  */
-#define SUBREG_OK_FOR_INDEX_P(X, OFFSET) \
-  (REGNO_OK_FOR_INDEX_P (REGNO (X)) && (OFFSET) == 0)
-
-#endif
-
-/* The 'Q' constraint is a pc relative load operand.  */
-#define EXTRA_CONSTRAINT_Q(OP)                                         \
-  (GET_CODE (OP) == MEM                                                \
-   && ((GET_CODE (XEXP ((OP), 0)) == LABEL_REF)                                \
-       || (GET_CODE (XEXP ((OP), 0)) == CONST                          \
-          && GET_CODE (XEXP (XEXP ((OP), 0), 0)) == PLUS               \
-          && GET_CODE (XEXP (XEXP (XEXP ((OP), 0), 0), 0)) == LABEL_REF \
-          && GET_CODE (XEXP (XEXP (XEXP ((OP), 0), 0), 1)) == CONST_INT)))
-
-/* Extra address constraints.  */
-#define EXTRA_CONSTRAINT_A(OP, STR) 0
-
-/* Constraint for selecting FLDI0 or FLDI1 instruction. If the clobber
-   operand is not SCRATCH (i.e. REG) then R0 is probably being
-   used, hence mova is being used, hence do not select this pattern */
-#define EXTRA_CONSTRAINT_Bsc(OP)    (GET_CODE(OP) == SCRATCH)
-#define EXTRA_CONSTRAINT_B(OP, STR) \
-  ((STR)[1] == 's' && (STR)[2] == 'c' ? EXTRA_CONSTRAINT_Bsc (OP) \
-   : 0)
-
-/* The `C16' constraint is a 16-bit constant, literal or symbolic.  */
-#define EXTRA_CONSTRAINT_C16(OP) \
-  (GET_CODE (OP) == CONST \
-   && GET_CODE (XEXP ((OP), 0)) == SIGN_EXTEND \
-   && (GET_MODE (XEXP ((OP), 0)) == DImode \
-       || GET_MODE (XEXP ((OP), 0)) == SImode) \
-   && 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)))
+   The suitable hard regs are always accepted and all pseudo regs
+   are also accepted if STRICT is not set.  */
+
+/* Nonzero if X is a reg that can be used as a base reg.  */
+#define REG_OK_FOR_BASE_P(X, STRICT)                   \
+  (GENERAL_OR_AP_REGISTER_P (REGNO (X))                        \
+   || (!STRICT && REGNO (X) >= FIRST_PSEUDO_REGISTER))
+
+/* Nonzero if X is a reg that can be used as an index.  */
+#define REG_OK_FOR_INDEX_P(X, STRICT)                  \
+  ((TARGET_SHMEDIA ? GENERAL_REGISTER_P (REGNO (X))    \
+    : REGNO (X) == R0_REG)                             \
+   || (!STRICT && REGNO (X) >= FIRST_PSEUDO_REGISTER))
+
+/* Nonzero if X/OFFSET is a reg that can be used as an index.  */
+#define SUBREG_OK_FOR_INDEX_P(X, OFFSET, STRICT)       \
+  ((TARGET_SHMEDIA ? GENERAL_REGISTER_P (REGNO (X))    \
+    : REGNO (X) == R0_REG && OFFSET == 0)              \
+   || (!STRICT && REGNO (X) >= FIRST_PSEUDO_REGISTER))
+
+/* Macros for extra constraints.  */
+
+#define IS_PC_RELATIVE_LOAD_ADDR_P(OP)                                 \
+  ((GET_CODE ((OP)) == LABEL_REF)                                      \
+   || (GET_CODE ((OP)) == CONST                                                \
+       && GET_CODE (XEXP ((OP), 0)) == PLUS                            \
+       && GET_CODE (XEXP (XEXP ((OP), 0), 0)) == LABEL_REF             \
+       && CONST_INT_P (XEXP (XEXP ((OP), 0), 1))))
+
+#define IS_NON_EXPLICIT_CONSTANT_P(OP)                                 \
+  (CONSTANT_P (OP)                                                     \
+   && !CONST_INT_P (OP)                                        \
+   && GET_CODE (OP) != CONST_DOUBLE                                    \
+   && (!flag_pic                                                       \
+       || (LEGITIMATE_PIC_OPERAND_P (OP)                               \
+          && !PIC_ADDR_P (OP)                                          \
+          && GET_CODE (OP) != LABEL_REF)))
 
 /* Check whether OP is a datalabel unspec.  */
 #define DATALABEL_REF_NO_CONST_P(OP) \
@@ -2323,19 +1989,16 @@ struct sh_args {
    && (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)))
+          && CONST_INT_P (XEXP (XEXP ((OP), 0), 1)))))
 
 #define PIC_ADDR_P(OP) \
   (GET_CODE (OP) == CONST && GET_CODE (XEXP ((OP), 0)) == UNSPEC \
    && XINT (XEXP ((OP), 0), 1) == UNSPEC_PIC)
 
-#define PIC_OFFSET_P(OP) \
-  (PIC_ADDR_P (OP) \
-   && GET_CODE (XVECEXP (XEXP ((OP), 0), 0, 0)) == MINUS \
-   && reg_mentioned_p (pc_rtx, XEXP (XVECEXP (XEXP ((OP), 0), 0, 0), 1)))
-
-#define PIC_DIRECT_ADDR_P(OP) \
-  (PIC_ADDR_P (OP) && GET_CODE (XVECEXP (XEXP ((OP), 0), 0, 0)) != MINUS)
+#define PCREL_SYMOFF_P(OP) \
+  (GET_CODE (OP) == CONST \
+   && GET_CODE (XEXP ((OP), 0)) == UNSPEC \
+   && XINT (XEXP ((OP), 0), 1) == UNSPEC_PCREL_SYMOFF)
 
 #define NON_PIC_REFERENCE_P(OP) \
   (GET_CODE (OP) == LABEL_REF || GET_CODE (OP) == SYMBOL_REF \
@@ -2347,7 +2010,7 @@ struct sh_args {
        && (GET_CODE (XEXP (XEXP ((OP), 0), 0)) == SYMBOL_REF \
           || GET_CODE (XEXP (XEXP ((OP), 0), 0)) == LABEL_REF \
           || DATALABEL_REF_NO_CONST_P (XEXP (XEXP ((OP), 0), 0))) \
-       && GET_CODE (XEXP (XEXP ((OP), 0), 1)) == CONST_INT))
+       && CONST_INT_P (XEXP (XEXP ((OP), 0), 1))))
 
 #define PIC_REFERENCE_P(OP) \
   (GOT_ENTRY_P (OP) || GOTPLT_ENTRY_P (OP) \
@@ -2356,256 +2019,45 @@ struct sh_args {
 #define MOVI_SHORI_BASE_OPERAND_P(OP) \
   (flag_pic \
    ? (GOT_ENTRY_P (OP) || GOTPLT_ENTRY_P (OP)  || GOTOFF_P (OP) \
-      || PIC_OFFSET_P (OP)) \
+      || PCREL_SYMOFF_P (OP)) \
    : NON_PIC_REFERENCE_P (OP))
-
-/* The `Csy' constraint is a label or a symbol.  */
-#define EXTRA_CONSTRAINT_Csy(OP) \
-  (NON_PIC_REFERENCE_P (OP) || PIC_DIRECT_ADDR_P (OP))
-
-/* A zero in any shape or form.  */
-#define EXTRA_CONSTRAINT_Z(OP) \
-  ((OP) == CONST0_RTX (GET_MODE (OP)))
-
-/* 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))))
-
-/* A non-explicit constant that can be loaded directly into a general purpose
-   register.  This is like 's' except we don't allow PIC_DIRECT_ADDR_P.  */
-#define EXTRA_CONSTRAINT_Cpg(OP) \
-  (CONSTANT_P (OP) \
-   && GET_CODE (OP) != CONST_INT \
-   && GET_CODE (OP) != CONST_DOUBLE \
-   && (!flag_pic \
-       || (LEGITIMATE_PIC_OPERAND_P (OP) \
-        && (! PIC_ADDR_P (OP) || PIC_OFFSET_P (OP)) \
-        && GET_CODE (OP) != LABEL_REF)))
-#define EXTRA_CONSTRAINT_C(OP, STR) \
-  ((STR)[1] == '1' && (STR)[2] == '6' ? EXTRA_CONSTRAINT_C16 (OP) \
-   : (STR)[1] == 's' && (STR)[2] == 'y' ? EXTRA_CONSTRAINT_Csy (OP) \
-   : (STR)[1] == 'p' && (STR)[2] == 'g' ? EXTRA_CONSTRAINT_Cpg (OP) \
-   : 0)
-
-#define EXTRA_MEMORY_CONSTRAINT(C,STR) ((C) == 'S')
-#define EXTRA_CONSTRAINT_Sr0(OP) \
-  (memory_operand((OP), GET_MODE (OP)) \
-   && ! refers_to_regno_p (R0_REG, R0_REG + 1, OP, (rtx *)0))
-#define EXTRA_CONSTRAINT_Sua(OP) \
-  (memory_operand((OP), GET_MODE (OP)) \
-   && GET_CODE (XEXP (OP, 0)) != PLUS)
-#define EXTRA_CONSTRAINT_S(OP, STR) \
-  ((STR)[1] == 'r' && (STR)[2] == '0' ? EXTRA_CONSTRAINT_Sr0 (OP) \
-   : (STR)[1] == 'u' && (STR)[2] == 'a' ? EXTRA_CONSTRAINT_Sua (OP) \
-   : 0)
-
-#define EXTRA_CONSTRAINT_STR(OP, C, STR)               \
-  ((C) == 'Q' ? EXTRA_CONSTRAINT_Q (OP)        \
-   : (C) == 'A' ? EXTRA_CONSTRAINT_A ((OP), (STR)) \
-   : (C) == 'B' ? EXTRA_CONSTRAINT_B ((OP), (STR)) \
-   : (C) == 'C' ? EXTRA_CONSTRAINT_C ((OP), (STR)) \
-   : (C) == 'S' ? EXTRA_CONSTRAINT_S ((OP), (STR)) \
-   : (C) == 'W' ? EXTRA_CONSTRAINT_W (OP) \
-   : (C) == 'Z' ? EXTRA_CONSTRAINT_Z (OP) \
-   : 0)
 \f
-/* GO_IF_LEGITIMATE_ADDRESS recognizes an RTL expression
-   that is a valid memory address for an instruction.
-   The MODE argument is the machine mode for the MEM expression
-   that wants to use this address.  */
-
-#define MODE_DISP_OK_4(X,MODE) \
-(GET_MODE_SIZE (MODE) == 4 && (unsigned) INTVAL (X) < 64       \
- && ! (INTVAL (X) & 3) && ! (TARGET_SH2E && (MODE) == SFmode))
-
-#define MODE_DISP_OK_8(X,MODE) \
-((GET_MODE_SIZE(MODE)==8) && ((unsigned)INTVAL(X)<60)  \
- && ! (INTVAL(X) & 3) && ! (TARGET_SH4 && (MODE) == DFmode))
-
-#undef MODE_DISP_OK_4
-#define MODE_DISP_OK_4(X,MODE) \
-((GET_MODE_SIZE (MODE) == 4 && (unsigned) INTVAL (X) < 64      \
-  && ! (INTVAL (X) & 3) && ! (TARGET_SH2E && (MODE) == SFmode)) \
-  || ((GET_MODE_SIZE(MODE)==4) && ((unsigned)INTVAL(X)<16383)  \
-  && ! (INTVAL(X) & 3) && TARGET_SH2A))
-
-#undef MODE_DISP_OK_8
-#define MODE_DISP_OK_8(X,MODE) \
-(((GET_MODE_SIZE(MODE)==8) && ((unsigned)INTVAL(X)<60) \
-  && ! (INTVAL(X) & 3) && ! ((TARGET_SH4 || TARGET_SH2A) && (MODE) == DFmode)) \
- || ((GET_MODE_SIZE(MODE)==8) && ((unsigned)INTVAL(X)<8192)    \
-  && ! (INTVAL(X) & (TARGET_SH2A_DOUBLE ? 7 : 3)) && (TARGET_SH2A && (MODE) == DFmode)))
-
-#define BASE_REGISTER_RTX_P(X)                         \
-  ((GET_CODE (X) == REG && REG_OK_FOR_BASE_P (X))      \
-   || (GET_CODE (X) == SUBREG                          \
-       && TRULY_NOOP_TRUNCATION (GET_MODE_BITSIZE (GET_MODE ((X))), \
+#define MAYBE_BASE_REGISTER_RTX_P(X, STRICT)                   \
+  ((REG_P (X) && REG_OK_FOR_BASE_P (X, STRICT))        \
+   || (GET_CODE (X) == SUBREG                                  \
+       && TRULY_NOOP_TRUNCATION (GET_MODE_BITSIZE (GET_MODE ((X))),    \
                                 GET_MODE_BITSIZE (GET_MODE (SUBREG_REG (X)))) \
-       && GET_CODE (SUBREG_REG (X)) == REG             \
-       && REG_OK_FOR_BASE_P (SUBREG_REG (X))))
+       && REG_P (SUBREG_REG (X))                       \
+       && REG_OK_FOR_BASE_P (SUBREG_REG (X), STRICT)))
 
 /* Since this must be r0, which is a single register class, we must check
    SUBREGs more carefully, to be sure that we don't accept one that extends
    outside the class.  */
-#define INDEX_REGISTER_RTX_P(X)                                \
-  ((GET_CODE (X) == REG && REG_OK_FOR_INDEX_P (X))     \
-   || (GET_CODE (X) == SUBREG                          \
+#define MAYBE_INDEX_REGISTER_RTX_P(X, STRICT)                          \
+  ((REG_P (X) && REG_OK_FOR_INDEX_P (X, STRICT))       \
+   || (GET_CODE (X) == SUBREG                                  \
        && TRULY_NOOP_TRUNCATION (GET_MODE_BITSIZE (GET_MODE ((X))), \
                                 GET_MODE_BITSIZE (GET_MODE (SUBREG_REG (X)))) \
-       && GET_CODE (SUBREG_REG (X)) == REG             \
-       && SUBREG_OK_FOR_INDEX_P (SUBREG_REG (X), SUBREG_BYTE (X))))
-
-/* 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
-   the above macros so we are in luck.
-
-   Allow  REG
-         REG+disp
-         REG+r0
-         REG++
-         --REG  */
-
-/* ??? 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.  */
-
-/* The SH allows a displacement in a QI or HI amode, but only when the
-   other operand is R0. GCC doesn't handle this very well, so we forgo
-   all of that.
-
-   A legitimate index for a QI or HI is 0, SI can be any number 0..63,
-   DI can be any number 0..60.  */
-
-#define GO_IF_LEGITIMATE_INDEX(MODE, OP, LABEL)                        \
-  do {                                                                 \
-    if (GET_CODE (OP) == CONST_INT)                                    \
-      {                                                                        \
-       if (TARGET_SHMEDIA)                                             \
-         {                                                             \
-           int MODE_SIZE;                                              \
-           /* Check if this the address of an unaligned load / store.  */\
-           if ((MODE) == VOIDmode)                                     \
-            {                                                          \
-             if (CONST_OK_FOR_I06 (INTVAL (OP)))                       \
-               goto LABEL;                                             \
-             break;                                                    \
-            }                                                          \
-           MODE_SIZE = GET_MODE_SIZE (MODE);                           \
-           if (! (INTVAL (OP) & (MODE_SIZE - 1))                       \
-               && INTVAL (OP) >= -512 * MODE_SIZE                      \
-               && INTVAL (OP) < 512 * MODE_SIZE)                       \
-             goto LABEL;                                               \
-           else                                                        \
-             break;                                                    \
-         }                                                             \
-       if (MODE_DISP_OK_4 ((OP), (MODE)))  goto LABEL;                 \
-       if (MODE_DISP_OK_8 ((OP), (MODE)))  goto LABEL;                 \
-      }                                                                        \
-  } while(0)
+       && REG_P (SUBREG_REG (X))               \
+       && SUBREG_OK_FOR_INDEX_P (SUBREG_REG (X), SUBREG_BYTE (X), STRICT)))
+
+#ifdef REG_OK_STRICT
+#define BASE_REGISTER_RTX_P(X) MAYBE_BASE_REGISTER_RTX_P(X, true)
+#define INDEX_REGISTER_RTX_P(X) MAYBE_INDEX_REGISTER_RTX_P(X, true)
+#else
+#define BASE_REGISTER_RTX_P(X) MAYBE_BASE_REGISTER_RTX_P(X, false)
+#define INDEX_REGISTER_RTX_P(X) MAYBE_INDEX_REGISTER_RTX_P(X, false)
+#endif
 
 #define ALLOW_INDEXED_ADDRESS \
   ((!TARGET_SHMEDIA32 && !TARGET_SHCOMPACT) || TARGET_ALLOW_INDEXED_ADDRESS)
 
-#define GO_IF_LEGITIMATE_ADDRESS(MODE, X, LABEL)                       \
-{                                                                      \
-  if (BASE_REGISTER_RTX_P (X))                                         \
-    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                                                \
-          && ((MODE) != PSImode || reload_completed))                  \
-    {                                                                  \
-      rtx xop0 = XEXP ((X), 0);                                                \
-      rtx xop1 = XEXP ((X), 1);                                                \
-      if (GET_MODE_SIZE (MODE) <= 8 && BASE_REGISTER_RTX_P (xop0))     \
-       GO_IF_LEGITIMATE_INDEX ((MODE), xop1, LABEL);                   \
-      if ((ALLOW_INDEXED_ADDRESS || GET_MODE (X) == DImode             \
-          || ((xop0 == stack_pointer_rtx || xop0 == frame_pointer_rtx) \
-              && REG_P (xop1) && REGNO (xop1) == R0_REG)               \
-          || ((xop1 == stack_pointer_rtx || xop1 == frame_pointer_rtx) \
-              && REG_P (xop0) && REGNO (xop0) == R0_REG))              \
-         && ((!TARGET_SHMEDIA && GET_MODE_SIZE (MODE) <= 4)            \
-             || (TARGET_SHMEDIA && GET_MODE_SIZE (MODE) <= 8)          \
-             || ((TARGET_SH4 || TARGET_SH2A_DOUBLE)                    \
-                 && TARGET_FMOVD && MODE == DFmode)))                  \
-       {                                                               \
-         if (BASE_REGISTER_RTX_P (xop1) && INDEX_REGISTER_RTX_P (xop0))\
-           goto LABEL;                                                 \
-         if (INDEX_REGISTER_RTX_P (xop1) && BASE_REGISTER_RTX_P (xop0))\
-           goto LABEL;                                                 \
-       }                                                               \
-    }                                                                  \
-}
+#define GO_IF_LEGITIMATE_INDEX(MODE, OP, WIN)  \
+  do {                                         \
+    if (sh_legitimate_index_p ((MODE), (OP)))  \
+      goto WIN;                                        \
+  } while (0)
 \f
-/* Try machine-dependent ways of modifying an illegitimate address
-   to be legitimate.  If we find one, return the new, valid address.
-   This macro is used in only one place: `memory_address' in explow.c.
-
-   OLDX is the address as it was before break_out_memory_refs was called.
-   In some cases it is useful to look at this to decide what needs to be done.
-
-   MODE and WIN are passed so that this macro can use
-   GO_IF_LEGITIMATE_ADDRESS.
-
-   It is always safe for this macro to do nothing.  It exists to recognize
-   opportunities to optimize the output.
-
-   For the SH, if X is almost suitable for indexing, but the offset is
-   out of range, convert it into a normal form so that cse has a chance
-   of reducing the number of address registers used.  */
-
-#define LEGITIMIZE_ADDRESS(X,OLDX,MODE,WIN)                    \
-{                                                              \
-  if (flag_pic)                                                        \
-    (X) = legitimize_pic_address (OLDX, MODE, NULL_RTX);       \
-  if (GET_CODE (X) == PLUS                                     \
-      && (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 || TARGET_SH2A_DOUBLE) && (MODE) == DFmode)                    \
-      && ! (TARGET_SH2E && (MODE) == SFmode))                  \
-    {                                                          \
-      rtx index_rtx = XEXP ((X), 1);                           \
-      HOST_WIDE_INT offset = INTVAL (index_rtx), offset_base;  \
-      rtx sum;                                                 \
-                                                               \
-      GO_IF_LEGITIMATE_INDEX ((MODE), index_rtx, WIN);         \
-      /* On rare occasions, we might get an unaligned pointer  \
-        that is indexed in a way to give an aligned address.   \
-        Therefore, keep the lower two bits in offset_base.  */ \
-      /* Instead of offset_base 128..131 use 124..127, so that \
-        simple add suffices.  */                               \
-      if (offset > 127)                                                \
-       {                                                       \
-         offset_base = ((offset + 4) & ~60) - 4;               \
-       }                                                       \
-      else                                                     \
-       offset_base = offset & ~60;                             \
-      /* Sometimes the normal form does not suit DImode.  We   \
-        could avoid that by using smaller ranges, but that     \
-        would give less optimized code when SImode is          \
-        prevalent.  */                                         \
-      if (GET_MODE_SIZE (MODE) + offset - offset_base <= 64)   \
-       {                                                       \
-         sum = expand_binop (Pmode, add_optab, XEXP ((X), 0),  \
-                             GEN_INT (offset_base), NULL_RTX, 0, \
-                             OPTAB_LIB_WIDEN);                 \
-                                                                \
-         (X) = gen_rtx_PLUS (Pmode, sum, GEN_INT (offset - offset_base)); \
-         goto WIN;                                             \
-       }                                                       \
-    }                                                          \
-}
-
 /* A C compound statement that attempts to replace X, which is an address
    that needs reloading, with a valid memory address for an operand of
    mode MODE.  WIN is a C statement label elsewhere in the code.
@@ -2617,14 +2069,14 @@ struct sh_args {
 {                                                                      \
   if (GET_CODE (X) == PLUS                                             \
       && (GET_MODE_SIZE (MODE) == 4 || GET_MODE_SIZE (MODE) == 8)      \
-      && GET_CODE (XEXP (X, 1)) == CONST_INT                           \
+      && CONST_INT_P (XEXP (X, 1))                                     \
       && BASE_REGISTER_RTX_P (XEXP (X, 0))                             \
       && ! TARGET_SHMEDIA                                              \
       && ! (TARGET_SH4 && (MODE) == DFmode)                            \
       && ! ((MODE) == PSImode && (TYPE) == RELOAD_FOR_INPUT_ADDRESS)   \
       && (ALLOW_INDEXED_ADDRESS                                                \
          || XEXP ((X), 0) == stack_pointer_rtx                         \
-         || XEXP ((X), 0) == frame_pointer_rtx))                       \
+         || XEXP ((X), 0) == hard_frame_pointer_rtx))                  \
     {                                                                  \
       rtx index_rtx = XEXP (X, 1);                                     \
       HOST_WIDE_INT offset = INTVAL (index_rtx), offset_base;          \
@@ -2640,8 +2092,8 @@ struct sh_args {
       if (TARGET_SH2E && MODE == SFmode)                               \
        {                                                               \
          X = copy_rtx (X);                                             \
-         push_reload (index_rtx, NULL_RTX, &XEXP (X, 1), NULL,         \
-                      R0_REGS, Pmode, VOIDmode, 0, 0, (OPNUM),         \
+         push_reload (X, NULL_RTX, &X, NULL,                           \
+                      BASE_REG_CLASS, Pmode, VOIDmode, 0, 0, (OPNUM),  \
                       (TYPE));                                         \
          goto WIN;                                                     \
        }                                                               \
@@ -2672,9 +2124,9 @@ struct sh_args {
   else if (GET_CODE (X) == PLUS                                                \
           && (GET_MODE_SIZE (MODE) == 4 || GET_MODE_SIZE (MODE) == 8)  \
           && GET_CODE (XEXP (X, 0)) == PLUS                            \
-          && GET_CODE (XEXP (XEXP (X, 0), 1)) == CONST_INT             \
+          && CONST_INT_P (XEXP (XEXP (X, 0), 1))                       \
           && BASE_REGISTER_RTX_P (XEXP (XEXP (X, 0), 0))               \
-          && GET_CODE (XEXP (X, 1)) == CONST_INT                       \
+          && CONST_INT_P (XEXP (X, 1))                                 \
           && ! TARGET_SHMEDIA                                          \
           && ! (TARGET_SH2E && MODE == SFmode))                        \
     {                                                                  \
@@ -2686,20 +2138,6 @@ struct sh_args {
       goto WIN;                                                                \
     }                                                                  \
 }
-
-/* Go to LABEL if ADDR (a legitimate address expression)
-   has an effect that depends on the machine mode it is used for.
-
-   ??? Strictly speaking, we should also include all indexed addressing,
-   because the index scale factor is the length of the operand.
-   However, the impact of GO_IF_MODE_DEPENDENT_ADDRESS would be to
-   high if we did that.  So we rely on reload to fix things up.  */
-
-#define GO_IF_MODE_DEPENDENT_ADDRESS(ADDR,LABEL)                       \
-{                                                                      \
-  if (GET_CODE(ADDR) == PRE_DEC || GET_CODE(ADDR) == POST_INC)         \
-    goto LABEL;                                                                \
-}
 \f
 /* Specify the machine mode that this machine uses
    for the index in the tablejump instruction.  */
@@ -2726,6 +2164,12 @@ struct sh_args {
    floating point types equivalent to `float'.  */
 #define DOUBLE_TYPE_SIZE ((TARGET_SH2E && ! TARGET_SH4 && ! TARGET_SH2A_DOUBLE) ? 32 : 64)
 
+#if defined(__SH2E__) || defined(__SH3E__) || defined( __SH2A_SINGLE_ONLY__) || defined( __SH4_SINGLE_ONLY__)
+#define LIBGCC2_DOUBLE_TYPE_SIZE 32
+#else
+#define LIBGCC2_DOUBLE_TYPE_SIZE 64
+#endif
+
 /* 'char' is signed by default.  */
 #define DEFAULT_SIGNED_CHAR  1
 
@@ -2814,14 +2258,14 @@ struct sh_args {
    in particular.  */
 
 #define INSN_SETS_ARE_DELAYED(X)               \
-  ((GET_CODE (X) == INSN                       \
+  ((NONJUMP_INSN_P (X)                 \
     && GET_CODE (PATTERN (X)) != SEQUENCE      \
     && GET_CODE (PATTERN (X)) != USE           \
     && GET_CODE (PATTERN (X)) != CLOBBER       \
     && get_attr_is_sfunc (X)))
 
 #define INSN_REFERENCES_ARE_DELAYED(X)                 \
-  ((GET_CODE (X) == INSN                       \
+  ((NONJUMP_INSN_P (X)                 \
     && GET_CODE (PATTERN (X)) != SEQUENCE      \
     && GET_CODE (PATTERN (X)) != USE           \
     && GET_CODE (PATTERN (X)) != CLOBBER       \
@@ -2870,7 +2314,8 @@ struct sh_args {
    The SH1 does not have delay slots, hence we get a pipeline stall
    at every branch.  The SH4 is superscalar, so the single delay slot
    is not sufficient to keep both pipelines filled.  */
-#define BRANCH_COST (TARGET_SH5 ? 1 : ! TARGET_SH2 || TARGET_HARD_SH4 ? 2 : 1)
+#define BRANCH_COST(speed_p, predictable_p) \
+       (TARGET_SH5 ? 1 : ! TARGET_SH2 || TARGET_HARD_SH4 ? 2 : 1)
 \f
 /* Assembler output control.  */
 
@@ -2931,7 +2376,7 @@ struct sh_args {
 #undef DO_GLOBAL_CTORS_BODY
 #define DO_GLOBAL_CTORS_BODY                   \
 {                                              \
-  typedef (*pfunc)();                          \
+  typedef void (*pfunc) (void);                        \
   extern pfunc __ctors[];                      \
   extern pfunc __ctors_end[];                  \
   pfunc *p;                                    \
@@ -2944,7 +2389,7 @@ struct sh_args {
 #undef DO_GLOBAL_DTORS_BODY
 #define DO_GLOBAL_DTORS_BODY                   \
 {                                              \
-  typedef (*pfunc)();                          \
+  typedef void (*pfunc) (void);                        \
   extern pfunc __dtors[];                      \
   extern pfunc __dtors_end[];                  \
   pfunc *p;                                    \
@@ -3011,16 +2456,18 @@ struct sh_args {
    ? (TARGET_SH5 ? 18 : 17) \
    : (REGNO) == PR_MEDIA_REG \
    ? (TARGET_SH5 ? 18 : (unsigned) -1) \
-   : (REGNO) == T_REG \
-   ? (TARGET_SH5 ? 242 : 18) \
    : (REGNO) == GBR_REG \
-   ? (TARGET_SH5 ? 238 : 19) \
+   ? (TARGET_SH5 ? 238 : 18) \
    : (REGNO) == MACH_REG \
    ? (TARGET_SH5 ? 239 : 20) \
    : (REGNO) == MACL_REG \
    ? (TARGET_SH5 ? 240 : 21) \
+   : (REGNO) == T_REG \
+   ? (TARGET_SH5 ? 242 : 22) \
    : (REGNO) == FPUL_REG \
    ? (TARGET_SH5 ? 244 : 23) \
+   : (REGNO) == FPSCR_REG \
+   ? (TARGET_SH5 ? 243 : 24) \
    : (unsigned) -1)
 
 /* This is how to output a reference to a symbol_ref.  On SH5,
@@ -3124,7 +2571,7 @@ struct sh_args {
    constants.  Used for PIC-specific UNSPECs.  */
 #define OUTPUT_ADDR_CONST_EXTRA(STREAM, X, FAIL) \
   do                                                                   \
-    if (GET_CODE (X) == UNSPEC && XVECLEN ((X), 0) == 1)       \
+    if (GET_CODE (X) == UNSPEC)                                                \
       {                                                                        \
        switch (XINT ((X), 1))                                          \
          {                                                             \
@@ -3173,6 +2620,52 @@ struct sh_args {
              assemble_name ((STREAM), name);                           \
            }                                                           \
            break;                                                      \
+         case UNSPEC_EXTRACT_S16:                                      \
+         case UNSPEC_EXTRACT_U16:                                      \
+           {                                                           \
+             rtx val, shift;                                           \
+                                                                       \
+             val = XVECEXP (X, 0, 0);                                  \
+             shift = XVECEXP (X, 0, 1);                                \
+             fputc ('(', STREAM);                                      \
+             if (shift != const0_rtx)                                  \
+               fputc ('(', STREAM);                                    \
+             if (GET_CODE (val) == CONST                               \
+                 || GET_RTX_CLASS (GET_CODE (val)) != RTX_OBJ)         \
+               {                                                       \
+                 fputc ('(', STREAM);                                  \
+                 output_addr_const (STREAM, val);                      \
+                 fputc (')', STREAM);                                  \
+               }                                                       \
+             else                                                      \
+               output_addr_const (STREAM, val);                        \
+             if (shift != const0_rtx)                                  \
+               {                                                       \
+                 fputs (" >> ", STREAM);                               \
+                 output_addr_const (STREAM, shift);                    \
+                 fputc (')', STREAM);                                  \
+               }                                                       \
+             fputs (" & 65535)", STREAM);                              \
+           }                                                           \
+           break;                                                      \
+         case UNSPEC_SYMOFF:                                           \
+           output_addr_const (STREAM, XVECEXP (X, 0, 0));              \
+           fputc ('-', STREAM);                                        \
+           if (GET_CODE (XVECEXP (X, 0, 1)) == CONST)                  \
+             {                                                         \
+               fputc ('(', STREAM);                                    \
+               output_addr_const (STREAM, XVECEXP (X, 0, 1));          \
+               fputc (')', STREAM);                                    \
+             }                                                         \
+           else                                                        \
+             output_addr_const (STREAM, XVECEXP (X, 0, 1));            \
+           break;                                                      \
+         case UNSPEC_PCREL_SYMOFF:                                     \
+           output_addr_const (STREAM, XVECEXP (X, 0, 0));              \
+           fputs ("-(", STREAM);                                       \
+           output_addr_const (STREAM, XVECEXP (X, 0, 1));              \
+           fputs ("-.)", STREAM);                                      \
+           break;                                                      \
          default:                                                      \
            goto FAIL;                                                  \
          }                                                             \
@@ -3225,18 +2718,13 @@ extern enum mdep_reorg_phase_e mdep_reorg_phase;
   c_register_pragma (0, "nosave_low_regs", sh_pr_nosave_low_regs);     \
 } while (0)
 
-/* Set when processing a function with pragma interrupt turned on.  */
-
-extern int pragma_interrupt;
+extern tree sh_deferred_function_attributes;
+extern tree *sh_deferred_function_attributes_tail;
 
 /* Set when processing a function with interrupt attribute.  */
 
 extern int current_function_interrupt;
 
-/* Set to an RTX containing the address of the stack to switch to
-   for interrupt functions.  */
-extern struct rtx_def *sp_switch;
-
 \f
 /* Instructions with unfilled delay slots take up an
    extra two bytes for the nop in the delay slot.
@@ -3245,73 +2733,6 @@ extern struct rtx_def *sp_switch;
 #define ADJUST_INSN_LENGTH(X, LENGTH)                          \
   (LENGTH) += sh_insn_length_adjustment (X);
 \f
-/* Define the codes that are matched by predicates in sh.c.  */
-#define PREDICATE_CODES \
-  {"and_operand", {SUBREG, REG, CONST_INT}},                           \
-  {"any_arith_reg_dest", {SUBREG, REG}},                               \
-  {"any_register_operand", {SUBREG, REG}},                             \
-  {"arith_operand", {SUBREG, REG, CONST_INT}},                         \
-  {"arith_reg_dest", {SUBREG, REG}},                                   \
-  {"arith_reg_operand", {SUBREG, REG, SIGN_EXTEND}},                   \
-  {"arith_reg_or_0_operand", {SUBREG, REG, CONST_INT, CONST_VECTOR}},  \
-  {"binary_float_operator", {PLUS, MINUS, MULT, DIV}},                 \
-  {"binary_logical_operator", {AND, IOR, XOR}},                                \
-  {"cache_address_operand", {PLUS, REG}},                              \
-  {"cmp_operand", {SUBREG, REG, CONST_INT}},                           \
-  {"cmpsi_operand", {SUBREG, REG, CONST_INT}},                         \
-  {"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}},     \
-  {"ext_dest_operand", {SUBREG, REG}},                                 \
-  {"fp_arith_reg_dest", {SUBREG, REG}},                                        \
-  {"fp_arith_reg_operand", {SUBREG, REG}},                             \
-  {"fpscr_operand", {REG}},                                            \
-  {"fpul_operand", {REG}},                                             \
-  {"general_extend_operand", {SUBREG, REG, MEM, TRUNCATE}},            \
-  {"general_movsrc_operand", {SUBREG, REG, CONST_INT, CONST_DOUBLE, MEM, CONST }}, \
-  {"general_movdst_operand", {SUBREG, REG, MEM}},                      \
-  {"unaligned_load_operand", {MEM}},                                   \
-  {"greater_comparison_operator", {GT,GE,GTU,GEU}},                    \
-  {"inqhi_operand", {TRUNCATE}},                                       \
-  {"int_gpr_dest", {SUBREG, REG}},                                     \
-  {"less_comparison_operator", {LT,LE,LTU,LEU}},                       \
-  {"logical_operand", {SUBREG, REG, CONST_INT}},                       \
-  {"logical_operator", {AND,IOR,XOR}},                                 \
-  {"logical_reg_operand", {SUBREG, REG}},                              \
-  {"mextr_bit_offset", {CONST_INT}},                                   \
-  {"minuend_operand", {SUBREG, REG, TRUNCATE, CONST_INT}},             \
-  {"noncommutative_float_operator", {MINUS, DIV}},                     \
-  {"sh_const_vec", {CONST_VECTOR}},                                    \
-  {"sh_1el_vec", {CONST_VECTOR}},                                      \
-  {"sh_register_operand", {REG, SUBREG, CONST_INT}},                   \
-  {"sh_rep_vec", {CONST_VECTOR}},                                      \
-  {"shift_count_operand", {CONST_INT, CONST_DOUBLE, CONST, SYMBOL_REF, \
-                          LABEL_REF, SUBREG, REG, ZERO_EXTEND, SIGN_EXTEND}},\
-  {"shift_count_reg_operand", {SUBREG, REG, ZERO_EXTEND, SIGN_EXTEND}},        \
-  {"shift_operator", {ASHIFT, ASHIFTRT, LSHIFTRT}},                    \
-  {"symbol_ref_operand", {SYMBOL_REF}},                                        \
-  {"target_operand", {SUBREG, REG, LABEL_REF, SYMBOL_REF, CONST, UNSPEC}},\
-  {"target_reg_operand", {SUBREG, REG}},                               \
-  {"trunc_hi_operand", {SUBREG, REG, TRUNCATE}},                       \
-  {"ua_address_operand", {SUBREG, REG, PLUS}},                         \
-  {"ua_offset", {CONST_INT}},                                          \
-  {"unary_float_operator", {ABS, NEG, SQRT}},                          \
-  {"xor_operand", {SUBREG, REG, CONST_INT}},                           \
-
-#define SPECIAL_MODE_PREDICATES \
-  "any_arith_reg_dest", \
-  "any_register_operand", \
-  "int_gpr_dest", \
-  "target_operand", \
-  "target_reg_operand", \
-  "trunc_hi_operand", \
-  /* This line intentionally left blank.  */
-
-#define any_register_operand register_operand
-#define any_arith_reg_dest arith_reg_dest
-#define ext_dest_operand arith_reg_operand
-
 /* 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,
    the value is constrained to be within the bounds of the declared
@@ -3426,20 +2847,6 @@ extern struct rtx_def *sp_switch;
 2:\n" TEXT_SECTION_ASM_OP);
 #endif /* (defined CRT_BEGIN || defined CRT_END) && ! __SHMEDIA__ */
 
-#define ALLOCATE_INITIAL_VALUE(hard_reg) \
-  (REGNO (hard_reg) == (TARGET_SHMEDIA ? PR_MEDIA_REG : PR_REG) \
-   ? (current_function_is_leaf \
-      && ! sh_pr_n_sets () \
-      && ! (TARGET_SHCOMPACT \
-           && ((current_function_args_info.call_cookie \
-                & ~ CALL_COOKIE_RET_TRAMP (1)) \
-               || current_function_has_nonlocal_label)) \
-      ? (hard_reg) \
-      : gen_rtx_MEM (Pmode, return_address_pointer_rtx)) \
-   : NULL_RTX)
-
-#define SIMULTANEOUS_PREFETCHES 2
-
 /* FIXME: middle-end support for highpart optimizations is missing.  */
 #define high_life_started reload_in_progress