OSDN Git Service

Patch from Nick Clifton.
[pf3gnuchains/gcc-fork.git] / gcc / config / sh / sh.c
index 94ca7a0..66a7da4 100644 (file)
@@ -1,23 +1,23 @@
-/* Output routines for GCC for Hitachi / SuperH SH.
+/* Output routines for GCC for Renesas / SuperH SH.
    Copyright (C) 1993, 1994, 1995, 1997, 1997, 1998, 1999, 2000, 2001, 2002,
-   2003 Free Software Foundation, Inc.
+   2003, 2004 Free Software Foundation, Inc.
    Contributed by Steve Chamberlain (sac@cygnus.com).
    Improved by Jim Wilson (wilson@cygnus.com). 
 
-This file is part of GNU CC.
+This file is part of GCC.
 
-GNU CC is free software; you can redistribute it and/or modify
+GCC is free software; you can redistribute it and/or modify
 it under the terms of the GNU General Public License as published by
 the Free Software Foundation; either version 2, or (at your option)
 any later version.
 
-GNU CC is distributed in the hope that it will be useful,
+GCC is distributed in the hope that it will be useful,
 but WITHOUT ANY WARRANTY; without even the implied warranty of
 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 GNU General Public License for more details.
 
 You should have received a copy of the GNU General Public License
-along with GNU CC; see the file COPYING.  If not, write to
+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.  */
 
@@ -48,6 +48,9 @@ Boston, MA 02111-1307, USA.  */
 #include "basic-block.h"
 #include "ra.h"
 #include "cfglayout.h"
+#include "intl.h"
+#include "sched-int.h"
+#include "ggc.h"
 
 int code_for_indirect_jump_scratch = CODE_FOR_indirect_jump_scratch;
 
@@ -56,7 +59,7 @@ int code_for_indirect_jump_scratch = CODE_FOR_indirect_jump_scratch;
 
 /* These are some macros to abstract register modes.  */
 #define CONST_OK_FOR_ADD(size) \
-  (TARGET_SHMEDIA ? CONST_OK_FOR_P (size) : CONST_OK_FOR_I (size))
+  (TARGET_SHMEDIA ? CONST_OK_FOR_I10 (size) : CONST_OK_FOR_I08 (size))
 #define GEN_MOV (*(TARGET_SHMEDIA64 ? gen_movdi : gen_movsi))
 #define GEN_ADD3 (*(TARGET_SHMEDIA64 ? gen_adddi3 : gen_addsi3))
 #define GEN_SUB3 (*(TARGET_SHMEDIA64 ? gen_subdi3 : gen_subsi3))
@@ -90,7 +93,7 @@ static int pragma_trapa;
    interrupted.  */
 int pragma_nosave_low_regs;
 
-/* This is used for communication between SETUP_INCOMING_VARARGS and
+/* This is used for communication between TARGET_SETUP_INCOMING_VARARGS and
    sh_expand_prologue.  */
 int current_function_anonymous_args;
 
@@ -99,6 +102,21 @@ int current_function_anonymous_args;
 /* Which cpu are we scheduling for.  */
 enum processor_type sh_cpu;
 
+/* Definitions used in ready queue reordering for first scheduling pass.  */
+
+/* Reg weights arrays for modes SFmode and SImode, indexed by insn LUID.  */
+static short *regmode_weight[2];
+
+/* Total SFmode and SImode weights of scheduled insns.  */
+static int curr_regmode_pressure[2];
+
+/* If true, skip cycles for Q -> R movement.  */
+static int skip_cycles = 0;
+
+/* Cached value of can_issue_more. This is cached in sh_variable_issue hook
+   and returned from sh_reorder2.  */
+static short cached_can_issue_more;
+
 /* Saved operands from the last compare to use when we generate an scc
    or bcc insn.  */
 
@@ -108,7 +126,7 @@ rtx sh_compare_op1;
 /* Provides the class number of the smallest class containing
    reg number.  */
 
-int regno_reg_class[FIRST_PSEUDO_REGISTER] =
+enum reg_class regno_reg_class[FIRST_PSEUDO_REGISTER] =
 {
   R0_REGS, GENERAL_REGS, GENERAL_REGS, GENERAL_REGS,
   GENERAL_REGS, GENERAL_REGS, GENERAL_REGS, GENERAL_REGS,
@@ -175,57 +193,93 @@ enum reg_class reg_class_from_letter[] =
 
 int assembler_dialect;
 
-static void split_branches PARAMS ((rtx));
-static int branch_dest PARAMS ((rtx));
-static void force_into PARAMS ((rtx, rtx));
-static void print_slot PARAMS ((rtx));
-static rtx add_constant PARAMS ((rtx, enum machine_mode, rtx));
-static void dump_table PARAMS ((rtx));
-static int hi_const PARAMS ((rtx));
-static int broken_move PARAMS ((rtx));
-static int mova_p PARAMS ((rtx));
-static rtx find_barrier PARAMS ((int, rtx, rtx));
-static int noncall_uses_reg PARAMS ((rtx, rtx, rtx *));
-static rtx gen_block_redirect PARAMS ((rtx, int, int));
-static void sh_reorg PARAMS ((void));
-static void output_stack_adjust PARAMS ((int, rtx, int, rtx (*) (rtx)));
-static rtx frame_insn PARAMS ((rtx));
-static rtx push PARAMS ((int));
-static void pop PARAMS ((int));
-static void push_regs PARAMS ((HARD_REG_SET *, int));
-static int calc_live_regs PARAMS ((HARD_REG_SET *));
-static void mark_use PARAMS ((rtx, rtx *));
-static HOST_WIDE_INT rounded_frame_size PARAMS ((int));
-static rtx mark_constant_pool_use PARAMS ((rtx));
+static bool shmedia_space_reserved_for_target_registers;
+
+static void split_branches (rtx);
+static int branch_dest (rtx);
+static void force_into (rtx, rtx);
+static void print_slot (rtx);
+static rtx add_constant (rtx, enum machine_mode, rtx);
+static void dump_table (rtx);
+static int hi_const (rtx);
+static int broken_move (rtx);
+static int mova_p (rtx);
+static rtx find_barrier (int, rtx, rtx);
+static int noncall_uses_reg (rtx, rtx, rtx *);
+static rtx gen_block_redirect (rtx, int, int);
+static void sh_reorg (void);
+static void output_stack_adjust (int, rtx, int, HARD_REG_SET *);
+static rtx frame_insn (rtx);
+static rtx push (int);
+static void pop (int);
+static void push_regs (HARD_REG_SET *, int);
+static int calc_live_regs (HARD_REG_SET *);
+static void mark_use (rtx, rtx *);
+static HOST_WIDE_INT rounded_frame_size (int);
+static rtx mark_constant_pool_use (rtx);
 const struct attribute_spec sh_attribute_table[];
-static tree sh_handle_interrupt_handler_attribute PARAMS ((tree *, tree, tree, int, bool *));
-static tree sh_handle_sp_switch_attribute PARAMS ((tree *, tree, tree, int, bool *));
-static tree sh_handle_trap_exit_attribute PARAMS ((tree *, tree, tree, int, bool *));
-static void sh_output_function_epilogue PARAMS ((FILE *, HOST_WIDE_INT));
-static void sh_insert_attributes PARAMS ((tree, tree *));
-static int sh_adjust_cost PARAMS ((rtx, rtx, rtx, int));
-static int sh_use_dfa_interface PARAMS ((void));
-static int sh_issue_rate PARAMS ((void));
-static bool sh_function_ok_for_sibcall PARAMS ((tree, tree));
-
-static bool sh_cannot_modify_jumps_p PARAMS ((void));
-static bool sh_ms_bitfield_layout_p PARAMS ((tree));
-
-static void sh_init_builtins PARAMS ((void));
-static void sh_media_init_builtins PARAMS ((void));
-static rtx sh_expand_builtin PARAMS ((tree, rtx, rtx, enum machine_mode, int));
-static void sh_output_mi_thunk PARAMS ((FILE *, tree, HOST_WIDE_INT,
-                                       HOST_WIDE_INT, tree));
-static int flow_dependent_p PARAMS ((rtx, rtx));
-static void flow_dependent_p_1 PARAMS ((rtx, rtx, void *));
-static int shiftcosts PARAMS ((rtx));
-static int andcosts PARAMS ((rtx));
-static int addsubcosts PARAMS ((rtx));
-static int multcosts PARAMS ((rtx));
-static bool unspec_caller_rtx_p PARAMS ((rtx));
-static bool sh_cannot_copy_insn_p PARAMS ((rtx));
-static bool sh_rtx_costs PARAMS ((rtx, int, int, int *));
-static int sh_address_cost PARAMS ((rtx));
+static tree sh_handle_interrupt_handler_attribute (tree *, tree, tree, int, bool *);
+static tree sh_handle_sp_switch_attribute (tree *, tree, tree, int, bool *);
+static tree sh_handle_trap_exit_attribute (tree *, tree, tree, int, bool *);
+static tree sh_handle_renesas_attribute (tree *, tree, tree, int, bool *);
+static void sh_output_function_epilogue (FILE *, HOST_WIDE_INT);
+static void sh_insert_attributes (tree, tree *);
+static int sh_adjust_cost (rtx, rtx, rtx, int);
+static int sh_use_dfa_interface (void);
+static int sh_issue_rate (void);
+static int sh_dfa_new_cycle (FILE *, int, rtx, int, int, int *sort_p);
+static short find_set_regmode_weight (rtx, enum machine_mode);
+static short find_insn_regmode_weight (rtx, enum machine_mode);
+static void find_regmode_weight (int, enum machine_mode);
+static void  sh_md_init_global (FILE *, int, int);
+static void  sh_md_finish_global (FILE *, int);
+static int rank_for_reorder (const void *, const void *);
+static void swap_reorder (rtx *, int);
+static void ready_reorder (rtx *, int);
+static short high_pressure (enum machine_mode);
+static int sh_reorder (FILE *, int, rtx *, int *, int);
+static int sh_reorder2 (FILE *, int, rtx *, int *, int);
+static void sh_md_init (FILE *, int, int);
+static int sh_variable_issue (FILE *, int, rtx, int);
+  
+static bool sh_function_ok_for_sibcall (tree, tree);
+
+static bool sh_cannot_modify_jumps_p (void);
+static int sh_target_reg_class (void);
+static bool sh_optimize_target_register_callee_saved (bool);
+static bool sh_ms_bitfield_layout_p (tree);
+
+static void sh_init_builtins (void);
+static void sh_media_init_builtins (void);
+static rtx sh_expand_builtin (tree, rtx, rtx, enum machine_mode, int);
+static void sh_output_mi_thunk (FILE *, tree, HOST_WIDE_INT, HOST_WIDE_INT, tree);
+static void sh_file_start (void);
+static int flow_dependent_p (rtx, rtx);
+static void flow_dependent_p_1 (rtx, rtx, void *);
+static int shiftcosts (rtx);
+static int andcosts (rtx);
+static int addsubcosts (rtx);
+static int multcosts (rtx);
+static bool unspec_caller_rtx_p (rtx);
+static bool sh_cannot_copy_insn_p (rtx);
+static bool sh_rtx_costs (rtx, int, int, int *);
+static int sh_address_cost (rtx);
+static int shmedia_target_regs_stack_space (HARD_REG_SET *);
+static int shmedia_reserve_space_for_target_registers_p (int, HARD_REG_SET *);
+static int shmedia_target_regs_stack_adjust (HARD_REG_SET *);
+static int scavenge_reg (HARD_REG_SET *s);
+struct save_schedule_s;
+static struct save_entry_s *sh5_schedule_saves (HARD_REG_SET *,
+                                               struct save_schedule_s *, int);
+
+static rtx sh_struct_value_rtx (tree, int);
+static bool sh_return_in_memory (tree, tree);
+static rtx sh_builtin_saveregs (void);
+static void sh_setup_incoming_varargs (CUMULATIVE_ARGS *, enum machine_mode, tree, int *, int);
+static bool sh_strict_argument_naming (CUMULATIVE_ARGS *);
+static bool sh_pretend_outgoing_varargs_named (CUMULATIVE_ARGS *);
+static tree sh_build_builtin_va_list (void);
+
 \f
 /* Initialize the GCC target structure.  */
 #undef TARGET_ATTRIBUTE_TABLE
@@ -252,6 +306,11 @@ static int sh_address_cost PARAMS ((rtx));
 #undef TARGET_ASM_CAN_OUTPUT_MI_THUNK
 #define TARGET_ASM_CAN_OUTPUT_MI_THUNK hook_bool_tree_hwi_hwi_tree_true
 
+#undef TARGET_ASM_FILE_START
+#define TARGET_ASM_FILE_START sh_file_start
+#undef TARGET_ASM_FILE_START_FILE_DIRECTIVE
+#define TARGET_ASM_FILE_START_FILE_DIRECTIVE true
+
 #undef TARGET_INSERT_ATTRIBUTES
 #define TARGET_INSERT_ATTRIBUTES sh_insert_attributes
 
@@ -264,8 +323,69 @@ static int sh_address_cost PARAMS ((rtx));
 #undef TARGET_SCHED_ISSUE_RATE
 #define TARGET_SCHED_ISSUE_RATE sh_issue_rate
 
+/* The next 5 hooks have been implemented for reenabling sched1.  With the
+   help of these macros we are limiting the movement of insns in sched1 to
+   reduce the register pressure.  The overall idea is to keep count of SImode 
+   and SFmode regs required by already scheduled insns. When these counts
+   cross some threshold values; give priority to insns that free registers.
+   The insn that frees registers is most likely to be the insn with lowest
+   LUID (original insn order); but such an insn might be there in the stalled 
+   queue (Q) instead of the ready queue (R).  To solve this, we skip cycles
+   upto a max of 8 cycles so that such insns may move from Q -> R.
+
+   The description of the hooks are as below:
+
+   TARGET_SCHED_INIT_GLOBAL: Added a new target hook in the generic
+   scheduler; it is called inside the sched_init function just after
+   find_insn_reg_weights function call. It is used to calculate the SImode
+   and SFmode weights of insns of basic blocks; much similiar to what
+   find_insn_reg_weights does. 
+   TARGET_SCHED_FINISH_GLOBAL: Corresponding cleanup hook.
+
+   TARGET_SCHED_DFA_NEW_CYCLE: Skip cycles if high register pressure is
+   indicated by TARGET_SCHED_REORDER2; doing this may move insns from
+   (Q)->(R).
+
+   TARGET_SCHED_REORDER: If the register pressure for SImode or SFmode is
+   high; reorder the ready queue so that the insn with lowest LUID will be
+   issued next.
+
+   TARGET_SCHED_REORDER2: If the register pressure is high, indicate to
+   TARGET_SCHED_DFA_NEW_CYCLE to skip cycles.
+
+   TARGET_SCHED_VARIABLE_ISSUE: Cache the value of can_issue_more so that it
+   can be returned from TARGET_SCHED_REORDER2.
+
+   TARGET_SCHED_INIT: Reset the register pressure counting variables.  */
+
+#undef TARGET_SCHED_DFA_NEW_CYCLE
+#define TARGET_SCHED_DFA_NEW_CYCLE sh_dfa_new_cycle
+
+#undef TARGET_SCHED_INIT_GLOBAL
+#define TARGET_SCHED_INIT_GLOBAL sh_md_init_global
+
+#undef TARGET_SCHED_FINISH_GLOBAL
+#define TARGET_SCHED_FINISH_GLOBAL sh_md_finish_global
+
+#undef TARGET_SCHED_VARIABLE_ISSUE
+#define TARGET_SCHED_VARIABLE_ISSUE sh_variable_issue
+
+#undef TARGET_SCHED_REORDER
+#define TARGET_SCHED_REORDER sh_reorder
+
+#undef TARGET_SCHED_REORDER2
+#define TARGET_SCHED_REORDER2 sh_reorder2
+
+#undef TARGET_SCHED_INIT
+#define TARGET_SCHED_INIT sh_md_init
+
 #undef TARGET_CANNOT_MODIFY_JUMPS_P
 #define TARGET_CANNOT_MODIFY_JUMPS_P sh_cannot_modify_jumps_p
+#undef TARGET_BRANCH_TARGET_REGISTER_CLASS
+#define TARGET_BRANCH_TARGET_REGISTER_CLASS sh_target_reg_class
+#undef TARGET_BRANCH_TARGET_REGISTER_CALLEE_SAVED
+#define TARGET_BRANCH_TARGET_REGISTER_CALLEE_SAVED \
+ sh_optimize_target_register_callee_saved
 
 #undef TARGET_MS_BITFIELD_LAYOUT_P
 #define TARGET_MS_BITFIELD_LAYOUT_P sh_ms_bitfield_layout_p
@@ -293,14 +413,45 @@ static int sh_address_cost PARAMS ((rtx));
 #define TARGET_HAVE_TLS true
 #endif
 
+#undef TARGET_PROMOTE_PROTOTYPES
+#define TARGET_PROMOTE_PROTOTYPES sh_promote_prototypes
+#undef TARGET_PROMOTE_FUNCTION_ARGS
+#define TARGET_PROMOTE_FUNCTION_ARGS sh_promote_prototypes
+#undef TARGET_PROMOTE_FUNCTION_RETURN
+#define TARGET_PROMOTE_FUNCTION_RETURN sh_promote_prototypes
+
+#undef TARGET_STRUCT_VALUE_RTX
+#define TARGET_STRUCT_VALUE_RTX sh_struct_value_rtx
+#undef TARGET_RETURN_IN_MEMORY
+#define TARGET_RETURN_IN_MEMORY sh_return_in_memory
+
+#undef TARGET_EXPAND_BUILTIN_SAVEREGS
+#define TARGET_EXPAND_BUILTIN_SAVEREGS sh_builtin_saveregs
+#undef TARGET_SETUP_INCOMING_VARARGS
+#define TARGET_SETUP_INCOMING_VARARGS sh_setup_incoming_varargs
+#undef TARGET_STRICT_ARGUMENT_NAMING
+#define TARGET_STRICT_ARGUMENT_NAMING sh_strict_argument_naming
+#undef TARGET_PRETEND_OUTGOING_VARARGS_NAMED
+#define TARGET_PRETEND_OUTGOING_VARARGS_NAMED sh_pretend_outgoing_varargs_named
+
+#undef TARGET_BUILD_BUILTIN_VA_LIST
+#define TARGET_BUILD_BUILTIN_VA_LIST sh_build_builtin_va_list
+
+#undef TARGET_PCH_VALID_P
+#define TARGET_PCH_VALID_P sh_pch_valid_p
+
+/* Return regmode weight for insn.  */
+#define INSN_REGMODE_WEIGHT(INSN, MODE)  regmode_weight[((MODE) == SImode) ? 0 : 1][INSN_UID (INSN)]
+
+/* Return current register pressure for regmode.  */
+#define CURR_REGMODE_PRESSURE(MODE)    curr_regmode_pressure[((MODE) == SImode) ? 0 : 1]
+
 struct gcc_target targetm = TARGET_INITIALIZER;
 \f
 /* Print the operand address in x to the stream.  */
 
 void
-print_operand_address (stream, x)
-     FILE *stream;
-     rtx x;
+print_operand_address (FILE *stream, rtx x)
 {
   switch (GET_CODE (x))
     {
@@ -361,7 +512,7 @@ print_operand_address (stream, x)
    ','  print LOCAL_LABEL_PREFIX
    '@'  print trap, rte or rts depending upon pragma interruptness
    '#'  output a nop if there is nothing to put in the delay slot
-   '''  print likelyhood suffix (/u for unlikely).
+   '''  print likelihood suffix (/u for unlikely).
    'O'  print a constant without the #
    'R'  print the LSW of a dp value - changes if in little endian
    'S'  print the MSW of a dp value - changes if in little endian
@@ -373,10 +524,7 @@ print_operand_address (stream, x)
    'o'  output an operator.  */
 
 void
-print_operand (stream, x, code)
-     FILE *stream;
-     rtx x;
-     int code;
+print_operand (FILE *stream, rtx x, int code)
 {
   switch (code)
     {
@@ -585,8 +733,7 @@ print_operand (stream, x, code)
 \f
 /* Like force_operand, but guarantees that VALUE ends up in TARGET.  */
 static void
-force_into (value, target)
-     rtx value, target;
+force_into (rtx value, rtx target)
 {
   value = force_operand (value, target);
   if (! rtx_equal_p (value, target))
@@ -601,8 +748,7 @@ force_into (value, target)
    OPERANDS[3] is the alignment safe to use.  */
 
 int
-expand_block_move (operands)
-     rtx *operands;
+expand_block_move (rtx *operands)
 {
   int align = INTVAL (operands[3]);
   int constp = (GET_CODE (operands[2]) == CONST_INT);
@@ -622,8 +768,8 @@ expand_block_move (operands)
          tree entry_name;
          rtx sym;
          rtx func_addr_rtx;
-         rtx r4 = gen_rtx (REG, SImode, 4);
-         rtx r5 = gen_rtx (REG, SImode, 5);
+         rtx r4 = gen_rtx_REG (SImode, 4);
+         rtx r5 = gen_rtx_REG (SImode, 5);
 
          entry_name = get_identifier ("__movstrSI12_i4");
 
@@ -640,9 +786,9 @@ expand_block_move (operands)
          rtx sym;
          rtx func_addr_rtx;
          int dwords;
-         rtx r4 = gen_rtx (REG, SImode, 4);
-         rtx r5 = gen_rtx (REG, SImode, 5);
-         rtx r6 = gen_rtx (REG, SImode, 6);
+         rtx r4 = gen_rtx_REG (SImode, 4);
+         rtx r5 = gen_rtx_REG (SImode, 5);
+         rtx r6 = gen_rtx_REG (SImode, 6);
 
          entry_name = get_identifier (bytes & 4
                                       ? "__movstr_i4_odd"
@@ -717,9 +863,7 @@ expand_block_move (operands)
    operands must be in a register.  */
 
 int
-prepare_move_operands (operands, mode)
-     rtx operands[];
-     enum machine_mode mode;
+prepare_move_operands (rtx operands[], enum machine_mode mode)
 {
   if ((mode == SImode || mode == DImode)
       && flag_pic
@@ -799,13 +943,13 @@ prepare_move_operands (operands, mode)
            {
            case TLS_MODEL_GLOBAL_DYNAMIC:
              tga_ret = gen_rtx_REG (Pmode, R0_REG);
-             emit_insn (gen_tls_global_dynamic (tga_ret, op1));
+             emit_call_insn (gen_tls_global_dynamic (tga_ret, op1));
              op1 = tga_ret;
              break;
 
            case TLS_MODEL_LOCAL_DYNAMIC:
              tga_ret = gen_rtx_REG (Pmode, R0_REG);
-             emit_insn (gen_tls_local_dynamic (tga_ret, op1));
+             emit_call_insn (gen_tls_local_dynamic (tga_ret, op1));
 
              tmp = gen_reg_rtx (Pmode);
              emit_move_insn (tmp, tga_ret);
@@ -856,8 +1000,7 @@ prepare_move_operands (operands, mode)
 /* Prepare the operands for an scc instruction; make sure that the
    compare has been done.  */
 rtx
-prepare_scc_operands (code)
-     enum rtx_code code;
+prepare_scc_operands (enum rtx_code code)
 {
   rtx t_reg = gen_rtx_REG (SImode, T_REG);
   enum rtx_code oldcode = code;
@@ -905,15 +1048,15 @@ prepare_scc_operands (code)
 
   if (TARGET_SH4 && GET_MODE_CLASS (mode) == MODE_FLOAT)
     (mode == SFmode ? emit_sf_insn : emit_df_insn)
-     (gen_rtx (PARALLEL, VOIDmode, gen_rtvec (2,
-               gen_rtx (SET, VOIDmode, t_reg,
-                        gen_rtx (code, SImode,
-                                 sh_compare_op0, sh_compare_op1)),
-               gen_rtx (USE, VOIDmode, get_fpscr_rtx ()))));
+     (gen_rtx_PARALLEL (VOIDmode, gen_rtvec (2,
+               gen_rtx_SET (VOIDmode, t_reg,
+                            gen_rtx_fmt_ee (code, SImode,
+                                            sh_compare_op0, sh_compare_op1)),
+               gen_rtx_USE (VOIDmode, get_fpscr_rtx ()))));
   else
-    emit_insn (gen_rtx (SET, VOIDmode, t_reg,
-                       gen_rtx (code, SImode, sh_compare_op0,
-                                sh_compare_op1)));
+    emit_insn (gen_rtx_SET (VOIDmode, t_reg,
+                           gen_rtx_fmt_ee (code, SImode,
+                                           sh_compare_op0, sh_compare_op1)));
 
   return t_reg;
 }
@@ -921,9 +1064,7 @@ prepare_scc_operands (code)
 /* Called from the md file, set up the operands of a compare instruction.  */
 
 void
-from_compare (operands, code)
-     rtx *operands;
-     int code;
+from_compare (rtx *operands, int code)
 {
   enum machine_mode mode = GET_MODE (sh_compare_op0);
   rtx insn;
@@ -948,13 +1089,13 @@ from_compare (operands, code)
   else
     insn = gen_rtx_SET (VOIDmode,
                        gen_rtx_REG (SImode, T_REG),
-                       gen_rtx (code, SImode, sh_compare_op0,
-                                sh_compare_op1));
+                       gen_rtx_fmt_ee (code, SImode,
+                                       sh_compare_op0, sh_compare_op1));
   if (TARGET_SH4 && GET_MODE_CLASS (mode) == MODE_FLOAT)
     {
-      insn = gen_rtx (PARALLEL, VOIDmode,
+      insn = gen_rtx_PARALLEL (VOIDmode,
                      gen_rtvec (2, insn,
-                                gen_rtx (USE, VOIDmode, get_fpscr_rtx ())));
+                                gen_rtx_USE (VOIDmode, get_fpscr_rtx ())));
       (mode == SFmode ? emit_sf_insn : emit_df_insn) (insn);
     }
   else
@@ -969,10 +1110,8 @@ from_compare (operands, code)
    to take care when we see overlapping source and dest registers.  */
 
 const char *
-output_movedouble (insn, operands, mode)
-     rtx insn ATTRIBUTE_UNUSED;
-     rtx operands[];
-     enum machine_mode mode;
+output_movedouble (rtx insn ATTRIBUTE_UNUSED, rtx operands[],
+                  enum machine_mode mode)
 {
   rtx dst = operands[0];
   rtx src = operands[1];
@@ -1047,18 +1186,15 @@ output_movedouble (insn, operands, mode)
    into a sequence where putting the slot insn at the end wouldn't work.  */
 
 static void
-print_slot (insn)
-     rtx insn;
+print_slot (rtx insn)
 {
-  final_scan_insn (XVECEXP (insn, 0, 1), asm_out_file, optimize, 0, 1);
+  final_scan_insn (XVECEXP (insn, 0, 1), asm_out_file, optimize, 0, 1, NULL);
 
   INSN_DELETED_P (XVECEXP (insn, 0, 1)) = 1;
 }
 
 const char *
-output_far_jump (insn, op)
-     rtx insn;
-     rtx op;
+output_far_jump (rtx insn, rtx op)
 {
   struct { rtx lab, reg, op; } this;
   rtx braf_base_lab = NULL_RTX;
@@ -1152,10 +1288,7 @@ static int lf = 100;
 /* Output code for ordinary branches.  */
 
 const char *
-output_branch (logic, insn, operands)
-     int logic;
-     rtx insn;
-     rtx *operands;
+output_branch (int logic, rtx insn, rtx *operands)
 {
   switch (get_attr_length (insn))
     {
@@ -1190,7 +1323,7 @@ output_branch (logic, insn, operands)
     
          output_asm_insn ("bra\t%l0", &op0);
          fprintf (asm_out_file, "\tnop\n");
-         (*targetm.asm_out.internal_label)(asm_out_file, "LF", label);
+         (*targetm.asm_out.internal_label) (asm_out_file, "LF", label);
     
          return "";
        }
@@ -1240,11 +1373,8 @@ output_branch (logic, insn, operands)
 }
 
 const char *
-output_branchy_insn (code, template, insn, operands)
-     enum rtx_code code;
-     const char *template;
-     rtx insn;
-     rtx *operands;
+output_branchy_insn (enum rtx_code code, const char *template,
+                    rtx insn, rtx *operands)
 {
   rtx next_insn = NEXT_INSN (insn);
 
@@ -1284,39 +1414,49 @@ output_branchy_insn (code, template, insn, operands)
 }
 
 const char *
-output_ieee_ccmpeq (insn, operands)
-     rtx insn, *operands;
+output_ieee_ccmpeq (rtx insn, rtx *operands)
 {
   return output_branchy_insn (NE, "bt\t%l9\\;fcmp/eq\t%1,%0", insn, operands);
 }
 \f
-/* Output to FILE the start of the assembler file.  */
+/* Output the start of the assembler file.  */
 
-void
-output_file_start (file)
-     FILE *file;
-{
-  output_file_directive (file, main_input_filename);
-
-  /* Switch to the data section so that the coffsem symbol
-     isn't in the text section.  */
-  data_section ();
+static void
+sh_file_start (void)
+{
+  default_file_start ();
+
+  if (TARGET_ELF)
+    /* We need to show the text section with the proper
+       attributes as in TEXT_SECTION_ASM_OP, before dwarf2out
+       emits it without attributes in TEXT_SECTION_ASM_OP, else GAS
+       will complain.  We can teach GAS specifically about the
+       default attributes for our choice of text section, but
+       then we would have to change GAS again if/when we change
+       the text section name.  */
+    fprintf (asm_out_file, "%s\n", TEXT_SECTION_ASM_OP);
+  else
+    /* Switch to the data section so that the coffsem symbol
+       isn't in the text section.  */
+    data_section ();
 
   if (TARGET_LITTLE_ENDIAN)
-    fprintf (file, "\t.little\n");
+    fputs ("\t.little\n", asm_out_file);
 
-  if (TARGET_SHCOMPACT)
-    fprintf (file, "\t.mode\tSHcompact\n");
-  else if (TARGET_SHMEDIA)
-    fprintf (file, "\t.mode\tSHmedia\n\t.abi\t%i\n",
-            TARGET_SHMEDIA64 ? 64 : 32);
+  if (!TARGET_ELF)
+    {
+      if (TARGET_SHCOMPACT)
+       fputs ("\t.mode\tSHcompact\n", asm_out_file);
+      else if (TARGET_SHMEDIA)
+       fprintf (asm_out_file, "\t.mode\tSHmedia\n\t.abi\t%i\n",
+                TARGET_SHMEDIA64 ? 64 : 32);
+    }
 }
 \f
 /* Check if PAT includes UNSPEC_CALLER unspec pattern.  */
 
 static bool
-unspec_caller_rtx_p (pat)
-     rtx pat;
+unspec_caller_rtx_p (rtx pat)
 {
   switch (GET_CODE (pat))
     {
@@ -1341,8 +1481,7 @@ unspec_caller_rtx_p (pat)
    that generates an unique label.  */
 
 static bool
-sh_cannot_copy_insn_p (insn)
-     rtx insn;
+sh_cannot_copy_insn_p (rtx insn)
 {
   rtx pat;
 
@@ -1413,8 +1552,7 @@ static const short ext_shift_amounts[32][4] = {
    of arbitrary constant shift instructions.  */
 
 int
-shift_insns_rtx (insn)
-     rtx insn;
+shift_insns_rtx (rtx insn)
 {
   rtx set_src = SET_SRC (XVECEXP (PATTERN (insn), 0, 0));
   int shift_count = INTVAL (XEXP (set_src, 1));
@@ -1428,15 +1566,14 @@ shift_insns_rtx (insn)
     case ASHIFT:
       return shift_insns[shift_count];
     default:
-      abort();
+      abort ();
     }
 }
 
 /* Return the cost of a shift.  */
 
 static inline int
-shiftcosts (x)
-     rtx x;
+shiftcosts (rtx x)
 {
   int value;
 
@@ -1475,8 +1612,7 @@ shiftcosts (x)
 /* Return the cost of an AND operation.  */
 
 static inline int
-andcosts (x)
-     rtx x;
+andcosts (rtx x)
 {
   int i;
 
@@ -1489,8 +1625,8 @@ andcosts (x)
   if (TARGET_SHMEDIA)
     {
       if ((GET_CODE (XEXP (x, 1)) == CONST_INT
-          && CONST_OK_FOR_J (INTVAL (XEXP (x, 1))))
-         || EXTRA_CONSTRAINT_S (XEXP (x, 1)))
+          && CONST_OK_FOR_I16 (INTVAL (XEXP (x, 1))))
+         || EXTRA_CONSTRAINT_C16 (XEXP (x, 1)))
        return 1;
       else
        return 2;
@@ -1499,13 +1635,13 @@ andcosts (x)
   /* These constants are single cycle extu.[bw] instructions.  */
   if (i == 0xff || i == 0xffff)
     return 1;
-  /* Constants that can be used in an and immediate instruction is a single
+  /* Constants that can be used in an and immediate instruction in a single
      cycle, but this requires r0, so make it a little more expensive.  */
-  if (CONST_OK_FOR_L (i))
+  if (CONST_OK_FOR_K08 (i))
     return 2;
   /* Constants that can be loaded with a mov immediate and an and.
      This case is probably unnecessary.  */
-  if (CONST_OK_FOR_I (i))
+  if (CONST_OK_FOR_I08 (i))
     return 2;
   /* Any other constants requires a 2 cycle pc-relative load plus an and.
      This case is probably unnecessary.  */
@@ -1515,8 +1651,7 @@ andcosts (x)
 /* Return the cost of an addition or a subtraction.  */
 
 static inline int
-addsubcosts (x)
-     rtx x;
+addsubcosts (rtx x)
 {
   /* Adding a register is a single cycle insn.  */
   if (GET_CODE (XEXP (x, 1)) == REG
@@ -1537,16 +1672,16 @@ addsubcosts (x)
        return TARGET_SHMEDIA64 ? 5 : 3;
 
       case CONST_INT:
-       if (CONST_OK_FOR_J (INTVAL (XEXP (x, 1))))
+       if (CONST_OK_FOR_I16 (INTVAL (XEXP (x, 1))))
           return 2;
-       else if (CONST_OK_FOR_J (INTVAL (XEXP (x, 1)) >> 16))
+       else if (CONST_OK_FOR_I16 (INTVAL (XEXP (x, 1)) >> 16))
          return 3;
-       else if (CONST_OK_FOR_J ((INTVAL (XEXP (x, 1)) >> 16) >> 16))
+       else if (CONST_OK_FOR_I16 ((INTVAL (XEXP (x, 1)) >> 16) >> 16))
          return 4;
 
        /* Fall through.  */
       default:
-         return 5;
+       return 5;
       }
 
   /* Any other constant requires a 2 cycle pc-relative load plus an
@@ -1556,8 +1691,7 @@ addsubcosts (x)
 
 /* Return the cost of a multiply.  */
 static inline int
-multcosts (x)
-     rtx x ATTRIBUTE_UNUSED;
+multcosts (rtx x ATTRIBUTE_UNUSED)
 {
   if (TARGET_SHMEDIA)
     return 3;
@@ -1586,9 +1720,7 @@ multcosts (x)
    scanned.  In either case, *TOTAL contains the cost result.  */
 
 static bool
-sh_rtx_costs (x, code, outer_code, total)
-     rtx x;
-     int code, outer_code, *total;
+sh_rtx_costs (rtx x, int code, int outer_code, int *total)
 {
   switch (code)
     {
@@ -1601,22 +1733,22 @@ sh_rtx_costs (x, code, outer_code, total)
            *total = 0;
          else if ((outer_code == IOR || outer_code == XOR
                    || outer_code == PLUS)
-                  && CONST_OK_FOR_P (INTVAL (x)))
+                  && CONST_OK_FOR_I10 (INTVAL (x)))
            *total = 0;
-         else if (CONST_OK_FOR_J (INTVAL (x)))
+         else if (CONST_OK_FOR_I16 (INTVAL (x)))
             *total = COSTS_N_INSNS (outer_code != SET);
-         else if (CONST_OK_FOR_J (INTVAL (x) >> 16))
+         else if (CONST_OK_FOR_I16 (INTVAL (x) >> 16))
            *total = COSTS_N_INSNS (2);
-         else if (CONST_OK_FOR_J ((INTVAL (x) >> 16) >> 16))
+         else if (CONST_OK_FOR_I16 ((INTVAL (x) >> 16) >> 16))
            *total = COSTS_N_INSNS (3);
           else
            *total = COSTS_N_INSNS (4);
          return true;
         }
-      if (CONST_OK_FOR_I (INTVAL (x)))
+      if (CONST_OK_FOR_I08 (INTVAL (x)))
         *total = 0;
       else if ((outer_code == AND || outer_code == IOR || outer_code == XOR)
-              && CONST_OK_FOR_L (INTVAL (x)))
+              && CONST_OK_FOR_K08 (INTVAL (x)))
         *total = 1;
       else
         *total = 8;
@@ -1680,8 +1812,7 @@ sh_rtx_costs (x, code, outer_code, total)
    since it increases pressure on r0.  */
 
 static int
-sh_address_cost (X)
-     rtx X;
+sh_address_cost (rtx X)
 {
   return (GET_CODE (X) == PLUS
          && ! CONSTANT_P (XEXP (X, 1))
@@ -1691,10 +1822,7 @@ sh_address_cost (X)
 /* Code to expand a shift.  */
 
 void
-gen_ashift (type, n, reg)
-     int type;
-     int n;
-     rtx reg;
+gen_ashift (int type, int n, rtx reg)
 {
   /* Negative values here come from the shift_amounts array.  */
   if (n < 0)
@@ -1726,10 +1854,7 @@ gen_ashift (type, n, reg)
 /* Same for HImode */
 
 void
-gen_ashift_hi (type, n, reg)
-     int type;
-     int n;
-     rtx reg;
+gen_ashift_hi (int type, int n, rtx reg)
 {
   /* Negative values here come from the shift_amounts array.  */
   if (n < 0)
@@ -1770,9 +1895,7 @@ gen_ashift_hi (type, n, reg)
    shift instructions.  */
    
 void
-gen_shifty_op (code, operands)
-     int code;
-     rtx *operands;
+gen_shifty_op (int code, rtx *operands)
 {
   int value = INTVAL (operands[2]);
   int max, i;
@@ -1818,13 +1941,11 @@ gen_shifty_op (code, operands)
    matter.  */
 
 void
-gen_shifty_hi_op (code, operands)
-     int code;
-     rtx *operands;
+gen_shifty_hi_op (int code, rtx *operands)
 {
   int value = INTVAL (operands[2]);
   int max, i;
-  void (*gen_fun) PARAMS ((int, int, rtx));
+  void (*gen_fun) (int, int, rtx);
 
   /* This operation is used by and_shl for SImode values with a few
      high bits known to be cleared.  */
@@ -1854,8 +1975,7 @@ gen_shifty_hi_op (code, operands)
 /* ??? Rewrite to use super-optimizer sequences.  */
 
 int
-expand_ashiftrt (operands)
-     rtx *operands;
+expand_ashiftrt (rtx *operands)
 {
   rtx sym;
   rtx wrk;
@@ -1926,8 +2046,7 @@ expand_ashiftrt (operands)
 }
 
 int
-sh_dynamicalize_shift_p (count)
-     rtx count;
+sh_dynamicalize_shift_p (rtx count)
 {
   return shift_insns[INTVAL (count)] > 1 + SH_DYNAMIC_SHIFT_COST;
 }
@@ -1953,9 +2072,7 @@ sh_dynamicalize_shift_p (count)
   shift_amounts for the last shift value that is to be used before the
   sign extend.  */
 int
-shl_and_kind (left_rtx, mask_rtx, attrp)
-     rtx left_rtx, mask_rtx;
-     int *attrp;
+shl_and_kind (rtx left_rtx, rtx mask_rtx, int *attrp)
 {
   unsigned HOST_WIDE_INT mask, lsb, mask2, lsb2;
   int left = INTVAL (left_rtx), right;
@@ -1971,7 +2088,7 @@ shl_and_kind (left_rtx, mask_rtx, attrp)
     mask = (unsigned HOST_WIDE_INT) INTVAL (mask_rtx) >> left;
   else
     mask = (unsigned HOST_WIDE_INT) GET_MODE_MASK (SImode) >> left;
-  /* Can this be expressed as a right shift / left shift pair ? */
+  /* Can this be expressed as a right shift / left shift pair */
   lsb = ((mask ^ (mask - 1)) >> 1) + 1;
   right = exact_log2 (lsb);
   mask2 = ~(mask + lsb - 1);
@@ -1985,15 +2102,15 @@ shl_and_kind (left_rtx, mask_rtx, attrp)
       int late_right = exact_log2 (lsb2);
       best_cost = shift_insns[left + late_right] + shift_insns[late_right];
     }
-  /* Try to use zero extend */
+  /* Try to use zero extend */
   if (mask2 == ~(lsb2 - 1))
     {
       int width, first;
 
       for (width = 8; width <= 16; width += 8)
        {
-         /* Can we zero-extend right away? */
-         if (lsb2 == (unsigned HOST_WIDE_INT)1 << width)
+         /* Can we zero-extend right away?  */
+         if (lsb2 == (unsigned HOST_WIDE_INT) 1 << width)
            {
              cost
                = 1 + ext_shift_insns[right] + ext_shift_insns[left + right];
@@ -2025,7 +2142,7 @@ shl_and_kind (left_rtx, mask_rtx, attrp)
                  best_len = cost;
                  if (attrp)
                    attrp[2] = first;
-                 }
+               }
            }
        }
     }
@@ -2034,7 +2151,7 @@ shl_and_kind (left_rtx, mask_rtx, attrp)
     {
       if (i > right)
        break;
-      if (! CONST_OK_FOR_L (mask >> i))
+      if (! CONST_OK_FOR_K08 (mask >> i))
        continue;
       cost = (i != 0) + 2 + ext_shift_insns[left + i];
       if (cost < best_cost)
@@ -2046,19 +2163,19 @@ shl_and_kind (left_rtx, mask_rtx, attrp)
        }
     }
   /* Try to use a scratch register to hold the AND operand.  */
-  can_ext = ((mask << left) & ((unsigned HOST_WIDE_INT)3 << 30)) == 0;
+  can_ext = ((mask << left) & ((unsigned HOST_WIDE_INT) 3 << 30)) == 0;
   for (i = 0; i <= 2; i++)
     {
       if (i > right)
        break;
-      cost = (i != 0) + (CONST_OK_FOR_I (mask >> i) ? 2 : 3)
+      cost = (i != 0) + (CONST_OK_FOR_I08 (mask >> i) ? 2 : 3)
        + (can_ext ? ext_shift_insns : shift_insns)[left + i];
       if (cost < best_cost)
        {
          best = 4 - can_ext;
          best_cost = cost;
          best_right = i;
-         best_len = cost - 1 - ! CONST_OK_FOR_I (mask >> i);
+         best_len = cost - 1 - ! CONST_OK_FOR_I08 (mask >> i);
        }
     }
 
@@ -2073,8 +2190,7 @@ shl_and_kind (left_rtx, mask_rtx, attrp)
 /* This is used in length attributes of the unnamed instructions
    corresponding to shl_and_kind return values of 1 and 2.  */
 int
-shl_and_length (insn)
-     rtx insn;
+shl_and_length (rtx insn)
 {
   rtx set_src, left_rtx, mask_rtx;
   int attributes[3];
@@ -2089,8 +2205,7 @@ shl_and_length (insn)
 /* This is used in length attribute of the and_shl_scratch instruction.  */
 
 int
-shl_and_scr_length (insn)
-     rtx insn;
+shl_and_scr_length (rtx insn)
 {
   rtx set_src = SET_SRC (XVECEXP (PATTERN (insn), 0, 0));
   int len = shift_insns[INTVAL (XEXP (set_src, 1))];
@@ -2107,14 +2222,13 @@ extern int rtx_equal_function_value_matters;
    method of generating them, i.e. returned zero.  */
 
 int
-gen_shl_and (dest, left_rtx, mask_rtx, source)
-     rtx dest, left_rtx, mask_rtx, source;
+gen_shl_and (rtx dest, rtx left_rtx, rtx mask_rtx, rtx source)
 {
   int attributes[3];
   unsigned HOST_WIDE_INT mask;
   int kind = shl_and_kind (left_rtx, mask_rtx, attributes);
   int right, total_shift;
-  void (*shift_gen_fun) PARAMS ((int, rtx*)) = gen_shifty_hi_op;
+  void (*shift_gen_fun) (int, rtx *) = gen_shifty_hi_op;
 
   right = attributes[0];
   total_shift = INTVAL (left_rtx) + right;
@@ -2131,10 +2245,10 @@ gen_shl_and (dest, left_rtx, mask_rtx, source)
        if (first < 0)
          {
            emit_insn ((mask << right) <= 0xff
-                      ? gen_zero_extendqisi2(dest,
-                                             gen_lowpart (QImode, source))
-                      : gen_zero_extendhisi2(dest,
-                                             gen_lowpart (HImode, source)));
+                      ? gen_zero_extendqisi2 (dest,
+                                              gen_lowpart (QImode, source))
+                      : gen_zero_extendhisi2 (dest,
+                                              gen_lowpart (HImode, source)));
            source = dest;
          }
        if (source != dest)
@@ -2154,8 +2268,8 @@ gen_shl_and (dest, left_rtx, mask_rtx, source)
          }
        if (first >= 0)
          emit_insn (mask <= 0xff
-                    ? gen_zero_extendqisi2(dest, gen_lowpart (QImode, dest))
-                    : gen_zero_extendhisi2(dest, gen_lowpart (HImode, dest)));
+                    ? gen_zero_extendqisi2 (dest, gen_lowpart (QImode, dest))
+                    : gen_zero_extendhisi2 (dest, gen_lowpart (HImode, dest)));
        if (total_shift > 0)
          {
            operands[2] = GEN_INT (total_shift);
@@ -2169,8 +2283,8 @@ gen_shl_and (dest, left_rtx, mask_rtx, source)
       /* If the topmost bit that matters is set, set the topmost bits
         that don't matter.  This way, we might be able to get a shorter
         signed constant.  */
-      if (mask & ((HOST_WIDE_INT)1 << (31 - total_shift)))
-       mask |= (HOST_WIDE_INT)~0 << (31 - total_shift);
+      if (mask & ((HOST_WIDE_INT) 1 << (31 - total_shift)))
+       mask |= (HOST_WIDE_INT) ~0 << (31 - total_shift);
     case 2:
       /* Don't expand fine-grained when combining, because that will
          make the pattern fail.  */
@@ -2240,9 +2354,7 @@ gen_shl_and (dest, left_rtx, mask_rtx, source)
   If COSTP is nonzero, assign the calculated cost to *COSTP.  */
 
 int
-shl_sext_kind (left_rtx, size_rtx, costp)
-     rtx left_rtx, size_rtx;
-     int *costp;
+shl_sext_kind (rtx left_rtx, rtx size_rtx, int *costp)
 {
   int left, size, insize, ext;
   int cost = 0, best_cost;
@@ -2336,8 +2448,7 @@ shl_sext_kind (left_rtx, size_rtx, costp)
    implementing this pattern.  */
 
 int
-shl_sext_length (insn)
-     rtx insn;
+shl_sext_length (rtx insn)
 {
   rtx set_src, left_rtx, size_rtx;
   int cost;
@@ -2352,8 +2463,7 @@ shl_sext_length (insn)
 /* Generate rtl for this pattern */
 
 int
-gen_shl_sext (dest, left_rtx, size_rtx, source)
-     rtx dest, left_rtx, size_rtx, source;
+gen_shl_sext (rtx dest, rtx left_rtx, rtx size_rtx, rtx source)
 {
   int kind;
   int left, size, insize, cost;
@@ -2391,8 +2501,8 @@ gen_shl_sext (dest, left_rtx, size_rtx, source)
            gen_shifty_hi_op (ASHIFT, operands);
          }
        emit_insn (kind & 1
-                  ? gen_extendqisi2(dest, gen_lowpart (QImode, dest))
-                  : gen_extendhisi2(dest, gen_lowpart (HImode, dest)));
+                  ? gen_extendqisi2 (dest, gen_lowpart (QImode, dest))
+                  : gen_extendhisi2 (dest, gen_lowpart (HImode, dest)));
        if (kind <= 2)
          {
            if (shift2)
@@ -2409,7 +2519,7 @@ gen_shl_sext (dest, left_rtx, size_rtx, source)
                  {
                    operands[2] = GEN_INT (shift2 + 1);
                    gen_shifty_op (ASHIFT, operands);
-                   operands[2] = GEN_INT (1);
+                   operands[2] = const1_rtx;
                    gen_shifty_op (ASHIFTRT, operands);
                    break;
                  }
@@ -2463,7 +2573,7 @@ gen_shl_sext (dest, left_rtx, size_rtx, source)
       operands[2] = kind == 7 ? GEN_INT (left + 1) : left_rtx;
       gen_shifty_op (ASHIFT, operands);
       if (kind == 7)
-       emit_insn (gen_ashrsi3_k (dest, dest, GEN_INT (1)));
+       emit_insn (gen_ashrsi3_k (dest, dest, const1_rtx));
       break;
     default:
       return -1;
@@ -2474,8 +2584,7 @@ gen_shl_sext (dest, left_rtx, size_rtx, source)
 /* Prefix a symbol_ref name with "datalabel".  */
 
 rtx
-gen_datalabel_ref (sym)
-     rtx sym;
+gen_datalabel_ref (rtx sym)
 {
   if (GET_CODE (sym) == LABEL_REF)
     return gen_rtx_CONST (GET_MODE (sym),
@@ -2578,10 +2687,7 @@ static int pool_window_last;
 /* Add a constant to the pool and return its label.  */
 
 static rtx
-add_constant (x, mode, last_value)
-     rtx x;
-     enum machine_mode mode;
-     rtx last_value;
+add_constant (rtx x, enum machine_mode mode, rtx last_value)
 {
   int i;
   rtx lab, new, ref, newref;
@@ -2653,8 +2759,7 @@ add_constant (x, mode, last_value)
 /* Output the literal table.  */
 
 static void
-dump_table (scan)
-     rtx scan;
+dump_table (rtx scan)
 {
   int i;
   int need_align = 1;
@@ -2718,7 +2823,7 @@ dump_table (scan)
                    {
                      lab = XEXP (ref, 0);
                      emit_insn_before (gen_consttable_window_end (lab),
-                                      align_insn);
+                                       align_insn);
                    }
                  delete_insn (align_insn);
                  align_insn = NULL_RTX;
@@ -2825,8 +2930,7 @@ dump_table (scan)
    mov.w instead of a mov.l.  */
 
 static int
-hi_const (src)
-     rtx src;
+hi_const (rtx src)
 {
   return (GET_CODE (src) == CONST_INT
          && INTVAL (src) >= -32768
@@ -2836,12 +2940,11 @@ hi_const (src)
 /* Nonzero if the insn is a move instruction which needs to be fixed.  */
 
 /* ??? For a DImode/DFmode moves, we don't need to fix it if each half of the
-   CONST_DOUBLE input value is CONST_OK_FOR_I.  For a SFmode move, we don't
-   need to fix it if the input value is CONST_OK_FOR_I.  */
+   CONST_DOUBLE input value is CONST_OK_FOR_I08.  For a SFmode move, we don't
+   need to fix it if the input value is CONST_OK_FOR_I08.  */
 
 static int
-broken_move (insn)
-     rtx insn;
+broken_move (rtx insn)
 {
   if (GET_CODE (insn) == INSN)
     {
@@ -2874,7 +2977,7 @@ broken_move (insn)
                && GET_CODE (SET_DEST (pat)) == REG
                && FP_REGISTER_P (REGNO (SET_DEST (pat))))
          && (GET_CODE (SET_SRC (pat)) != CONST_INT
-             || ! CONST_OK_FOR_I (INTVAL (SET_SRC (pat)))))
+             || ! CONST_OK_FOR_I08 (INTVAL (SET_SRC (pat)))))
        return 1;
     }
 
@@ -2882,8 +2985,7 @@ broken_move (insn)
 }
 
 static int
-mova_p (insn)
-     rtx insn;
+mova_p (rtx insn)
 {
   return (GET_CODE (insn) == INSN
          && GET_CODE (PATTERN (insn)) == SET
@@ -2898,9 +3000,7 @@ mova_p (insn)
    the range.  */
 
 static rtx
-find_barrier (num_mova, mova, from)
-     int num_mova;
-     rtx mova, from;
+find_barrier (int num_mova, rtx mova, rtx from)
 {
   int count_si = 0;
   int count_hi = 0;
@@ -2992,7 +3092,7 @@ find_barrier (num_mova, mova, from)
                 the limit is the same, but the alignment requirements
                 are higher.  We may waste up to 4 additional bytes
                 for alignment, and the DF/DI constant may have
-                another SF/SI constant placed before it. */
+                another SF/SI constant placed before it.  */
              if (TARGET_SHCOMPACT
                  && ! found_di
                  && (mode == DFmode || mode == DImode))
@@ -3142,8 +3242,7 @@ find_barrier (num_mova, mova, from)
    register is not used anywhere else in this instruction - except as the
    destination of a set, return this register; else, return 0.  */
 rtx
-sfunc_uses_reg (insn)
-     rtx insn;
+sfunc_uses_reg (rtx insn)
 {
   int i;
   rtx pattern, part, reg_part, reg;
@@ -3181,10 +3280,7 @@ sfunc_uses_reg (insn)
    is set by INSN.  */
 
 static int
-noncall_uses_reg (reg, insn, set)
-     rtx reg;
-     rtx insn;
-     rtx *set;
+noncall_uses_reg (rtx reg, rtx insn, rtx *set)
 {
   rtx pattern, reg2;
 
@@ -3269,8 +3365,7 @@ noncall_uses_reg (reg, insn, set)
    registers 0..15, respectively, are used as outputs, or are clobbered.
    IS_DEST should be set to 16 if X is the destination of a SET, else to 0.  */
 int
-regs_used (x, is_dest)
-     rtx x; int is_dest;
+regs_used (rtx x, int is_dest)
 {
   enum rtx_code code;
   const char *fmt;
@@ -3346,9 +3441,7 @@ regs_used (x, is_dest)
    If a blocking instruction is made or recognized, return it.  */
    
 static rtx
-gen_block_redirect (jump, addr, need_block)
-     rtx jump;
-     int addr, need_block;
+gen_block_redirect (rtx jump, int addr, int need_block)
 {
   int dead = 0;
   rtx prev = prev_nonnote_insn (jump);
@@ -3368,6 +3461,14 @@ gen_block_redirect (jump, addr, need_block)
       else if (recog_memoized (prev) == CODE_FOR_block_branch_redirect)
        need_block = 0;
     }
+  if (GET_CODE (PATTERN (jump)) == RETURN)
+    {
+      if (! need_block)
+       return prev;
+      /* Reorg even does nasty things with return insns that cause branches
+        to go out of range - see find_end_label and callers.  */
+      return emit_insn_before (gen_block_branch_redirect (const0_rtx) , jump);
+    }
   /* We can't use JUMP_LABEL here because it might be undefined
      when not optimizing.  */
   dest = XEXP (SET_SRC (PATTERN (jump)), 0);
@@ -3412,7 +3513,7 @@ gen_block_redirect (jump, addr, need_block)
          if (INSN_DELETED_P (scan))
            continue;
          code = GET_CODE (scan);
-         if (GET_RTX_CLASS (code) == 'i')
+         if (INSN_P (scan))
            {
              used |= regs_used (PATTERN (scan), 0);
              if (code == CALL_INSN)
@@ -3507,11 +3608,10 @@ struct far_branch
   int address;
 };
 
-static void gen_far_branch PARAMS ((struct far_branch *));
+static void gen_far_branch (struct far_branch *);
 enum mdep_reorg_phase_e mdep_reorg_phase;
 static void
-gen_far_branch (bp)
-     struct far_branch *bp;
+gen_far_branch (struct far_branch *bp)
 {
   rtx insn = bp->insert_place;
   rtx jump;
@@ -3527,7 +3627,7 @@ gen_far_branch (bp)
     jump = emit_jump_insn_after (gen_return (), insn);
   /* Emit a barrier so that reorg knows that any following instructions
      are not reachable via a fall-through path.
-     But don't do this when not optimizing, since we wouldn't supress the
+     But don't do this when not optimizing, since we wouldn't suppress the
      alignment for the barrier then, and could end up with out-of-range
      pc-relative loads.  */
   if (optimize)
@@ -3536,19 +3636,23 @@ gen_far_branch (bp)
   JUMP_LABEL (jump) = bp->far_label;
   if (! invert_jump (insn, label, 1))
     abort ();
-  (emit_insn_after
-   (gen_stuff_delay_slot
-    (GEN_INT (INSN_UID (XEXP (SET_SRC (PATTERN (jump)), 0))),
-     GEN_INT (recog_memoized (insn) == CODE_FOR_branch_false)),
-    insn));
+  /* If we are branching around a jump (rather than a return), prevent
+     reorg from using an insn from the jump target as the delay slot insn -
+     when reorg did this, it pessimized code (we rather hide the delay slot)
+     and it could cause branches to go out of range.  */
+  if (bp->far_label)
+    (emit_insn_after
+     (gen_stuff_delay_slot
+      (GEN_INT (INSN_UID (XEXP (SET_SRC (PATTERN (jump)), 0))),
+       GEN_INT (recog_memoized (insn) == CODE_FOR_branch_false)),
+      insn));
   /* Prevent reorg from undoing our splits.  */
   gen_block_redirect (jump, bp->address += 2, 2);
 }
 
 /* Fix up ADDR_DIFF_VECs.  */
 void
-fixup_addr_diff_vecs (first)
-     rtx first;
+fixup_addr_diff_vecs (rtx first)
 {
   rtx insn;
 
@@ -3592,8 +3696,7 @@ fixup_addr_diff_vecs (first)
 /* BARRIER_OR_LABEL is either a BARRIER or a CODE_LABEL immediately following
    a barrier.  Return the base 2 logarithm of the desired alignment.  */
 int
-barrier_align (barrier_or_label)
-     rtx barrier_or_label;
+barrier_align (rtx barrier_or_label)
 {
   rtx next = next_real_insn (barrier_or_label), pat, prev;
   int slot, credit, jump_to_next = 0;
@@ -3618,7 +3721,7 @@ barrier_align (barrier_or_label)
         the table to the minimum for proper code alignment.  */
       return ((TARGET_SMALLCODE
               || ((unsigned) XVECLEN (pat, 1) * GET_MODE_SIZE (GET_MODE (pat))
-                  <= (unsigned)1 << (CACHE_LOG - 2)))
+                  <= (unsigned) 1 << (CACHE_LOG - 2)))
              ? 1 << TARGET_SHMEDIA : align_jumps_log);
     }
 
@@ -3713,8 +3816,7 @@ barrier_align (barrier_or_label)
    Applying loop alignment to small constant or switch tables is a waste
    of space, so we suppress this too.  */
 int
-sh_loop_align (label)
-     rtx label;
+sh_loop_align (rtx label)
 {
   rtx next = label;
 
@@ -3735,7 +3837,7 @@ sh_loop_align (label)
    scheduling.  */
 
 static void
-sh_reorg ()
+sh_reorg (void)
 {
   rtx first, insn, mova = NULL_RTX;
   int num_mova;
@@ -4082,8 +4184,10 @@ sh_reorg ()
                  if (GET_CODE (dst) == REG && FP_ANY_REGISTER_P (REGNO (dst)))
                    {
                      /* This must be an insn that clobbers r0.  */
-                     rtx clobber = XVECEXP (PATTERN (scan), 0,
-                                            XVECLEN (PATTERN (scan), 0) - 1);
+                     rtx *clobberp = &XVECEXP (PATTERN (scan), 0,
+                                               XVECLEN (PATTERN (scan), 0)
+                                               - 1);
+                     rtx clobber = *clobberp;
 
                      if (GET_CODE (clobber) != CLOBBER
                          || ! rtx_equal_p (XEXP (clobber, 0), r0_rtx))
@@ -4119,7 +4223,7 @@ sh_reorg ()
                        }
                      last_float_move = scan;
                      last_float = src;
-                     newsrc = gen_rtx (MEM, mode,
+                     newsrc = gen_rtx_MEM (mode,
                                        (((TARGET_SH4 && ! TARGET_FMOVD)
                                          || REGNO (dst) == FPUL_REG)
                                         ? r0_inc_rtx
@@ -4127,7 +4231,8 @@ sh_reorg ()
                      last_float_addr = &XEXP (newsrc, 0);
 
                      /* Remove the clobber of r0.  */
-                     XEXP (clobber, 0) = gen_rtx_SCRATCH (Pmode);
+                     *clobberp = gen_rtx_CLOBBER (GET_MODE (clobber),
+                                                  gen_rtx_SCRATCH (Pmode));
                      RTX_UNCHANGING_P (newsrc) = 1;
                    }
                  /* This is a mova needing a label.  Create it.  */
@@ -4188,9 +4293,7 @@ sh_reorg ()
 }
 
 int
-get_dest_uid (label, max_uid)
-     rtx label;
-     int max_uid;
+get_dest_uid (rtx label, int max_uid)
 {
   rtx dest = next_real_insn (label);
   int dest_uid;
@@ -4219,8 +4322,7 @@ get_dest_uid (label, max_uid)
    find branches with common targets more easily.  */
 
 static void
-split_branches (first)
-     rtx first;
+split_branches (rtx first)
 {
   rtx insn;
   struct far_branch **uid_branch, *far_branch_list = 0;
@@ -4444,10 +4546,8 @@ split_branches (first)
    does not bother to update them.  */
 
 void
-final_prescan_insn (insn, opvec, noperands)
-     rtx insn;
-     rtx *opvec ATTRIBUTE_UNUSED;
-     int noperands ATTRIBUTE_UNUSED;
+final_prescan_insn (rtx insn, rtx *opvec ATTRIBUTE_UNUSED,
+                   int noperands ATTRIBUTE_UNUSED)
 {
   if (TARGET_DUMPISIZE)
     fprintf (asm_out_file, "\n! at %04x\n", INSN_ADDRESSES (INSN_UID (insn)));
@@ -4483,7 +4583,7 @@ final_prescan_insn (insn, opvec, noperands)
    only be labels.  */
 
 const char *
-output_jump_label_table ()
+output_jump_label_table (void)
 {
   int i;
 
@@ -4528,17 +4628,16 @@ output_jump_label_table ()
 
 static int extra_push;
 
-/* Adjust the stack by SIZE bytes.  REG holds the rtl of the register
-  to be adjusted, and TEMP, if nonnegative, holds the register number
-  of a general register that we may clobber.  */
+/* Adjust the stack by SIZE bytes.  REG holds the rtl of the register to be
+   adjusted.  If epilogue_p is zero, this is for a prologue; otherwise, it's
+   for an epilogue.  If LIVE_REGS_MASK is nonzero, it points to a HARD_REG_SET
+   of all the registers that are about to be restored, and hence dead.  */
 
 static void
-output_stack_adjust (size, reg, temp, emit_fn)
-     int size;
-     rtx reg;
-     int temp;
-     rtx (*emit_fn) PARAMS ((rtx));
+output_stack_adjust (int size, rtx reg, int epilogue_p,
+                    HARD_REG_SET *live_regs_mask)
 {
+  rtx (*emit_fn) (rtx) = epilogue_p ? &emit_insn : &frame_insn;
   if (size)
     {
       HOST_WIDE_INT align = STACK_BOUNDARY / BITS_PER_UNIT;
@@ -4561,10 +4660,43 @@ output_stack_adjust (size, reg, temp, emit_fn)
        {
          rtx const_reg;
          rtx insn;
+         int temp = epilogue_p ? 7 : (TARGET_SH5 ? 0 : 1);
+         int i;
 
          /* If TEMP is invalid, we could temporarily save a general
             register to MACL.  However, there is currently no need
             to handle this case, so just abort when we see it.  */
+         if (current_function_interrupt
+             || ! call_used_regs[temp] || fixed_regs[temp])
+           temp = -1;
+         if (temp < 0 && ! current_function_interrupt)
+           {
+             HARD_REG_SET temps;
+             COPY_HARD_REG_SET (temps, call_used_reg_set);
+             AND_COMPL_HARD_REG_SET (temps, call_fixed_reg_set);
+             if (epilogue_p)
+               {
+                 for (i = 0; i < HARD_REGNO_NREGS (FIRST_RET_REG, DImode); i++)
+                   CLEAR_HARD_REG_BIT (temps, FIRST_RET_REG + i);
+                 if (current_function_calls_eh_return)
+                   {
+                     CLEAR_HARD_REG_BIT (temps, EH_RETURN_STACKADJ_REGNO);
+                     for (i = 0; i <= 3; i++)
+                       CLEAR_HARD_REG_BIT (temps, EH_RETURN_DATA_REGNO (i));
+                   }
+               }
+             else
+               {
+                 for (i = FIRST_PARM_REG;
+                      i < FIRST_PARM_REG + NPARM_REGS (SImode); i++)
+                   CLEAR_HARD_REG_BIT (temps, i);
+                 if (current_function_needs_context)
+                   CLEAR_HARD_REG_BIT (temps, STATIC_CHAIN_REGNUM);
+               }
+             temp = scavenge_reg (&temps);
+           }
+         if (temp < 0 && live_regs_mask)
+           temp = scavenge_reg (live_regs_mask);
          if (temp < 0)
            abort ();
          const_reg = gen_rtx_REG (GET_MODE (reg), temp);
@@ -4582,7 +4714,7 @@ output_stack_adjust (size, reg, temp, emit_fn)
              emit_insn (GEN_MOV (const_reg, GEN_INT (size)));
              insn = emit_fn (GEN_ADD3 (reg, reg, const_reg));
            }
-         if (emit_fn == frame_insn)
+         if (! epilogue_p)
            REG_NOTES (insn)
              = (gen_rtx_EXPR_LIST
                 (REG_FRAME_RELATED_EXPR,
@@ -4594,8 +4726,7 @@ output_stack_adjust (size, reg, temp, emit_fn)
 }
 
 static rtx
-frame_insn (x)
-     rtx x;
+frame_insn (rtx x)
 {
   x = emit_insn (x);
   RTX_FRAME_RELATED_P (x) = 1;
@@ -4605,8 +4736,7 @@ frame_insn (x)
 /* Output RTL to push register RN onto the stack.  */
 
 static rtx
-push (rn)
-     int rn;
+push (int rn)
 {
   rtx x;
   if (rn == FPUL_REG)
@@ -4635,8 +4765,7 @@ push (rn)
 /* Output RTL to pop register RN from the stack.  */
 
 static void
-pop (rn)
-     int rn;
+pop (int rn)
 {
   rtx x;
   if (rn == FPUL_REG)
@@ -4664,9 +4793,7 @@ pop (rn)
 /* Generate code to push the regs specified in the mask.  */
 
 static void
-push_regs (mask, interrupt_handler)
-     HARD_REG_SET *mask;
-     int interrupt_handler;
+push_regs (HARD_REG_SET *mask, int interrupt_handler)
 {
   int i;
   int skip_fpscr = 0;
@@ -4685,7 +4812,7 @@ push_regs (mask, interrupt_handler)
          HARD_REG_SET unsaved;
 
          push (FPSCR_REG);
-         COMPL_HARD_REG_SET(unsaved, *mask);
+         COMPL_HARD_REG_SET (unsaved, *mask);
          fpscr_set_from_mem (NORMAL_MODE (FP_MODE), unsaved);
          skip_fpscr = 1;
        }
@@ -4698,6 +4825,53 @@ push_regs (mask, interrupt_handler)
     push (PR_REG);
 }
 
+/* Calculate how much extra space is needed to save all callee-saved
+   target registers.
+   LIVE_REGS_MASK is the register mask calculated by calc_live_regs.  */
+
+static int
+shmedia_target_regs_stack_space (HARD_REG_SET *live_regs_mask)
+{
+  int reg;
+  int stack_space = 0;
+  int interrupt_handler = sh_cfun_interrupt_handler_p ();
+
+  for (reg = LAST_TARGET_REG; reg >= FIRST_TARGET_REG; reg--)
+    if ((! call_used_regs[reg] || interrupt_handler)
+        && ! TEST_HARD_REG_BIT (*live_regs_mask, reg))
+      /* Leave space to save this target register on the stack,
+        in case target register allocation wants to use it.  */
+      stack_space += GET_MODE_SIZE (REGISTER_NATURAL_MODE (reg));
+  return stack_space;
+}
+   
+/* Decide whether we should reserve space for callee-save target registers,
+   in case target register allocation wants to use them.  REGS_SAVED is
+   the space, in bytes, that is already required for register saves.
+   LIVE_REGS_MASK is the register mask calculated by calc_live_regs.  */
+
+static int
+shmedia_reserve_space_for_target_registers_p (int regs_saved,
+                                             HARD_REG_SET *live_regs_mask)
+{
+  if (optimize_size)
+    return 0;
+  return shmedia_target_regs_stack_space (live_regs_mask) <= regs_saved;
+}
+
+/* Decide how much space to reserve for callee-save target registers
+   in case target register allocation wants to use them.
+   LIVE_REGS_MASK is the register mask calculated by calc_live_regs.  */
+
+static int
+shmedia_target_regs_stack_adjust (HARD_REG_SET *live_regs_mask)
+{
+  if (shmedia_space_reserved_for_target_registers)
+    return shmedia_target_regs_stack_space (live_regs_mask);
+  else
+    return 0;
+}
+
 /* Work out the registers which need to be saved, both as a mask and a
    count of saved words.  Return the count.
 
@@ -4706,18 +4880,16 @@ push_regs (mask, interrupt_handler)
    make sure that all the regs it clobbers are safe too.  */
 
 static int
-calc_live_regs (live_regs_mask)
-     HARD_REG_SET *live_regs_mask;
+calc_live_regs (HARD_REG_SET *live_regs_mask)
 {
   int reg;
   int count;
   int interrupt_handler;
-  int pr_live;
+  int pr_live, has_call;
 
   interrupt_handler = sh_cfun_interrupt_handler_p ();
 
-  for (count = 0; 32 * count < FIRST_PSEUDO_REGISTER; count++)
-    CLEAR_HARD_REG_SET (*live_regs_mask);
+  CLEAR_HARD_REG_SET (*live_regs_mask);
   if (TARGET_SH4 && TARGET_FMOVD && interrupt_handler
       && regs_ever_live[FPSCR_REG])
     target_flags &= ~FPU_SINGLE_BIT;
@@ -4736,7 +4908,9 @@ calc_live_regs (live_regs_mask)
      the initial value can become the PR_MEDIA_REG hard register, as seen for
      execute/20010122-1.c:test9.  */
   if (TARGET_SHMEDIA)
-    pr_live = regs_ever_live[PR_MEDIA_REG];
+    /* ??? this function is called from initial_elimination_offset, hence we
+       can't use the result of sh_media_register_for_return here.  */
+    pr_live = sh_pr_n_sets ();
   else
     {
       rtx pr_initial = has_hard_reg_initial_val (Pmode, PR_REG);
@@ -4744,6 +4918,10 @@ calc_live_regs (live_regs_mask)
                 ? (GET_CODE (pr_initial) != REG
                    || REGNO (pr_initial) != (PR_REG))
                 : regs_ever_live[PR_REG]);
+      /* For Shcompact, if not optimizing, we end up with a memory reference
+        using the return address pointer for __builtin_return_address even
+        though there is no actual need to put the PR register on the stack.  */
+      pr_live |= regs_ever_live[RETURN_ADDRESS_POINTER_REGNUM];
     }
   /* Force PR to be live if the prologue has to call the SHmedia
      argument decoder or register saver.  */
@@ -4752,6 +4930,7 @@ calc_live_regs (live_regs_mask)
           & ~ CALL_COOKIE_RET_TRAMP (1))
          || current_function_has_nonlocal_label))
     pr_live = 1;
+  has_call = TARGET_SHMEDIA ? ! leaf_function_p () : pr_live;
   for (count = 0, reg = FIRST_PSEUDO_REGISTER - 1; reg >= 0; reg--)
     {
       if (reg == (TARGET_SHMEDIA ? PR_MEDIA_REG : PR_REG)
@@ -4761,7 +4940,9 @@ calc_live_regs (live_regs_mask)
             (regs_ever_live[reg]
              || (call_used_regs[reg]
                  && (! fixed_regs[reg] || reg == MACH_REG || reg == MACL_REG)
-                 && pr_live))
+                 && has_call)
+             || (has_call && REGISTER_NATURAL_MODE (reg) == SImode
+                 && (GENERAL_REGISTER_P (reg) || TARGET_REGISTER_P (reg))))
             && reg != STACK_POINTER_REGNUM && reg != ARG_POINTER_REGNUM
             && reg != RETURN_ADDRESS_POINTER_REGNUM
             && reg != T_REG && reg != GBR_REG
@@ -4771,13 +4952,17 @@ calc_live_regs (live_regs_mask)
             (TARGET_SHCOMPACT
              && flag_pic
              && current_function_args_info.call_cookie
-             && reg == PIC_OFFSET_TABLE_REGNUM)
+             && reg == (int) PIC_OFFSET_TABLE_REGNUM)
             || (regs_ever_live[reg] && ! call_used_regs[reg])
             || (current_function_calls_eh_return
-                && (reg == EH_RETURN_DATA_REGNO (0)
-                    || reg == EH_RETURN_DATA_REGNO (1)
-                    || reg == EH_RETURN_DATA_REGNO (2)
-                    || reg == EH_RETURN_DATA_REGNO (3)))))
+                && (reg == (int) EH_RETURN_DATA_REGNO (0)
+                    || reg == (int) EH_RETURN_DATA_REGNO (1)
+                    || reg == (int) EH_RETURN_DATA_REGNO (2)
+                    || reg == (int) EH_RETURN_DATA_REGNO (3)))
+            || ((reg == MACL_REG || reg == MACH_REG)
+                && regs_ever_live[reg]
+                && sh_cfun_attr_renesas_p ())
+            ))
        {
          SET_HARD_REG_BIT (*live_regs_mask, reg);
          count += GET_MODE_SIZE (REGISTER_NATURAL_MODE (reg));
@@ -4801,6 +4986,32 @@ calc_live_regs (live_regs_mask)
            }
        }
     }
+  /* If we have a target register optimization pass after prologue / epilogue
+     threading, we need to assume all target registers will be live even if
+     they aren't now.  */
+  if (flag_branch_target_load_optimize2
+      && TARGET_SAVE_ALL_TARGET_REGS
+      && shmedia_space_reserved_for_target_registers)
+    for (reg = LAST_TARGET_REG; reg >= FIRST_TARGET_REG; reg--)
+      if ((! call_used_regs[reg] || interrupt_handler)
+         && ! TEST_HARD_REG_BIT (*live_regs_mask, reg))
+       {
+         SET_HARD_REG_BIT (*live_regs_mask, reg);
+         count += GET_MODE_SIZE (REGISTER_NATURAL_MODE (reg));
+       }
+  /* If this is an interrupt handler, we don't have any call-clobbered
+     registers we can conveniently use for target register save/restore.
+     Make sure we save at least one general purpose register when we need
+     to save target registers.  */
+  if (interrupt_handler
+      && hard_regs_intersect_p (live_regs_mask,
+                               &reg_class_contents[TARGET_REGS])
+      && ! hard_regs_intersect_p (live_regs_mask,
+                                 &reg_class_contents[GENERAL_REGS]))
+    {
+      SET_HARD_REG_BIT (*live_regs_mask, R0_REG);
+      count += GET_MODE_SIZE (REGISTER_NATURAL_MODE (R0_REG));
+    }
 
   return count;
 }
@@ -4811,8 +5022,7 @@ calc_live_regs (live_regs_mask)
    stack for register saves.  Return the frame size, padded
    appropriately so that the stack stays properly aligned.  */
 static HOST_WIDE_INT
-rounded_frame_size (pushed)
-     int pushed;
+rounded_frame_size (int pushed)
 {
   HOST_WIDE_INT size = get_frame_size ();
   HOST_WIDE_INT align = STACK_BOUNDARY / BITS_PER_UNIT;
@@ -4824,13 +5034,16 @@ rounded_frame_size (pushed)
    unchanged along the whole function.  We set it up as the return
    value in the prologue.  */
 int
-sh_media_register_for_return ()
+sh_media_register_for_return (void)
 {
   int regno;
   int tr0_used;
 
   if (! current_function_is_leaf)
     return -1;
+  if (lookup_attribute ("interrupt_handler",
+                       DECL_ATTRIBUTES (current_function_decl)))
+    return -1;
 
   tr0_used = flag_pic && regs_ever_live[PIC_OFFSET_TABLE_REGNUM];
 
@@ -4841,8 +5054,132 @@ sh_media_register_for_return ()
   return -1;
 }
 
+/* The maximum registers we need to save are:
+   - 62 general purpose registers (r15 is stack pointer, r63 is zero)
+   - 32 floating point registers (for each pair, we save none,
+         one single precision value, or a double precision value).
+   -  8 target registers
+   -  add 1 entry for a delimiter.  */
+#define MAX_SAVED_REGS (62+32+8)
+
+typedef struct save_entry_s
+{
+  unsigned char reg;
+  unsigned char mode;
+  short offset;
+} save_entry;
+
+#define MAX_TEMPS 4
+
+/* There will be a delimiter entry with VOIDmode both at the start and the
+   end of a filled in schedule.  The end delimiter has the offset of the
+   save with the smallest (i.e. most negative) offset.  */
+typedef struct save_schedule_s
+{
+  save_entry entries[MAX_SAVED_REGS + 2];
+  int temps[MAX_TEMPS+1];
+} save_schedule;
+
+/* Fill in SCHEDULE according to LIVE_REGS_MASK.  If RESTORE is nonzero,
+   use reverse order.  Returns the last entry written to (not counting
+   the delimiter).  OFFSET_BASE is a number to be added to all offset
+   entries.  */
+   
+static save_entry *
+sh5_schedule_saves (HARD_REG_SET *live_regs_mask, save_schedule *schedule,
+                   int offset_base)
+{
+  int align, i;
+  save_entry *entry = schedule->entries;
+  int tmpx = 0;
+  int offset;
+
+  if (! current_function_interrupt)
+    for (i = FIRST_GENERAL_REG; tmpx < MAX_TEMPS && i <= LAST_GENERAL_REG; i++)
+      if (call_used_regs[i] && ! fixed_regs[i] && i != PR_MEDIA_REG
+         && ! FUNCTION_ARG_REGNO_P (i)
+         && i != FIRST_RET_REG
+         && ! (current_function_needs_context && i == STATIC_CHAIN_REGNUM)
+         && ! (current_function_calls_eh_return
+               && (i == EH_RETURN_STACKADJ_REGNO
+                   || ((unsigned) i <= EH_RETURN_DATA_REGNO (0)
+                       && (unsigned) i >= EH_RETURN_DATA_REGNO (3)))))
+       schedule->temps[tmpx++] = i;
+  entry->reg = -1;
+  entry->mode = VOIDmode;
+  entry->offset = offset_base;
+  entry++;
+  /* We loop twice: first, we save 8-byte aligned registers in the
+     higher addresses, that are known to be aligned.  Then, we
+     proceed to saving 32-bit registers that don't need 8-byte
+     alignment.
+     If this is an interrupt function, all registers that need saving
+     need to be saved in full.  moreover, we need to postpone saving
+     target registers till we have saved some general purpose registers
+     we can then use as scratch registers.  */
+  offset = offset_base;
+  for (align = 1; align >= 0; align--)
+    {
+      for (i = FIRST_PSEUDO_REGISTER - 1; i >= 0; i--)
+       if (TEST_HARD_REG_BIT (*live_regs_mask, i))
+         {
+           enum machine_mode mode = REGISTER_NATURAL_MODE (i);
+           int reg = i;
+
+           if (current_function_interrupt)
+             {
+               if (TARGET_REGISTER_P (i))
+                 continue;
+               if (GENERAL_REGISTER_P (i))
+                 mode = DImode;
+             }
+           if (mode == SFmode && (i % 2) == 1
+               && ! TARGET_FPU_SINGLE && FP_REGISTER_P (i)
+               && (TEST_HARD_REG_BIT (*live_regs_mask, (i ^ 1))))
+             {
+               mode = DFmode;
+               i--;
+               reg--;
+             }
+
+           /* If we're doing the aligned pass and this is not aligned,
+              or we're doing the unaligned pass and this is aligned,
+              skip it.  */
+           if ((GET_MODE_SIZE (mode) % (STACK_BOUNDARY / BITS_PER_UNIT) == 0)
+               != align)
+             continue;
+
+           if (current_function_interrupt
+               && GENERAL_REGISTER_P (i)
+               && tmpx < MAX_TEMPS)
+             schedule->temps[tmpx++] = i;
+
+           offset -= GET_MODE_SIZE (mode);
+           entry->reg = i;
+           entry->mode = mode;
+           entry->offset = offset;
+           entry++;
+         }
+      if (align && current_function_interrupt)
+       for (i = LAST_TARGET_REG; i >= FIRST_TARGET_REG; i--)
+         if (TEST_HARD_REG_BIT (*live_regs_mask, i))
+           {
+             offset -= GET_MODE_SIZE (DImode);
+             entry->reg = i;
+             entry->mode = DImode;
+             entry->offset = offset;
+             entry++;
+           }
+    }
+  entry->reg = -1;
+  entry->mode = VOIDmode;
+  entry->offset = offset;
+  schedule->temps[tmpx] = -1;
+  return entry - 1;
+}
+
 void
-sh_expand_prologue ()
+sh_expand_prologue (void)
 {
   HARD_REG_SET live_regs_mask;
   int d, i;
@@ -4855,7 +5192,7 @@ sh_expand_prologue ()
      and partially on the stack, e.g. a large structure.  */
   output_stack_adjust (-current_function_pretend_args_size
                       - current_function_args_info.stack_regs * 8,
-                      stack_pointer_rtx, TARGET_SH5 ? 0 : 1, frame_insn);
+                      stack_pointer_rtx, 0, NULL);
 
   extra_push = 0;
 
@@ -4901,6 +5238,9 @@ sh_expand_prologue ()
          rtx insn = emit_move_insn (gen_rtx_REG (DImode, tr),
                                     gen_rtx_REG (DImode, PR_MEDIA_REG));
 
+         /* ??? We should suppress saving pr when we don't need it, but this
+            is tricky because of builtin_return_address.  */
+
          /* If this function only exits with sibcalls, this copy
             will be flagged as dead.  */
          REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_MAYBE_DEAD,
@@ -4913,7 +5253,8 @@ sh_expand_prologue ()
   if (current_function_stdarg)
     {
       /* This is not used by the SH2E calling convention  */
-      if (TARGET_SH1 && ! TARGET_SH2E && ! TARGET_SH5 && ! TARGET_HITACHI)
+      if (TARGET_SH1 && ! TARGET_SH2E && ! TARGET_SH5
+         && ! (TARGET_HITACHI || sh_cfun_attr_renesas_p ()))
        {
          /* Push arg regs as if they'd been provided by caller in stack.  */
          for (i = 0; i < NPARM_REGS(SImode); i++)
@@ -4944,155 +5285,191 @@ sh_expand_prologue ()
     
   if (TARGET_SH5)
     {
-      int i;
-      int offset;
-      int align;
-      rtx r0 = gen_rtx_REG (Pmode, R0_REG);
+      int offset_base, offset;
+      rtx r0 = NULL_RTX;
       int offset_in_r0 = -1;
       int sp_in_r0 = 0;
-
-      if (d % (STACK_BOUNDARY / BITS_PER_UNIT))
+      int tregs_space = shmedia_target_regs_stack_adjust (&live_regs_mask);
+      int total_size, save_size;
+      save_schedule schedule;
+      save_entry *entry;
+      int *tmp_pnt;
+
+      if (call_used_regs[R0_REG] && ! fixed_regs[R0_REG]
+         && ! current_function_interrupt)
+       r0 = gen_rtx_REG (Pmode, R0_REG);
+
+      /* D is the actual number of bytes that we need for saving registers,
+        however, in initial_elimination_offset we have committed to using
+        an additional TREGS_SPACE amount of bytes - in order to keep both
+        addresses to arguments supplied by the caller and local variables
+        valid, we must keep this gap.  Place it between the incoming
+        arguments and the actually saved registers in a bid to optimize
+        locality of reference.  */
+      total_size = d + tregs_space;
+      total_size += rounded_frame_size (total_size);
+      save_size = total_size - rounded_frame_size (d);
+      if (save_size % (STACK_BOUNDARY / BITS_PER_UNIT))
        d_rounding = ((STACK_BOUNDARY / BITS_PER_UNIT)
-                     - d % (STACK_BOUNDARY / BITS_PER_UNIT));
-
-      offset = d + d_rounding;
-      output_stack_adjust (-offset, stack_pointer_rtx, 1, frame_insn);
-
-      /* We loop twice: first, we save 8-byte aligned registers in the
-        higher addresses, that are known to be aligned.  Then, we
-        proceed to saving 32-bit registers that don't need 8-byte
-        alignment.  */
-      /* Note that if you change this code in a way that affects where
-        the return register is saved, you have to update not only
-        sh_expand_epilogue, but also sh_set_return_address.  */
-      for (align = 1; align >= 0; align--)
-       for (i = FIRST_PSEUDO_REGISTER - 1; i >= 0; i--)
-         if (TEST_HARD_REG_BIT (live_regs_mask, i))
-           {
-             enum machine_mode mode = REGISTER_NATURAL_MODE (i);
-             int reg = i;
-             rtx reg_rtx, mem_rtx, pre_dec = NULL_RTX;
-
-             if (mode == SFmode && (i % 2) == 1
-                 && ! TARGET_FPU_SINGLE && FP_REGISTER_P (i)
-                 && (TEST_HARD_REG_BIT (live_regs_mask, (i ^ 1))))
-               {
-                 mode = DFmode;
-                 i--;
-                 reg--;
-               }
-               
-             /* If we're doing the aligned pass and this is not aligned,
-                or we're doing the unaligned pass and this is aligned,
-                skip it.  */
-             if ((GET_MODE_SIZE (mode) % (STACK_BOUNDARY / BITS_PER_UNIT)
-                  == 0) != align)
-               continue;
+                       - save_size % (STACK_BOUNDARY / BITS_PER_UNIT));
+
+      /* If adjusting the stack in a single step costs nothing extra, do so.
+        I.e. either if a single addi is enough, or we need a movi anyway,
+        and we don't exceed the maximum offset range (the test for the
+        latter is conservative for simplicity).  */
+      if (TARGET_SHMEDIA
+         && (CONST_OK_FOR_I10 (-total_size)
+             || (! CONST_OK_FOR_I10 (-(save_size + d_rounding))
+                 && total_size <= 2044)))
+       d_rounding = total_size - save_size;
+
+      offset_base = d + d_rounding;
+
+      output_stack_adjust (-(save_size + d_rounding), stack_pointer_rtx,
+                          0, NULL);
+
+      sh5_schedule_saves (&live_regs_mask, &schedule, offset_base);
+      tmp_pnt = schedule.temps;
+      for (entry = &schedule.entries[1]; entry->mode != VOIDmode; entry++)
+        {
+         enum machine_mode mode = entry->mode;
+         int reg = entry->reg;
+         rtx reg_rtx, mem_rtx, pre_dec = NULL_RTX;
 
-             offset -= GET_MODE_SIZE (mode);
+         offset = entry->offset;
 
-             reg_rtx = gen_rtx_REG (mode, reg);
+         reg_rtx = gen_rtx_REG (mode, reg);
 
-             mem_rtx = gen_rtx_MEM (mode,
-                                    gen_rtx_PLUS (Pmode,
-                                                  stack_pointer_rtx,
-                                                  GEN_INT (offset)));
+         mem_rtx = gen_rtx_MEM (mode,
+                                gen_rtx_PLUS (Pmode,
+                                              stack_pointer_rtx,
+                                              GEN_INT (offset)));
 
-             GO_IF_LEGITIMATE_ADDRESS (mode, XEXP (mem_rtx, 0), try_pre_dec);
+         GO_IF_LEGITIMATE_ADDRESS (mode, XEXP (mem_rtx, 0), try_pre_dec);
 
-             mem_rtx = NULL_RTX;
+         if (! r0)
+           abort ();
+         mem_rtx = NULL_RTX;
 
-           try_pre_dec:
-             do
-               if (HAVE_PRE_DECREMENT
-                   && (offset_in_r0 - offset == GET_MODE_SIZE (mode)
-                       || mem_rtx == NULL_RTX
-                       || i == PR_REG || SPECIAL_REGISTER_P (i)))
-                 {
-                   pre_dec = gen_rtx_MEM (mode,
-                                          gen_rtx_PRE_DEC (Pmode, r0));
+       try_pre_dec:
+         do
+           if (HAVE_PRE_DECREMENT
+               && (offset_in_r0 - offset == GET_MODE_SIZE (mode)
+                   || mem_rtx == NULL_RTX
+                   || reg == PR_REG || SPECIAL_REGISTER_P (reg)))
+             {
+               pre_dec = gen_rtx_MEM (mode,
+                                      gen_rtx_PRE_DEC (Pmode, r0));
 
-                   GO_IF_LEGITIMATE_ADDRESS (mode, XEXP (pre_dec, 0),
-                                             pre_dec_ok);
+               GO_IF_LEGITIMATE_ADDRESS (mode, XEXP (pre_dec, 0),
+                                         pre_dec_ok);
 
-                   pre_dec = NULL_RTX;
+               pre_dec = NULL_RTX;
 
-                   break;
+               break;
 
-                 pre_dec_ok:
-                   mem_rtx = NULL_RTX;
-                   offset += GET_MODE_SIZE (mode);
-                 }
-             while (0);
+             pre_dec_ok:
+               mem_rtx = NULL_RTX;
+               offset += GET_MODE_SIZE (mode);
+             }
+         while (0);
 
-             if (mem_rtx != NULL_RTX)
-               goto addr_ok;
+         if (mem_rtx != NULL_RTX)
+           goto addr_ok;
 
-             if (offset_in_r0 == -1)
-               {
-                 emit_move_insn (r0, GEN_INT (offset));
-                 offset_in_r0 = offset;
-               }
-             else if (offset != offset_in_r0)
+         if (offset_in_r0 == -1)
+           {
+             emit_move_insn (r0, GEN_INT (offset));
+             offset_in_r0 = offset;
+           }
+         else if (offset != offset_in_r0)
+           {
+             emit_move_insn (r0,
+                             gen_rtx_PLUS
+                             (Pmode, r0,
+                              GEN_INT (offset - offset_in_r0)));
+             offset_in_r0 += offset - offset_in_r0;
+           }
+                                             
+         if (pre_dec != NULL_RTX)
+           {
+             if (! sp_in_r0)
                {
                  emit_move_insn (r0,
                                  gen_rtx_PLUS
-                                 (Pmode, r0,
-                                  GEN_INT (offset - offset_in_r0)));
-                 offset_in_r0 += offset - offset_in_r0;
+                                 (Pmode, r0, stack_pointer_rtx));
+                 sp_in_r0 = 1;
                }
-                                                 
-             if (pre_dec != NULL_RTX)
-               {
-                 if (! sp_in_r0)
-                   {
-                     emit_move_insn (r0,
-                                     gen_rtx_PLUS
-                                     (Pmode, r0, stack_pointer_rtx));
-                     sp_in_r0 = 1;
-                   }
 
-                 offset -= GET_MODE_SIZE (mode);
-                 offset_in_r0 -= GET_MODE_SIZE (mode);
+             offset -= GET_MODE_SIZE (mode);
+             offset_in_r0 -= GET_MODE_SIZE (mode);
+
+             mem_rtx = pre_dec;
+           }
+         else if (sp_in_r0)
+           mem_rtx = gen_rtx_MEM (mode, r0);
+         else
+           mem_rtx = gen_rtx_MEM (mode,
+                                  gen_rtx_PLUS (Pmode,
+                                                stack_pointer_rtx,
+                                                r0));
+
+         /* We must not use an r0-based address for target-branch
+            registers or for special registers without pre-dec
+            memory addresses, since we store their values in r0
+            first.  */
+         if (TARGET_REGISTER_P (reg)
+             || ((reg == PR_REG || SPECIAL_REGISTER_P (reg))
+                 && mem_rtx != pre_dec))
+           abort ();
 
-                 mem_rtx = pre_dec;
-               }
-             else if (sp_in_r0)
-               mem_rtx = gen_rtx_MEM (mode, r0);
-             else
-               mem_rtx = gen_rtx_MEM (mode,
-                                      gen_rtx_PLUS (Pmode,
-                                                    stack_pointer_rtx,
-                                                    r0));
-
-             /* We must not use an r0-based address for target-branch
-                registers or for special registers without pre-dec
-                memory addresses, since we store their values in r0
-                first.  */
-             if (TARGET_REGISTER_P (i)
-                 || ((i == PR_REG || SPECIAL_REGISTER_P (i))
-                     && mem_rtx != pre_dec))
-               abort ();
-
-           addr_ok:
-             if (TARGET_REGISTER_P (i)
-                 || ((i == PR_REG || SPECIAL_REGISTER_P (i))
-                     && mem_rtx != pre_dec))
-               {
-                 rtx r0mode = gen_rtx_REG (GET_MODE (reg_rtx), R0_REG);
+       addr_ok:
+         if (TARGET_REGISTER_P (reg)
+             || ((reg == PR_REG || SPECIAL_REGISTER_P (reg))
+                 && mem_rtx != pre_dec))
+           {
+             rtx tmp_reg = gen_rtx_REG (GET_MODE (reg_rtx), *tmp_pnt);
 
-                 emit_move_insn (r0mode, reg_rtx);
+             emit_move_insn (tmp_reg, reg_rtx);
 
+             if (REGNO (tmp_reg) == R0_REG)
+               {
                  offset_in_r0 = -1;
                  sp_in_r0 = 0;
-
-                 reg_rtx = r0mode;
+                 if (refers_to_regno_p (R0_REG, R0_REG+1, mem_rtx, (rtx *) 0))
+                   abort ();
                }
 
-             emit_move_insn (mem_rtx, reg_rtx);
+             if (*++tmp_pnt <= 0)
+               tmp_pnt = schedule.temps;
+
+             reg_rtx = tmp_reg;
            }
+         {
+           rtx insn;
+
+           /* Mark as interesting for dwarf cfi generator */
+           insn = emit_move_insn (mem_rtx, reg_rtx);
+           RTX_FRAME_RELATED_P (insn) = 1;
+
+           if (TARGET_SHCOMPACT && (offset_in_r0 != -1)) 
+             {
+               rtx reg_rtx = gen_rtx_REG (mode, reg);
+               rtx set, note_rtx;
+               rtx mem_rtx = gen_rtx_MEM (mode,
+                                          gen_rtx_PLUS (Pmode,
+                                                        stack_pointer_rtx,
+                                                        GEN_INT (offset)));
+
+               set = gen_rtx_SET (VOIDmode, mem_rtx, reg_rtx);
+               note_rtx = gen_rtx_EXPR_LIST (REG_FRAME_RELATED_EXPR, set,
+                                             REG_NOTES (insn));
+               REG_NOTES (insn) = note_rtx;
+             }
+         }
+       }
 
-      if (offset != d_rounding)
+      if (entry->offset != d_rounding)
        abort ();
     }
   else
@@ -5144,7 +5521,7 @@ sh_expand_prologue ()
   target_flags = save_flags;
 
   output_stack_adjust (-rounded_frame_size (d) + d_rounding,
-                      stack_pointer_rtx, TARGET_SH5 ? 0 : 1, frame_insn);
+                      stack_pointer_rtx, 0, NULL);
 
   if (frame_pointer_needed)
     frame_insn (GEN_MOV (frame_pointer_rtx, stack_pointer_rtx));
@@ -5161,27 +5538,50 @@ sh_expand_prologue ()
 }
 
 void
-sh_expand_epilogue ()
+sh_expand_epilogue (void)
 {
   HARD_REG_SET live_regs_mask;
   int d, i;
   int d_rounding = 0;
 
   int save_flags = target_flags;
-  int frame_size;
+  int frame_size, save_size;
   int fpscr_deferred = 0;
 
   d = calc_live_regs (&live_regs_mask);
 
-  if (TARGET_SH5 && d % (STACK_BOUNDARY / BITS_PER_UNIT))
-    d_rounding = ((STACK_BOUNDARY / BITS_PER_UNIT)
-                 - d % (STACK_BOUNDARY / BITS_PER_UNIT));
+  save_size = d;
+  frame_size = rounded_frame_size (d);
+
+  if (TARGET_SH5)
+    {
+      int tregs_space = shmedia_target_regs_stack_adjust (&live_regs_mask);
+      int total_size;
+      if (d % (STACK_BOUNDARY / BITS_PER_UNIT))
+      d_rounding = ((STACK_BOUNDARY / BITS_PER_UNIT)
+                   - d % (STACK_BOUNDARY / BITS_PER_UNIT));
+
+      total_size = d + tregs_space;
+      total_size += rounded_frame_size (total_size);
+      save_size = total_size - frame_size;
+
+      /* If adjusting the stack in a single step costs nothing extra, do so.
+        I.e. either if a single addi is enough, or we need a movi anyway,
+        and we don't exceed the maximum offset range (the test for the
+        latter is conservative for simplicity).  */
+      if (TARGET_SHMEDIA
+         && ! frame_pointer_needed
+         && (CONST_OK_FOR_I10 (total_size)
+             || (! CONST_OK_FOR_I10 (save_size + d_rounding)
+                 && total_size <= 2044)))
+       d_rounding = frame_size;
 
-  frame_size = rounded_frame_size (d) - d_rounding;
+      frame_size -= d_rounding;
+    }
 
   if (frame_pointer_needed)
     {
-      output_stack_adjust (frame_size, frame_pointer_rtx, 7, emit_insn);
+      output_stack_adjust (frame_size, frame_pointer_rtx, 1, &live_regs_mask);
 
       /* We must avoid moving the stack pointer adjustment past code
         which reads from the local frame, else an interrupt could
@@ -5197,7 +5597,7 @@ sh_expand_epilogue ()
         occur after the SP adjustment and clobber data in the local
         frame.  */
       emit_insn (gen_blockage ());
-      output_stack_adjust (frame_size, stack_pointer_rtx, 7, emit_insn);
+      output_stack_adjust (frame_size, stack_pointer_rtx, 1, &live_regs_mask);
     }
 
   if (SHMEDIA_REGS_STACK_ADJUST ())
@@ -5218,173 +5618,159 @@ sh_expand_epilogue ()
     emit_insn (gen_toggle_sz ());
   if (TARGET_SH5)
     {
-      int offset = d_rounding;
+      int offset_base, offset;
       int offset_in_r0 = -1;
       int sp_in_r0 = 0;
-      int align;
       rtx r0 = gen_rtx_REG (Pmode, R0_REG);
-      int tmp_regno = R20_REG;
-      
-      /* We loop twice: first, we save 8-byte aligned registers in the
-        higher addresses, that are known to be aligned.  Then, we
-        proceed to saving 32-bit registers that don't need 8-byte
-        alignment.  */
-      for (align = 0; align <= 1; align++)
-       for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
-         if (TEST_HARD_REG_BIT (live_regs_mask, i))
-           {
-             enum machine_mode mode = REGISTER_NATURAL_MODE (i);
-             int reg = i;
-             rtx reg_rtx, mem_rtx, post_inc = NULL_RTX, insn;
-
-             if (mode == SFmode && (i % 2) == 0
-                 && ! TARGET_FPU_SINGLE && FP_REGISTER_P (i)
-                 && (TEST_HARD_REG_BIT (live_regs_mask, (i ^ 1))))
-               {
-                 mode = DFmode;
-                 i++;
-               }
+      save_schedule schedule;
+      save_entry *entry;
+      int *tmp_pnt;
+
+      entry = sh5_schedule_saves (&live_regs_mask, &schedule, d_rounding);
+      offset_base = -entry[1].offset + d_rounding;
+      tmp_pnt = schedule.temps;
+      for (; entry->mode != VOIDmode; entry--)
+       {
+         enum machine_mode mode = entry->mode;
+         int reg = entry->reg;
+         rtx reg_rtx, mem_rtx, post_inc = NULL_RTX, insn;
 
-             /* If we're doing the aligned pass and this is not aligned,
-                or we're doing the unaligned pass and this is aligned,
-                skip it.  */
-             if ((GET_MODE_SIZE (mode) % (STACK_BOUNDARY / BITS_PER_UNIT)
-                  == 0) != align)
-               continue;
+         offset = offset_base + entry->offset;
+         reg_rtx = gen_rtx_REG (mode, reg);
 
-             reg_rtx = gen_rtx_REG (mode, reg);
+         mem_rtx = gen_rtx_MEM (mode,
+                                gen_rtx_PLUS (Pmode,
+                                              stack_pointer_rtx,
+                                              GEN_INT (offset)));
 
-             mem_rtx = gen_rtx_MEM (mode,
-                                    gen_rtx_PLUS (Pmode,
-                                                  stack_pointer_rtx,
-                                                  GEN_INT (offset)));
+         GO_IF_LEGITIMATE_ADDRESS (mode, XEXP (mem_rtx, 0), try_post_inc);
 
-             GO_IF_LEGITIMATE_ADDRESS (mode, XEXP (mem_rtx, 0), try_post_inc);
+         mem_rtx = NULL_RTX;
 
-             mem_rtx = NULL_RTX;
+       try_post_inc:
+         do
+           if (HAVE_POST_INCREMENT
+               && (offset == offset_in_r0
+                   || (offset + GET_MODE_SIZE (mode) != d + d_rounding
+                       && mem_rtx == NULL_RTX)
+                   || reg == PR_REG || SPECIAL_REGISTER_P (reg)))
+             {
+               post_inc = gen_rtx_MEM (mode,
+                                       gen_rtx_POST_INC (Pmode, r0));
 
-           try_post_inc:
-             do
-               if (HAVE_POST_INCREMENT
-                   && (offset == offset_in_r0
-                       || (offset + GET_MODE_SIZE (mode) != d + d_rounding
-                           && mem_rtx == NULL_RTX)
-                       || i == PR_REG || SPECIAL_REGISTER_P (i)))
-                 {
-                   post_inc = gen_rtx_MEM (mode,
-                                           gen_rtx_POST_INC (Pmode, r0));
+               GO_IF_LEGITIMATE_ADDRESS (mode, XEXP (post_inc, 0),
+                                         post_inc_ok);
 
-                   GO_IF_LEGITIMATE_ADDRESS (mode, XEXP (post_inc, 0),
-                                             post_inc_ok);
+               post_inc = NULL_RTX;
 
-                   post_inc = NULL_RTX;
+               break;
+               
+             post_inc_ok:
+               mem_rtx = NULL_RTX;
+             }
+         while (0);
+         
+         if (mem_rtx != NULL_RTX)
+           goto addr_ok;
 
-                   break;
-                   
-                 post_inc_ok:
-                   mem_rtx = NULL_RTX;
-                 }
-             while (0);
+         if (offset_in_r0 == -1)
+           {
+             emit_move_insn (r0, GEN_INT (offset));
+             offset_in_r0 = offset;
+           }
+         else if (offset != offset_in_r0)
+           {
+             emit_move_insn (r0,
+                             gen_rtx_PLUS
+                             (Pmode, r0,
+                              GEN_INT (offset - offset_in_r0)));
+             offset_in_r0 += offset - offset_in_r0;
+           }
              
-             if (mem_rtx != NULL_RTX)
-               goto addr_ok;
-
-             if (offset_in_r0 == -1)
-               {
-                 emit_move_insn (r0, GEN_INT (offset));
-                 offset_in_r0 = offset;
-               }
-             else if (offset != offset_in_r0)
+         if (post_inc != NULL_RTX)
+           {
+             if (! sp_in_r0)
                {
                  emit_move_insn (r0,
                                  gen_rtx_PLUS
-                                 (Pmode, r0,
-                                  GEN_INT (offset - offset_in_r0)));
-                 offset_in_r0 += offset - offset_in_r0;
+                                 (Pmode, r0, stack_pointer_rtx));
+                 sp_in_r0 = 1;
                }
-                 
-             if (post_inc != NULL_RTX)
-               {
-                 if (! sp_in_r0)
-                   {
-                     emit_move_insn (r0,
-                                     gen_rtx_PLUS
-                                     (Pmode, r0, stack_pointer_rtx));
-                     sp_in_r0 = 1;
-                   }
-                 
-                 mem_rtx = post_inc;
+             
+             mem_rtx = post_inc;
 
-                 offset_in_r0 += GET_MODE_SIZE (mode);
-               }
-             else if (sp_in_r0)
-               mem_rtx = gen_rtx_MEM (mode, r0);
-             else
-               mem_rtx = gen_rtx_MEM (mode,
-                                      gen_rtx_PLUS (Pmode,
-                                                    stack_pointer_rtx,
-                                                    r0));
-
-             if ((i == PR_REG || SPECIAL_REGISTER_P (i))
-                 && mem_rtx != post_inc)
-               abort ();
-
-           addr_ok:
-             if ((i == PR_REG || SPECIAL_REGISTER_P (i))
-                 && mem_rtx != post_inc)
-               {
-                 insn = emit_move_insn (r0, mem_rtx);
-                 mem_rtx = r0;
-               }
-             else if (TARGET_REGISTER_P (i))
-               {
-                 rtx tmp_reg = gen_rtx_REG (mode, tmp_regno);
-
-                 /* Give the scheduler a bit of freedom by using R20..R23
-                    in a round-robin fashion.  Don't use R1 here because
-                    we want to use it for EH_RETURN_STACKADJ_RTX.  */
-                 insn = emit_move_insn (tmp_reg, mem_rtx);
-                 mem_rtx = tmp_reg;
-                 if (++tmp_regno > R23_REG)
-                   tmp_regno = R20_REG;
-               }
+             offset_in_r0 += GET_MODE_SIZE (mode);
+           }
+         else if (sp_in_r0)
+           mem_rtx = gen_rtx_MEM (mode, r0);
+         else
+           mem_rtx = gen_rtx_MEM (mode,
+                                  gen_rtx_PLUS (Pmode,
+                                                stack_pointer_rtx,
+                                                r0));
 
-             insn = emit_move_insn (reg_rtx, mem_rtx);
+         if ((reg == PR_REG || SPECIAL_REGISTER_P (reg))
+             && mem_rtx != post_inc)
+           abort ();
 
-             offset += GET_MODE_SIZE (mode);
+       addr_ok:
+         if ((reg == PR_REG || SPECIAL_REGISTER_P (reg))
+             && mem_rtx != post_inc)
+           {
+             insn = emit_move_insn (r0, mem_rtx);
+             mem_rtx = r0;
+           }
+         else if (TARGET_REGISTER_P (reg))
+           {
+             rtx tmp_reg = gen_rtx_REG (mode, *tmp_pnt);
+
+             /* Give the scheduler a bit of freedom by using up to
+                MAX_TEMPS registers in a round-robin fashion.  */
+             insn = emit_move_insn (tmp_reg, mem_rtx);
+             mem_rtx = tmp_reg;
+             if (*++tmp_pnt < 0)
+               tmp_pnt = schedule.temps;
            }
 
-      if (offset != d + d_rounding)
-       abort ();
+         insn = emit_move_insn (reg_rtx, mem_rtx);
+         if (reg == PR_MEDIA_REG && sh_media_register_for_return () >= 0)
+           /* This is dead, unless we return with a sibcall.  */
+           REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_MAYBE_DEAD,
+                                                 const0_rtx,
+                                                 REG_NOTES (insn));
+       }
 
-      goto finish;
+      if (entry->offset + offset_base != d + d_rounding)
+       abort ();
     }
-  else
-    d = 0;
-  if (TEST_HARD_REG_BIT (live_regs_mask, PR_REG))
-    pop (PR_REG);
-  for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
+  else /* ! TARGET_SH5 */
     {
-      int j = (FIRST_PSEUDO_REGISTER - 1) - i;
+      save_size = 0;
+      if (TEST_HARD_REG_BIT (live_regs_mask, PR_REG))
+       pop (PR_REG);
+      for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
+       {
+         int j = (FIRST_PSEUDO_REGISTER - 1) - i;
+  
+         if (j == FPSCR_REG && current_function_interrupt && TARGET_FMOVD
+             && hard_regs_intersect_p (&live_regs_mask,
+                                       &reg_class_contents[DF_REGS]))
+           fpscr_deferred = 1;
+         else if (j != PR_REG && TEST_HARD_REG_BIT (live_regs_mask, j))
+           pop (j);
+         if (j == FIRST_FP_REG && fpscr_deferred)
+           pop (FPSCR_REG);
 
-      if (j == FPSCR_REG && current_function_interrupt && TARGET_FMOVD
-         && hard_regs_intersect_p (&live_regs_mask,
-                                   &reg_class_contents[DF_REGS]))
-       fpscr_deferred = 1;
-      else if (j != PR_REG && TEST_HARD_REG_BIT (live_regs_mask, j))
-       pop (j);
-      if (j == FIRST_FP_REG && fpscr_deferred)
-       pop (FPSCR_REG);
+       }
     }
- finish:
   if (target_flags != save_flags && ! current_function_interrupt)
     emit_insn (gen_toggle_sz ());
   target_flags = save_flags;
 
   output_stack_adjust (extra_push + current_function_pretend_args_size
-                      + d + d_rounding
+                      + save_size + d_rounding
                       + current_function_args_info.stack_regs * 8,
-                      stack_pointer_rtx, 7, emit_insn);
+                      stack_pointer_rtx, 1, NULL);
 
   if (current_function_calls_eh_return)
     emit_insn (GEN_ADD3 (stack_pointer_rtx, stack_pointer_rtx,
@@ -5405,7 +5791,7 @@ sh_expand_epilogue ()
 static int sh_need_epilogue_known = 0;
 
 int
-sh_need_epilogue ()
+sh_need_epilogue (void)
 {
   if (! sh_need_epilogue_known)
     {
@@ -5424,12 +5810,10 @@ sh_need_epilogue ()
    TEMP is available as a scratch register, if needed.  */
 
 void
-sh_set_return_address (ra, tmp)
-     rtx ra, tmp;
+sh_set_return_address (rtx ra, rtx tmp)
 {
   HARD_REG_SET live_regs_mask;
   int d;
-  int d_rounding = 0;
   int pr_reg = TARGET_SHMEDIA ? PR_MEDIA_REG : PR_REG;
   int pr_offset;
 
@@ -5461,56 +5845,26 @@ sh_set_return_address (ra, tmp)
 
   if (TARGET_SH5)
     {
-      int i;
       int offset;
-      int align;
+      save_schedule schedule;
+      save_entry *entry;
       
-      if (d % (STACK_BOUNDARY / BITS_PER_UNIT))
-       d_rounding = ((STACK_BOUNDARY / BITS_PER_UNIT)
-                     - d % (STACK_BOUNDARY / BITS_PER_UNIT));
-
-      offset = 0;
-
-      /* We loop twice: first, we save 8-byte aligned registers in the
-        higher addresses, that are known to be aligned.  Then, we
-        proceed to saving 32-bit registers that don't need 8-byte
-        alignment.  */
-      for (align = 0; align <= 1; align++)
-       for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
-         if (TEST_HARD_REG_BIT (live_regs_mask, i))
-           {
-             enum machine_mode mode = REGISTER_NATURAL_MODE (i);
-
-             if (mode == SFmode && (i % 2) == 0
-                 && ! TARGET_FPU_SINGLE && FP_REGISTER_P (i)
-                 && (TEST_HARD_REG_BIT (live_regs_mask, (i ^ 1))))
-               {
-                 mode = DFmode;
-                 i++;
-               }
-
-             /* If we're doing the aligned pass and this is not aligned,
-                or we're doing the unaligned pass and this is aligned,
-                skip it.  */
-             if ((GET_MODE_SIZE (mode) % (STACK_BOUNDARY / BITS_PER_UNIT)
-                  == 0) != align)
-               continue;
-
-             if (i == pr_reg)
-               goto found;
-
-             offset += GET_MODE_SIZE (mode);
-           }
+      entry = sh5_schedule_saves (&live_regs_mask, &schedule, 0);
+      offset = entry[1].offset;
+      for (; entry->mode != VOIDmode; entry--)
+       if (entry->reg == pr_reg)
+         goto found;
 
       /* We can't find pr register.  */
       abort ();
 
     found:
-      pr_offset = (rounded_frame_size (d) - d_rounding + offset
+      offset = entry->offset - offset;
+      pr_offset = (rounded_frame_size (d) + offset
                   + SHMEDIA_REGS_STACK_ADJUST ());
     }
   else
-    pr_offset = rounded_frame_size (d) - d_rounding;
+    pr_offset = rounded_frame_size (d);
 
   emit_insn (GEN_MOV (tmp, GEN_INT (pr_offset)));
   emit_insn (GEN_ADD3 (tmp, tmp, frame_pointer_rtx));
@@ -5522,17 +5876,16 @@ sh_set_return_address (ra, tmp)
 /* Clear variables at function end.  */
 
 static void
-sh_output_function_epilogue (file, size)
-     FILE *file ATTRIBUTE_UNUSED;
-     HOST_WIDE_INT size ATTRIBUTE_UNUSED;
+sh_output_function_epilogue (FILE *file ATTRIBUTE_UNUSED,
+                            HOST_WIDE_INT size ATTRIBUTE_UNUSED)
 {
   trap_exit = pragma_interrupt = pragma_trapa = pragma_nosave_low_regs = 0;
   sh_need_epilogue_known = 0;
   sp_switch = NULL_RTX;
 }
 
-rtx
-sh_builtin_saveregs ()
+static rtx
+sh_builtin_saveregs (void)
 {
   /* First unnamed integer register.  */
   int first_intreg = current_function_args_info.arg_count[(int) SH_ARG_INT];
@@ -5644,16 +5997,16 @@ sh_builtin_saveregs ()
          mem = gen_rtx_MEM (DFmode, fpregs);
          set_mem_alias_set (mem, alias_set);
          emit_move_insn (mem, 
-                         gen_rtx (REG, DFmode, BASE_ARG_REG (DFmode) + regno));
+                         gen_rtx_REG (DFmode, BASE_ARG_REG (DFmode) + regno));
        }
       regno = first_floatreg;
       if (regno & 1)
        {
-         emit_insn (gen_addsi3 (fpregs, fpregs, GEN_INT (- UNITS_PER_WORD)));
+         emit_insn (gen_addsi3 (fpregs, fpregs, GEN_INT (-UNITS_PER_WORD)));
          mem = gen_rtx_MEM (SFmode, fpregs);
          set_mem_alias_set (mem, alias_set);
          emit_move_insn (mem,
-                         gen_rtx (REG, SFmode, BASE_ARG_REG (SFmode) + regno
+                         gen_rtx_REG (SFmode, BASE_ARG_REG (SFmode) + regno
                                                - (TARGET_LITTLE_ENDIAN != 0)));
        }
     }
@@ -5662,7 +6015,7 @@ sh_builtin_saveregs ()
       {
         rtx mem;
 
-       emit_insn (gen_addsi3 (fpregs, fpregs, GEN_INT (- UNITS_PER_WORD)));
+       emit_insn (gen_addsi3 (fpregs, fpregs, GEN_INT (-UNITS_PER_WORD)));
        mem = gen_rtx_MEM (SFmode, fpregs);
        set_mem_alias_set (mem, alias_set);
        emit_move_insn (mem,
@@ -5675,16 +6028,17 @@ sh_builtin_saveregs ()
 
 /* Define the `__builtin_va_list' type for the ABI.  */
 
-tree
-sh_build_va_list ()
+static tree
+sh_build_builtin_va_list (void)
 {
   tree f_next_o, f_next_o_limit, f_next_fp, f_next_fp_limit, f_next_stack;
   tree record;
 
-  if (TARGET_SH5 || (! TARGET_SH2E && ! TARGET_SH4) || TARGET_HITACHI)
+  if (TARGET_SH5 || (! TARGET_SH2E && ! TARGET_SH4)
+      || TARGET_HITACHI || sh_cfun_attr_renesas_p ())
     return ptr_type_node;
 
-  record = make_node (RECORD_TYPE);
+  record = (*lang_hooks.types.make_type) (RECORD_TYPE);
 
   f_next_o = build_decl (FIELD_DECL, get_identifier ("__va_next_o"),
                         ptr_type_node);
@@ -5719,9 +6073,7 @@ sh_build_va_list ()
 /* Implement `va_start' for varargs and stdarg.  */
 
 void
-sh_va_start (valist, nextarg)
-     tree valist;
-     rtx nextarg;
+sh_va_start (tree valist, rtx nextarg)
 {
   tree f_next_o, f_next_o_limit, f_next_fp, f_next_fp_limit, f_next_stack;
   tree next_o, next_o_limit, next_fp, next_fp_limit, next_stack;
@@ -5735,7 +6087,8 @@ sh_va_start (valist, nextarg)
       return;
     }
 
-  if ((! TARGET_SH2E && ! TARGET_SH4) || TARGET_HITACHI)
+  if ((! TARGET_SH2E && ! TARGET_SH4)
+      || TARGET_HITACHI || sh_cfun_attr_renesas_p ())
     {
       std_expand_builtin_va_start (valist, nextarg);
       return;
@@ -5797,14 +6150,14 @@ sh_va_start (valist, nextarg)
 /* Implement `va_arg'.  */
 
 rtx
-sh_va_arg (valist, type)
-     tree valist, type;
+sh_va_arg (tree valist, tree type)
 {
   HOST_WIDE_INT size, rsize;
   tree tmp, pptr_type_node;
   rtx addr_rtx, r;
-  rtx result;
+  rtx result_ptr, result = NULL_RTX;
   int pass_by_ref = MUST_PASS_IN_STACK (TYPE_MODE (type), type);
+  rtx lab_over;
 
   size = int_size_in_bytes (type);
   rsize = (size + UNITS_PER_WORD - 1) & -UNITS_PER_WORD;
@@ -5813,12 +6166,13 @@ sh_va_arg (valist, type)
   if (pass_by_ref)
     type = build_pointer_type (type);
 
-  if (! TARGET_SH5 && (TARGET_SH2E || TARGET_SH4) && ! TARGET_HITACHI)
+  if (! TARGET_SH5 && (TARGET_SH2E || TARGET_SH4)
+      && ! (TARGET_HITACHI || sh_cfun_attr_renesas_p ()))
     {
       tree f_next_o, f_next_o_limit, f_next_fp, f_next_fp_limit, f_next_stack;
       tree next_o, next_o_limit, next_fp, next_fp_limit, next_stack;
       int pass_as_float;
-      rtx lab_false, lab_over;
+      rtx lab_false;
 
       f_next_o = TYPE_FIELDS (va_list_type_node);
       f_next_o_limit = TREE_CHAIN (f_next_o);
@@ -5836,6 +6190,16 @@ sh_va_arg (valist, type)
       next_stack = build (COMPONENT_REF, TREE_TYPE (f_next_stack),
                          valist, f_next_stack);
 
+      /* Structures with a single member with a distinct mode are passed
+        like their member.  This is relevant if the latter has a REAL_TYPE
+        or COMPLEX_TYPE type.  */
+      if (TREE_CODE (type) == RECORD_TYPE
+         && TYPE_FIELDS (type)
+         && TREE_CODE (TYPE_FIELDS (type)) == FIELD_DECL
+         && (TREE_CODE (TREE_TYPE (TYPE_FIELDS (type))) == REAL_TYPE
+             || TREE_CODE (TREE_TYPE (TYPE_FIELDS (type))) == COMPLEX_TYPE)
+          && TREE_CHAIN (TYPE_FIELDS (type)) == NULL_TREE)
+       type = TREE_TYPE (TYPE_FIELDS (type));
       if (TARGET_SH4)
        {
          pass_as_float = ((TREE_CODE (type) == REAL_TYPE && size <= 8)
@@ -5852,6 +6216,9 @@ sh_va_arg (valist, type)
       lab_false = gen_label_rtx ();
       lab_over = gen_label_rtx ();
 
+      tmp = make_tree (pptr_type_node, addr_rtx);
+      valist = build1 (INDIRECT_REF, ptr_type_node, tmp);
+
       if (pass_as_float)
        {
          int first_floatreg
@@ -5881,6 +6248,37 @@ sh_va_arg (valist, type)
          if (r != addr_rtx)
            emit_move_insn (addr_rtx, r);
 
+#ifdef FUNCTION_ARG_SCmode_WART
+         if (TYPE_MODE (type) == SCmode && TARGET_SH4 && TARGET_LITTLE_ENDIAN)
+           {
+             rtx addr, real, imag, result_value, slot;
+             tree subtype = TREE_TYPE (type);
+
+             addr = std_expand_builtin_va_arg (valist, subtype);
+#ifdef POINTERS_EXTEND_UNSIGNED
+             if (GET_MODE (addr) != Pmode)
+               addr = convert_memory_address (Pmode, addr);
+#endif
+             imag = gen_rtx_MEM (TYPE_MODE (type), addr);
+             set_mem_alias_set (imag, get_varargs_alias_set ());
+
+             addr = std_expand_builtin_va_arg (valist, subtype);
+#ifdef POINTERS_EXTEND_UNSIGNED
+             if (GET_MODE (addr) != Pmode)
+               addr = convert_memory_address (Pmode, addr);
+#endif
+             real = gen_rtx_MEM (TYPE_MODE (type), addr);
+             set_mem_alias_set (real, get_varargs_alias_set ());
+
+             result_value = gen_rtx_CONCAT (SCmode, real, imag);
+             /* ??? this interface is stupid - why require a pointer?  */
+             result = gen_reg_rtx (Pmode);
+             slot = assign_stack_temp (SCmode, 8, 0);
+             emit_move_insn (slot, result_value);
+             emit_move_insn (result, XEXP (slot, 0));
+           }
+#endif /* FUNCTION_ARG_SCmode_WART */
+
          emit_jump_insn (gen_jump (lab_over));
          emit_barrier ();
          emit_label (lab_false);
@@ -5923,20 +6321,26 @@ sh_va_arg (valist, type)
            emit_move_insn (addr_rtx, r);
        }
 
-      emit_label (lab_over);
-
-      tmp = make_tree (pptr_type_node, addr_rtx);
-      valist = build1 (INDIRECT_REF, ptr_type_node, tmp);
+      if (! result)
+        emit_label (lab_over);
     }
 
   /* ??? In va-sh.h, there had been code to make values larger than
      size 8 indirect.  This does not match the FUNCTION_ARG macros.  */
 
-  result = std_expand_builtin_va_arg (valist, type);
-  if (pass_by_ref)
+  result_ptr = std_expand_builtin_va_arg (valist, type);
+  if (result)
     {
-#ifdef POINTERS_EXTEND_UNSIGNED
-      if (GET_MODE (addr) != Pmode)
+      emit_move_insn (result, result_ptr);
+      emit_label (lab_over);
+    }
+  else
+    result = result_ptr;
+
+  if (pass_by_ref)
+    {
+#ifdef POINTERS_EXTEND_UNSIGNED
+      if (GET_MODE (addr) != Pmode)
        addr = convert_memory_address (Pmode, result);
 #endif
       result = gen_rtx_MEM (ptr_mode, force_reg (Pmode, result));
@@ -5947,13 +6351,332 @@ sh_va_arg (valist, type)
   return result;
 }
 
+bool
+sh_promote_prototypes (tree type)
+{
+  if (TARGET_HITACHI)
+    return 0;
+  if (! type)
+    return 1;
+  return ! sh_attr_renesas_p (type);
+}
+
+/* Define where to put the arguments to a function.
+   Value is zero to push the argument on the stack,
+   or a hard register in which to store the argument.
+
+   MODE is the argument's machine mode.
+   TYPE is the data type of the argument (as a tree).
+    This is null for libcalls where that information may
+    not be available.
+   CUM is a variable of type CUMULATIVE_ARGS which gives info about
+    the preceding args and about the function being called.
+   NAMED is nonzero if this argument is a named parameter
+    (otherwise it is an extra parameter matching an ellipsis).
+
+   On SH the first args are normally in registers
+   and the rest are pushed.  Any arg that starts within the first
+   NPARM_REGS words is at least partially passed in a register unless
+   its data type forbids.  */
+
+
+rtx
+sh_function_arg (CUMULATIVE_ARGS *ca, enum machine_mode mode,
+                tree type, int named)
+{
+  if (! TARGET_SH5 && mode == VOIDmode)
+    return GEN_INT (ca->renesas_abi ? 1 : 0);
+
+  if (! TARGET_SH5
+      && PASS_IN_REG_P (*ca, mode, type)
+      && (named || ! (TARGET_HITACHI || ca->renesas_abi)))
+    {
+      int regno;
+
+      if (mode == SCmode && TARGET_SH4 && TARGET_LITTLE_ENDIAN
+         && (! FUNCTION_ARG_SCmode_WART || (ROUND_REG (*ca, mode) & 1)))
+       {
+         rtx r1 = gen_rtx_EXPR_LIST (VOIDmode,
+                                     gen_rtx_REG (SFmode,
+                                                  BASE_ARG_REG (mode)
+                                                  + (ROUND_REG (*ca, mode) ^ 1)),
+                                     const0_rtx);
+         rtx r2 = gen_rtx_EXPR_LIST (VOIDmode,
+                                     gen_rtx_REG (SFmode,
+                                                  BASE_ARG_REG (mode)
+                                                  + ((ROUND_REG (*ca, mode) + 1) ^ 1)),
+                                     GEN_INT (4));
+         return gen_rtx_PARALLEL(SCmode, gen_rtvec(2, r1, r2));
+       }
+
+     /* If the alignment of a DF value causes an SF register to be
+       skipped, we will use that skipped register for the next SF
+       value.  */
+      if ((TARGET_HITACHI || ca->renesas_abi)
+         && ca->free_single_fp_reg
+         && mode == SFmode)
+       return gen_rtx_REG (mode, ca->free_single_fp_reg);
+
+      regno = (BASE_ARG_REG (mode) + ROUND_REG (*ca, mode))
+              ^ (mode == SFmode && TARGET_SH4
+                 && TARGET_LITTLE_ENDIAN != 0
+                 && ! TARGET_HITACHI && ! ca->renesas_abi);
+      return gen_rtx_REG (mode, regno);
+
+    }
+  
+  if (TARGET_SH5)
+    {
+      if (mode == VOIDmode && TARGET_SHCOMPACT)
+       return GEN_INT (ca->call_cookie);
+
+      /* The following test assumes unnamed arguments are promoted to
+        DFmode.  */
+      if (mode == SFmode && ca->free_single_fp_reg)
+       return SH5_PROTOTYPED_FLOAT_ARG (*ca, mode, ca->free_single_fp_reg);
+
+      if ((GET_SH_ARG_CLASS (mode) == SH_ARG_FLOAT)
+         && (named || ! ca->prototype_p)
+         && ca->arg_count[(int) SH_ARG_FLOAT] < NPARM_REGS (SFmode))
+       {
+         if (! ca->prototype_p && TARGET_SHMEDIA)
+           return SH5_PROTOTYPELESS_FLOAT_ARG (*ca, mode);
+
+         return SH5_PROTOTYPED_FLOAT_ARG (*ca, mode,
+                                          FIRST_FP_PARM_REG
+                                          + ca->arg_count[(int) SH_ARG_FLOAT]);
+       }
+
+      if (ca->arg_count[(int) SH_ARG_INT] < NPARM_REGS (SImode)
+         && (! TARGET_SHCOMPACT
+             || (! SHCOMPACT_FORCE_ON_STACK (mode, type)
+                 && ! SH5_WOULD_BE_PARTIAL_NREGS (*ca, mode,
+                                                  type, named))))
+       {
+         return gen_rtx_REG (mode, (FIRST_PARM_REG
+                                      + ca->arg_count[(int) SH_ARG_INT]));
+       }
+
+      return 0;
+    }
+
+  return 0;
+}
+/* Update the data in CUM to advance over an argument
+   of mode MODE and data type TYPE.
+   (TYPE is null for libcalls where that information may not be
+   available.)  */
+
+void
+sh_function_arg_advance (CUMULATIVE_ARGS *ca, enum machine_mode mode,
+                        tree type, int named)
+{
+  if (ca->force_mem)
+    ca->force_mem = 0;
+  else if (TARGET_SH5)
+    {
+      tree type2 = (ca->byref && type
+                   ? TREE_TYPE (type)
+                   : type);
+      enum machine_mode mode2 = (ca->byref && type
+                                ? TYPE_MODE (type2)
+                                : mode);
+      int dwords = ((ca->byref
+                    ? ca->byref
+                    : mode2 == BLKmode
+                    ? int_size_in_bytes (type2)
+                    : GET_MODE_SIZE (mode2)) + 7) / 8;
+      int numregs = MIN (dwords, NPARM_REGS (SImode)
+                        - ca->arg_count[(int) SH_ARG_INT]);
+
+      if (numregs)
+       {
+         ca->arg_count[(int) SH_ARG_INT] += numregs;
+         if (TARGET_SHCOMPACT
+             && SHCOMPACT_FORCE_ON_STACK (mode2, type2))
+           {
+             ca->call_cookie
+               |= CALL_COOKIE_INT_REG (ca->arg_count[(int) SH_ARG_INT]
+                                       - numregs, 1);
+             /* N.B. We want this also for outgoing.  */
+             ca->stack_regs += numregs;
+           }
+         else if (ca->byref)
+           {
+             if (! ca->outgoing)
+               ca->stack_regs += numregs;
+             ca->byref_regs += numregs;
+             ca->byref = 0;
+             do
+               ca->call_cookie
+                 |= CALL_COOKIE_INT_REG (ca->arg_count[(int) SH_ARG_INT]
+                                         - numregs, 2);
+             while (--numregs);
+             ca->call_cookie
+               |= CALL_COOKIE_INT_REG (ca->arg_count[(int) SH_ARG_INT]
+                                       - 1, 1);
+           }
+         else if (dwords > numregs)
+           {
+             int pushregs = numregs;
+
+             if (TARGET_SHCOMPACT)
+               ca->stack_regs += numregs;
+             while (pushregs < NPARM_REGS (SImode) - 1
+                    && (CALL_COOKIE_INT_REG_GET
+                        (ca->call_cookie,
+                         NPARM_REGS (SImode) - pushregs)
+                        == 1))
+               {
+                 ca->call_cookie
+                   &= ~ CALL_COOKIE_INT_REG (NPARM_REGS (SImode)
+                                             - pushregs, 1);
+                 pushregs++;
+               }
+             if (numregs == NPARM_REGS (SImode))
+               ca->call_cookie
+                 |= CALL_COOKIE_INT_REG (0, 1)
+                 | CALL_COOKIE_STACKSEQ (numregs - 1);
+             else
+               ca->call_cookie
+                 |= CALL_COOKIE_STACKSEQ (numregs);
+           }
+       }
+      if (GET_SH_ARG_CLASS (mode2) == SH_ARG_FLOAT
+         && (named || ! ca->prototype_p))
+       {
+         if (mode2 == SFmode && ca->free_single_fp_reg)
+           ca->free_single_fp_reg = 0;
+         else if (ca->arg_count[(int) SH_ARG_FLOAT]
+                  < NPARM_REGS (SFmode))
+           {
+             int numfpregs
+               = MIN ((GET_MODE_SIZE (mode2) + 7) / 8 * 2,
+                      NPARM_REGS (SFmode)
+                      - ca->arg_count[(int) SH_ARG_FLOAT]);
+
+             ca->arg_count[(int) SH_ARG_FLOAT] += numfpregs;
+
+             if (TARGET_SHCOMPACT && ! ca->prototype_p)
+               {
+                 if (ca->outgoing && numregs > 0)
+                   do
+                     {
+                       ca->call_cookie
+                         |= (CALL_COOKIE_INT_REG
+                             (ca->arg_count[(int) SH_ARG_INT]
+                              - numregs + ((numfpregs - 2) / 2),
+                              4 + (ca->arg_count[(int) SH_ARG_FLOAT]
+                                   - numfpregs) / 2));
+                     }
+                   while (numfpregs -= 2);
+               }
+             else if (mode2 == SFmode && (named)
+                      && (ca->arg_count[(int) SH_ARG_FLOAT]
+                          < NPARM_REGS (SFmode)))
+               ca->free_single_fp_reg
+                 = FIRST_FP_PARM_REG - numfpregs
+                 + ca->arg_count[(int) SH_ARG_FLOAT] + 1;
+           }
+       }
+      return;
+    }
+
+  if ((TARGET_HITACHI || ca->renesas_abi) && TARGET_FPU_DOUBLE)
+    {
+      /* Note that we've used the skipped register.  */
+      if (mode == SFmode && ca->free_single_fp_reg)
+       {
+         ca->free_single_fp_reg = 0;
+         return;
+       }
+      /* When we have a DF after an SF, there's an SF register that get
+        skipped in order to align the DF value.  We note this skipped
+        register, because the next SF value will use it, and not the
+        SF that follows the DF.  */
+      if (mode == DFmode
+         && ROUND_REG (*ca, DFmode) != ROUND_REG (*ca, SFmode))
+       {
+         ca->free_single_fp_reg = (ROUND_REG (*ca, SFmode)
+                                   + BASE_ARG_REG (mode));
+       }
+    }
+
+  if (! (TARGET_SH4 || ca->renesas_abi)
+      || PASS_IN_REG_P (*ca, mode, type))
+    (ca->arg_count[(int) GET_SH_ARG_CLASS (mode)]
+     = (ROUND_REG (*ca, mode)
+       + (mode == BLKmode
+          ? ROUND_ADVANCE (int_size_in_bytes (type))
+          : ROUND_ADVANCE (GET_MODE_SIZE (mode)))));
+}
+
+/* The Renesas calling convention doesn't quite fit into this scheme since
+   the address is passed like an invisible argument, but one that is always
+   passed in memory.  */
+static rtx
+sh_struct_value_rtx (tree fndecl, int incoming ATTRIBUTE_UNUSED)
+{
+  if (TARGET_HITACHI || sh_attr_renesas_p (fndecl))
+    return 0;
+  return gen_rtx_REG (Pmode, 2);
+}
+
+/* Worker function for TARGET_RETURN_IN_MEMORY.  */
+
+static bool
+sh_return_in_memory (tree type, tree fndecl)
+{
+  if (TARGET_SH5)
+    {
+      if (TYPE_MODE (type) == BLKmode)
+       return ((unsigned HOST_WIDE_INT) int_size_in_bytes (type)) > 8;
+      else
+       return GET_MODE_SIZE (TYPE_MODE (type)) > 8;
+    }
+  else
+    {
+      return (TYPE_MODE (type) == BLKmode
+             || ((TARGET_HITACHI || sh_attr_renesas_p (fndecl))
+                 && TREE_CODE (type) == RECORD_TYPE));
+    }
+}
+
+/* We actually emit the code in sh_expand_prologue.  We used to use
+   a static variable to flag that we need to emit this code, but that
+   doesn't when inlining, when functions are deferred and then emitted
+   later.  Fortunately, we already have two flags that are part of struct
+   function that tell if a function uses varargs or stdarg.  */
+static void
+sh_setup_incoming_varargs (CUMULATIVE_ARGS *ca ATTRIBUTE_UNUSED,
+                          enum machine_mode mode ATTRIBUTE_UNUSED,
+                          tree type ATTRIBUTE_UNUSED,
+                          int *pretend_arg_size ATTRIBUTE_UNUSED,
+                          int second_time ATTRIBUTE_UNUSED)
+{
+  if (! current_function_stdarg)
+    abort ();
+}
+
+static bool
+sh_strict_argument_naming (CUMULATIVE_ARGS *ca ATTRIBUTE_UNUSED)
+{
+  return TARGET_SH5;
+}
+
+static bool
+sh_pretend_outgoing_varargs_named (CUMULATIVE_ARGS *ca)
+{
+  return ! (TARGET_HITACHI || ca->renesas_abi) && ! TARGET_SH5;
+}
+
+
 /* Define the offset between two registers, one to be eliminated, and
    the other its replacement, at the start of a routine.  */
 
 int
-initial_elimination_offset (from, to)
-     int from;
-     int to;
+initial_elimination_offset (int from, int to)
 {
   int regs_saved;
   int regs_saved_rounding = 0;
@@ -5961,10 +6684,18 @@ initial_elimination_offset (from, to)
   int total_auto_space;
   int save_flags = target_flags;
   int copy_flags;
-
   HARD_REG_SET live_regs_mask;
+
+  shmedia_space_reserved_for_target_registers = false;
   regs_saved = calc_live_regs (&live_regs_mask);
   regs_saved += SHMEDIA_REGS_STACK_ADJUST ();
+
+  if (shmedia_reserve_space_for_target_registers_p (regs_saved, &live_regs_mask))
+    {
+      shmedia_space_reserved_for_target_registers = true;
+      regs_saved += shmedia_target_regs_stack_adjust (&live_regs_mask);
+    }
+
   if (TARGET_SH5 && regs_saved % (STACK_BOUNDARY / BITS_PER_UNIT))
     regs_saved_rounding = ((STACK_BOUNDARY / BITS_PER_UNIT)
                           - regs_saved % (STACK_BOUNDARY / BITS_PER_UNIT));
@@ -5992,9 +6723,10 @@ initial_elimination_offset (from, to)
     {
       if (TARGET_SH5)
        {
-         int i, n = total_saved_regs_space;
-         int align;
+         int n = total_saved_regs_space;
          int pr_reg = TARGET_SHMEDIA ? PR_MEDIA_REG : PR_REG;
+         save_schedule schedule;
+         save_entry *entry;
          
          n += total_auto_space;
 
@@ -6004,40 +6736,13 @@ initial_elimination_offset (from, to)
 
          target_flags = copy_flags;
 
-         /* We loop twice: first, check 8-byte aligned registers,
-            that are stored in the higher addresses, that are known
-            to be aligned.  Then, check 32-bit registers that don't
-            need 8-byte alignment.  */
-         for (align = 1; align >= 0; align--)
-           for (i = FIRST_PSEUDO_REGISTER - 1; i >= 0; i--)
-             if (TEST_HARD_REG_BIT (live_regs_mask, i))
-               {
-                 enum machine_mode mode = REGISTER_NATURAL_MODE (i);
-
-                 if (mode == SFmode && (i % 2) == 1
-                     && ! TARGET_FPU_SINGLE && FP_REGISTER_P (i)
-                     && TEST_HARD_REG_BIT (live_regs_mask, (i ^ 1)))
-                   {
-                     mode = DFmode;
-                     i--;
-                   }
-               
-                 /* If we're doing the aligned pass and this is not aligned,
-                    or we're doing the unaligned pass and this is aligned,
-                    skip it.  */
-                 if ((GET_MODE_SIZE (mode) % (STACK_BOUNDARY / BITS_PER_UNIT)
-                      == 0) != align)
-                   continue;
-
-                 n -= GET_MODE_SIZE (mode);
-
-                 if (i == pr_reg)
-                   {
-                     target_flags = save_flags;
-                     return n;
-                   }
-               }
-
+         sh5_schedule_saves (&live_regs_mask, &schedule, n);
+         for (entry = &schedule.entries[1]; entry->mode != VOIDmode; entry++)
+           if (entry->reg == pr_reg)
+             {
+               target_flags = save_flags;
+               return entry->offset;
+             }
          abort ();
        }
       else
@@ -6047,26 +6752,23 @@ initial_elimination_offset (from, to)
   abort ();
 }
 \f
-/* Handle machine specific pragmas to be semi-compatible with Hitachi
+/* Handle machine specific pragmas to be semi-compatible with Renesas
    compiler.  */
 
 void
-sh_pr_interrupt (pfile)
-     struct cpp_reader *pfile ATTRIBUTE_UNUSED;
+sh_pr_interrupt (struct cpp_reader *pfile ATTRIBUTE_UNUSED)
 {
   pragma_interrupt = 1;
 }
 
 void
-sh_pr_trapa (pfile)
-     struct cpp_reader *pfile ATTRIBUTE_UNUSED;
+sh_pr_trapa (struct cpp_reader *pfile ATTRIBUTE_UNUSED)
 {
   pragma_interrupt = pragma_trapa = 1;
 }
 
 void
-sh_pr_nosave_low_regs (pfile)
-     struct cpp_reader *pfile ATTRIBUTE_UNUSED;
+sh_pr_nosave_low_regs (struct cpp_reader *pfile ATTRIBUTE_UNUSED)
 {
   pragma_nosave_low_regs = 1;
 }
@@ -6074,9 +6776,7 @@ sh_pr_nosave_low_regs (pfile)
 /* Generate 'handle_interrupt' attribute for decls */
 
 static void
-sh_insert_attributes (node, attributes)
-     tree node;
-     tree * attributes;
+sh_insert_attributes (tree node, tree *attributes)
 {
   if (! pragma_interrupt
       || TREE_CODE (node) != FUNCTION_DECL)
@@ -6100,7 +6800,12 @@ sh_insert_attributes (node, attributes)
    to run on.
 
    trap_exit -- use a trapa to exit an interrupt function instead of
-   an rte instruction.  */
+   an rte instruction.
+
+   renesas -- use Renesas calling/layout conventions (functions and
+   structures).
+
+*/
 
 const struct attribute_spec sh_attribute_table[] =
 {
@@ -6108,18 +6813,17 @@ const struct attribute_spec sh_attribute_table[] =
   { "interrupt_handler", 0, 0, true,  false, false, sh_handle_interrupt_handler_attribute },
   { "sp_switch",         1, 1, true,  false, false, sh_handle_sp_switch_attribute },
   { "trap_exit",         1, 1, true,  false, false, sh_handle_trap_exit_attribute },
+  { "renesas",           0, 0, false, true, false, sh_handle_renesas_attribute },
   { NULL,                0, 0, false, false, false, NULL }
 };
 
 /* Handle an "interrupt_handler" attribute; arguments as in
    struct attribute_spec.handler.  */
 static tree
-sh_handle_interrupt_handler_attribute (node, name, args, flags, no_add_attrs)
-     tree *node;
-     tree name;
-     tree args ATTRIBUTE_UNUSED;
-     int flags ATTRIBUTE_UNUSED;
-     bool *no_add_attrs;
+sh_handle_interrupt_handler_attribute (tree *node, tree name,
+                                      tree args ATTRIBUTE_UNUSED,
+                                      int flags ATTRIBUTE_UNUSED,
+                                      bool *no_add_attrs)
 {
   if (TREE_CODE (*node) != FUNCTION_DECL)
     {
@@ -6139,12 +6843,8 @@ sh_handle_interrupt_handler_attribute (node, name, args, flags, no_add_attrs)
 /* Handle an "sp_switch" attribute; arguments as in
    struct attribute_spec.handler.  */
 static tree
-sh_handle_sp_switch_attribute (node, name, args, flags, no_add_attrs)
-     tree *node;
-     tree name;
-     tree args;
-     int flags ATTRIBUTE_UNUSED;
-     bool *no_add_attrs;
+sh_handle_sp_switch_attribute (tree *node, tree name, tree args,
+                              int flags ATTRIBUTE_UNUSED, bool *no_add_attrs)
 {
   if (TREE_CODE (*node) != FUNCTION_DECL)
     {
@@ -6178,12 +6878,8 @@ sh_handle_sp_switch_attribute (node, name, args, flags, no_add_attrs)
 /* Handle an "trap_exit" attribute; arguments as in
    struct attribute_spec.handler.  */
 static tree
-sh_handle_trap_exit_attribute (node, name, args, flags, no_add_attrs)
-     tree *node;
-     tree name;
-     tree args;
-     int flags ATTRIBUTE_UNUSED;
-     bool *no_add_attrs;
+sh_handle_trap_exit_attribute (tree *node, tree name, tree args,
+                              int flags ATTRIBUTE_UNUSED, bool *no_add_attrs)
 {
   if (TREE_CODE (*node) != FUNCTION_DECL)
     {
@@ -6213,13 +6909,129 @@ sh_handle_trap_exit_attribute (node, name, args, flags, no_add_attrs)
   return NULL_TREE;
 }
 
+static tree
+sh_handle_renesas_attribute (tree *node ATTRIBUTE_UNUSED,
+                            tree name ATTRIBUTE_UNUSED,
+                            tree args ATTRIBUTE_UNUSED,
+                            int flags ATTRIBUTE_UNUSED,
+                            bool *no_add_attrs ATTRIBUTE_UNUSED)
+{
+  return NULL_TREE;
+}
+
+/* True if __attribute__((renesas)) or -mrenesas.  */
+int
+sh_attr_renesas_p (tree td)
+{
+  if (TARGET_HITACHI)
+    return 1;
+  if (td == 0)
+    return 0;
+  if (DECL_P (td))
+    td = TREE_TYPE (td);
+  return (lookup_attribute ("renesas", TYPE_ATTRIBUTES (td))
+         != NULL_TREE);
+}
+
+/* True if __attribute__((renesas)) or -mrenesas, for the current
+   function.  */
+int
+sh_cfun_attr_renesas_p (void)
+{
+  return sh_attr_renesas_p (current_function_decl);
+}
+
 int
-sh_cfun_interrupt_handler_p ()
+sh_cfun_interrupt_handler_p (void)
 {
   return (lookup_attribute ("interrupt_handler",
                            DECL_ATTRIBUTES (current_function_decl))
          != NULL_TREE);
 }
+
+/* ??? target_switches in toplev.c is static, hence we have to duplicate it.  */
+static const struct
+{
+  const char *const name;
+  const int value;
+  const char *const description;
+}
+sh_target_switches[] = TARGET_SWITCHES;
+#define target_switches sh_target_switches
+
+/* Like default_pch_valid_p, but take flag_mask into account.  */
+const char *
+sh_pch_valid_p (const void *data_p, size_t len)
+{
+  const char *data = (const char *)data_p;
+  const char *flag_that_differs = NULL;
+  size_t i;
+  int old_flags;
+  int flag_mask
+    = (SH1_BIT | SH2_BIT | SH3_BIT | SH_E_BIT | HARD_SH4_BIT | FPU_SINGLE_BIT
+       | SH4_BIT | HITACHI_BIT | LITTLE_ENDIAN_BIT);
+  
+  /* -fpic and -fpie also usually make a PCH invalid.  */
+  if (data[0] != flag_pic)
+    return _("created and used with different settings of -fpic");
+  if (data[1] != flag_pie)
+    return _("created and used with different settings of -fpie");
+  data += 2;
+
+  /* Check target_flags.  */
+  memcpy (&old_flags, data, sizeof (target_flags));
+  if (((old_flags ^ target_flags) & flag_mask) != 0)
+    {
+      for (i = 0; i < ARRAY_SIZE (target_switches); i++)
+       {
+         int bits;
+
+         bits = target_switches[i].value;
+         if (bits < 0)
+           bits = -bits;
+         bits &= flag_mask;
+         if ((target_flags & bits) != (old_flags & bits))
+           {
+             flag_that_differs = target_switches[i].name;
+             goto make_message;
+           }
+       }
+      abort ();
+    }
+  data += sizeof (target_flags);
+  len -= sizeof (target_flags);
+  
+  /* Check string options.  */
+#ifdef TARGET_OPTIONS
+  for (i = 0; i < ARRAY_SIZE (target_options); i++)
+    {
+      const char *str = *target_options[i].variable;
+      size_t l;
+      if (! str)
+       str = "";
+      l = strlen (str) + 1;
+      if (len < l || memcmp (data, str, l) != 0)
+       {
+         flag_that_differs = target_options[i].prefix;
+         goto make_message;
+       }
+      data += l;
+      len -= l;
+    }
+#endif
+
+  return NULL;
+  
+ make_message:
+  {
+    char *r;
+    asprintf (&r, _("created and used with differing settings of `-m%s'"),
+                 flag_that_differs);
+    if (r == NULL)
+      return _("out of memory");
+    return r;
+  }
+}
 \f
 /* Predicates used by the templates.  */
 
@@ -6227,9 +7039,7 @@ sh_cfun_interrupt_handler_p ()
    Used only in general_movsrc_operand.  */
 
 int
-system_reg_operand (op, mode)
-     rtx op;
-     enum machine_mode mode ATTRIBUTE_UNUSED;
+system_reg_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
 {
   switch (REGNO (op))
     {
@@ -6246,9 +7056,7 @@ system_reg_operand (op, mode)
    invalid as are subregs of system registers.  */
 
 int
-general_movsrc_operand (op, mode)
-     rtx op;
-     enum machine_mode mode;
+general_movsrc_operand (rtx op, enum machine_mode mode)
 {
   if (GET_CODE (op) == MEM)
     {
@@ -6282,9 +7090,7 @@ general_movsrc_operand (op, mode)
    Same as general_operand, but no preinc allowed.  */
 
 int
-general_movdst_operand (op, mode)
-     rtx op;
-     enum machine_mode mode;
+general_movdst_operand (rtx op, enum machine_mode mode)
 {
   /* Only pre dec allowed.  */
   if (GET_CODE (op) == MEM && GET_CODE (XEXP (op, 0)) == POST_INC)
@@ -6296,9 +7102,7 @@ general_movdst_operand (op, mode)
 /* Returns 1 if OP is a normal arithmetic register.  */
 
 int
-arith_reg_operand (op, mode)
-     rtx op;
-     enum machine_mode mode;
+arith_reg_operand (rtx op, enum machine_mode mode)
 {
   if (register_operand (op, mode))
     {
@@ -6323,9 +7127,7 @@ arith_reg_operand (op, mode)
    because this would lead to missing sign extensions when truncating from
    DImode to SImode.  */
 int
-arith_reg_dest (op, mode)
-     rtx op;
-     enum machine_mode mode;
+arith_reg_dest (rtx op, enum machine_mode mode)
 {
   if (mode == DImode && GET_CODE (op) == SUBREG
       && GET_MODE_SIZE (GET_MODE (SUBREG_REG (op))) < 8)
@@ -6334,9 +7136,7 @@ arith_reg_dest (op, mode)
 }
 
 int
-int_gpr_dest (op, mode)
-     rtx op;
-     enum machine_mode mode ATTRIBUTE_UNUSED;
+int_gpr_dest (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
 {
   enum machine_mode op_mode = GET_MODE (op);
 
@@ -6349,9 +7149,7 @@ int_gpr_dest (op, mode)
 }
 
 int
-fp_arith_reg_operand (op, mode)
-     rtx op;
-     enum machine_mode mode;
+fp_arith_reg_operand (rtx op, enum machine_mode mode)
 {
   if (register_operand (op, mode))
     {
@@ -6373,9 +7171,7 @@ fp_arith_reg_operand (op, mode)
 /* Returns 1 if OP is a valid source operand for an arithmetic insn.  */
 
 int
-arith_operand (op, mode)
-     rtx op;
-     enum machine_mode mode;
+arith_operand (rtx op, enum machine_mode mode)
 {
   if (arith_reg_operand (op, mode))
     return 1;
@@ -6383,17 +7179,17 @@ arith_operand (op, mode)
   if (TARGET_SHMEDIA)
     {
       /* FIXME: We should be checking whether the CONST_INT fits in a
-        CONST_OK_FOR_J here, but this causes reload_cse to crash when
+        CONST_OK_FOR_I16 here, but this causes reload_cse to crash when
         attempting to transform a sequence of two 64-bit sets of the
         same register from literal constants into a set and an add,
         when the difference is too wide for an add.  */
       if (GET_CODE (op) == CONST_INT
-         || EXTRA_CONSTRAINT_S (op))
+         || EXTRA_CONSTRAINT_C16 (op))
        return 1;
       else
        return 0;
     }
-  else if (GET_CODE (op) == CONST_INT && CONST_OK_FOR_I (INTVAL (op)))
+  else if (GET_CODE (op) == CONST_INT && CONST_OK_FOR_I08 (INTVAL (op)))
     return 1;
 
   return 0;
@@ -6402,14 +7198,12 @@ arith_operand (op, mode)
 /* Returns 1 if OP is a valid source operand for a compare insn.  */
 
 int
-arith_reg_or_0_operand (op, mode)
-     rtx op;
-     enum machine_mode mode;
+arith_reg_or_0_operand (rtx op, enum machine_mode mode)
 {
   if (arith_reg_operand (op, mode))
     return 1;
 
-  if (EXTRA_CONSTRAINT_U (op))
+  if (EXTRA_CONSTRAINT_Z (op))
     return 1;
 
   return 0;
@@ -6419,41 +7213,35 @@ arith_reg_or_0_operand (op, mode)
    that takes either a register or a 6-bit immediate.  */
 
 int
-shmedia_6bit_operand (op, mode)
-     rtx op;
-     enum machine_mode mode;
+shmedia_6bit_operand (rtx op, enum machine_mode mode)
 {
   return (arith_reg_operand (op, mode)
-         || (GET_CODE (op) == CONST_INT && CONST_OK_FOR_O (INTVAL (op))));
+         || (GET_CODE (op) == CONST_INT && CONST_OK_FOR_I06 (INTVAL (op))));
 }
 
 /* Returns 1 if OP is a valid source operand for a logical operation.  */
 
 int
-logical_operand (op, mode)
-     rtx op;
-     enum machine_mode mode;
+logical_operand (rtx op, enum machine_mode mode)
 {
   if (arith_reg_operand (op, mode))
     return 1;
 
   if (TARGET_SHMEDIA)
     {
-      if (GET_CODE (op) == CONST_INT && CONST_OK_FOR_P (INTVAL (op)))
+      if (GET_CODE (op) == CONST_INT && CONST_OK_FOR_I10 (INTVAL (op)))
        return 1;
       else
        return 0;
     }
-  else if (GET_CODE (op) == CONST_INT && CONST_OK_FOR_L (INTVAL (op)))
+  else if (GET_CODE (op) == CONST_INT && CONST_OK_FOR_K08 (INTVAL (op)))
     return 1;
 
   return 0;
 }
 
 int
-and_operand (op, mode)
-     rtx op;
-     enum machine_mode mode;
+and_operand (rtx op, enum machine_mode mode)
 {
   if (logical_operand (op, mode))
     return 1;
@@ -6462,9 +7250,8 @@ and_operand (op, mode)
   if (TARGET_SHMEDIA
       && mode == DImode
       && GET_CODE (op) == CONST_INT
-      && (INTVAL (op) == (unsigned) 0xffffffff
-         || INTVAL (op) == (HOST_WIDE_INT) -1 << 32))
-       return 1;
+      && CONST_OK_FOR_J16 (INTVAL (op)))
+    return 1;
 
   return 0;
 }
@@ -6472,8 +7259,7 @@ and_operand (op, mode)
 /* Nonzero if OP is a floating point value with value 0.0.  */
 
 int
-fp_zero_operand (op)
-     rtx op;
+fp_zero_operand (rtx op)
 {
   REAL_VALUE_TYPE r;
 
@@ -6487,8 +7273,7 @@ fp_zero_operand (op)
 /* Nonzero if OP is a floating point value with value 1.0.  */
 
 int
-fp_one_operand (op)
-     rtx op;
+fp_one_operand (rtx op)
 {
   REAL_VALUE_TYPE r;
 
@@ -6507,33 +7292,27 @@ fp_one_operand (op)
    choosing an fldi alternative during reload and thus failing to
    allocate a scratch register for the constant loading.  */
 int
-fldi_ok ()
+fldi_ok (void)
 {
   return ! TARGET_SH4 || TARGET_FMOVD || reload_completed;
 }
 
 int
-tertiary_reload_operand (op, mode)
-     rtx op;
-     enum machine_mode mode ATTRIBUTE_UNUSED;
+tertiary_reload_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
 {
   enum rtx_code code = GET_CODE (op);
   return code == MEM || (TARGET_SH4 && code == CONST_DOUBLE);
 }
 
 int
-fpscr_operand (op, mode)
-     rtx op;
-     enum machine_mode mode ATTRIBUTE_UNUSED;
+fpscr_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
 {
   return (GET_CODE (op) == REG && REGNO (op) == FPSCR_REG
          && GET_MODE (op) == PSImode);
 }
 
 int
-fpul_operand (op, mode)
-     rtx op;
-     enum machine_mode mode;
+fpul_operand (rtx op, enum machine_mode mode)
 {
   if (TARGET_SHMEDIA)
     return fp_arith_reg_operand (op, mode);
@@ -6544,18 +7323,14 @@ fpul_operand (op, mode)
 }
 
 int
-symbol_ref_operand (op, mode)
-     rtx op;
-     enum machine_mode mode ATTRIBUTE_UNUSED;
+symbol_ref_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
 {
   return (GET_CODE (op) == SYMBOL_REF);
 }
 
 /* Return the TLS type for TLS symbols, 0 for otherwise.  */
 int
-tls_symbolic_operand (op, mode)
-     rtx op;
-     enum machine_mode mode ATTRIBUTE_UNUSED;
+tls_symbolic_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
 {
   if (GET_CODE (op) != SYMBOL_REF)
     return 0;
@@ -6563,9 +7338,7 @@ tls_symbolic_operand (op, mode)
 }
 
 int
-commutative_float_operator (op, mode)
-     rtx op;
-     enum machine_mode mode;
+commutative_float_operator (rtx op, enum machine_mode mode)
 {
   if (GET_MODE (op) != mode)
     return 0;
@@ -6581,9 +7354,7 @@ commutative_float_operator (op, mode)
 }
 
 int
-noncommutative_float_operator (op, mode)
-     rtx op;
-     enum machine_mode mode;
+noncommutative_float_operator (rtx op, enum machine_mode mode)
 {
   if (GET_MODE (op) != mode)
     return 0;
@@ -6599,9 +7370,7 @@ noncommutative_float_operator (op, mode)
 }
 
 int
-unary_float_operator (op, mode)
-     rtx op;
-     enum machine_mode mode;
+unary_float_operator (rtx op, enum machine_mode mode)
 {
   if (GET_MODE (op) != mode)
     return 0;
@@ -6618,9 +7387,7 @@ unary_float_operator (op, mode)
 }
 
 int
-binary_float_operator (op, mode)
-     rtx op;
-     enum machine_mode mode;
+binary_float_operator (rtx op, enum machine_mode mode)
 {
   if (GET_MODE (op) != mode)
     return 0;
@@ -6638,9 +7405,7 @@ binary_float_operator (op, mode)
 }
 
 int
-binary_logical_operator (op, mode)
-     rtx op;
-     enum machine_mode mode;
+binary_logical_operator (rtx op, enum machine_mode mode)
 {
   if (GET_MODE (op) != mode)
     return 0;
@@ -6657,17 +7422,14 @@ binary_logical_operator (op, mode)
 }
 
 int
-equality_comparison_operator (op, mode)
-     rtx op;
-     enum machine_mode mode;
+equality_comparison_operator (rtx op, enum machine_mode mode)
 {
   return ((mode == VOIDmode || GET_MODE (op) == mode)
          && (GET_CODE (op) == EQ || GET_CODE (op) == NE));
 }
 
-int greater_comparison_operator (op, mode)
-     rtx op;
-     enum machine_mode mode;
+int
+greater_comparison_operator (rtx op, enum machine_mode mode)
 {
   if (mode != VOIDmode && GET_MODE (op) == mode)
     return 0;
@@ -6683,9 +7445,8 @@ int greater_comparison_operator (op, mode)
     }
 }
 
-int less_comparison_operator (op, mode)
-     rtx op;
-     enum machine_mode mode;
+int
+less_comparison_operator (rtx op, enum machine_mode mode)
 {
   if (mode != VOIDmode && GET_MODE (op) == mode)
     return 0;
@@ -6703,9 +7464,7 @@ int less_comparison_operator (op, mode)
 
 /* Accept pseudos and branch target registers.  */
 int
-target_reg_operand (op, mode)
-     rtx op;
-     enum machine_mode mode;
+target_reg_operand (rtx op, enum machine_mode mode)
 {
   if (mode != DImode
       || GET_MODE (op) != DImode)
@@ -6730,37 +7489,31 @@ target_reg_operand (op, mode)
 /* Same as target_reg_operand, except that label_refs and symbol_refs
    are accepted before reload.  */
 int
-target_operand (op, mode)
-     rtx op;
-     enum machine_mode mode;
+target_operand (rtx op, enum machine_mode mode)
 {
   if (mode != DImode)
     return 0;
 
   if ((GET_MODE (op) == DImode || GET_MODE (op) == VOIDmode)
-      && EXTRA_CONSTRAINT_T (op))
+      && EXTRA_CONSTRAINT_Csy (op))
     return ! reload_completed;
 
   return target_reg_operand (op, mode);
 }
 
 int
-mextr_bit_offset (op, mode)
-     rtx op;
-     enum machine_mode mode ATTRIBUTE_UNUSED;
+mextr_bit_offset (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
 {
   HOST_WIDE_INT i;
 
   if (GET_CODE (op) != CONST_INT)
     return 0;
   i = INTVAL (op);
-  return i >= 1*8 && i <= 7*8 && (i & 7) == 0;
+  return i >= 1 * 8 && i <= 7 * 8 && (i & 7) == 0;
 }
 
 int
-extend_reg_operand (op, mode)
-     rtx op;
-     enum machine_mode mode;
+extend_reg_operand (rtx op, enum machine_mode mode)
 {
   return (GET_CODE (op) == TRUNCATE
          ? arith_operand
@@ -6768,9 +7521,7 @@ extend_reg_operand (op, mode)
 }
 
 int
-trunc_hi_operand (op, mode)
-     rtx op;
-     enum machine_mode mode;
+trunc_hi_operand (rtx op, enum machine_mode mode)
 {
   enum machine_mode op_mode = GET_MODE (op);
 
@@ -6781,9 +7532,7 @@ trunc_hi_operand (op, mode)
 }
 
 int
-extend_reg_or_0_operand (op, mode)
-     rtx op;
-     enum machine_mode mode;
+extend_reg_or_0_operand (rtx op, enum machine_mode mode)
 {
   return (GET_CODE (op) == TRUNCATE
          ? arith_operand
@@ -6791,9 +7540,7 @@ extend_reg_or_0_operand (op, mode)
 }
 
 int
-general_extend_operand (op, mode)
-     rtx op;
-     enum machine_mode mode;
+general_extend_operand (rtx op, enum machine_mode mode)
 {
   return (GET_CODE (op) == TRUNCATE
          ? arith_operand
@@ -6801,9 +7548,7 @@ general_extend_operand (op, mode)
 }
 
 int
-inqhi_operand (op, mode)
-     rtx op;
-     enum machine_mode mode;
+inqhi_operand (rtx op, enum machine_mode mode)
 {
   if (GET_CODE (op) != TRUNCATE || mode != GET_MODE (op))
     return 0;
@@ -6814,9 +7559,7 @@ inqhi_operand (op, mode)
 }
 
 int
-sh_rep_vec (v, mode)
-     rtx v;
-     enum machine_mode mode;
+sh_rep_vec (rtx v, enum machine_mode mode)
 {
   int i;
   rtx x, y;
@@ -6829,7 +7572,7 @@ sh_rep_vec (v, mode)
   if (GET_MODE_UNIT_SIZE (mode) == 1)
     {
       y = XVECEXP (v, 0, i);
-      for (i -= 2 ; i >= 0; i -= 2)
+      for (i -= 2; i >= 0; i -= 2)
        if (! rtx_equal_p (XVECEXP (v, 0, i + 1), x)
            || ! rtx_equal_p (XVECEXP (v, 0, i), y))
          return 0;
@@ -6844,9 +7587,7 @@ sh_rep_vec (v, mode)
 /* Determine if V is a constant vector matching MODE with only one element
    that is not a sign extension.  Two byte-sized elements count as one.  */
 int
-sh_1el_vec (v, mode)
-     rtx v;
-     enum machine_mode mode;
+sh_1el_vec (rtx v, enum machine_mode mode)
 {
   int unit_size;
   int i, last, least, sign_ix;
@@ -6877,9 +7618,7 @@ sh_1el_vec (v, mode)
 }
 
 int
-sh_const_vec (v, mode)
-     rtx v;
-     enum machine_mode mode;
+sh_const_vec (rtx v, enum machine_mode mode)
 {
   int i;
 
@@ -6896,8 +7635,7 @@ sh_const_vec (v, mode)
 /* Return the destination address of a branch.  */
    
 static int
-branch_dest (branch)
-     rtx branch;
+branch_dest (rtx branch)
 {
   rtx dest = SET_SRC (PATTERN (branch));
   int dest_uid;
@@ -6913,9 +7651,7 @@ branch_dest (branch)
    We assume REG is a reload reg, and therefore does
    not live past labels.  It may live past calls or jumps though.  */
 int
-reg_unused_after (reg, insn)
-     rtx reg;
-     rtx insn;
+reg_unused_after (rtx reg, rtx insn)
 {
   enum rtx_code code;
   rtx set;
@@ -6930,6 +7666,10 @@ reg_unused_after (reg, insn)
 
   while ((insn = NEXT_INSN (insn)))
     {
+      rtx set;
+      if (!INSN_P (insn))
+       continue;
+
       code = GET_CODE (insn);
 
 #if 0
@@ -6986,17 +7726,14 @@ reg_unused_after (reg, insn)
          else if (code == JUMP_INSN)
            return 0;
        }
-      else if (GET_RTX_CLASS (code) == 'i')
-       {
-         rtx set = single_set (insn);
 
-         if (set && reg_overlap_mentioned_p (reg, SET_SRC (set)))
-           return 0;
-         if (set && reg_overlap_mentioned_p (reg, SET_DEST (set)))
-           return GET_CODE (SET_DEST (set)) != MEM;
-         if (set == 0 && reg_overlap_mentioned_p (reg, PATTERN (insn)))
-           return 0;
-       }
+      set = single_set (insn);
+      if (set && reg_overlap_mentioned_p (reg, SET_SRC (set)))
+       return 0;
+      if (set && reg_overlap_mentioned_p (reg, SET_DEST (set)))
+       return GET_CODE (SET_DEST (set)) != MEM;
+      if (set == 0 && reg_overlap_mentioned_p (reg, PATTERN (insn)))
+       return 0;
 
       if (code == CALL_INSN && call_used_regs[REGNO (reg)])
        return 1;
@@ -7008,11 +7745,11 @@ reg_unused_after (reg, insn)
 
 static GTY(()) rtx fpscr_rtx;
 rtx
-get_fpscr_rtx ()
+get_fpscr_rtx (void)
 {
   if (! fpscr_rtx)
     {
-      fpscr_rtx = gen_rtx (REG, PSImode, FPSCR_REG);
+      fpscr_rtx = gen_rtx_REG (PSImode, FPSCR_REG);
       REG_USERVAR_P (fpscr_rtx) = 1;
       mark_user_reg (fpscr_rtx);
     }
@@ -7022,51 +7759,41 @@ get_fpscr_rtx ()
 }
 
 void
-emit_sf_insn (pat)
-     rtx pat;
+emit_sf_insn (rtx pat)
 {
   emit_insn (pat);
 }
 
 void
-emit_df_insn (pat)
-     rtx pat;
+emit_df_insn (rtx pat)
 {
   emit_insn (pat);
 }
 
 void
-expand_sf_unop (fun, operands)
-     rtx (*fun) PARAMS ((rtx, rtx, rtx));
-     rtx *operands;
+expand_sf_unop (rtx (*fun) (rtx, rtx, rtx), rtx *operands)
 {
   emit_sf_insn ((*fun) (operands[0], operands[1], get_fpscr_rtx ()));
 }
 
 void
-expand_sf_binop (fun, operands)
-     rtx (*fun) PARAMS ((rtx, rtx, rtx, rtx));
-     rtx *operands;
+expand_sf_binop (rtx (*fun) (rtx, rtx, rtx, rtx), rtx *operands)
 {
   emit_sf_insn ((*fun) (operands[0], operands[1], operands[2],
                         get_fpscr_rtx ()));
 }
 
 void
-expand_df_unop (fun, operands)
-     rtx (*fun) PARAMS ((rtx, rtx, rtx));
-     rtx *operands;
+expand_df_unop (rtx (*fun) (rtx, rtx, rtx), rtx *operands)
 {
   emit_df_insn ((*fun) (operands[0], operands[1], get_fpscr_rtx ()));
 }
 
 void
-expand_df_binop (fun, operands)
-     rtx (*fun) PARAMS ((rtx, rtx, rtx, rtx));
-     rtx *operands;
+expand_df_binop (rtx (*fun) (rtx, rtx, rtx, rtx), rtx *operands)
 {
   emit_df_insn ((*fun) (operands[0], operands[1], operands[2],
-                        get_fpscr_rtx ()));
+                       get_fpscr_rtx ()));
 }
 \f
 /* ??? gcc does flow analysis strictly after common subexpression
@@ -7097,8 +7824,7 @@ f(double a)
    same basic block.  */
 
 static void 
-mark_use (x, reg_set_block)
-     rtx x, *reg_set_block;
+mark_use (rtx x, rtx *reg_set_block)
 {
   enum rtx_code code;
 
@@ -7150,7 +7876,7 @@ mark_use (x, reg_set_block)
     }
 }
 \f
-static rtx get_free_reg PARAMS ((HARD_REG_SET));
+static rtx get_free_reg (HARD_REG_SET);
 
 /* This function returns a register to use to load the address to load
    the fpscr from.  Currently it always returns r1 or r7, but when we are
@@ -7167,8 +7893,7 @@ __complex__ long long f (double d) { if (d == 0) return 2; else return 3; }
    the middle.  */
 
 static rtx
-get_free_reg (regs_live)
-     HARD_REG_SET regs_live;
+get_free_reg (HARD_REG_SET regs_live)
 {
   if (! TEST_HARD_REG_BIT (regs_live, 1))
     return gen_rtx_REG (Pmode, 1);
@@ -7184,9 +7909,7 @@ get_free_reg (regs_live)
 /* This function will set the fpscr from memory. 
    MODE is the mode we are setting it to.  */
 void
-fpscr_set_from_mem (mode, regs_live)
-     int mode;
-     HARD_REG_SET regs_live;
+fpscr_set_from_mem (int mode, HARD_REG_SET regs_live)
 {
   enum attr_fp_mode fp_mode = mode;
   rtx addr_reg = get_free_reg (regs_live);
@@ -7203,8 +7926,7 @@ fpscr_set_from_mem (mode, regs_live)
 #endif
 
 int
-sh_insn_length_adjustment (insn)
-     rtx insn;
+sh_insn_length_adjustment (rtx insn)
 {
   /* Instructions with unfilled delay slots take up an extra two bytes for
      the nop in the delay slot.  */
@@ -7287,8 +8009,7 @@ sh_insn_length_adjustment (insn)
 /* Return TRUE if X references a SYMBOL_REF or LABEL_REF whose symbol
    isn't protected by a PIC unspec.  */
 int
-nonpic_symbol_mentioned_p (x)
-     rtx x;
+nonpic_symbol_mentioned_p (rtx x)
 {
   register const char *fmt;
   register int i;
@@ -7310,7 +8031,7 @@ nonpic_symbol_mentioned_p (x)
          || XINT (x, 1) == UNSPEC_GOTTPOFF
          || XINT (x, 1) == UNSPEC_DTPOFF
          || XINT (x, 1) == UNSPEC_PLT))
-      return 0;
+    return 0;
 
   fmt = GET_RTX_FORMAT (GET_CODE (x));
   for (i = GET_RTX_LENGTH (GET_CODE (x)) - 1; i >= 0; i--)
@@ -7333,10 +8054,8 @@ nonpic_symbol_mentioned_p (x)
 /* Convert a non-PIC address in `orig' to a PIC address using @GOT or
    @GOTOFF in `reg'.  */
 rtx
-legitimize_pic_address (orig, mode, reg)
-     rtx orig;
-     enum machine_mode mode ATTRIBUTE_UNUSED;
-     rtx reg;
+legitimize_pic_address (rtx orig, enum machine_mode mode ATTRIBUTE_UNUSED,
+                       rtx reg)
 {
   if (tls_symbolic_operand (orig, Pmode))
     return orig;
@@ -7364,8 +8083,7 @@ legitimize_pic_address (orig, mode, reg)
 /* Mark the use of a constant in the literal table. If the constant
    has multiple labels, make it unique.  */
 static rtx
-mark_constant_pool_use (x)
-     rtx x;
+mark_constant_pool_use (rtx x)
 {
   rtx insn, lab, pattern;
 
@@ -7431,9 +8149,7 @@ mark_constant_pool_use (x)
    of an unconditional jump BRANCH2.  We only want to do this if the
    resulting branch will have a short displacement.  */
 int 
-sh_can_redirect_branch (branch1, branch2)
-     rtx branch1;
-     rtx branch2;
+sh_can_redirect_branch (rtx branch1, rtx branch2)
 {
   if (flag_expensive_optimizations && simplejump_p (branch2))
     {
@@ -7465,19 +8181,17 @@ sh_can_redirect_branch (branch1, branch2)
 
 /* Return nonzero if register old_reg can be renamed to register new_reg.  */
 int
-sh_hard_regno_rename_ok (old_reg, new_reg)
-     unsigned int old_reg ATTRIBUTE_UNUSED;
-     unsigned int new_reg;
+sh_hard_regno_rename_ok (unsigned int old_reg ATTRIBUTE_UNUSED,
+                        unsigned int new_reg)
 {
-
-/* Interrupt functions can only use registers that have already been
-   saved by the prologue, even if they would normally be
-   call-clobbered.  */
+  /* Interrupt functions can only use registers that have already been
+     saved by the prologue, even if they would normally be
+     call-clobbered.  */
 
   if (sh_cfun_interrupt_handler_p () && !regs_ever_live[new_reg])
-     return 0;
+    return 0;
 
-   return 1;
+  return 1;
 }
 
 /* Function to update the integer COST
@@ -7488,18 +8202,14 @@ sh_hard_regno_rename_ok (old_reg, new_reg)
    the same cost as a data-dependence.  The return value should be
    the new value for COST.  */
 static int
-sh_adjust_cost (insn, link, dep_insn, cost)
-     rtx insn;
-     rtx link ATTRIBUTE_UNUSED;
-     rtx dep_insn;
-     int cost;
+sh_adjust_cost (rtx insn, rtx link ATTRIBUTE_UNUSED, rtx dep_insn, int cost)
 {
   rtx reg, use_pat;
 
   if (TARGET_SHMEDIA)
     {
       /* On SHmedia, if the dependence is an anti-dependence or
-         output-dependence, there is no cost. */              
+         output-dependence, there is no cost.  */
       if (REG_NOTE_KIND (link) != 0)
         cost = 0;
 
@@ -7557,7 +8267,7 @@ sh_adjust_cost (insn, link, dep_insn, cost)
               && get_attr_type (insn) == TYPE_DYN_SHIFT
               && get_attr_any_int_load (dep_insn) == ANY_INT_LOAD_YES
               && reg_overlap_mentioned_p (SET_DEST (PATTERN (dep_insn)),
-                                          XEXP (SET_SRC (single_set(insn)),
+                                          XEXP (SET_SRC (single_set (insn)),
                                                 1)))
        cost++;
       /* When an LS group instruction with a latency of less than
@@ -7598,8 +8308,7 @@ sh_adjust_cost (insn, link, dep_insn, cost)
 /* Check if INSN is flow-dependent on DEP_INSN.  Can also be used to check
    if DEP_INSN is anti-flow dependent on INSN.  */
 static int
-flow_dependent_p (insn, dep_insn)
-     rtx insn, dep_insn;
+flow_dependent_p (rtx insn, rtx dep_insn)
 {
   rtx tmp = PATTERN (insn);
 
@@ -7609,10 +8318,7 @@ flow_dependent_p (insn, dep_insn)
 
 /* A helper function for flow_dependent_p called through note_stores.  */
 static void
-flow_dependent_p_1 (x, pat, data)
-     rtx x;
-     rtx pat ATTRIBUTE_UNUSED;
-     void *data;
+flow_dependent_p_1 (rtx x, rtx pat ATTRIBUTE_UNUSED, void *data)
 {
   rtx * pinsn = (rtx *) data;
 
@@ -7625,7 +8331,7 @@ flow_dependent_p_1 (x, pat, data)
    do not look like function calls to leaf_function_p.  Hence we must
    do this extra check.  */
 int
-sh_pr_n_sets ()
+sh_pr_n_sets (void)
 {
   return REG_N_SETS (TARGET_SHMEDIA ? PR_MEDIA_REG : PR_REG);
 }
@@ -7633,7 +8339,7 @@ sh_pr_n_sets ()
 /* This Function returns nonzero if the DFA based scheduler interface
    is to be used.  At present this is supported for the SH4 only.  */
 static int
-sh_use_dfa_interface()
+sh_use_dfa_interface (void)
 {
   if (TARGET_HARD_SH4)
     return 1;
@@ -7644,7 +8350,7 @@ sh_use_dfa_interface()
 /* This function returns "2" to indicate dual issue for the SH4
    processor.  To be used by the DFA pipeline description.  */
 static int
-sh_issue_rate()
+sh_issue_rate (void)
 {
   if (TARGET_SUPERSCALAR)
     return 2;
@@ -7652,19 +8358,330 @@ sh_issue_rate()
     return 1;
 }
 
+/* Functions for ready queue reordering for sched1.  */
+
+/* Get weight for mode for a set x.  */
+static short
+find_set_regmode_weight (rtx x, enum machine_mode mode)
+{
+  if (GET_CODE (x) == CLOBBER && register_operand (SET_DEST (x), mode))
+    return 1;
+  if (GET_CODE (x) == SET && register_operand (SET_DEST (x), mode))
+    {
+      if (GET_CODE (SET_DEST (x)) == REG)
+       {
+         if (!reg_mentioned_p (SET_DEST (x), SET_SRC (x)))
+           return 1;
+         else
+           return 0;
+       }
+      return 1;
+    }
+  return 0;
+}
+
+/* Get regmode weight for insn.  */
+static short
+find_insn_regmode_weight (rtx insn, enum machine_mode mode)
+{
+  short reg_weight = 0;
+  rtx x;
+
+  /* Increment weight for each register born here.  */
+  x = PATTERN (insn);
+  reg_weight += find_set_regmode_weight (x, mode);
+  if (GET_CODE (x) == PARALLEL)
+    {
+      int j;
+      for (j = XVECLEN (x, 0) - 1; j >= 0; j--)
+       {
+         x = XVECEXP (PATTERN (insn), 0, j);
+         reg_weight += find_set_regmode_weight (x, mode);
+       }
+    }
+  /* Decrement weight for each register that dies here.  */
+  for (x = REG_NOTES (insn); x; x = XEXP (x, 1))
+    {
+      if (REG_NOTE_KIND (x) == REG_DEAD || REG_NOTE_KIND (x) == REG_UNUSED)
+       {
+         rtx note = XEXP (x, 0);
+         if (GET_CODE (note) == REG && GET_MODE (note) == mode)
+           reg_weight--;
+       }
+    }
+  return reg_weight;
+}
+
+/* Calculate regmode weights for all insns of a basic block.  */
+static void
+find_regmode_weight (int b, enum machine_mode mode)
+{
+  rtx insn, next_tail, head, tail;
+
+  get_block_head_tail (b, &head, &tail);
+  next_tail = NEXT_INSN (tail);
+
+  for (insn = head; insn != next_tail; insn = NEXT_INSN (insn))
+    {
+      /* Handle register life information.  */
+      if (!INSN_P (insn))
+       continue;
+
+      if (mode == SFmode)
+       INSN_REGMODE_WEIGHT (insn, mode) =
+         find_insn_regmode_weight (insn, mode) + 2 * find_insn_regmode_weight (insn, DFmode);
+      else if (mode == SImode)
+       INSN_REGMODE_WEIGHT (insn, mode) =
+         find_insn_regmode_weight (insn, mode) + 2 * find_insn_regmode_weight (insn, DImode);
+    }
+}
+
+/* Comparison function for ready queue sorting.  */
+static int
+rank_for_reorder (const void *x, const void *y)
+{
+  rtx tmp = *(const rtx *) y;
+  rtx tmp2 = *(const rtx *) x;
+
+  /* The insn in a schedule group should be issued the first.  */
+  if (SCHED_GROUP_P (tmp) != SCHED_GROUP_P (tmp2))
+    return SCHED_GROUP_P (tmp2) ? 1 : -1;
+
+  /* If insns are equally good, sort by INSN_LUID (original insn order), This 
+     minimizes instruction movement, thus minimizing sched's effect on
+     register pressure.  */
+  return INSN_LUID (tmp) - INSN_LUID (tmp2);
+}
+
+/* Resort the array A in which only element at index N may be out of order.  */
+static void
+swap_reorder (rtx *a, int n)
+{
+  rtx insn = a[n - 1];
+  int i = n - 2;
+
+  while (i >= 0 && rank_for_reorder (a + i, &insn) >= 0)
+    {
+      a[i + 1] = a[i];
+      i -= 1;
+    }
+  a[i + 1] = insn;
+}
+
+#define SCHED_REORDER(READY, N_READY)                                  \
+  do                                                                   \
+    {                                                                  \
+      if ((N_READY) == 2)                                              \
+       swap_reorder (READY, N_READY);                                  \
+      else if ((N_READY) > 2)                                          \
+       qsort (READY, N_READY, sizeof (rtx), rank_for_reorder);         \
+    }                                                                  \
+  while (0)
+
+/* Sort the ready list READY by ascending priority, using the SCHED_REORDER
+   macro.  */
+static void
+ready_reorder (rtx *ready, int nready)
+{
+  SCHED_REORDER (ready, nready);
+}
+
+/* Calculate regmode weights for all insns of all basic block.  */
+static void
+sh_md_init_global (FILE *dump ATTRIBUTE_UNUSED,
+                  int verbose ATTRIBUTE_UNUSED,
+                  int old_max_uid)
+{
+  basic_block b;
+
+  regmode_weight[0] = (short *) xcalloc (old_max_uid, sizeof (short));
+  regmode_weight[1] = (short *) xcalloc (old_max_uid, sizeof (short));
+
+  FOR_EACH_BB_REVERSE (b)
+  {
+    find_regmode_weight (b->index, SImode);
+    find_regmode_weight (b->index, SFmode);
+  }
+
+  CURR_REGMODE_PRESSURE (SImode) = 0;
+  CURR_REGMODE_PRESSURE (SFmode) = 0;
+
+}
+
+/* Cleanup.  */
+static void
+sh_md_finish_global (FILE *dump ATTRIBUTE_UNUSED,
+                    int verbose ATTRIBUTE_UNUSED)
+{
+  if (regmode_weight[0])
+    {
+      free (regmode_weight[0]);
+      regmode_weight[0] = NULL;
+    }
+  if (regmode_weight[1])
+    {
+      free (regmode_weight[1]);
+      regmode_weight[1] = NULL;
+    }
+}
+
+/* Cache the can_issue_more so that we can return it from reorder2. Also,
+   keep count of register pressures on SImode and SFmode. */
+static int
+sh_variable_issue (FILE *dump ATTRIBUTE_UNUSED,
+                  int sched_verbose ATTRIBUTE_UNUSED,
+                  rtx insn,
+                  int can_issue_more)
+{
+  if (GET_CODE (PATTERN (insn)) != USE
+      && GET_CODE (PATTERN (insn)) != CLOBBER)
+    cached_can_issue_more = can_issue_more - 1;
+  else
+    cached_can_issue_more = can_issue_more;
+
+  if (reload_completed)
+    return cached_can_issue_more;
+
+  CURR_REGMODE_PRESSURE (SImode) += INSN_REGMODE_WEIGHT (insn, SImode);
+  CURR_REGMODE_PRESSURE (SFmode) += INSN_REGMODE_WEIGHT (insn, SFmode);
+
+  return cached_can_issue_more;
+}
+
+static void
+sh_md_init (FILE *dump ATTRIBUTE_UNUSED,
+           int verbose ATTRIBUTE_UNUSED,
+           int veclen ATTRIBUTE_UNUSED)
+{
+  CURR_REGMODE_PRESSURE (SImode) = 0;
+  CURR_REGMODE_PRESSURE (SFmode) = 0;
+}
+
+/* Some magic numbers.  */
+/* Pressure on register r0 can lead to spill failures. so avoid sched1 for
+   functions that already have high pressure on r0. */
+#define R0_MAX_LIFE_REGIONS 2
+#define R0_MAX_LIVE_LENGTH 12
+/* Register Pressure thresholds for SImode and SFmode registers.  */
+#define SIMODE_MAX_WEIGHT 5
+#define SFMODE_MAX_WEIGHT 10
+
+/* Return true if the pressure is high for MODE.  */
+static short
+high_pressure (enum machine_mode mode)
+{
+  /* Pressure on register r0 can lead to spill failures. so avoid sched1 for
+     functions that already have high pressure on r0. */
+  if ((REG_N_SETS (0) - REG_N_DEATHS (0)) >= R0_MAX_LIFE_REGIONS
+      && REG_LIVE_LENGTH (0) >= R0_MAX_LIVE_LENGTH)
+    return 1;
+
+  if (mode == SFmode)
+    return (CURR_REGMODE_PRESSURE (SFmode) > SFMODE_MAX_WEIGHT);
+  else
+    return (CURR_REGMODE_PRESSURE (SImode) > SIMODE_MAX_WEIGHT);
+}
+
+/* Reorder ready queue if register pressure is high.  */
+static int
+sh_reorder (FILE *dump ATTRIBUTE_UNUSED,
+           int sched_verbose ATTRIBUTE_UNUSED,
+           rtx *ready,
+           int *n_readyp,
+           int clock_var ATTRIBUTE_UNUSED)
+{
+  if (reload_completed)
+    return sh_issue_rate ();
+
+  if (high_pressure (SFmode) || high_pressure (SImode))
+    {
+      ready_reorder (ready, *n_readyp);
+    }
+
+  return sh_issue_rate ();
+}
+
+/* Skip cycles if the current register pressure is high.  */
+static int 
+sh_reorder2 (FILE *dump ATTRIBUTE_UNUSED,
+            int sched_verbose ATTRIBUTE_UNUSED,
+            rtx *ready ATTRIBUTE_UNUSED,
+            int *n_readyp ATTRIBUTE_UNUSED,
+            int clock_var ATTRIBUTE_UNUSED)
+{
+  if (reload_completed)
+    return cached_can_issue_more;
+
+  if (high_pressure(SFmode) || high_pressure (SImode)) 
+    skip_cycles = 1;
+
+  return cached_can_issue_more;
+}
+
+/* Skip cycles without sorting the ready queue. This will move insn from
+   Q->R. If this is the last cycle we are skipping; allow sorting of ready
+   queue by sh_reorder.  */ 
+
+/* Generally, skipping these many cycles are sufficient for all insns to move 
+   from Q -> R.  */ 
+#define MAX_SKIPS 8 
+
+static int
+sh_dfa_new_cycle (FILE *sched_dump ATTRIBUTE_UNUSED,
+                 int sched_verbose ATTRIBUTE_UNUSED,
+                 rtx insn ATTRIBUTE_UNUSED,
+                 int last_clock_var,
+                 int clock_var,
+                 int *sort_p)
+{
+  if (reload_completed)
+    return 0;
+
+  if (skip_cycles) 
+    {
+      if ((clock_var - last_clock_var) < MAX_SKIPS)
+       {
+         *sort_p = 0;
+         return 1;
+       }
+      /* If this is the last cycle we are skipping, allow reordering of R.  */
+      if ((clock_var - last_clock_var) == MAX_SKIPS)
+       {
+         *sort_p = 1;
+         return 1;
+       }
+    }
+
+  skip_cycles = 0;
+
+  return 0;
+}
+
 /* SHmedia requires registers for branches, so we can't generate new
    branches past reload.  */
 static bool
-sh_cannot_modify_jumps_p ()
+sh_cannot_modify_jumps_p (void)
 {
   return (TARGET_SHMEDIA && (reload_in_progress || reload_completed));
 }
 
+static int
+sh_target_reg_class (void)
+{
+  return TARGET_SHMEDIA ? TARGET_REGS : NO_REGS;
+}
+
 static bool
-sh_ms_bitfield_layout_p (record_type)
-     tree record_type ATTRIBUTE_UNUSED;
+sh_optimize_target_register_callee_saved (bool after_prologue_epilogue_gen)
 {
-  return TARGET_SH5;
+  return (shmedia_space_reserved_for_target_registers
+         && (! after_prologue_epilogue_gen || TARGET_SAVE_ALL_TARGET_REGS));
+}
+
+static bool
+sh_ms_bitfield_layout_p (tree record_type ATTRIBUTE_UNUSED)
+{
+  return (TARGET_SH5 || TARGET_HITACHI || sh_attr_renesas_p (record_type));
 }
 \f
 /* 
@@ -7684,8 +8701,7 @@ sh_ms_bitfield_layout_p (record_type)
    CXT is an RTX for the static chain value for the function.  */
 
 void
-sh_initialize_trampoline (tramp, fnaddr, cxt)
-     rtx tramp, fnaddr, cxt;
+sh_initialize_trampoline (rtx tramp, rtx fnaddr, rtx cxt)
 {
   if (TARGET_SHMEDIA64)
     {
@@ -7789,14 +8805,14 @@ sh_initialize_trampoline (tramp, fnaddr, cxt)
                                 movishori));
       emit_insn (gen_rotrdi3_mextr (quad0, quad0,
                                    GEN_INT (TARGET_LITTLE_ENDIAN ? 24 : 56)));
-      emit_insn (gen_ashldi3_media (quad0, quad0, GEN_INT (2)));
+      emit_insn (gen_ashldi3_media (quad0, quad0, const2_rtx));
       emit_move_insn (gen_rtx_MEM (DImode, tramp), quad0);
       emit_insn (gen_mshflo_w_x (gen_rtx_SUBREG (V4HImode, cxtload, 0),
                                 gen_rtx_SUBREG (V2HImode, cxt, 0),
                                 movishori));
       emit_insn (gen_rotrdi3_mextr (cxtload, cxtload,
                                    GEN_INT (TARGET_LITTLE_ENDIAN ? 24 : 56)));
-      emit_insn (gen_ashldi3_media (cxtload, cxtload, GEN_INT (2)));
+      emit_insn (gen_ashldi3_media (cxtload, cxtload, const2_rtx));
       if (TARGET_LITTLE_ENDIAN)
        {
          emit_insn (gen_mshflo_l_di (quad1, ptabs, cxtload));
@@ -7842,9 +8858,7 @@ sh_initialize_trampoline (tramp, fnaddr, cxt)
    own stack frame, so it must not pass pointers or references to
    these arguments to other functions by means of sibling calls.  */
 static bool
-sh_function_ok_for_sibcall (decl, exp)
-     tree decl;
-     tree exp ATTRIBUTE_UNUSED;
+sh_function_ok_for_sibcall (tree decl, tree exp ATTRIBUTE_UNUSED)
 {
   return (decl 
          && (! TARGET_SHCOMPACT
@@ -7912,10 +8926,10 @@ static const char signature_args[][4] =
 #define SH_BLTIN_PV 20
   { 0, 8 },
 };
-/* mcmv: operands considered unsigned. */
+/* mcmv: operands considered unsigned.  */
 /* mmulsum_wq, msad_ubq: result considered unsigned long long.  */
-/* mperm: control value considered unsigned int. */
-/* mshalds, mshard, mshards, mshlld, mshlrd: shift count is unsigned int. */
+/* mperm: control value considered unsigned int.  */
+/* mshalds, mshard, mshards, mshlld, mshlrd: shift count is unsigned int.  */
 /* mshards_q: returns signed short.  */
 /* nsb: takes long long arg, returns unsigned char.  */
 static const struct builtin_description bdesc[] =
@@ -8012,13 +9026,13 @@ static const struct builtin_description bdesc[] =
 };
 
 static void
-sh_media_init_builtins ()
+sh_media_init_builtins (void)
 {
   tree shared[SH_BLTIN_NUM_SHARED_SIGNATURES];
   const struct builtin_description *d;
 
   memset (shared, 0, sizeof shared);
-  for (d = bdesc; d - bdesc < (int) (sizeof bdesc / sizeof bdesc[0]); d++)
+  for (d = bdesc; d - bdesc < (int) ARRAY_SIZE (bdesc); d++)
     {
       tree type, arg_type;
       int signature = d->signature;
@@ -8066,7 +9080,7 @@ sh_media_init_builtins ()
 }
 
 static void
-sh_init_builtins ()
+sh_init_builtins (void)
 {
   if (TARGET_SHMEDIA)
     sh_media_init_builtins ();
@@ -8079,12 +9093,8 @@ sh_init_builtins ()
    IGNORE is nonzero if the value is to be ignored.  */
 
 static rtx
-sh_expand_builtin (exp, target, subtarget, mode, ignore)
-     tree exp;
-     rtx target;
-     rtx subtarget ATTRIBUTE_UNUSED;
-     enum machine_mode mode ATTRIBUTE_UNUSED;
-     int ignore;
+sh_expand_builtin (tree exp, rtx target, rtx subtarget ATTRIBUTE_UNUSED,
+                  enum machine_mode mode ATTRIBUTE_UNUSED, int ignore)
 {
   tree fndecl = TREE_OPERAND (TREE_OPERAND (exp, 0), 0);
   tree arglist = TREE_OPERAND (exp, 1);
@@ -8157,13 +9167,11 @@ sh_expand_builtin (exp, target, subtarget, mode, ignore)
 }
 
 void
-sh_expand_unop_v2sf (code, op0, op1)
-     enum rtx_code code;
-     rtx op0, op1;
+sh_expand_unop_v2sf (enum rtx_code code, rtx op0, rtx op1)
 {
   rtx sel0 = const0_rtx;
   rtx sel1 = const1_rtx;
-  rtx (*fn) PARAMS ((rtx, rtx, rtx, rtx, rtx)) = gen_unary_sf_op;
+  rtx (*fn) (rtx, rtx, rtx, rtx, rtx) = gen_unary_sf_op;
   rtx op = gen_rtx_fmt_e (code, SFmode, op1);
 
   emit_insn ((*fn) (op0, op1, op, sel0, sel0));
@@ -8171,13 +9179,11 @@ sh_expand_unop_v2sf (code, op0, op1)
 }
 
 void
-sh_expand_binop_v2sf (code, op0, op1, op2)
-     enum rtx_code code;
-     rtx op0, op1, op2;
+sh_expand_binop_v2sf (enum rtx_code code, rtx op0, rtx op1, rtx op2)
 {
   rtx sel0 = const0_rtx;
   rtx sel1 = const1_rtx;
-  rtx (*fn) PARAMS ((rtx, rtx, rtx, rtx, rtx, rtx, rtx, rtx))
+  rtx (*fn) (rtx, rtx, rtx, rtx, rtx, rtx, rtx, rtx)
     = gen_binary_sf_op;
   rtx op = gen_rtx_fmt_ee (code, SFmode, op1, op2);
 
@@ -8188,22 +9194,21 @@ sh_expand_binop_v2sf (code, op0, op1, op2)
 /* Return the class of registers for which a mode change from FROM to TO
    is invalid.  */
 bool
-sh_cannot_change_mode_class (from, to, class)
-     enum machine_mode from, to;
-     enum reg_class class;
+sh_cannot_change_mode_class (enum machine_mode from, enum machine_mode to,
+                            enum reg_class class)
 {
   if (GET_MODE_SIZE (from) != GET_MODE_SIZE (to))
     {
-       if (TARGET_LITTLE_ENDIAN)
-         {
-          if (GET_MODE_SIZE (to) < 8 || GET_MODE_SIZE (from) < 8)
-            return reg_classes_intersect_p (DF_REGS, class);
-        }
-       else
-        {
-          if (GET_MODE_SIZE (from) < 8)
-            return reg_classes_intersect_p (DF_HI_REGS, class);
-        }
+      if (TARGET_LITTLE_ENDIAN)
+       {
+         if (GET_MODE_SIZE (to) < 8 || GET_MODE_SIZE (from) < 8)
+           return reg_classes_intersect_p (DF_REGS, class);
+       }
+      else
+       {
+         if (GET_MODE_SIZE (from) < 8)
+           return reg_classes_intersect_p (DF_HI_REGS, class);
+       }
     }
   return 0;
 }
@@ -8213,9 +9218,7 @@ sh_cannot_change_mode_class (from, to, class)
    that label is used.  */
 
 void
-sh_mark_label (address, nuses)
-     rtx address;
-     int nuses;
+sh_mark_label (rtx address, int nuses)
 {
   if (GOTOFF_P (address))
     {
@@ -8238,28 +9241,30 @@ sh_mark_label (address, nuses)
    register information here is not used for SFmode.  */
 
 int
-sh_register_move_cost (mode, srcclass, dstclass)
-     enum machine_mode mode;
-     enum reg_class srcclass, dstclass;
+sh_register_move_cost (enum machine_mode mode,
+                      enum reg_class srcclass, enum reg_class dstclass)
 {
   if (dstclass == T_REGS || dstclass == PR_REGS)
     return 10;
 
+  if (dstclass == MAC_REGS && srcclass == MAC_REGS)
+    return 4;
+
   if (mode == SImode && ! TARGET_SHMEDIA && TARGET_FMOVD
       && REGCLASS_HAS_FP_REG (srcclass)
       && REGCLASS_HAS_FP_REG (dstclass))
     return 4;
 
   if ((REGCLASS_HAS_FP_REG (dstclass) && srcclass == MAC_REGS)
-      || (dstclass== MAC_REGS && REGCLASS_HAS_FP_REG (srcclass)))
+      || (dstclass == MAC_REGS && REGCLASS_HAS_FP_REG (srcclass)))
     return 9;
 
   if ((REGCLASS_HAS_FP_REG (dstclass)
        && REGCLASS_HAS_GENERAL_REG (srcclass))
       || (REGCLASS_HAS_GENERAL_REG (dstclass)
          && REGCLASS_HAS_FP_REG (srcclass)))
-   return ((TARGET_SHMEDIA ? 4 : TARGET_FMOVD ? 8 : 12)
-          * ((GET_MODE_SIZE (mode) + 7) / 8U));
+    return ((TARGET_SHMEDIA ? 4 : TARGET_FMOVD ? 8 : 12)
+           * ((GET_MODE_SIZE (mode) + 7) / 8U));
 
   if ((dstclass == FPUL_REGS
        && REGCLASS_HAS_GENERAL_REG (srcclass))
@@ -8293,20 +9298,26 @@ sh_register_move_cost (mode, srcclass, dstclass)
 /* Like register_operand, but take into account that SHMEDIA can use
    the constant zero like a general register.  */
 int
-sh_register_operand (op, mode)
-     rtx op;
-     enum machine_mode mode;
+sh_register_operand (rtx op, enum machine_mode mode)
 {
   if (op == CONST0_RTX (mode) && TARGET_SHMEDIA)
     return 1;
   return register_operand (op, mode);
 }
 
-static rtx emit_load_ptr PARAMS ((rtx, rtx));
+int
+cmpsi_operand (rtx op, enum machine_mode mode)
+{
+  if (GET_CODE (op) == REG && REGNO (op) == T_REG
+      && GET_MODE (op) == SImode)
+    return 1;
+  return arith_operand (op, mode);
+}
+
+static rtx emit_load_ptr (rtx, rtx);
 
 static rtx
-emit_load_ptr (reg, addr)
-     rtx reg, addr;
+emit_load_ptr (rtx reg, rtx addr)
 {
   rtx mem = gen_rtx_MEM (ptr_mode, addr);
 
@@ -8316,38 +9327,35 @@ emit_load_ptr (reg, addr)
 }
 
 void
-sh_output_mi_thunk (file, thunk_fndecl, delta, vcall_offset, function)
-     FILE *file;
-     tree thunk_fndecl ATTRIBUTE_UNUSED;
-     HOST_WIDE_INT delta;
-     HOST_WIDE_INT vcall_offset;
-     tree function;
+sh_output_mi_thunk (FILE *file, tree thunk_fndecl ATTRIBUTE_UNUSED,
+                   HOST_WIDE_INT delta, HOST_WIDE_INT vcall_offset,
+                   tree function)
 {
   CUMULATIVE_ARGS cum;
   int structure_value_byref = 0;
   rtx this, this_value, sibcall, insns, funexp;
   tree funtype = TREE_TYPE (function);
-  int simple_add
-    = (TARGET_SHMEDIA ? CONST_OK_FOR_J (delta) : CONST_OK_FOR_I (delta));
+  int simple_add = CONST_OK_FOR_ADD (delta);
   int did_load = 0;
   rtx scratch0, scratch1, scratch2;
 
   reload_completed = 1;
+  epilogue_completed = 1;
   no_new_pseudos = 1;
   current_function_uses_only_leaf_regs = 1;
 
-  emit_note (NULL, NOTE_INSN_PROLOGUE_END);
+  emit_note (NOTE_INSN_PROLOGUE_END);
 
   /* Find the "this" pointer.  We have such a wide range of ABIs for the
      SH that it's best to do this completely machine independently.
      "this" is passed as first argument, unless a structure return pointer 
      comes first, in which case "this" comes second.  */
-  INIT_CUMULATIVE_ARGS (cum, funtype, NULL_RTX, 0);
+  INIT_CUMULATIVE_ARGS (cum, funtype, NULL_RTX, 0, 1);
 #ifndef PCC_STATIC_STRUCT_RETURN
-  if (aggregate_value_p (TREE_TYPE (TREE_TYPE (function))))
+  if (aggregate_value_p (TREE_TYPE (TREE_TYPE (function)), function))
     structure_value_byref = 1;
 #endif /* not PCC_STATIC_STRUCT_RETURN */
-  if (structure_value_byref && struct_value_rtx == 0)
+  if (structure_value_byref && sh_struct_value_rtx (function, 0) == 0)
     { 
       tree ptype = build_pointer_type (TREE_TYPE (funtype));
 
@@ -8411,9 +9419,7 @@ sh_output_mi_thunk (file, thunk_fndecl, delta, vcall_offset, function)
          emit_move_insn (scratch1, GEN_INT (vcall_offset));
          offset_addr = gen_rtx_PLUS (Pmode, scratch0, scratch1);
        }
-      else if (TARGET_SHMEDIA
-              ? CONST_OK_FOR_J (vcall_offset)
-              : CONST_OK_FOR_I (vcall_offset))
+      else if (CONST_OK_FOR_ADD (vcall_offset))
        {
          emit_insn (gen_add2_insn (scratch0, GEN_INT (vcall_offset)));
          offset_addr = scratch0;
@@ -8428,7 +9434,7 @@ sh_output_mi_thunk (file, thunk_fndecl, delta, vcall_offset, function)
        abort (); /* FIXME */
       emit_load_ptr (scratch0, offset_addr);
 
-     if (Pmode != ptr_mode)
+      if (Pmode != ptr_mode)
        scratch0 = gen_rtx_TRUNCATE (ptr_mode, scratch0);
       emit_insn (gen_add2_insn (this, scratch0));
     }
@@ -8456,19 +9462,18 @@ sh_output_mi_thunk (file, thunk_fndecl, delta, vcall_offset, function)
 
   if (optimize > 0 && flag_schedule_insns_after_reload)
     {
-
-      find_basic_blocks (insns, max_reg_num (), rtl_dump_file);
-      life_analysis (insns, rtl_dump_file, PROP_FINAL);
+      find_basic_blocks (insns, max_reg_num (), dump_file);
+      life_analysis (insns, dump_file, PROP_FINAL);
 
       split_all_insns (1);
 
-      schedule_insns (rtl_dump_file);
+      schedule_insns (dump_file);
     }
 
   sh_reorg ();
 
   if (optimize > 0 && flag_delayed_branch)
-      dbr_schedule (insns, rtl_dump_file);
+    dbr_schedule (insns, dump_file);
   shorten_branches (insns);
   final_start_function (insns, file, 1);
   final (insns, file, 1, 0);
@@ -8484,6 +9489,7 @@ sh_output_mi_thunk (file, thunk_fndecl, delta, vcall_offset, function)
     }
 
   reload_completed = 0;
+  epilogue_completed = 0;
   no_new_pseudos = 0;
 }
 
@@ -8495,4 +9501,123 @@ function_symbol (const char *name)
   return sym;
 }
 
+/* Find the number of a general purpose register in S.  */
+static int
+scavenge_reg (HARD_REG_SET *s)
+{
+  int r;
+  for (r = FIRST_GENERAL_REG; r <= LAST_GENERAL_REG; r++)
+    if (TEST_HARD_REG_BIT (*s, r))
+      return r;
+  return -1;
+}
+
+rtx
+sh_get_pr_initial_val (void)
+{
+  rtx val;
+
+  /* ??? Unfortunately, get_hard_reg_initial_val doesn't always work for the
+     PR register on SHcompact, because it might be clobbered by the prologue.
+     We check first if that is known to be the case.  */
+  if (TARGET_SHCOMPACT
+      && ((current_function_args_info.call_cookie
+          & ~ CALL_COOKIE_RET_TRAMP (1))
+         || current_function_has_nonlocal_label))
+    return gen_rtx_MEM (SImode, return_address_pointer_rtx);
+
+  /* If we haven't finished rtl generation, there might be a nonlocal label
+     that we haven't seen yet.
+     ??? get_hard_reg_initial_val fails if it is called while no_new_pseudos
+     is set, unless it has been called before for the same register.  And even
+     then, we end in trouble if we didn't use the register in the same
+     basic block before.  So call get_hard_reg_initial_val now and wrap it
+     in an unspec if we might need to replace it.  */
+  /* ??? We also must do this for TARGET_SH1 in general, because otherwise
+     combine can put the pseudo returned by get_hard_reg_initial_val into
+     instructions that need a general purpose registers, which will fail to
+     be recognized when the pseudo becomes allocated to PR.  */
+  val
+    = get_hard_reg_initial_val (Pmode, TARGET_SHMEDIA ? PR_MEDIA_REG : PR_REG);
+  if (TARGET_SH1)
+    return gen_rtx_UNSPEC (SImode, gen_rtvec (1, val), UNSPEC_RA);
+  return val;
+}
+
+int
+sh_expand_t_scc (enum rtx_code code, rtx target)
+{
+  rtx result = target;
+  HOST_WIDE_INT val;
+
+  if (GET_CODE (sh_compare_op0) != REG || REGNO (sh_compare_op0) != T_REG
+      || GET_CODE (sh_compare_op1) != CONST_INT)
+    return 0;
+  if (GET_CODE (result) != REG)
+    result = gen_reg_rtx (SImode);
+  val = INTVAL (sh_compare_op1);
+  if ((code == EQ && val == 1) || (code == NE && val == 0))
+    emit_insn (gen_movt (result));
+  else if ((code == EQ && val == 0) || (code == NE && val == 1))
+    {
+      emit_insn (gen_rtx_CLOBBER (VOIDmode, result));
+      emit_insn (gen_subc (result, result, result));
+      emit_insn (gen_addsi3 (result, result, const1_rtx));
+    }
+  else if (code == EQ || code == NE)
+    emit_insn (gen_move_insn (result, GEN_INT (code == NE)));
+  else
+    return 0;
+  if (result != target)
+    emit_move_insn (target, result);
+  return 1;
+}
+
+/* INSN is an sfunc; return the rtx that describes the address used.  */
+static rtx
+extract_sfunc_addr (rtx insn)
+{
+  rtx pattern, part = NULL_RTX;
+  int len, i;
+
+  pattern = PATTERN (insn);
+  len = XVECLEN (pattern, 0);
+  for (i = 0; i < len; i++)
+    {
+      part = XVECEXP (pattern, 0, i);
+      if (GET_CODE (part) == USE && GET_MODE (XEXP (part, 0)) == Pmode
+         && GENERAL_REGISTER_P (true_regnum (XEXP (part, 0))))
+       return XEXP (part, 0);
+    }
+  if (GET_CODE (XVECEXP (pattern, 0, 0)) == UNSPEC_VOLATILE)
+    return XVECEXP (XVECEXP (pattern, 0, 0), 0, 1);
+  abort ();
+}
+
+/* Verify that the register in use_sfunc_addr still agrees with the address
+   used in the sfunc.  This prevents fill_slots_from_thread from changing
+   use_sfunc_addr.
+   INSN is the use_sfunc_addr instruction, and REG is the register it
+   guards.  */
+int
+check_use_sfunc_addr (rtx insn, rtx reg)
+{
+  /* Search for the sfunc.  It should really come right after INSN.  */
+  while ((insn = NEXT_INSN (insn)))
+    {
+      if (GET_CODE (insn) == CODE_LABEL || GET_CODE (insn) == JUMP_INSN)
+       break;
+      if (! INSN_P (insn))
+       continue;
+       
+      if (GET_CODE (PATTERN (insn)) == SEQUENCE)
+       insn = XVECEXP (PATTERN (insn), 0, 0);
+      if (GET_CODE (PATTERN (insn)) != PARALLEL
+         || get_attr_type (insn) != TYPE_SFUNC)
+       continue;
+      return rtx_equal_p (extract_sfunc_addr (insn), reg);
+    }
+  abort ();
+}
+
 #include "gt-sh.h"