• Main Page
  • Modules
  • Data Types
  • Files

osprey-gcc/gcc/config/sh/sh.c

Go to the documentation of this file.
00001 /* Output routines for GCC for Renesas / SuperH SH.
00002    Copyright (C) 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
00003    2003, 2004, 2005 Free Software Foundation, Inc.
00004    Contributed by Steve Chamberlain (sac@cygnus.com).
00005    Improved by Jim Wilson (wilson@cygnus.com).
00006 
00007 This file is part of GCC.
00008 
00009 GCC is free software; you can redistribute it and/or modify
00010 it under the terms of the GNU General Public License as published by
00011 the Free Software Foundation; either version 2, or (at your option)
00012 any later version.
00013 
00014 GCC is distributed in the hope that it will be useful,
00015 but WITHOUT ANY WARRANTY; without even the implied warranty of
00016 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00017 GNU General Public License for more details.
00018 
00019 You should have received a copy of the GNU General Public License
00020 along with GCC; see the file COPYING.  If not, write to
00021 the Free Software Foundation, 59 Temple Place - Suite 330,
00022 Boston, MA 02111-1307, USA.  */
00023 
00024 #include "config.h"
00025 #include "system.h"
00026 #include "coretypes.h"
00027 #include "tm.h"
00028 #include "insn-config.h"
00029 #include "rtl.h"
00030 #include "tree.h"
00031 #include "flags.h"
00032 #include "expr.h"
00033 #include "optabs.h"
00034 #include "function.h"
00035 #include "regs.h"
00036 #include "hard-reg-set.h"
00037 #include "output.h"
00038 #include "insn-attr.h"
00039 #include "toplev.h"
00040 #include "recog.h"
00041 #include "c-pragma.h"
00042 #include "integrate.h"
00043 #include "dwarf2.h"
00044 #include "tm_p.h"
00045 #include "target.h"
00046 #include "target-def.h"
00047 #include "real.h"
00048 #include "langhooks.h"
00049 #include "basic-block.h"
00050 #include "cfglayout.h"
00051 #include "intl.h"
00052 #include "sched-int.h"
00053 #include "ggc.h"
00054 #include "tree-gimple.h"
00055 
00056 
00057 int code_for_indirect_jump_scratch = CODE_FOR_indirect_jump_scratch;
00058 
00059 #define MSW (TARGET_LITTLE_ENDIAN ? 1 : 0)
00060 #define LSW (TARGET_LITTLE_ENDIAN ? 0 : 1)
00061 
00062 /* These are some macros to abstract register modes.  */
00063 #define CONST_OK_FOR_ADD(size) \
00064   (TARGET_SHMEDIA ? CONST_OK_FOR_I10 (size) : CONST_OK_FOR_I08 (size))
00065 #define GEN_MOV (*(TARGET_SHMEDIA64 ? gen_movdi : gen_movsi))
00066 #define GEN_ADD3 (*(TARGET_SHMEDIA64 ? gen_adddi3 : gen_addsi3))
00067 #define GEN_SUB3 (*(TARGET_SHMEDIA64 ? gen_subdi3 : gen_subsi3))
00068 
00069 /* Set to 1 by expand_prologue() when the function is an interrupt handler.  */
00070 int current_function_interrupt;
00071 
00072 /* ??? The pragma interrupt support will not work for SH3.  */
00073 /* This is set by #pragma interrupt and #pragma trapa, and causes gcc to
00074    output code for the next function appropriate for an interrupt handler.  */
00075 int pragma_interrupt;
00076 
00077 /* This is set by the trap_exit attribute for functions.   It specifies
00078    a trap number to be used in a trapa instruction at function exit
00079    (instead of an rte instruction).  */
00080 int trap_exit;
00081 
00082 /* This is used by the sp_switch attribute for functions.  It specifies
00083    a variable holding the address of the stack the interrupt function
00084    should switch to/from at entry/exit.  */
00085 rtx sp_switch;
00086 
00087 /* This is set by #pragma trapa, and is similar to the above, except that
00088    the compiler doesn't emit code to preserve all registers.  */
00089 static int pragma_trapa;
00090 
00091 /* This is set by #pragma nosave_low_regs.  This is useful on the SH3,
00092    which has a separate set of low regs for User and Supervisor modes.
00093    This should only be used for the lowest level of interrupts.  Higher levels
00094    of interrupts must save the registers in case they themselves are
00095    interrupted.  */
00096 int pragma_nosave_low_regs;
00097 
00098 /* This is used for communication between TARGET_SETUP_INCOMING_VARARGS and
00099    sh_expand_prologue.  */
00100 int current_function_anonymous_args;
00101 
00102 /* Global variables for machine-dependent things.  */
00103 
00104 /* Which cpu are we scheduling for.  */
00105 enum processor_type sh_cpu;
00106 
00107 /* Definitions used in ready queue reordering for first scheduling pass.  */
00108 
00109 /* Reg weights arrays for modes SFmode and SImode, indexed by insn LUID.  */
00110 static short *regmode_weight[2];
00111 
00112 /* Total SFmode and SImode weights of scheduled insns.  */
00113 static int curr_regmode_pressure[2];
00114 
00115 /* If true, skip cycles for Q -> R movement.  */
00116 static int skip_cycles = 0;
00117 
00118 /* Cached value of can_issue_more. This is cached in sh_variable_issue hook
00119    and returned from sh_reorder2.  */
00120 static short cached_can_issue_more;
00121 
00122 /* Saved operands from the last compare to use when we generate an scc
00123    or bcc insn.  */
00124 
00125 rtx sh_compare_op0;
00126 rtx sh_compare_op1;
00127 
00128 /* Provides the class number of the smallest class containing
00129    reg number.  */
00130 
00131 enum reg_class regno_reg_class[FIRST_PSEUDO_REGISTER] =
00132 {
00133   R0_REGS, GENERAL_REGS, GENERAL_REGS, GENERAL_REGS,
00134   GENERAL_REGS, GENERAL_REGS, GENERAL_REGS, GENERAL_REGS,
00135   GENERAL_REGS, GENERAL_REGS, GENERAL_REGS, GENERAL_REGS,
00136   GENERAL_REGS, GENERAL_REGS, GENERAL_REGS, GENERAL_REGS,
00137   GENERAL_REGS, GENERAL_REGS, GENERAL_REGS, GENERAL_REGS,
00138   GENERAL_REGS, GENERAL_REGS, GENERAL_REGS, GENERAL_REGS,
00139   GENERAL_REGS, GENERAL_REGS, GENERAL_REGS, GENERAL_REGS,
00140   GENERAL_REGS, GENERAL_REGS, GENERAL_REGS, GENERAL_REGS,
00141   GENERAL_REGS, GENERAL_REGS, GENERAL_REGS, GENERAL_REGS,
00142   GENERAL_REGS, GENERAL_REGS, GENERAL_REGS, GENERAL_REGS,
00143   GENERAL_REGS, GENERAL_REGS, GENERAL_REGS, GENERAL_REGS,
00144   GENERAL_REGS, GENERAL_REGS, GENERAL_REGS, GENERAL_REGS,
00145   GENERAL_REGS, GENERAL_REGS, GENERAL_REGS, GENERAL_REGS,
00146   GENERAL_REGS, GENERAL_REGS, GENERAL_REGS, GENERAL_REGS,
00147   GENERAL_REGS, GENERAL_REGS, GENERAL_REGS, GENERAL_REGS,
00148   GENERAL_REGS, GENERAL_REGS, GENERAL_REGS, GENERAL_REGS,
00149   FP0_REGS,FP_REGS, FP_REGS, FP_REGS,
00150   FP_REGS, FP_REGS, FP_REGS, FP_REGS,
00151   FP_REGS, FP_REGS, FP_REGS, FP_REGS,
00152   FP_REGS, FP_REGS, FP_REGS, FP_REGS,
00153   FP_REGS, FP_REGS, FP_REGS, FP_REGS,
00154   FP_REGS, FP_REGS, FP_REGS, FP_REGS,
00155   FP_REGS, FP_REGS, FP_REGS, FP_REGS,
00156   FP_REGS, FP_REGS, FP_REGS, FP_REGS,
00157   FP_REGS, FP_REGS, FP_REGS, FP_REGS,
00158   FP_REGS, FP_REGS, FP_REGS, FP_REGS,
00159   FP_REGS, FP_REGS, FP_REGS, FP_REGS,
00160   FP_REGS, FP_REGS, FP_REGS, FP_REGS,
00161   FP_REGS, FP_REGS, FP_REGS, FP_REGS,
00162   FP_REGS, FP_REGS, FP_REGS, FP_REGS,
00163   FP_REGS, FP_REGS, FP_REGS, FP_REGS,
00164   FP_REGS, FP_REGS, FP_REGS, FP_REGS,
00165   TARGET_REGS, TARGET_REGS, TARGET_REGS, TARGET_REGS,
00166   TARGET_REGS, TARGET_REGS, TARGET_REGS, TARGET_REGS,
00167   DF_REGS, DF_REGS, DF_REGS, DF_REGS,
00168   DF_REGS, DF_REGS, DF_REGS, DF_REGS,
00169   NO_REGS, GENERAL_REGS, PR_REGS, T_REGS,
00170   MAC_REGS, MAC_REGS, FPUL_REGS, FPSCR_REGS,
00171   GENERAL_REGS,
00172 };
00173 
00174 char sh_register_names[FIRST_PSEUDO_REGISTER] \
00175   [MAX_REGISTER_NAME_LENGTH + 1] = SH_REGISTER_NAMES_INITIALIZER;
00176 
00177 char sh_additional_register_names[ADDREGNAMES_SIZE] \
00178   [MAX_ADDITIONAL_REGISTER_NAME_LENGTH + 1]
00179   = SH_ADDITIONAL_REGISTER_NAMES_INITIALIZER;
00180 
00181 /* Provide reg_class from a letter such as appears in the machine
00182    description.  *: target independently reserved letter.
00183    reg_class_from_letter['e' - 'a'] is set to NO_REGS for TARGET_FMOVD.  */
00184 
00185 enum reg_class reg_class_from_letter[] =
00186 {
00187   /* a */ ALL_REGS,  /* b */ TARGET_REGS, /* c */ FPSCR_REGS, /* d */ DF_REGS,
00188   /* e */ FP_REGS,   /* f */ FP_REGS,  /* g **/ NO_REGS,     /* h */ NO_REGS,
00189   /* i **/ NO_REGS,  /* j */ NO_REGS,  /* k */ SIBCALL_REGS, /* l */ PR_REGS,
00190   /* m **/ NO_REGS,  /* n **/ NO_REGS, /* o **/ NO_REGS,     /* p **/ NO_REGS,
00191   /* q */ NO_REGS,   /* r **/ NO_REGS, /* s **/ NO_REGS,     /* t */ T_REGS,
00192   /* u */ NO_REGS,   /* v */ NO_REGS,  /* w */ FP0_REGS,     /* x */ MAC_REGS,
00193   /* y */ FPUL_REGS, /* z */ R0_REGS
00194 };
00195 
00196 int assembler_dialect;
00197 
00198 static bool shmedia_space_reserved_for_target_registers;
00199 
00200 static void split_branches (rtx);
00201 static int branch_dest (rtx);
00202 static void force_into (rtx, rtx);
00203 static void print_slot (rtx);
00204 static rtx add_constant (rtx, enum machine_mode, rtx);
00205 static void dump_table (rtx, rtx);
00206 static int hi_const (rtx);
00207 static int broken_move (rtx);
00208 static int mova_p (rtx);
00209 static rtx find_barrier (int, rtx, rtx);
00210 static int noncall_uses_reg (rtx, rtx, rtx *);
00211 static rtx gen_block_redirect (rtx, int, int);
00212 static void sh_reorg (void);
00213 static void output_stack_adjust (int, rtx, int, HARD_REG_SET *);
00214 static rtx frame_insn (rtx);
00215 static rtx push (int);
00216 static void pop (int);
00217 static void push_regs (HARD_REG_SET *, int);
00218 static int calc_live_regs (HARD_REG_SET *);
00219 static void mark_use (rtx, rtx *);
00220 static HOST_WIDE_INT rounded_frame_size (int);
00221 static rtx mark_constant_pool_use (rtx);
00222 const struct attribute_spec sh_attribute_table[];
00223 static tree sh_handle_interrupt_handler_attribute (tree *, tree, tree, int, bool *);
00224 static tree sh_handle_sp_switch_attribute (tree *, tree, tree, int, bool *);
00225 static tree sh_handle_trap_exit_attribute (tree *, tree, tree, int, bool *);
00226 static tree sh_handle_renesas_attribute (tree *, tree, tree, int, bool *);
00227 static void sh_output_function_epilogue (FILE *, HOST_WIDE_INT);
00228 static void sh_insert_attributes (tree, tree *);
00229 static int sh_adjust_cost (rtx, rtx, rtx, int);
00230 static int sh_issue_rate (void);
00231 static int sh_dfa_new_cycle (FILE *, int, rtx, int, int, int *sort_p);
00232 static short find_set_regmode_weight (rtx, enum machine_mode);
00233 static short find_insn_regmode_weight (rtx, enum machine_mode);
00234 static void find_regmode_weight (int, enum machine_mode);
00235 static void  sh_md_init_global (FILE *, int, int);
00236 static void  sh_md_finish_global (FILE *, int);
00237 static int rank_for_reorder (const void *, const void *);
00238 static void swap_reorder (rtx *, int);
00239 static void ready_reorder (rtx *, int);
00240 static short high_pressure (enum machine_mode);
00241 static int sh_reorder (FILE *, int, rtx *, int *, int);
00242 static int sh_reorder2 (FILE *, int, rtx *, int *, int);
00243 static void sh_md_init (FILE *, int, int);
00244 static int sh_variable_issue (FILE *, int, rtx, int);
00245 
00246 static bool sh_function_ok_for_sibcall (tree, tree);
00247 
00248 static bool sh_cannot_modify_jumps_p (void);
00249 static int sh_target_reg_class (void);
00250 static bool sh_optimize_target_register_callee_saved (bool);
00251 static bool sh_ms_bitfield_layout_p (tree);
00252 
00253 static void sh_init_builtins (void);
00254 static void sh_media_init_builtins (void);
00255 static rtx sh_expand_builtin (tree, rtx, rtx, enum machine_mode, int);
00256 static void sh_output_mi_thunk (FILE *, tree, HOST_WIDE_INT, HOST_WIDE_INT, tree);
00257 static void sh_file_start (void);
00258 static int flow_dependent_p (rtx, rtx);
00259 static void flow_dependent_p_1 (rtx, rtx, void *);
00260 static int shiftcosts (rtx);
00261 static int andcosts (rtx);
00262 static int addsubcosts (rtx);
00263 static int multcosts (rtx);
00264 static bool unspec_caller_rtx_p (rtx);
00265 static bool sh_cannot_copy_insn_p (rtx);
00266 static bool sh_rtx_costs (rtx, int, int, int *);
00267 static int sh_address_cost (rtx);
00268 static int shmedia_target_regs_stack_space (HARD_REG_SET *);
00269 static int shmedia_reserve_space_for_target_registers_p (int, HARD_REG_SET *);
00270 static int shmedia_target_regs_stack_adjust (HARD_REG_SET *);
00271 static int scavenge_reg (HARD_REG_SET *s);
00272 struct save_schedule_s;
00273 static struct save_entry_s *sh5_schedule_saves (HARD_REG_SET *,
00274             struct save_schedule_s *, int);
00275 
00276 static rtx sh_struct_value_rtx (tree, int);
00277 static bool sh_return_in_memory (tree, tree);
00278 static rtx sh_builtin_saveregs (void);
00279 static void sh_setup_incoming_varargs (CUMULATIVE_ARGS *, enum machine_mode, tree, int *, int);
00280 static bool sh_strict_argument_naming (CUMULATIVE_ARGS *);
00281 static bool sh_pretend_outgoing_varargs_named (CUMULATIVE_ARGS *);
00282 static tree sh_build_builtin_va_list (void);
00283 static tree sh_gimplify_va_arg_expr (tree, tree, tree *, tree *);
00284 static bool sh_pass_by_reference (CUMULATIVE_ARGS *, enum machine_mode,
00285           tree, bool);
00286 static bool sh_callee_copies (CUMULATIVE_ARGS *, enum machine_mode,
00287             tree, bool);
00288 static int sh_arg_partial_bytes (CUMULATIVE_ARGS *, enum machine_mode,
00289                tree, bool);
00290 static int sh_dwarf_calling_convention (tree);
00291 static int hard_regs_intersect_p (HARD_REG_SET *, HARD_REG_SET *);
00292 
00293 
00294 /* Initialize the GCC target structure.  */
00295 #undef TARGET_ATTRIBUTE_TABLE
00296 #define TARGET_ATTRIBUTE_TABLE sh_attribute_table
00297 
00298 /* The next two are used for debug info when compiling with -gdwarf.  */
00299 #undef TARGET_ASM_UNALIGNED_HI_OP
00300 #define TARGET_ASM_UNALIGNED_HI_OP "\t.uaword\t"
00301 #undef TARGET_ASM_UNALIGNED_SI_OP
00302 #define TARGET_ASM_UNALIGNED_SI_OP "\t.ualong\t"
00303 
00304 /* These are NULLed out on non-SH5 in OVERRIDE_OPTIONS.  */
00305 #undef TARGET_ASM_UNALIGNED_DI_OP
00306 #define TARGET_ASM_UNALIGNED_DI_OP "\t.uaquad\t"
00307 #undef TARGET_ASM_ALIGNED_DI_OP
00308 #define TARGET_ASM_ALIGNED_DI_OP "\t.quad\t"
00309 
00310 #undef TARGET_ASM_FUNCTION_EPILOGUE
00311 #define TARGET_ASM_FUNCTION_EPILOGUE sh_output_function_epilogue
00312 
00313 #undef TARGET_ASM_OUTPUT_MI_THUNK
00314 #define TARGET_ASM_OUTPUT_MI_THUNK sh_output_mi_thunk
00315 
00316 #undef TARGET_ASM_CAN_OUTPUT_MI_THUNK
00317 #define TARGET_ASM_CAN_OUTPUT_MI_THUNK hook_bool_tree_hwi_hwi_tree_true
00318 
00319 #undef TARGET_ASM_FILE_START
00320 #define TARGET_ASM_FILE_START sh_file_start
00321 #undef TARGET_ASM_FILE_START_FILE_DIRECTIVE
00322 #define TARGET_ASM_FILE_START_FILE_DIRECTIVE true
00323 
00324 #undef TARGET_INSERT_ATTRIBUTES
00325 #define TARGET_INSERT_ATTRIBUTES sh_insert_attributes
00326 
00327 #undef TARGET_SCHED_ADJUST_COST
00328 #define TARGET_SCHED_ADJUST_COST sh_adjust_cost
00329 
00330 #undef TARGET_SCHED_ISSUE_RATE
00331 #define TARGET_SCHED_ISSUE_RATE sh_issue_rate
00332 
00333 /* The next 5 hooks have been implemented for reenabling sched1.  With the
00334    help of these macros we are limiting the movement of insns in sched1 to
00335    reduce the register pressure.  The overall idea is to keep count of SImode
00336    and SFmode regs required by already scheduled insns. When these counts
00337    cross some threshold values; give priority to insns that free registers.
00338    The insn that frees registers is most likely to be the insn with lowest
00339    LUID (original insn order); but such an insn might be there in the stalled
00340    queue (Q) instead of the ready queue (R).  To solve this, we skip cycles
00341    upto a max of 8 cycles so that such insns may move from Q -> R.
00342 
00343    The description of the hooks are as below:
00344 
00345    TARGET_SCHED_INIT_GLOBAL: Added a new target hook in the generic
00346    scheduler; it is called inside the sched_init function just after
00347    find_insn_reg_weights function call. It is used to calculate the SImode
00348    and SFmode weights of insns of basic blocks; much similar to what
00349    find_insn_reg_weights does.
00350    TARGET_SCHED_FINISH_GLOBAL: Corresponding cleanup hook.
00351 
00352    TARGET_SCHED_DFA_NEW_CYCLE: Skip cycles if high register pressure is
00353    indicated by TARGET_SCHED_REORDER2; doing this may move insns from
00354    (Q)->(R).
00355 
00356    TARGET_SCHED_REORDER: If the register pressure for SImode or SFmode is
00357    high; reorder the ready queue so that the insn with lowest LUID will be
00358    issued next.
00359 
00360    TARGET_SCHED_REORDER2: If the register pressure is high, indicate to
00361    TARGET_SCHED_DFA_NEW_CYCLE to skip cycles.
00362 
00363    TARGET_SCHED_VARIABLE_ISSUE: Cache the value of can_issue_more so that it
00364    can be returned from TARGET_SCHED_REORDER2.
00365 
00366    TARGET_SCHED_INIT: Reset the register pressure counting variables.  */
00367 
00368 #undef TARGET_SCHED_DFA_NEW_CYCLE
00369 #define TARGET_SCHED_DFA_NEW_CYCLE sh_dfa_new_cycle
00370 
00371 #undef TARGET_SCHED_INIT_GLOBAL
00372 #define TARGET_SCHED_INIT_GLOBAL sh_md_init_global
00373 
00374 #undef TARGET_SCHED_FINISH_GLOBAL
00375 #define TARGET_SCHED_FINISH_GLOBAL sh_md_finish_global
00376 
00377 #undef TARGET_SCHED_VARIABLE_ISSUE
00378 #define TARGET_SCHED_VARIABLE_ISSUE sh_variable_issue
00379 
00380 #undef TARGET_SCHED_REORDER
00381 #define TARGET_SCHED_REORDER sh_reorder
00382 
00383 #undef TARGET_SCHED_REORDER2
00384 #define TARGET_SCHED_REORDER2 sh_reorder2
00385 
00386 #undef TARGET_SCHED_INIT
00387 #define TARGET_SCHED_INIT sh_md_init
00388 
00389 #undef TARGET_CANNOT_MODIFY_JUMPS_P
00390 #define TARGET_CANNOT_MODIFY_JUMPS_P sh_cannot_modify_jumps_p
00391 #undef TARGET_BRANCH_TARGET_REGISTER_CLASS
00392 #define TARGET_BRANCH_TARGET_REGISTER_CLASS sh_target_reg_class
00393 #undef TARGET_BRANCH_TARGET_REGISTER_CALLEE_SAVED
00394 #define TARGET_BRANCH_TARGET_REGISTER_CALLEE_SAVED \
00395  sh_optimize_target_register_callee_saved
00396 
00397 #undef TARGET_MS_BITFIELD_LAYOUT_P
00398 #define TARGET_MS_BITFIELD_LAYOUT_P sh_ms_bitfield_layout_p
00399 
00400 #undef TARGET_INIT_BUILTINS
00401 #define TARGET_INIT_BUILTINS sh_init_builtins
00402 #undef TARGET_EXPAND_BUILTIN
00403 #define TARGET_EXPAND_BUILTIN sh_expand_builtin
00404 
00405 #undef TARGET_FUNCTION_OK_FOR_SIBCALL
00406 #define TARGET_FUNCTION_OK_FOR_SIBCALL sh_function_ok_for_sibcall
00407 
00408 #undef TARGET_CANNOT_COPY_INSN_P
00409 #define TARGET_CANNOT_COPY_INSN_P sh_cannot_copy_insn_p
00410 #undef TARGET_RTX_COSTS
00411 #define TARGET_RTX_COSTS sh_rtx_costs
00412 #undef TARGET_ADDRESS_COST
00413 #define TARGET_ADDRESS_COST sh_address_cost
00414 
00415 #undef TARGET_MACHINE_DEPENDENT_REORG
00416 #define TARGET_MACHINE_DEPENDENT_REORG sh_reorg
00417 
00418 #ifdef HAVE_AS_TLS
00419 #undef TARGET_HAVE_TLS
00420 #define TARGET_HAVE_TLS true
00421 #endif
00422 
00423 #undef TARGET_PROMOTE_PROTOTYPES
00424 #define TARGET_PROMOTE_PROTOTYPES sh_promote_prototypes
00425 #undef TARGET_PROMOTE_FUNCTION_ARGS
00426 #define TARGET_PROMOTE_FUNCTION_ARGS sh_promote_prototypes
00427 #undef TARGET_PROMOTE_FUNCTION_RETURN
00428 #define TARGET_PROMOTE_FUNCTION_RETURN sh_promote_prototypes
00429 
00430 #undef TARGET_STRUCT_VALUE_RTX
00431 #define TARGET_STRUCT_VALUE_RTX sh_struct_value_rtx
00432 #undef TARGET_RETURN_IN_MEMORY
00433 #define TARGET_RETURN_IN_MEMORY sh_return_in_memory
00434 
00435 #undef TARGET_EXPAND_BUILTIN_SAVEREGS
00436 #define TARGET_EXPAND_BUILTIN_SAVEREGS sh_builtin_saveregs
00437 #undef TARGET_SETUP_INCOMING_VARARGS
00438 #define TARGET_SETUP_INCOMING_VARARGS sh_setup_incoming_varargs
00439 #undef TARGET_STRICT_ARGUMENT_NAMING
00440 #define TARGET_STRICT_ARGUMENT_NAMING sh_strict_argument_naming
00441 #undef TARGET_PRETEND_OUTGOING_VARARGS_NAMED
00442 #define TARGET_PRETEND_OUTGOING_VARARGS_NAMED sh_pretend_outgoing_varargs_named
00443 #undef TARGET_MUST_PASS_IN_STACK
00444 #define TARGET_MUST_PASS_IN_STACK must_pass_in_stack_var_size
00445 #undef TARGET_PASS_BY_REFERENCE
00446 #define TARGET_PASS_BY_REFERENCE sh_pass_by_reference
00447 #undef TARGET_CALLEE_COPIES
00448 #define TARGET_CALLEE_COPIES sh_callee_copies
00449 #undef TARGET_ARG_PARTIAL_BYTES
00450 #define TARGET_ARG_PARTIAL_BYTES sh_arg_partial_bytes
00451 
00452 #undef TARGET_BUILD_BUILTIN_VA_LIST
00453 #define TARGET_BUILD_BUILTIN_VA_LIST sh_build_builtin_va_list
00454 #undef TARGET_GIMPLIFY_VA_ARG_EXPR
00455 #define TARGET_GIMPLIFY_VA_ARG_EXPR sh_gimplify_va_arg_expr
00456 
00457 #undef TARGET_VECTOR_MODE_SUPPORTED_P
00458 #define TARGET_VECTOR_MODE_SUPPORTED_P sh_vector_mode_supported_p
00459 
00460 #undef TARGET_PCH_VALID_P
00461 #define TARGET_PCH_VALID_P sh_pch_valid_p
00462 
00463 #undef TARGET_DWARF_CALLING_CONVENTION
00464 #define TARGET_DWARF_CALLING_CONVENTION sh_dwarf_calling_convention
00465 
00466 /* Return regmode weight for insn.  */
00467 #define INSN_REGMODE_WEIGHT(INSN, MODE)  regmode_weight[((MODE) == SImode) ? 0 : 1][INSN_UID (INSN)]
00468 
00469 /* Return current register pressure for regmode.  */
00470 #define CURR_REGMODE_PRESSURE(MODE)   curr_regmode_pressure[((MODE) == SImode) ? 0 : 1]
00471 
00472 #ifdef SYMBIAN
00473 
00474 #undef  TARGET_ENCODE_SECTION_INFO
00475 #define TARGET_ENCODE_SECTION_INFO  sh_symbian_encode_section_info
00476 #undef  TARGET_STRIP_NAME_ENCODING
00477 #define TARGET_STRIP_NAME_ENCODING  sh_symbian_strip_name_encoding
00478 #undef  TARGET_CXX_IMPORT_EXPORT_CLASS
00479 #define TARGET_CXX_IMPORT_EXPORT_CLASS  symbian_import_export_class
00480 
00481 #endif /* SYMBIAN */
00482 
00483 struct gcc_target targetm = TARGET_INITIALIZER;
00484 
00485 /* Print the operand address in x to the stream.  */
00486 
00487 void
00488 print_operand_address (FILE *stream, rtx x)
00489 {
00490   switch (GET_CODE (x))
00491     {
00492     case REG:
00493     case SUBREG:
00494       fprintf (stream, "@%s", reg_names[true_regnum (x)]);
00495       break;
00496 
00497     case PLUS:
00498       {
00499   rtx base = XEXP (x, 0);
00500   rtx index = XEXP (x, 1);
00501 
00502   switch (GET_CODE (index))
00503     {
00504     case CONST_INT:
00505       fprintf (stream, "@(%d,%s)", (int) INTVAL (index),
00506          reg_names[true_regnum (base)]);
00507       break;
00508 
00509     case REG:
00510     case SUBREG:
00511       {
00512         int base_num = true_regnum (base);
00513         int index_num = true_regnum (index);
00514 
00515         fprintf (stream, "@(r0,%s)",
00516            reg_names[MAX (base_num, index_num)]);
00517         break;
00518       }
00519 
00520     default:
00521       debug_rtx (x);
00522       abort ();
00523     }
00524       }
00525       break;
00526 
00527     case PRE_DEC:
00528       fprintf (stream, "@-%s", reg_names[true_regnum (XEXP (x, 0))]);
00529       break;
00530 
00531     case POST_INC:
00532       fprintf (stream, "@%s+", reg_names[true_regnum (XEXP (x, 0))]);
00533       break;
00534 
00535     default:
00536       x = mark_constant_pool_use (x);
00537       output_addr_const (stream, x);
00538       break;
00539     }
00540 }
00541 
00542 /* Print operand x (an rtx) in assembler syntax to file stream
00543    according to modifier code.
00544 
00545    '.'  print a .s if insn needs delay slot
00546    ','  print LOCAL_LABEL_PREFIX
00547    '@'  print trap, rte or rts depending upon pragma interruptness
00548    '#'  output a nop if there is nothing to put in the delay slot
00549    '''  print likelihood suffix (/u for unlikely).
00550    'O'  print a constant without the #
00551    'R'  print the LSW of a dp value - changes if in little endian
00552    'S'  print the MSW of a dp value - changes if in little endian
00553    'T'  print the next word of a dp value - same as 'R' in big endian mode.
00554    'M'  print an `x' if `m' will print `base,index'.
00555    'N'  print 'r63' if the operand is (const_int 0).
00556    'd'  print a V2SF reg as dN instead of fpN.
00557    'm'  print a pair `base,offset' or `base,index', for LD and ST.
00558    'u'  prints the lowest 16 bits of CONST_INT, as an unsigned value.
00559    'o'  output an operator.  */
00560 
00561 void
00562 print_operand (FILE *stream, rtx x, int code)
00563 {
00564   switch (code)
00565     {
00566     case '.':
00567       if (final_sequence
00568     && ! INSN_ANNULLED_BRANCH_P (XVECEXP (final_sequence, 0, 0))
00569     && get_attr_length (XVECEXP (final_sequence, 0, 1)))
00570   fprintf (stream, ASSEMBLER_DIALECT ? "/s" : ".s");
00571       break;
00572     case ',':
00573       fprintf (stream, "%s", LOCAL_LABEL_PREFIX);
00574       break;
00575     case '@':
00576       if (trap_exit)
00577   fprintf (stream, "trapa #%d", trap_exit);
00578       else if (sh_cfun_interrupt_handler_p ())
00579   fprintf (stream, "rte");
00580       else
00581   fprintf (stream, "rts");
00582       break;
00583     case '#':
00584       /* Output a nop if there's nothing in the delay slot.  */
00585       if (dbr_sequence_length () == 0)
00586   fprintf (stream, "\n\tnop");
00587       break;
00588     case '\'':
00589       {
00590   rtx note = find_reg_note (current_output_insn, REG_BR_PROB, 0);
00591 
00592   if (note && INTVAL (XEXP (note, 0)) * 2 < REG_BR_PROB_BASE)
00593     fputs ("/u", stream);
00594   break;
00595       }
00596     case 'O':
00597       x = mark_constant_pool_use (x);
00598       output_addr_const (stream, x);
00599       break;
00600     case 'R':
00601       fputs (reg_names[REGNO (x) + LSW], (stream));
00602       break;
00603     case 'S':
00604       fputs (reg_names[REGNO (x) + MSW], (stream));
00605       break;
00606     case 'T':
00607       /* Next word of a double.  */
00608       switch (GET_CODE (x))
00609   {
00610   case REG:
00611     fputs (reg_names[REGNO (x) + 1], (stream));
00612     break;
00613   case MEM:
00614     if (GET_CODE (XEXP (x, 0)) != PRE_DEC
00615         && GET_CODE (XEXP (x, 0)) != POST_INC)
00616       x = adjust_address (x, SImode, 4);
00617     print_operand_address (stream, XEXP (x, 0));
00618     break;
00619   default:
00620     break;
00621   }
00622       break;
00623     case 'o':
00624       switch (GET_CODE (x))
00625   {
00626   case PLUS:  fputs ("add", stream); break;
00627   case MINUS: fputs ("sub", stream); break;
00628   case MULT:  fputs ("mul", stream); break;
00629   case DIV:   fputs ("div", stream); break;
00630   case EQ:    fputs ("eq",  stream); break;
00631   case NE:    fputs ("ne",  stream); break;
00632   case GT:  case LT:  fputs ("gt",  stream); break;
00633   case GE:  case LE:  fputs ("ge",  stream); break;
00634   case GTU: case LTU: fputs ("gtu", stream); break;
00635   case GEU: case LEU: fputs ("geu", stream); break;
00636   default:
00637     break;
00638   }
00639       break;
00640     case 'M':
00641       if (GET_CODE (x) == MEM
00642     && GET_CODE (XEXP (x, 0)) == PLUS
00643     && (GET_CODE (XEXP (XEXP (x, 0), 1)) == REG
00644         || GET_CODE (XEXP (XEXP (x, 0), 1)) == SUBREG))
00645   fputc ('x', stream);
00646       break;
00647 
00648     case 'm':
00649       if (GET_CODE (x) != MEM)
00650   abort ();
00651       x = XEXP (x, 0);
00652       switch (GET_CODE (x))
00653   {
00654   case REG:
00655   case SUBREG:
00656     print_operand (stream, x, 0);
00657     fputs (", 0", stream);
00658     break;
00659 
00660   case PLUS:
00661     print_operand (stream, XEXP (x, 0), 0);
00662     fputs (", ", stream);
00663     print_operand (stream, XEXP (x, 1), 0);
00664     break;
00665 
00666   default:
00667     abort ();
00668   }
00669       break;
00670 
00671     case 'd':
00672       if (GET_CODE (x) != REG || GET_MODE (x) != V2SFmode)
00673   abort ();
00674 
00675       fprintf ((stream), "d%s", reg_names[REGNO (x)] + 1);
00676       break;
00677 
00678     case 'N':
00679       if (x == CONST0_RTX (GET_MODE (x)))
00680   {
00681     fprintf ((stream), "r63");
00682     break;
00683   }
00684       goto default_output;
00685     case 'u':
00686       if (GET_CODE (x) == CONST_INT)
00687   {
00688     fprintf ((stream), "%u", (unsigned) INTVAL (x) & (0x10000 - 1));
00689     break;
00690   }
00691       /* Fall through.  */
00692 
00693     default_output:
00694     default:
00695       switch (GET_CODE (x))
00696   {
00697     /* FIXME: We need this on SHmedia32 because reload generates
00698        some sign-extended HI or QI loads into DImode registers
00699        but, because Pmode is SImode, the address ends up with a
00700        subreg:SI of the DImode register.  Maybe reload should be
00701        fixed so as to apply alter_subreg to such loads?  */
00702   case SUBREG:
00703     if (SUBREG_BYTE (x) != 0
00704         || GET_CODE (SUBREG_REG (x)) != REG)
00705       abort ();
00706 
00707     x = SUBREG_REG (x);
00708     /* Fall through.  */
00709 
00710   case REG:
00711     if (FP_REGISTER_P (REGNO (x))
00712         && GET_MODE (x) == V16SFmode)
00713       fprintf ((stream), "mtrx%s", reg_names[REGNO (x)] + 2);
00714     else if (FP_REGISTER_P (REGNO (x))
00715        && GET_MODE (x) == V4SFmode)
00716       fprintf ((stream), "fv%s", reg_names[REGNO (x)] + 2);
00717     else if (GET_CODE (x) == REG
00718        && GET_MODE (x) == V2SFmode)
00719       fprintf ((stream), "fp%s", reg_names[REGNO (x)] + 2);
00720     else if (FP_REGISTER_P (REGNO (x))
00721        && GET_MODE_SIZE (GET_MODE (x)) > 4)
00722       fprintf ((stream), "d%s", reg_names[REGNO (x)] + 1);
00723     else
00724       fputs (reg_names[REGNO (x)], (stream));
00725     break;
00726 
00727   case MEM:
00728     output_address (XEXP (x, 0));
00729     break;
00730 
00731   case CONST:
00732     if (TARGET_SHMEDIA
00733         && GET_CODE (XEXP (x, 0)) == SIGN_EXTEND
00734         && GET_MODE (XEXP (x, 0)) == DImode
00735         && GET_CODE (XEXP (XEXP (x, 0), 0)) == TRUNCATE
00736         && GET_MODE (XEXP (XEXP (x, 0), 0)) == HImode)
00737       {
00738         rtx val = XEXP (XEXP (XEXP (x, 0), 0), 0);
00739 
00740         fputc ('(', stream);
00741         if (GET_CODE (val) == ASHIFTRT)
00742     {
00743       fputc ('(', stream);
00744       if (GET_CODE (XEXP (val, 0)) == CONST)
00745         fputc ('(', stream);
00746       output_addr_const (stream, XEXP (val, 0));
00747       if (GET_CODE (XEXP (val, 0)) == CONST)
00748         fputc (')', stream);
00749       fputs (" >> ", stream);
00750       output_addr_const (stream, XEXP (val, 1));
00751       fputc (')', stream);
00752     }
00753         else
00754     {
00755       if (GET_CODE (val) == CONST)
00756         fputc ('(', stream);
00757       output_addr_const (stream, val);
00758       if (GET_CODE (val) == CONST)
00759         fputc (')', stream);
00760     }
00761         fputs (" & 65535)", stream);
00762         break;
00763       }
00764 
00765     /* Fall through.  */
00766   default:
00767     if (TARGET_SH1)
00768       fputc ('#', stream);
00769     output_addr_const (stream, x);
00770     break;
00771   }
00772       break;
00773     }
00774 }
00775 
00776 /* Like force_operand, but guarantees that VALUE ends up in TARGET.  */
00777 static void
00778 force_into (rtx value, rtx target)
00779 {
00780   value = force_operand (value, target);
00781   if (! rtx_equal_p (value, target))
00782     emit_insn (gen_move_insn (target, value));
00783 }
00784 
00785 /* Emit code to perform a block move.  Choose the best method.
00786 
00787    OPERANDS[0] is the destination.
00788    OPERANDS[1] is the source.
00789    OPERANDS[2] is the size.
00790    OPERANDS[3] is the alignment safe to use.  */
00791 
00792 int
00793 expand_block_move (rtx *operands)
00794 {
00795   int align = INTVAL (operands[3]);
00796   int constp = (GET_CODE (operands[2]) == CONST_INT);
00797   int bytes = (constp ? INTVAL (operands[2]) : 0);
00798 
00799   if (! constp)
00800     return 0;
00801 
00802   /* If we could use mov.l to move words and dest is word-aligned, we
00803      can use movua.l for loads and still generate a relatively short
00804      and efficient sequence.  */
00805   if (TARGET_SH4A_ARCH && align < 4
00806       && MEM_ALIGN (operands[0]) >= 32
00807       && can_move_by_pieces (bytes, 32))
00808     {
00809       rtx dest = copy_rtx (operands[0]);
00810       rtx src = copy_rtx (operands[1]);
00811       /* We could use different pseudos for each copied word, but
00812    since movua can only load into r0, it's kind of
00813    pointless.  */
00814       rtx temp = gen_reg_rtx (SImode);
00815       rtx src_addr = copy_addr_to_reg (XEXP (src, 0));
00816       int copied = 0;
00817 
00818       while (copied + 4 <= bytes)
00819   {
00820     rtx to = adjust_address (dest, SImode, copied);
00821     rtx from = adjust_automodify_address (src, SImode, src_addr, copied);
00822 
00823     emit_insn (gen_movua (temp, from));
00824     emit_move_insn (src_addr, plus_constant (src_addr, 4));
00825     emit_move_insn (to, temp);
00826     copied += 4;
00827   }
00828 
00829       if (copied < bytes)
00830   move_by_pieces (adjust_address (dest, BLKmode, copied),
00831       adjust_automodify_address (src, BLKmode,
00832                src_addr, copied),
00833       bytes - copied, align, 0);
00834 
00835       return 1;
00836     }
00837 
00838   /* If it isn't a constant number of bytes, or if it doesn't have 4 byte
00839      alignment, or if it isn't a multiple of 4 bytes, then fail.  */
00840   if (align < 4 || (bytes % 4 != 0))
00841     return 0;
00842 
00843   if (TARGET_HARD_SH4)
00844     {
00845       if (bytes < 12)
00846   return 0;
00847       else if (bytes == 12)
00848   {
00849     tree entry_name;
00850     rtx sym;
00851     rtx func_addr_rtx;
00852     rtx r4 = gen_rtx_REG (SImode, 4);
00853     rtx r5 = gen_rtx_REG (SImode, 5);
00854 
00855     entry_name = get_identifier ("__movmemSI12_i4");
00856 
00857     sym = function_symbol (IDENTIFIER_POINTER (entry_name));
00858     func_addr_rtx = copy_to_mode_reg (Pmode, sym);
00859     force_into (XEXP (operands[0], 0), r4);
00860     force_into (XEXP (operands[1], 0), r5);
00861     emit_insn (gen_block_move_real_i4 (func_addr_rtx));
00862     return 1;
00863   }
00864       else if (! TARGET_SMALLCODE)
00865   {
00866     tree entry_name;
00867     rtx sym;
00868     rtx func_addr_rtx;
00869     int dwords;
00870     rtx r4 = gen_rtx_REG (SImode, 4);
00871     rtx r5 = gen_rtx_REG (SImode, 5);
00872     rtx r6 = gen_rtx_REG (SImode, 6);
00873 
00874     entry_name = get_identifier (bytes & 4
00875                ? "__movmem_i4_odd"
00876                : "__movmem_i4_even");
00877     sym = function_symbol (IDENTIFIER_POINTER (entry_name));
00878     func_addr_rtx = copy_to_mode_reg (Pmode, sym);
00879     force_into (XEXP (operands[0], 0), r4);
00880     force_into (XEXP (operands[1], 0), r5);
00881 
00882     dwords = bytes >> 3;
00883     emit_insn (gen_move_insn (r6, GEN_INT (dwords - 1)));
00884     emit_insn (gen_block_lump_real_i4 (func_addr_rtx));
00885     return 1;
00886   }
00887       else
00888   return 0;
00889     }
00890   if (bytes < 64)
00891     {
00892       char entry[30];
00893       tree entry_name;
00894       rtx sym;
00895       rtx func_addr_rtx;
00896       rtx r4 = gen_rtx_REG (SImode, 4);
00897       rtx r5 = gen_rtx_REG (SImode, 5);
00898 
00899       sprintf (entry, "__movmemSI%d", bytes);
00900       entry_name = get_identifier (entry);
00901       sym = function_symbol (IDENTIFIER_POINTER (entry_name));
00902       func_addr_rtx = copy_to_mode_reg (Pmode, sym);
00903       force_into (XEXP (operands[0], 0), r4);
00904       force_into (XEXP (operands[1], 0), r5);
00905       emit_insn (gen_block_move_real (func_addr_rtx));
00906       return 1;
00907     }
00908 
00909   /* This is the same number of bytes as a memcpy call, but to a different
00910      less common function name, so this will occasionally use more space.  */
00911   if (! TARGET_SMALLCODE)
00912     {
00913       tree entry_name;
00914       rtx sym;
00915       rtx func_addr_rtx;
00916       int final_switch, while_loop;
00917       rtx r4 = gen_rtx_REG (SImode, 4);
00918       rtx r5 = gen_rtx_REG (SImode, 5);
00919       rtx r6 = gen_rtx_REG (SImode, 6);
00920 
00921       entry_name = get_identifier ("__movmem");
00922       sym = function_symbol (IDENTIFIER_POINTER (entry_name));
00923       func_addr_rtx = copy_to_mode_reg (Pmode, sym);
00924       force_into (XEXP (operands[0], 0), r4);
00925       force_into (XEXP (operands[1], 0), r5);
00926 
00927       /* r6 controls the size of the move.  16 is decremented from it
00928    for each 64 bytes moved.  Then the negative bit left over is used
00929    as an index into a list of move instructions.  e.g., a 72 byte move
00930    would be set up with size(r6) = 14, for one iteration through the
00931    big while loop, and a switch of -2 for the last part.  */
00932 
00933       final_switch = 16 - ((bytes / 4) % 16);
00934       while_loop = ((bytes / 4) / 16 - 1) * 16;
00935       emit_insn (gen_move_insn (r6, GEN_INT (while_loop + final_switch)));
00936       emit_insn (gen_block_lump_real (func_addr_rtx));
00937       return 1;
00938     }
00939 
00940   return 0;
00941 }
00942 
00943 /* Prepare operands for a move define_expand; specifically, one of the
00944    operands must be in a register.  */
00945 
00946 int
00947 prepare_move_operands (rtx operands[], enum machine_mode mode)
00948 {
00949   if ((mode == SImode || mode == DImode)
00950       && flag_pic
00951       && ! ((mode == Pmode || mode == ptr_mode)
00952       && tls_symbolic_operand (operands[1], Pmode) != 0))
00953     {
00954       rtx temp;
00955       if (SYMBOLIC_CONST_P (operands[1]))
00956   {
00957     if (GET_CODE (operands[0]) == MEM)
00958       operands[1] = force_reg (Pmode, operands[1]);
00959     else if (TARGET_SHMEDIA
00960        && GET_CODE (operands[1]) == LABEL_REF
00961        && target_reg_operand (operands[0], mode))
00962       /* It's ok.  */;
00963     else
00964       {
00965         temp = no_new_pseudos ? operands[0] : gen_reg_rtx (Pmode);
00966         operands[1] = legitimize_pic_address (operands[1], mode, temp);
00967       }
00968   }
00969       else if (GET_CODE (operands[1]) == CONST
00970          && GET_CODE (XEXP (operands[1], 0)) == PLUS
00971          && SYMBOLIC_CONST_P (XEXP (XEXP (operands[1], 0), 0)))
00972   {
00973     temp = no_new_pseudos ? operands[0] : gen_reg_rtx (Pmode);
00974     temp = legitimize_pic_address (XEXP (XEXP (operands[1], 0), 0),
00975            mode, temp);
00976     operands[1] = expand_binop (mode, add_optab, temp,
00977               XEXP (XEXP (operands[1], 0), 1),
00978               no_new_pseudos ? temp
00979               : gen_reg_rtx (Pmode),
00980               0, OPTAB_LIB_WIDEN);
00981   }
00982     }
00983 
00984   if (! reload_in_progress && ! reload_completed)
00985     {
00986       /* Copy the source to a register if both operands aren't registers.  */
00987       if (! register_operand (operands[0], mode)
00988     && ! sh_register_operand (operands[1], mode))
00989   operands[1] = copy_to_mode_reg (mode, operands[1]);
00990 
00991       if (GET_CODE (operands[0]) == MEM && ! memory_operand (operands[0], mode))
00992   {
00993     /* This is like change_address_1 (operands[0], mode, 0, 1) ,
00994        except that we can't use that function because it is static.  */
00995     rtx new = change_address (operands[0], mode, 0);
00996     MEM_COPY_ATTRIBUTES (new, operands[0]);
00997     operands[0] = new;
00998   }
00999 
01000       /* This case can happen while generating code to move the result
01001    of a library call to the target.  Reject `st r0,@(rX,rY)' because
01002    reload will fail to find a spill register for rX, since r0 is already
01003    being used for the source.  */
01004       else if (refers_to_regno_p (R0_REG, R0_REG + 1, operands[1], (rtx *)0)
01005          && GET_CODE (operands[0]) == MEM
01006          && GET_CODE (XEXP (operands[0], 0)) == PLUS
01007          && GET_CODE (XEXP (XEXP (operands[0], 0), 1)) == REG)
01008   operands[1] = copy_to_mode_reg (mode, operands[1]);
01009     }
01010 
01011   if (mode == Pmode || mode == ptr_mode)
01012     {
01013       rtx op0, op1;
01014       enum tls_model tls_kind;
01015 
01016       op0 = operands[0];
01017       op1 = operands[1];
01018       if ((tls_kind = tls_symbolic_operand (op1, Pmode)))
01019   {
01020     rtx tga_op1, tga_ret, tmp, tmp2;
01021 
01022     switch (tls_kind)
01023       {
01024       case TLS_MODEL_GLOBAL_DYNAMIC:
01025         tga_ret = gen_rtx_REG (Pmode, R0_REG);
01026         emit_call_insn (gen_tls_global_dynamic (tga_ret, op1));
01027         op1 = tga_ret;
01028         break;
01029 
01030       case TLS_MODEL_LOCAL_DYNAMIC:
01031         tga_ret = gen_rtx_REG (Pmode, R0_REG);
01032         emit_call_insn (gen_tls_local_dynamic (tga_ret, op1));
01033 
01034         tmp = gen_reg_rtx (Pmode);
01035         emit_move_insn (tmp, tga_ret);
01036 
01037         if (register_operand (op0, Pmode))
01038     tmp2 = op0;
01039         else
01040     tmp2 = gen_reg_rtx (Pmode);
01041 
01042         emit_insn (gen_symDTPOFF2reg (tmp2, op1, tmp));
01043         op1 = tmp2;
01044         break;
01045 
01046       case TLS_MODEL_INITIAL_EXEC:
01047         if (! flag_pic)
01048     {
01049       /* Don't schedule insns for getting GOT address when
01050          the first scheduling is enabled, to avoid spill
01051          failures for R0.  */
01052       if (flag_schedule_insns)
01053         emit_insn (gen_blockage ());
01054       emit_insn (gen_GOTaddr2picreg ());
01055       emit_insn (gen_rtx_USE (VOIDmode, gen_rtx_REG (SImode,
01056                  PIC_REG)));
01057       if (flag_schedule_insns)
01058         emit_insn (gen_blockage ());
01059     }
01060         tga_op1 = no_new_pseudos ? op0 : gen_reg_rtx (Pmode);
01061         tmp = gen_sym2GOTTPOFF (op1);
01062         emit_insn (gen_tls_initial_exec (tga_op1, tmp));
01063         op1 = tga_op1;
01064         break;
01065 
01066       case TLS_MODEL_LOCAL_EXEC:
01067         tmp2 = gen_reg_rtx (Pmode);
01068         emit_insn (gen_load_gbr (tmp2));
01069         tmp = gen_reg_rtx (Pmode);
01070         emit_insn (gen_symTPOFF2reg (tmp, op1));
01071 
01072         if (register_operand (op0, Pmode))
01073     op1 = op0;
01074         else
01075     op1 = gen_reg_rtx (Pmode);
01076 
01077         emit_insn (gen_addsi3 (op1, tmp, tmp2));
01078         break;
01079 
01080       default:
01081         abort ();
01082       }
01083     operands[1] = op1;
01084   }
01085     }
01086 
01087   return 0;
01088 }
01089 
01090 /* Prepare the operands for an scc instruction; make sure that the
01091    compare has been done.  */
01092 rtx
01093 prepare_scc_operands (enum rtx_code code)
01094 {
01095   rtx t_reg = gen_rtx_REG (SImode, T_REG);
01096   enum rtx_code oldcode = code;
01097   enum machine_mode mode;
01098 
01099   /* First need a compare insn.  */
01100   switch (code)
01101     {
01102     case NE:
01103       /* It isn't possible to handle this case.  */
01104       abort ();
01105     case LT:
01106       code = GT;
01107       break;
01108     case LE:
01109       code = GE;
01110       break;
01111     case LTU:
01112       code = GTU;
01113       break;
01114     case LEU:
01115       code = GEU;
01116       break;
01117     default:
01118       break;
01119     }
01120   if (code != oldcode)
01121     {
01122       rtx tmp = sh_compare_op0;
01123       sh_compare_op0 = sh_compare_op1;
01124       sh_compare_op1 = tmp;
01125     }
01126 
01127   mode = GET_MODE (sh_compare_op0);
01128   if (mode == VOIDmode)
01129     mode = GET_MODE (sh_compare_op1);
01130 
01131   sh_compare_op0 = force_reg (mode, sh_compare_op0);
01132   if ((code != EQ && code != NE
01133        && (sh_compare_op1 != const0_rtx
01134      || code == GTU  || code == GEU || code == LTU || code == LEU))
01135       || (mode == DImode && sh_compare_op1 != const0_rtx)
01136       || (TARGET_SH2E && GET_MODE_CLASS (mode) == MODE_FLOAT))
01137     sh_compare_op1 = force_reg (mode, sh_compare_op1);
01138 
01139   if ((TARGET_SH4 || TARGET_SH2A) && GET_MODE_CLASS (mode) == MODE_FLOAT)
01140     (mode == SFmode ? emit_sf_insn : emit_df_insn)
01141      (gen_rtx_PARALLEL (VOIDmode, gen_rtvec (2,
01142     gen_rtx_SET (VOIDmode, t_reg,
01143            gen_rtx_fmt_ee (code, SImode,
01144                sh_compare_op0, sh_compare_op1)),
01145     gen_rtx_USE (VOIDmode, get_fpscr_rtx ()))));
01146   else
01147     emit_insn (gen_rtx_SET (VOIDmode, t_reg,
01148           gen_rtx_fmt_ee (code, SImode,
01149               sh_compare_op0, sh_compare_op1)));
01150 
01151   return t_reg;
01152 }
01153 
01154 /* Called from the md file, set up the operands of a compare instruction.  */
01155 
01156 void
01157 from_compare (rtx *operands, int code)
01158 {
01159   enum machine_mode mode = GET_MODE (sh_compare_op0);
01160   rtx insn;
01161   if (mode == VOIDmode)
01162     mode = GET_MODE (sh_compare_op1);
01163   if (code != EQ
01164       || mode == DImode
01165       || (TARGET_SH2E && GET_MODE_CLASS (mode) == MODE_FLOAT))
01166     {
01167       /* Force args into regs, since we can't use constants here.  */
01168       sh_compare_op0 = force_reg (mode, sh_compare_op0);
01169       if (sh_compare_op1 != const0_rtx
01170     || code == GTU  || code == GEU
01171     || (TARGET_SH2E && GET_MODE_CLASS (mode) == MODE_FLOAT))
01172   sh_compare_op1 = force_reg (mode, sh_compare_op1);
01173     }
01174   if (TARGET_SH2E && GET_MODE_CLASS (mode) == MODE_FLOAT && code == GE)
01175     {
01176       from_compare (operands, GT);
01177       insn = gen_ieee_ccmpeqsf_t (sh_compare_op0, sh_compare_op1);
01178     }
01179   else
01180     insn = gen_rtx_SET (VOIDmode,
01181       gen_rtx_REG (SImode, T_REG),
01182       gen_rtx_fmt_ee (code, SImode,
01183           sh_compare_op0, sh_compare_op1));
01184   if ((TARGET_SH4 || TARGET_SH2A) && GET_MODE_CLASS (mode) == MODE_FLOAT)
01185     {
01186       insn = gen_rtx_PARALLEL (VOIDmode,
01187           gen_rtvec (2, insn,
01188          gen_rtx_USE (VOIDmode, get_fpscr_rtx ())));
01189       (mode == SFmode ? emit_sf_insn : emit_df_insn) (insn);
01190     }
01191   else
01192     emit_insn (insn);
01193 }
01194 
01195 /* Functions to output assembly code.  */
01196 
01197 /* Return a sequence of instructions to perform DI or DF move.
01198 
01199    Since the SH cannot move a DI or DF in one instruction, we have
01200    to take care when we see overlapping source and dest registers.  */
01201 
01202 const char *
01203 output_movedouble (rtx insn ATTRIBUTE_UNUSED, rtx operands[],
01204        enum machine_mode mode)
01205 {
01206   rtx dst = operands[0];
01207   rtx src = operands[1];
01208 
01209   if (GET_CODE (dst) == MEM
01210       && GET_CODE (XEXP (dst, 0)) == PRE_DEC)
01211     return "mov.l %T1,%0\n\tmov.l %1,%0";
01212 
01213   if (register_operand (dst, mode)
01214       && register_operand (src, mode))
01215     {
01216       if (REGNO (src) == MACH_REG)
01217   return "sts mach,%S0\n\tsts macl,%R0";
01218 
01219       /* When mov.d r1,r2 do r2->r3 then r1->r2;
01220          when mov.d r1,r0 do r1->r0 then r2->r1.  */
01221 
01222       if (REGNO (src) + 1 == REGNO (dst))
01223   return "mov %T1,%T0\n\tmov  %1,%0";
01224       else
01225   return "mov %1,%0\n\tmov  %T1,%T0";
01226     }
01227   else if (GET_CODE (src) == CONST_INT)
01228     {
01229       if (INTVAL (src) < 0)
01230   output_asm_insn ("mov #-1,%S0", operands);
01231       else
01232   output_asm_insn ("mov #0,%S0", operands);
01233 
01234       return "mov %1,%R0";
01235     }
01236   else if (GET_CODE (src) == MEM)
01237     {
01238       int ptrreg = -1;
01239       int dreg = REGNO (dst);
01240       rtx inside = XEXP (src, 0);
01241 
01242       if (GET_CODE (inside) == REG)
01243   ptrreg = REGNO (inside);
01244       else if (GET_CODE (inside) == SUBREG)
01245   ptrreg = subreg_regno (inside);
01246       else if (GET_CODE (inside) == PLUS)
01247   {
01248     ptrreg = REGNO (XEXP (inside, 0));
01249     /* ??? A r0+REG address shouldn't be possible here, because it isn't
01250        an offsettable address.  Unfortunately, offsettable addresses use
01251        QImode to check the offset, and a QImode offsettable address
01252        requires r0 for the other operand, which is not currently
01253        supported, so we can't use the 'o' constraint.
01254        Thus we must check for and handle r0+REG addresses here.
01255        We punt for now, since this is likely very rare.  */
01256     if (GET_CODE (XEXP (inside, 1)) == REG)
01257       abort ();
01258   }
01259       else if (GET_CODE (inside) == LABEL_REF)
01260   return "mov.l %1,%0\n\tmov.l  %1+4,%T0";
01261       else if (GET_CODE (inside) == POST_INC)
01262   return "mov.l %1,%0\n\tmov.l  %1,%T0";
01263       else
01264   abort ();
01265 
01266       /* Work out the safe way to copy.  Copy into the second half first.  */
01267       if (dreg == ptrreg)
01268   return "mov.l %T1,%T0\n\tmov.l  %1,%0";
01269     }
01270 
01271   return "mov.l %1,%0\n\tmov.l  %T1,%T0";
01272 }
01273 
01274 /* Print an instruction which would have gone into a delay slot after
01275    another instruction, but couldn't because the other instruction expanded
01276    into a sequence where putting the slot insn at the end wouldn't work.  */
01277 
01278 static void
01279 print_slot (rtx insn)
01280 {
01281   final_scan_insn (XVECEXP (insn, 0, 1), asm_out_file, optimize, 0, 1, NULL);
01282 
01283   INSN_DELETED_P (XVECEXP (insn, 0, 1)) = 1;
01284 }
01285 
01286 const char *
01287 output_far_jump (rtx insn, rtx op)
01288 {
01289   struct { rtx lab, reg, op; } this;
01290   rtx braf_base_lab = NULL_RTX;
01291   const char *jump;
01292   int far;
01293   int offset = branch_dest (insn) - INSN_ADDRESSES (INSN_UID (insn));
01294   rtx prev;
01295 
01296   this.lab = gen_label_rtx ();
01297 
01298   if (TARGET_SH2
01299       && offset >= -32764
01300       && offset - get_attr_length (insn) <= 32766)
01301     {
01302       far = 0;
01303       jump = "mov.w %O0,%1; braf  %1";
01304     }
01305   else
01306     {
01307       far = 1;
01308       if (flag_pic)
01309   {
01310     if (TARGET_SH2)
01311       jump = "mov.l %O0,%1; braf  %1";
01312     else
01313       jump = "mov.l r0,@-r15; mova  %O0,r0; mov.l @r0,%1; add r0,%1; mov.l  @r15+,r0; jmp @%1";
01314   }
01315       else
01316   jump = "mov.l %O0,%1; jmp @%1";
01317     }
01318   /* If we have a scratch register available, use it.  */
01319   if (GET_CODE ((prev = prev_nonnote_insn (insn))) == INSN
01320       && INSN_CODE (prev) == CODE_FOR_indirect_jump_scratch)
01321     {
01322       this.reg = SET_DEST (XVECEXP (PATTERN (prev), 0, 0));
01323       if (REGNO (this.reg) == R0_REG && flag_pic && ! TARGET_SH2)
01324   jump = "mov.l r1,@-r15; mova  %O0,r0; mov.l @r0,r1; add r1,r0; mov.l  @r15+,r1; jmp @%1";
01325       output_asm_insn (jump, &this.lab);
01326       if (dbr_sequence_length ())
01327   print_slot (final_sequence);
01328       else
01329   output_asm_insn ("nop", 0);
01330     }
01331   else
01332     {
01333       /* Output the delay slot insn first if any.  */
01334       if (dbr_sequence_length ())
01335   print_slot (final_sequence);
01336 
01337       this.reg = gen_rtx_REG (SImode, 13);
01338       /* We must keep the stack aligned to 8-byte boundaries on SH5.
01339    Fortunately, MACL is fixed and call-clobbered, and we never
01340    need its value across jumps, so save r13 in it instead of in
01341    the stack.  */
01342       if (TARGET_SH5)
01343   output_asm_insn ("lds r13, macl", 0);
01344       else
01345   output_asm_insn ("mov.l r13,@-r15", 0);
01346       output_asm_insn (jump, &this.lab);
01347       if (TARGET_SH5)
01348   output_asm_insn ("sts macl, r13", 0);
01349       else
01350   output_asm_insn ("mov.l @r15+,r13", 0);
01351     }
01352   if (far && flag_pic && TARGET_SH2)
01353     {
01354       braf_base_lab = gen_label_rtx ();
01355       (*targetm.asm_out.internal_label) (asm_out_file, "L",
01356          CODE_LABEL_NUMBER (braf_base_lab));
01357     }
01358   if (far)
01359     output_asm_insn (".align  2", 0);
01360   (*targetm.asm_out.internal_label) (asm_out_file, "L", CODE_LABEL_NUMBER (this.lab));
01361   this.op = op;
01362   if (far && flag_pic)
01363     {
01364       if (TARGET_SH2)
01365   this.lab = braf_base_lab;
01366       output_asm_insn (".long %O2-%O0", &this.lab);
01367     }
01368   else
01369     output_asm_insn (far ? ".long %O2" : ".word %O2-%O0", &this.lab);
01370   return "";
01371 }
01372 
01373 /* Local label counter, used for constants in the pool and inside
01374    pattern branches.  */
01375 
01376 static int lf = 100;
01377 
01378 /* Output code for ordinary branches.  */
01379 
01380 const char *
01381 output_branch (int logic, rtx insn, rtx *operands)
01382 {
01383   switch (get_attr_length (insn))
01384     {
01385     case 6:
01386       /* This can happen if filling the delay slot has caused a forward
01387    branch to exceed its range (we could reverse it, but only
01388    when we know we won't overextend other branches; this should
01389    best be handled by relaxation).
01390    It can also happen when other condbranches hoist delay slot insn
01391    from their destination, thus leading to code size increase.
01392    But the branch will still be in the range -4092..+4098 bytes.  */
01393 
01394       if (! TARGET_RELAX)
01395   {
01396     int label = lf++;
01397     /* The call to print_slot will clobber the operands.  */
01398     rtx op0 = operands[0];
01399 
01400     /* If the instruction in the delay slot is annulled (true), then
01401        there is no delay slot where we can put it now.  The only safe
01402        place for it is after the label.  final will do that by default.  */
01403 
01404     if (final_sequence
01405         && ! INSN_ANNULLED_BRANCH_P (XVECEXP (final_sequence, 0, 0))
01406         && get_attr_length (XVECEXP (final_sequence, 0, 1)))
01407       {
01408         asm_fprintf (asm_out_file, "\tb%s%ss\t%LLF%d\n", logic ? "f" : "t",
01409                      ASSEMBLER_DIALECT ? "/" : ".", label);
01410         print_slot (final_sequence);
01411       }
01412     else
01413       asm_fprintf (asm_out_file, "\tb%s\t%LLF%d\n", logic ? "f" : "t", label);
01414 
01415     output_asm_insn ("bra\t%l0", &op0);
01416     fprintf (asm_out_file, "\tnop\n");
01417     (*targetm.asm_out.internal_label) (asm_out_file, "LF", label);
01418 
01419     return "";
01420   }
01421       /* When relaxing, handle this like a short branch.  The linker
01422    will fix it up if it still doesn't fit after relaxation.  */
01423     case 2:
01424       return logic ? "bt%.\t%l0" : "bf%.\t%l0";
01425 
01426       /* These are for SH2e, in which we have to account for the
01427    extra nop because of the hardware bug in annulled branches.  */
01428     case 8:
01429       if (! TARGET_RELAX)
01430   {
01431     int label = lf++;
01432 
01433     if (final_sequence
01434         && INSN_ANNULLED_BRANCH_P (XVECEXP (final_sequence, 0, 0)))
01435       abort ();
01436     asm_fprintf (asm_out_file, "b%s%ss\t%LLF%d\n",
01437            logic ? "f" : "t",
01438            ASSEMBLER_DIALECT ? "/" : ".", label);
01439     fprintf (asm_out_file, "\tnop\n");
01440     output_asm_insn ("bra\t%l0", operands);
01441     fprintf (asm_out_file, "\tnop\n");
01442     (*targetm.asm_out.internal_label) (asm_out_file, "LF", label);
01443 
01444     return "";
01445   }
01446       /* When relaxing, fall through.  */
01447     case 4:
01448       {
01449   char buffer[10];
01450 
01451   sprintf (buffer, "b%s%ss\t%%l0",
01452      logic ? "t" : "f",
01453      ASSEMBLER_DIALECT ? "/" : ".");
01454   output_asm_insn (buffer, &operands[0]);
01455   return "nop";
01456       }
01457 
01458     default:
01459       /* There should be no longer branches now - that would
01460    indicate that something has destroyed the branches set
01461    up in machine_dependent_reorg.  */
01462       abort ();
01463     }
01464 }
01465 
01466 const char *
01467 output_branchy_insn (enum rtx_code code, const char *template,
01468          rtx insn, rtx *operands)
01469 {
01470   rtx next_insn = NEXT_INSN (insn);
01471 
01472   if (next_insn && GET_CODE (next_insn) == JUMP_INSN && condjump_p (next_insn))
01473     {
01474       rtx src = SET_SRC (PATTERN (next_insn));
01475       if (GET_CODE (src) == IF_THEN_ELSE && GET_CODE (XEXP (src, 0)) != code)
01476   {
01477     /* Following branch not taken */
01478     operands[9] = gen_label_rtx ();
01479     emit_label_after (operands[9], next_insn);
01480     INSN_ADDRESSES_NEW (operands[9],
01481             INSN_ADDRESSES (INSN_UID (next_insn))
01482             + get_attr_length (next_insn));
01483     return template;
01484   }
01485       else
01486   {
01487     int offset = (branch_dest (next_insn)
01488       - INSN_ADDRESSES (INSN_UID (next_insn)) + 4);
01489     if (offset >= -252 && offset <= 258)
01490       {
01491         if (GET_CODE (src) == IF_THEN_ELSE)
01492     /* branch_true */
01493     src = XEXP (src, 1);
01494         operands[9] = src;
01495         return template;
01496       }
01497   }
01498     }
01499   operands[9] = gen_label_rtx ();
01500   emit_label_after (operands[9], insn);
01501   INSN_ADDRESSES_NEW (operands[9],
01502           INSN_ADDRESSES (INSN_UID (insn))
01503           + get_attr_length (insn));
01504   return template;
01505 }
01506 
01507 const char *
01508 output_ieee_ccmpeq (rtx insn, rtx *operands)
01509 {
01510   return output_branchy_insn (NE, "bt\t%l9\\;fcmp/eq\t%1,%0", insn, operands);
01511 }
01512 
01513 /* Output the start of the assembler file.  */
01514 
01515 static void
01516 sh_file_start (void)
01517 {
01518   default_file_start ();
01519 
01520 #ifdef SYMBIAN
01521   /* Declare the .directive section before it is used.  */
01522   fputs ("\t.section .directive, \"SM\", @progbits, 1\n", asm_out_file);
01523   fputs ("\t.asciz \"#<SYMEDIT>#\\n\"\n", asm_out_file);
01524 #endif
01525 
01526   if (TARGET_ELF)
01527     /* We need to show the text section with the proper
01528        attributes as in TEXT_SECTION_ASM_OP, before dwarf2out
01529        emits it without attributes in TEXT_SECTION_ASM_OP, else GAS
01530        will complain.  We can teach GAS specifically about the
01531        default attributes for our choice of text section, but
01532        then we would have to change GAS again if/when we change
01533        the text section name.  */
01534     fprintf (asm_out_file, "%s\n", TEXT_SECTION_ASM_OP);
01535   else
01536     /* Switch to the data section so that the coffsem symbol
01537        isn't in the text section.  */
01538     data_section ();
01539 
01540   if (TARGET_LITTLE_ENDIAN)
01541     fputs ("\t.little\n", asm_out_file);
01542 
01543   if (!TARGET_ELF)
01544     {
01545       if (TARGET_SHCOMPACT)
01546   fputs ("\t.mode\tSHcompact\n", asm_out_file);
01547       else if (TARGET_SHMEDIA)
01548   fprintf (asm_out_file, "\t.mode\tSHmedia\n\t.abi\t%i\n",
01549      TARGET_SHMEDIA64 ? 64 : 32);
01550     }
01551 }
01552 
01553 /* Check if PAT includes UNSPEC_CALLER unspec pattern.  */
01554 
01555 static bool
01556 unspec_caller_rtx_p (rtx pat)
01557 {
01558   switch (GET_CODE (pat))
01559     {
01560     case CONST:
01561       return unspec_caller_rtx_p (XEXP (pat, 0));
01562     case PLUS:
01563     case MINUS:
01564       if (unspec_caller_rtx_p (XEXP (pat, 0)))
01565   return true;
01566       return unspec_caller_rtx_p (XEXP (pat, 1));
01567     case UNSPEC:
01568       if (XINT (pat, 1) == UNSPEC_CALLER)
01569   return true;
01570     default:
01571       break;
01572     }
01573 
01574   return false;
01575 }
01576 
01577 /* Indicate that INSN cannot be duplicated.  This is true for insn
01578    that generates an unique label.  */
01579 
01580 static bool
01581 sh_cannot_copy_insn_p (rtx insn)
01582 {
01583   rtx pat;
01584 
01585   if (!reload_completed || !flag_pic)
01586     return false;
01587 
01588   if (GET_CODE (insn) != INSN)
01589     return false;
01590   if (asm_noperands (insn) >= 0)
01591     return false;
01592 
01593   pat = PATTERN (insn);
01594   if (GET_CODE (pat) != SET)
01595     return false;
01596   pat = SET_SRC (pat);
01597 
01598   if (unspec_caller_rtx_p (pat))
01599     return true;
01600 
01601   return false;
01602 }
01603 
01604 /* Actual number of instructions used to make a shift by N.  */
01605 static const char ashiftrt_insns[] =
01606   { 0,1,2,3,4,5,8,8,8,8,8,8,8,8,8,8,2,3,4,5,8,8,8,8,8,8,8,8,8,8,8,2};
01607 
01608 /* Left shift and logical right shift are the same.  */
01609 static const char shift_insns[]    =
01610   { 0,1,1,2,2,3,3,4,1,2,2,3,3,4,3,3,1,2,2,3,3,4,3,3,2,3,3,4,4,4,3,3};
01611 
01612 /* Individual shift amounts needed to get the above length sequences.
01613    One bit right shifts clobber the T bit, so when possible, put one bit
01614    shifts in the middle of the sequence, so the ends are eligible for
01615    branch delay slots.  */
01616 static const short shift_amounts[32][5] = {
01617   {0}, {1}, {2}, {2, 1},
01618   {2, 2}, {2, 1, 2}, {2, 2, 2}, {2, 2, 1, 2},
01619   {8}, {8, 1}, {8, 2}, {8, 1, 2},
01620   {8, 2, 2}, {8, 2, 1, 2}, {8, -2, 8}, {8, -1, 8},
01621   {16}, {16, 1}, {16, 2}, {16, 1, 2},
01622   {16, 2, 2}, {16, 2, 1, 2}, {16, -2, 8}, {16, -1, 8},
01623   {16, 8}, {16, 1, 8}, {16, 8, 2}, {16, 8, 1, 2},
01624   {16, 8, 2, 2}, {16, -1, -2, 16}, {16, -2, 16}, {16, -1, 16}};
01625 
01626 /* Likewise, but for shift amounts < 16, up to three highmost bits
01627    might be clobbered.  This is typically used when combined with some
01628    kind of sign or zero extension.  */
01629 
01630 static const char ext_shift_insns[]    =
01631   { 0,1,1,2,2,3,2,2,1,2,2,3,3,3,2,2,1,2,2,3,3,4,3,3,2,3,3,4,4,4,3,3};
01632 
01633 static const short ext_shift_amounts[32][4] = {
01634   {0}, {1}, {2}, {2, 1},
01635   {2, 2}, {2, 1, 2}, {8, -2}, {8, -1},
01636   {8}, {8, 1}, {8, 2}, {8, 1, 2},
01637   {8, 2, 2}, {16, -2, -1}, {16, -2}, {16, -1},
01638   {16}, {16, 1}, {16, 2}, {16, 1, 2},
01639   {16, 2, 2}, {16, 2, 1, 2}, {16, -2, 8}, {16, -1, 8},
01640   {16, 8}, {16, 1, 8}, {16, 8, 2}, {16, 8, 1, 2},
01641   {16, 8, 2, 2}, {16, -1, -2, 16}, {16, -2, 16}, {16, -1, 16}};
01642 
01643 /* Assuming we have a value that has been sign-extended by at least one bit,
01644    can we use the ext_shift_amounts with the last shift turned to an arithmetic shift
01645    to shift it by N without data loss, and quicker than by other means?  */
01646 #define EXT_SHIFT_SIGNED(n) (((n) | 8) == 15)
01647 
01648 /* This is used in length attributes in sh.md to help compute the length
01649    of arbitrary constant shift instructions.  */
01650 
01651 int
01652 shift_insns_rtx (rtx insn)
01653 {
01654   rtx set_src = SET_SRC (XVECEXP (PATTERN (insn), 0, 0));
01655   int shift_count = INTVAL (XEXP (set_src, 1));
01656   enum rtx_code shift_code = GET_CODE (set_src);
01657 
01658   switch (shift_code)
01659     {
01660     case ASHIFTRT:
01661       return ashiftrt_insns[shift_count];
01662     case LSHIFTRT:
01663     case ASHIFT:
01664       return shift_insns[shift_count];
01665     default:
01666       abort ();
01667     }
01668 }
01669 
01670 /* Return the cost of a shift.  */
01671 
01672 static inline int
01673 shiftcosts (rtx x)
01674 {
01675   int value;
01676 
01677   if (TARGET_SHMEDIA)
01678     return 1;
01679 
01680   if (GET_MODE_SIZE (GET_MODE (x)) > UNITS_PER_WORD)
01681     {
01682       if (GET_MODE (x) == DImode
01683     && GET_CODE (XEXP (x, 1)) == CONST_INT
01684     && INTVAL (XEXP (x, 1)) == 1)
01685   return 2;
01686 
01687       /* Everything else is invalid, because there is no pattern for it.  */
01688       return 10000;
01689     }
01690   /* If shift by a non constant, then this will be expensive.  */
01691   if (GET_CODE (XEXP (x, 1)) != CONST_INT)
01692     return SH_DYNAMIC_SHIFT_COST;
01693 
01694   value = INTVAL (XEXP (x, 1));
01695 
01696   /* Otherwise, return the true cost in instructions.  */
01697   if (GET_CODE (x) == ASHIFTRT)
01698     {
01699       int cost = ashiftrt_insns[value];
01700       /* If SH3, then we put the constant in a reg and use shad.  */
01701       if (cost > 1 + SH_DYNAMIC_SHIFT_COST)
01702   cost = 1 + SH_DYNAMIC_SHIFT_COST;
01703       return cost;
01704     }
01705   else
01706     return shift_insns[value];
01707 }
01708 
01709 /* Return the cost of an AND operation.  */
01710 
01711 static inline int
01712 andcosts (rtx x)
01713 {
01714   int i;
01715 
01716   /* Anding with a register is a single cycle and instruction.  */
01717   if (GET_CODE (XEXP (x, 1)) != CONST_INT)
01718     return 1;
01719 
01720   i = INTVAL (XEXP (x, 1));
01721 
01722   if (TARGET_SHMEDIA)
01723     {
01724       if ((GET_CODE (XEXP (x, 1)) == CONST_INT
01725      && CONST_OK_FOR_I16 (INTVAL (XEXP (x, 1))))
01726     || EXTRA_CONSTRAINT_C16 (XEXP (x, 1)))
01727   return 1;
01728       else
01729   return 2;
01730     }
01731 
01732   /* These constants are single cycle extu.[bw] instructions.  */
01733   if (i == 0xff || i == 0xffff)
01734     return 1;
01735   /* Constants that can be used in an and immediate instruction in a single
01736      cycle, but this requires r0, so make it a little more expensive.  */
01737   if (CONST_OK_FOR_K08 (i))
01738     return 2;
01739   /* Constants that can be loaded with a mov immediate and an and.
01740      This case is probably unnecessary.  */
01741   if (CONST_OK_FOR_I08 (i))
01742     return 2;
01743   /* Any other constants requires a 2 cycle pc-relative load plus an and.
01744      This case is probably unnecessary.  */
01745   return 3;
01746 }
01747 
01748 /* Return the cost of an addition or a subtraction.  */
01749 
01750 static inline int
01751 addsubcosts (rtx x)
01752 {
01753   /* Adding a register is a single cycle insn.  */
01754   if (GET_CODE (XEXP (x, 1)) == REG
01755       || GET_CODE (XEXP (x, 1)) == SUBREG)
01756     return 1;
01757 
01758   /* Likewise for small constants.  */
01759   if (GET_CODE (XEXP (x, 1)) == CONST_INT
01760       && CONST_OK_FOR_ADD (INTVAL (XEXP (x, 1))))
01761     return 1;
01762 
01763   if (TARGET_SHMEDIA)
01764     switch (GET_CODE (XEXP (x, 1)))
01765       {
01766       case CONST:
01767       case LABEL_REF:
01768       case SYMBOL_REF:
01769   return TARGET_SHMEDIA64 ? 5 : 3;
01770 
01771       case CONST_INT:
01772   if (CONST_OK_FOR_I16 (INTVAL (XEXP (x, 1))))
01773           return 2;
01774   else if (CONST_OK_FOR_I16 (INTVAL (XEXP (x, 1)) >> 16))
01775     return 3;
01776   else if (CONST_OK_FOR_I16 ((INTVAL (XEXP (x, 1)) >> 16) >> 16))
01777     return 4;
01778 
01779   /* Fall through.  */
01780       default:
01781   return 5;
01782       }
01783 
01784   /* Any other constant requires a 2 cycle pc-relative load plus an
01785      addition.  */
01786   return 3;
01787 }
01788 
01789 /* Return the cost of a multiply.  */
01790 static inline int
01791 multcosts (rtx x ATTRIBUTE_UNUSED)
01792 {
01793   if (TARGET_SHMEDIA)
01794     return 3;
01795 
01796   if (TARGET_SH2)
01797     {
01798       /* We have a mul insn, so we can never take more than the mul and the
01799    read of the mac reg, but count more because of the latency and extra
01800    reg usage.  */
01801       if (TARGET_SMALLCODE)
01802   return 2;
01803       return 3;
01804     }
01805 
01806   /* If we're aiming at small code, then just count the number of
01807      insns in a multiply call sequence.  */
01808   if (TARGET_SMALLCODE)
01809     return 5;
01810 
01811   /* Otherwise count all the insns in the routine we'd be calling too.  */
01812   return 20;
01813 }
01814 
01815 /* Compute a (partial) cost for rtx X.  Return true if the complete
01816    cost has been computed, and false if subexpressions should be
01817    scanned.  In either case, *TOTAL contains the cost result.  */
01818 
01819 static bool
01820 sh_rtx_costs (rtx x, int code, int outer_code, int *total)
01821 {
01822   switch (code)
01823     {
01824     case CONST_INT:
01825       if (TARGET_SHMEDIA)
01826         {
01827     if (INTVAL (x) == 0)
01828       *total = 0;
01829     else if (outer_code == AND && and_operand ((x), DImode))
01830       *total = 0;
01831     else if ((outer_code == IOR || outer_code == XOR
01832               || outer_code == PLUS)
01833        && CONST_OK_FOR_I10 (INTVAL (x)))
01834       *total = 0;
01835     else if (CONST_OK_FOR_I16 (INTVAL (x)))
01836             *total = COSTS_N_INSNS (outer_code != SET);
01837     else if (CONST_OK_FOR_I16 (INTVAL (x) >> 16))
01838       *total = COSTS_N_INSNS (2);
01839     else if (CONST_OK_FOR_I16 ((INTVAL (x) >> 16) >> 16))
01840       *total = COSTS_N_INSNS (3);
01841           else
01842       *total = COSTS_N_INSNS (4);
01843     return true;
01844         }
01845       if (CONST_OK_FOR_I08 (INTVAL (x)))
01846         *total = 0;
01847       else if ((outer_code == AND || outer_code == IOR || outer_code == XOR)
01848          && CONST_OK_FOR_K08 (INTVAL (x)))
01849         *total = 1;
01850       else
01851         *total = 8;
01852       return true;
01853 
01854     case CONST:
01855     case LABEL_REF:
01856     case SYMBOL_REF:
01857       if (TARGET_SHMEDIA64)
01858         *total = COSTS_N_INSNS (4);
01859       else if (TARGET_SHMEDIA32)
01860         *total = COSTS_N_INSNS (2);
01861       else
01862   *total = 5;
01863       return true;
01864 
01865     case CONST_DOUBLE:
01866       if (TARGET_SHMEDIA)
01867         *total = COSTS_N_INSNS (4);
01868       else
01869         *total = 10;
01870       return true;
01871 
01872     case PLUS:
01873       *total = COSTS_N_INSNS (addsubcosts (x));
01874       return true;
01875 
01876     case AND:
01877       *total = COSTS_N_INSNS (andcosts (x));
01878       return true;
01879 
01880     case MULT:
01881       *total = COSTS_N_INSNS (multcosts (x));
01882       return true;
01883 
01884     case ASHIFT:
01885     case ASHIFTRT:
01886     case LSHIFTRT:
01887       *total = COSTS_N_INSNS (shiftcosts (x));
01888       return true;
01889 
01890     case DIV:
01891     case UDIV:
01892     case MOD:
01893     case UMOD:
01894       *total = COSTS_N_INSNS (20);
01895       return true;
01896 
01897     case FLOAT:
01898     case FIX:
01899       *total = 100;
01900       return true;
01901 
01902     default:
01903       return false;
01904     }
01905 }
01906 
01907 /* Compute the cost of an address.  For the SH, all valid addresses are
01908    the same cost.  Use a slightly higher cost for reg + reg addressing,
01909    since it increases pressure on r0.  */
01910 
01911 static int
01912 sh_address_cost (rtx X)
01913 {
01914   return (GET_CODE (X) == PLUS
01915     && ! CONSTANT_P (XEXP (X, 1))
01916     && ! TARGET_SHMEDIA ? 1 : 0);
01917 }
01918 
01919 /* Code to expand a shift.  */
01920 
01921 void
01922 gen_ashift (int type, int n, rtx reg)
01923 {
01924   /* Negative values here come from the shift_amounts array.  */
01925   if (n < 0)
01926     {
01927       if (type == ASHIFT)
01928   type = LSHIFTRT;
01929       else
01930   type = ASHIFT;
01931       n = -n;
01932     }
01933 
01934   switch (type)
01935     {
01936     case ASHIFTRT:
01937       emit_insn (gen_ashrsi3_k (reg, reg, GEN_INT (n)));
01938       break;
01939     case LSHIFTRT:
01940       if (n == 1)
01941   emit_insn (gen_lshrsi3_m (reg, reg, GEN_INT (n)));
01942       else
01943   emit_insn (gen_lshrsi3_k (reg, reg, GEN_INT (n)));
01944       break;
01945     case ASHIFT:
01946       emit_insn (gen_ashlsi3_std (reg, reg, GEN_INT (n)));
01947       break;
01948     }
01949 }
01950 
01951 /* Same for HImode */
01952 
01953 void
01954 gen_ashift_hi (int type, int n, rtx reg)
01955 {
01956   /* Negative values here come from the shift_amounts array.  */
01957   if (n < 0)
01958     {
01959       if (type == ASHIFT)
01960   type = LSHIFTRT;
01961       else
01962   type = ASHIFT;
01963       n = -n;
01964     }
01965 
01966   switch (type)
01967     {
01968     case ASHIFTRT:
01969     case LSHIFTRT:
01970       /* We don't have HImode right shift operations because using the
01971    ordinary 32 bit shift instructions for that doesn't generate proper
01972    zero/sign extension.
01973    gen_ashift_hi is only called in contexts where we know that the
01974    sign extension works out correctly.  */
01975       {
01976   int offset = 0;
01977   if (GET_CODE (reg) == SUBREG)
01978     {
01979       offset = SUBREG_BYTE (reg);
01980       reg = SUBREG_REG (reg);
01981     }
01982   gen_ashift (type, n, gen_rtx_SUBREG (SImode, reg, offset));
01983   break;
01984       }
01985     case ASHIFT:
01986       emit_insn (gen_ashlhi3_k (reg, reg, GEN_INT (n)));
01987       break;
01988     }
01989 }
01990 
01991 /* Output RTL to split a constant shift into its component SH constant
01992    shift instructions.  */
01993 
01994 void
01995 gen_shifty_op (int code, rtx *operands)
01996 {
01997   int value = INTVAL (operands[2]);
01998   int max, i;
01999 
02000   /* Truncate the shift count in case it is out of bounds.  */
02001   value = value & 0x1f;
02002 
02003   if (value == 31)
02004     {
02005       if (code == LSHIFTRT)
02006   {
02007     emit_insn (gen_rotlsi3_1 (operands[0], operands[0]));
02008     emit_insn (gen_movt (operands[0]));
02009     return;
02010   }
02011       else if (code == ASHIFT)
02012   {
02013     /* There is a two instruction sequence for 31 bit left shifts,
02014        but it requires r0.  */
02015     if (GET_CODE (operands[0]) == REG && REGNO (operands[0]) == 0)
02016       {
02017         emit_insn (gen_andsi3 (operands[0], operands[0], const1_rtx));
02018         emit_insn (gen_rotlsi3_31 (operands[0], operands[0]));
02019         return;
02020       }
02021   }
02022     }
02023   else if (value == 0)
02024     {
02025       /* This can happen when not optimizing.  We must output something here
02026    to prevent the compiler from aborting in final.c after the try_split
02027    call.  */
02028       emit_insn (gen_nop ());
02029       return;
02030     }
02031 
02032   max = shift_insns[value];
02033   for (i = 0; i < max; i++)
02034     gen_ashift (code, shift_amounts[value][i], operands[0]);
02035 }
02036 
02037 /* Same as above, but optimized for values where the topmost bits don't
02038    matter.  */
02039 
02040 void
02041 gen_shifty_hi_op (int code, rtx *operands)
02042 {
02043   int value = INTVAL (operands[2]);
02044   int max, i;
02045   void (*gen_fun) (int, int, rtx);
02046 
02047   /* This operation is used by and_shl for SImode values with a few
02048      high bits known to be cleared.  */
02049   value &= 31;
02050   if (value == 0)
02051     {
02052       emit_insn (gen_nop ());
02053       return;
02054     }
02055 
02056   gen_fun = GET_MODE (operands[0]) == HImode ? gen_ashift_hi : gen_ashift;
02057   if (code == ASHIFT)
02058     {
02059       max = ext_shift_insns[value];
02060       for (i = 0; i < max; i++)
02061   gen_fun (code, ext_shift_amounts[value][i], operands[0]);
02062     }
02063   else
02064     /* When shifting right, emit the shifts in reverse order, so that
02065        solitary negative values come first.  */
02066     for (i = ext_shift_insns[value] - 1; i >= 0; i--)
02067       gen_fun (code, ext_shift_amounts[value][i], operands[0]);
02068 }
02069 
02070 /* Output RTL for an arithmetic right shift.  */
02071 
02072 /* ??? Rewrite to use super-optimizer sequences.  */
02073 
02074 int
02075 expand_ashiftrt (rtx *operands)
02076 {
02077   rtx sym;
02078   rtx wrk;
02079   char func[18];
02080   tree func_name;
02081   int value;
02082 
02083   if (TARGET_SH3)
02084     {
02085       if (GET_CODE (operands[2]) != CONST_INT)
02086   {
02087     rtx count = copy_to_mode_reg (SImode, operands[2]);
02088     emit_insn (gen_negsi2 (count, count));
02089     emit_insn (gen_ashrsi3_d (operands[0], operands[1], count));
02090     return 1;
02091   }
02092       else if (ashiftrt_insns[INTVAL (operands[2]) & 31]
02093          > 1 + SH_DYNAMIC_SHIFT_COST)
02094   {
02095     rtx count
02096       = force_reg (SImode, GEN_INT (- (INTVAL (operands[2]) & 31)));
02097     emit_insn (gen_ashrsi3_d (operands[0], operands[1], count));
02098     return 1;
02099   }
02100     }
02101   if (GET_CODE (operands[2]) != CONST_INT)
02102     return 0;
02103 
02104   value = INTVAL (operands[2]) & 31;
02105 
02106   if (value == 31)
02107     {
02108       emit_insn (gen_ashrsi2_31 (operands[0], operands[1]));
02109       return 1;
02110     }
02111   else if (value >= 16 && value <= 19)
02112     {
02113       wrk = gen_reg_rtx (SImode);
02114       emit_insn (gen_ashrsi2_16 (wrk, operands[1]));
02115       value -= 16;
02116       while (value--)
02117   gen_ashift (ASHIFTRT, 1, wrk);
02118       emit_move_insn (operands[0], wrk);
02119       return 1;
02120     }
02121   /* Expand a short sequence inline, longer call a magic routine.  */
02122   else if (value <= 5)
02123     {
02124       wrk = gen_reg_rtx (SImode);
02125       emit_move_insn (wrk, operands[1]);
02126       while (value--)
02127   gen_ashift (ASHIFTRT, 1, wrk);
02128       emit_move_insn (operands[0], wrk);
02129       return 1;
02130     }
02131 
02132   wrk = gen_reg_rtx (Pmode);
02133 
02134   /* Load the value into an arg reg and call a helper.  */
02135   emit_move_insn (gen_rtx_REG (SImode, 4), operands[1]);
02136   sprintf (func, "__ashiftrt_r4_%d", value);
02137   func_name = get_identifier (func);
02138   sym = function_symbol (IDENTIFIER_POINTER (func_name));
02139   emit_move_insn (wrk, sym);
02140   emit_insn (gen_ashrsi3_n (GEN_INT (value), wrk));
02141   emit_move_insn (operands[0], gen_rtx_REG (SImode, 4));
02142   return 1;
02143 }
02144 
02145 int
02146 sh_dynamicalize_shift_p (rtx count)
02147 {
02148   return shift_insns[INTVAL (count)] > 1 + SH_DYNAMIC_SHIFT_COST;
02149 }
02150 
02151 /* Try to find a good way to implement the combiner pattern
02152   [(set (match_operand:SI 0 "register_operand" "r")
02153         (and:SI (ashift:SI (match_operand:SI 1 "register_operand" "r")
02154                            (match_operand:SI 2 "const_int_operand" "n"))
02155                 (match_operand:SI 3 "const_int_operand" "n"))) .
02156   LEFT_RTX is operand 2 in the above pattern, and MASK_RTX is operand 3.
02157   return 0 for simple right / left or left/right shift combination.
02158   return 1 for a combination of shifts with zero_extend.
02159   return 2 for a combination of shifts with an AND that needs r0.
02160   return 3 for a combination of shifts with an AND that needs an extra
02161     scratch register, when the three highmost bits of the AND mask are clear.
02162   return 4 for a combination of shifts with an AND that needs an extra
02163     scratch register, when any of the three highmost bits of the AND mask
02164     is set.
02165   If ATTRP is set, store an initial right shift width in ATTRP[0],
02166   and the instruction length in ATTRP[1] .  These values are not valid
02167   when returning 0.
02168   When ATTRP is set and returning 1, ATTRP[2] gets set to the index into
02169   shift_amounts for the last shift value that is to be used before the
02170   sign extend.  */
02171 int
02172 shl_and_kind (rtx left_rtx, rtx mask_rtx, int *attrp)
02173 {
02174   unsigned HOST_WIDE_INT mask, lsb, mask2, lsb2;
02175   int left = INTVAL (left_rtx), right;
02176   int best = 0;
02177   int cost, best_cost = 10000;
02178   int best_right = 0, best_len = 0;
02179   int i;
02180   int can_ext;
02181 
02182   if (left < 0 || left > 31)
02183     return 0;
02184   if (GET_CODE (mask_rtx) == CONST_INT)
02185     mask = (unsigned HOST_WIDE_INT) INTVAL (mask_rtx) >> left;
02186   else
02187     mask = (unsigned HOST_WIDE_INT) GET_MODE_MASK (SImode) >> left;
02188   /* Can this be expressed as a right shift / left shift pair?  */
02189   lsb = ((mask ^ (mask - 1)) >> 1) + 1;
02190   right = exact_log2 (lsb);
02191   mask2 = ~(mask + lsb - 1);
02192   lsb2 = ((mask2 ^ (mask2 - 1)) >> 1) + 1;
02193   /* mask has no zeroes but trailing zeroes <==> ! mask2 */
02194   if (! mask2)
02195     best_cost = shift_insns[right] + shift_insns[right + left];
02196   /* mask has no trailing zeroes <==> ! right */
02197   else if (! right && mask2 == ~(lsb2 - 1))
02198     {
02199       int late_right = exact_log2 (lsb2);
02200       best_cost = shift_insns[left + late_right] + shift_insns[late_right];
02201     }
02202   /* Try to use zero extend.  */
02203   if (mask2 == ~(lsb2 - 1))
02204     {
02205       int width, first;
02206 
02207       for (width = 8; width <= 16; width += 8)
02208   {
02209     /* Can we zero-extend right away?  */
02210     if (lsb2 == (unsigned HOST_WIDE_INT) 1 << width)
02211       {
02212         cost
02213     = 1 + ext_shift_insns[right] + ext_shift_insns[left + right];
02214         if (cost < best_cost)
02215     {
02216       best = 1;
02217       best_cost = cost;
02218       best_right = right;
02219       best_len = cost;
02220       if (attrp)
02221         attrp[2] = -1;
02222     }
02223         continue;
02224       }
02225     /* ??? Could try to put zero extend into initial right shift,
02226        or even shift a bit left before the right shift.  */
02227     /* Determine value of first part of left shift, to get to the
02228        zero extend cut-off point.  */
02229     first = width - exact_log2 (lsb2) + right;
02230     if (first >= 0 && right + left - first >= 0)
02231       {
02232         cost = ext_shift_insns[right] + ext_shift_insns[first] + 1
02233     + ext_shift_insns[right + left - first];
02234         if (cost < best_cost)
02235     {
02236       best = 1;
02237       best_cost = cost;
02238       best_right = right;
02239       best_len = cost;
02240       if (attrp)
02241         attrp[2] = first;
02242     }
02243       }
02244   }
02245     }
02246   /* Try to use r0 AND pattern */
02247   for (i = 0; i <= 2; i++)
02248     {
02249       if (i > right)
02250   break;
02251       if (! CONST_OK_FOR_K08 (mask >> i))
02252   continue;
02253       cost = (i != 0) + 2 + ext_shift_insns[left + i];
02254       if (cost < best_cost)
02255   {
02256     best = 2;
02257     best_cost = cost;
02258     best_right = i;
02259     best_len = cost - 1;
02260   }
02261     }
02262   /* Try to use a scratch register to hold the AND operand.  */
02263   can_ext = ((mask << left) & ((unsigned HOST_WIDE_INT) 3 << 30)) == 0;
02264   for (i = 0; i <= 2; i++)
02265     {
02266       if (i > right)
02267   break;
02268       cost = (i != 0) + (CONST_OK_FOR_I08 (mask >> i) ? 2 : 3)
02269   + (can_ext ? ext_shift_insns : shift_insns)[left + i];
02270       if (cost < best_cost)
02271   {
02272     best = 4 - can_ext;
02273     best_cost = cost;
02274     best_right = i;
02275     best_len = cost - 1 - ! CONST_OK_FOR_I08 (mask >> i);
02276   }
02277     }
02278 
02279   if (attrp)
02280     {
02281       attrp[0] = best_right;
02282       attrp[1] = best_len;
02283     }
02284   return best;
02285 }
02286 
02287 /* This is used in length attributes of the unnamed instructions
02288    corresponding to shl_and_kind return values of 1 and 2.  */
02289 int
02290 shl_and_length (rtx insn)
02291 {
02292   rtx set_src, left_rtx, mask_rtx;
02293   int attributes[3];
02294 
02295   set_src = SET_SRC (XVECEXP (PATTERN (insn), 0, 0));
02296   left_rtx = XEXP (XEXP (set_src, 0), 1);
02297   mask_rtx = XEXP (set_src, 1);
02298   shl_and_kind (left_rtx, mask_rtx, attributes);
02299   return attributes[1];
02300 }
02301 
02302 /* This is used in length attribute of the and_shl_scratch instruction.  */
02303 
02304 int
02305 shl_and_scr_length (rtx insn)
02306 {
02307   rtx set_src = SET_SRC (XVECEXP (PATTERN (insn), 0, 0));
02308   int len = shift_insns[INTVAL (XEXP (set_src, 1))];
02309   rtx op = XEXP (set_src, 0);
02310   len += shift_insns[INTVAL (XEXP (op, 1))] + 1;
02311   op = XEXP (XEXP (op, 0), 0);
02312   return len + shift_insns[INTVAL (XEXP (op, 1))];
02313 }
02314 
02315 /* Generate rtl for instructions for which shl_and_kind advised a particular
02316    method of generating them, i.e. returned zero.  */
02317 
02318 int
02319 gen_shl_and (rtx dest, rtx left_rtx, rtx mask_rtx, rtx source)
02320 {
02321   int attributes[3];
02322   unsigned HOST_WIDE_INT mask;
02323   int kind = shl_and_kind (left_rtx, mask_rtx, attributes);
02324   int right, total_shift;
02325   void (*shift_gen_fun) (int, rtx *) = gen_shifty_hi_op;
02326 
02327   right = attributes[0];
02328   total_shift = INTVAL (left_rtx) + right;
02329   mask = (unsigned HOST_WIDE_INT) INTVAL (mask_rtx) >> total_shift;
02330   switch (kind)
02331     {
02332     default:
02333       return -1;
02334     case 1:
02335       {
02336   int first = attributes[2];
02337   rtx operands[3];
02338 
02339   if (first < 0)
02340     {
02341       emit_insn ((mask << right) <= 0xff
02342            ? gen_zero_extendqisi2 (dest,
02343                  gen_lowpart (QImode, source))
02344            : gen_zero_extendhisi2 (dest,
02345                  gen_lowpart (HImode, source)));
02346       source = dest;
02347     }
02348   if (source != dest)
02349     emit_insn (gen_movsi (dest, source));
02350   operands[0] = dest;
02351   if (right)
02352     {
02353       operands[2] = GEN_INT (right);
02354       gen_shifty_hi_op (LSHIFTRT, operands);
02355     }
02356   if (first > 0)
02357     {
02358       operands[2] = GEN_INT (first);
02359       gen_shifty_hi_op (ASHIFT, operands);
02360       total_shift -= first;
02361       mask <<= first;
02362     }
02363   if (first >= 0)
02364     emit_insn (mask <= 0xff
02365          ? gen_zero_extendqisi2 (dest, gen_lowpart (QImode, dest))
02366          : gen_zero_extendhisi2 (dest, gen_lowpart (HImode, dest)));
02367   if (total_shift > 0)
02368     {
02369       operands[2] = GEN_INT (total_shift);
02370       gen_shifty_hi_op (ASHIFT, operands);
02371     }
02372   break;
02373       }
02374     case 4:
02375       shift_gen_fun = gen_shifty_op;
02376     case 3:
02377       /* If the topmost bit that matters is set, set the topmost bits
02378    that don't matter.  This way, we might be able to get a shorter
02379    signed constant.  */
02380       if (mask & ((HOST_WIDE_INT) 1 << (31 - total_shift)))
02381   mask |= (HOST_WIDE_INT) ~0 << (31 - total_shift);
02382     case 2:
02383       /* Don't expand fine-grained when combining, because that will
02384          make the pattern fail.  */
02385       if (currently_expanding_to_rtl
02386     || reload_in_progress || reload_completed)
02387   {
02388     rtx operands[3];
02389 
02390     /* Cases 3 and 4 should be handled by this split
02391        only while combining  */
02392     if (kind > 2)
02393       abort ();
02394     if (right)
02395       {
02396         emit_insn (gen_lshrsi3 (dest, source, GEN_INT (right)));
02397         source = dest;
02398       }
02399     emit_insn (gen_andsi3 (dest, source, GEN_INT (mask)));
02400     if (total_shift)
02401       {
02402         operands[0] = dest;
02403         operands[1] = dest;
02404         operands[2] = GEN_INT (total_shift);
02405         shift_gen_fun (ASHIFT, operands);
02406       }
02407     break;
02408   }
02409       else
02410   {
02411     int neg = 0;
02412     if (kind != 4 && total_shift < 16)
02413       {
02414         neg = -ext_shift_amounts[total_shift][1];
02415         if (neg > 0)
02416     neg -= ext_shift_amounts[total_shift][2];
02417         else
02418     neg = 0;
02419       }
02420     emit_insn (gen_and_shl_scratch (dest, source,
02421             GEN_INT (right),
02422             GEN_INT (mask),
02423             GEN_INT (total_shift + neg),
02424             GEN_INT (neg)));
02425     emit_insn (gen_movsi (dest, dest));
02426     break;
02427   }
02428     }
02429   return 0;
02430 }
02431 
02432 /* Try to find a good way to implement the combiner pattern
02433   [(set (match_operand:SI 0 "register_operand" "=r")
02434         (sign_extract:SI (ashift:SI (match_operand:SI 1 "register_operand" "r")
02435                                     (match_operand:SI 2 "const_int_operand" "n")
02436                          (match_operand:SI 3 "const_int_operand" "n")
02437                          (const_int 0)))
02438    (clobber (reg:SI T_REG))]
02439   LEFT_RTX is operand 2 in the above pattern, and SIZE_RTX is operand 3.
02440   return 0 for simple left / right shift combination.
02441   return 1 for left shift / 8 bit sign extend / left shift.
02442   return 2 for left shift / 16 bit sign extend / left shift.
02443   return 3 for left shift / 8 bit sign extend / shift / sign extend.
02444   return 4 for left shift / 16 bit sign extend / shift / sign extend.
02445   return 5 for left shift / 16 bit sign extend / right shift
02446   return 6 for < 8 bit sign extend / left shift.
02447   return 7 for < 8 bit sign extend / left shift / single right shift.
02448   If COSTP is nonzero, assign the calculated cost to *COSTP.  */
02449 
02450 int
02451 shl_sext_kind (rtx left_rtx, rtx size_rtx, int *costp)
02452 {
02453   int left, size, insize, ext;
02454   int cost = 0, best_cost;
02455   int kind;
02456 
02457   left = INTVAL (left_rtx);
02458   size = INTVAL (size_rtx);
02459   insize = size - left;
02460   if (insize <= 0)
02461     abort ();
02462   /* Default to left / right shift.  */
02463   kind = 0;
02464   best_cost = shift_insns[32 - insize] + ashiftrt_insns[32 - size];
02465   if (size <= 16)
02466     {
02467       /* 16 bit shift / sign extend / 16 bit shift */
02468       cost = shift_insns[16 - insize] + 1 + ashiftrt_insns[16 - size];
02469       /* If ashiftrt_insns[16 - size] is 8, this choice will be overridden
02470    below, by alternative 3 or something even better.  */
02471       if (cost < best_cost)
02472   {
02473     kind = 5;
02474     best_cost = cost;
02475   }
02476     }
02477   /* Try a plain sign extend between two shifts.  */
02478   for (ext = 16; ext >= insize; ext -= 8)
02479     {
02480       if (ext <= size)
02481   {
02482     cost = ext_shift_insns[ext - insize] + 1 + shift_insns[size - ext];
02483     if (cost < best_cost)
02484       {
02485         kind = ext / (unsigned) 8;
02486         best_cost = cost;
02487       }
02488   }
02489       /* Check if we can do a sloppy shift with a final signed shift
02490    restoring the sign.  */
02491       if (EXT_SHIFT_SIGNED (size - ext))
02492   cost = ext_shift_insns[ext - insize] + ext_shift_insns[size - ext] + 1;
02493       /* If not, maybe it's still cheaper to do the second shift sloppy,
02494    and do a final sign extend?  */
02495       else if (size <= 16)
02496   cost = ext_shift_insns[ext - insize] + 1
02497     + ext_shift_insns[size > ext ? size - ext : ext - size] + 1;
02498       else
02499   continue;
02500       if (cost < best_cost)
02501   {
02502     kind = ext / (unsigned) 8 + 2;
02503     best_cost = cost;
02504   }
02505     }
02506   /* Check if we can sign extend in r0 */
02507   if (insize < 8)
02508     {
02509       cost = 3 + shift_insns[left];
02510       if (cost < best_cost)
02511   {
02512     kind = 6;
02513     best_cost = cost;
02514   }
02515       /* Try the same with a final signed shift.  */
02516       if (left < 31)
02517   {
02518     cost = 3 + ext_shift_insns[left + 1] + 1;
02519     if (cost < best_cost)
02520       {
02521         kind = 7;
02522         best_cost = cost;
02523       }
02524   }
02525     }
02526   if (TARGET_SH3)
02527     {
02528       /* Try to use a dynamic shift.  */
02529       cost = shift_insns[32 - insize] + 1 + SH_DYNAMIC_SHIFT_COST;
02530       if (cost < best_cost)
02531   {
02532     kind = 0;
02533     best_cost = cost;
02534   }
02535     }
02536   if (costp)
02537     *costp = cost;
02538   return kind;
02539 }
02540 
02541 /* Function to be used in the length attribute of the instructions
02542    implementing this pattern.  */
02543 
02544 int
02545 shl_sext_length (rtx insn)
02546 {
02547   rtx set_src, left_rtx, size_rtx;
02548   int cost;
02549 
02550   set_src = SET_SRC (XVECEXP (PATTERN (insn), 0, 0));
02551   left_rtx = XEXP (XEXP (set_src, 0), 1);
02552   size_rtx = XEXP (set_src, 1);
02553   shl_sext_kind (left_rtx, size_rtx, &cost);
02554   return cost;
02555 }
02556 
02557 /* Generate rtl for this pattern */
02558 
02559 int
02560 gen_shl_sext (rtx dest, rtx left_rtx, rtx size_rtx, rtx source)
02561 {
02562   int kind;
02563   int left, size, insize, cost;
02564   rtx operands[3];
02565 
02566   kind = shl_sext_kind (left_rtx, size_rtx, &cost);
02567   left = INTVAL (left_rtx);
02568   size = INTVAL (size_rtx);
02569   insize = size - left;
02570   switch (kind)
02571     {
02572     case 1:
02573     case 2:
02574     case 3:
02575     case 4:
02576       {
02577   int ext = kind & 1 ? 8 : 16;
02578   int shift2 = size - ext;
02579 
02580   /* Don't expand fine-grained when combining, because that will
02581      make the pattern fail.  */
02582   if (! currently_expanding_to_rtl
02583       && ! reload_in_progress && ! reload_completed)
02584     {
02585       emit_insn (gen_shl_sext_ext (dest, source, left_rtx, size_rtx));
02586       emit_insn (gen_movsi (dest, source));
02587       break;
02588     }
02589   if (dest != source)
02590     emit_insn (gen_movsi (dest, source));
02591   operands[0] = dest;
02592   if (ext - insize)
02593     {
02594       operands[2] = GEN_INT (ext - insize);
02595       gen_shifty_hi_op (ASHIFT, operands);
02596     }
02597   emit_insn (kind & 1
02598        ? gen_extendqisi2 (dest, gen_lowpart (QImode, dest))
02599        : gen_extendhisi2 (dest, gen_lowpart (HImode, dest)));
02600   if (kind <= 2)
02601     {
02602       if (shift2)
02603         {
02604     operands[2] = GEN_INT (shift2);
02605     gen_shifty_op (ASHIFT, operands);
02606         }
02607     }
02608   else
02609     {
02610       if (shift2 > 0)
02611         {
02612     if (EXT_SHIFT_SIGNED (shift2))
02613       {
02614         operands[2] = GEN_INT (shift2 + 1);
02615         gen_shifty_op (ASHIFT, operands);
02616         operands[2] = const1_rtx;
02617         gen_shifty_op (ASHIFTRT, operands);
02618         break;
02619       }
02620     operands[2] = GEN_INT (shift2);
02621     gen_shifty_hi_op (ASHIFT, operands);
02622         }
02623       else if (shift2)
02624         {
02625     operands[2] = GEN_INT (-shift2);
02626     gen_shifty_hi_op (LSHIFTRT, operands);
02627         }
02628       emit_insn (size <= 8
02629            ? gen_extendqisi2 (dest, gen_lowpart (QImode, dest))
02630            : gen_extendhisi2 (dest, gen_lowpart (HImode, dest)));
02631     }
02632   break;
02633       }
02634     case 5:
02635       {
02636   int i = 16 - size;
02637   if (! currently_expanding_to_rtl
02638       && ! reload_in_progress && ! reload_completed)
02639     emit_insn (gen_shl_sext_ext (dest, source, left_rtx, size_rtx));
02640   else
02641     {
02642       operands[0] = dest;
02643       operands[2] = GEN_INT (16 - insize);
02644       gen_shifty_hi_op (ASHIFT, operands);
02645       emit_insn (gen_extendhisi2 (dest, gen_lowpart (HImode, dest)));
02646     }
02647   /* Don't use gen_ashrsi3 because it generates new pseudos.  */
02648   while (--i >= 0)
02649     gen_ashift (ASHIFTRT, 1, dest);
02650   break;
02651       }
02652     case 6:
02653     case 7:
02654       /* Don't expand fine-grained when combining, because that will
02655    make the pattern fail.  */
02656       if (! currently_expanding_to_rtl
02657     && ! reload_in_progress && ! reload_completed)
02658   {
02659     emit_insn (gen_shl_sext_ext (dest, source, left_rtx, size_rtx));
02660     emit_insn (gen_movsi (dest, source));
02661     break;
02662   }
02663       emit_insn (gen_andsi3 (dest, source, GEN_INT ((1 << insize) - 1)));
02664       emit_insn (gen_xorsi3 (dest, dest, GEN_INT (1 << (insize - 1))));
02665       emit_insn (gen_addsi3 (dest, dest, GEN_INT (-1 << (insize - 1))));
02666       operands[0] = dest;
02667       operands[2] = kind == 7 ? GEN_INT (left + 1) : left_rtx;
02668       gen_shifty_op (ASHIFT, operands);
02669       if (kind == 7)
02670   emit_insn (gen_ashrsi3_k (dest, dest, const1_rtx));
02671       break;
02672     default:
02673       return -1;
02674     }
02675   return 0;
02676 }
02677 
02678 /* Prefix a symbol_ref name with "datalabel".  */
02679 
02680 rtx
02681 gen_datalabel_ref (rtx sym)
02682 {
02683   if (GET_CODE (sym) == LABEL_REF)
02684     return gen_rtx_CONST (GET_MODE (sym),
02685         gen_rtx_UNSPEC (GET_MODE (sym),
02686             gen_rtvec (1, sym),
02687             UNSPEC_DATALABEL));
02688 
02689   if (GET_CODE (sym) != SYMBOL_REF)
02690     abort ();
02691 
02692   return sym;
02693 }
02694 
02695 
02696 /* The SH cannot load a large constant into a register, constants have to
02697    come from a pc relative load.  The reference of a pc relative load
02698    instruction must be less than 1k infront of the instruction.  This
02699    means that we often have to dump a constant inside a function, and
02700    generate code to branch around it.
02701 
02702    It is important to minimize this, since the branches will slow things
02703    down and make things bigger.
02704 
02705    Worst case code looks like:
02706 
02707    mov.l L1,rn
02708    bra   L2
02709    nop
02710    align
02711    L1:   .long value
02712    L2:
02713    ..
02714 
02715    mov.l L3,rn
02716    bra   L4
02717    nop
02718    align
02719    L3:   .long value
02720    L4:
02721    ..
02722 
02723    We fix this by performing a scan before scheduling, which notices which
02724    instructions need to have their operands fetched from the constant table
02725    and builds the table.
02726 
02727    The algorithm is:
02728 
02729    scan, find an instruction which needs a pcrel move.  Look forward, find the
02730    last barrier which is within MAX_COUNT bytes of the requirement.
02731    If there isn't one, make one.  Process all the instructions between
02732    the find and the barrier.
02733 
02734    In the above example, we can tell that L3 is within 1k of L1, so
02735    the first move can be shrunk from the 3 insn+constant sequence into
02736    just 1 insn, and the constant moved to L3 to make:
02737 
02738    mov.l        L1,rn
02739    ..
02740    mov.l        L3,rn
02741    bra          L4
02742    nop
02743    align
02744    L3:.long value
02745    L4:.long value
02746 
02747    Then the second move becomes the target for the shortening process.  */
02748 
02749 typedef struct
02750 {
02751   rtx value;      /* Value in table.  */
02752   rtx label;      /* Label of value.  */
02753   rtx wend;     /* End of window.  */
02754   enum machine_mode mode; /* Mode of value.  */
02755 
02756   /* True if this constant is accessed as part of a post-increment
02757      sequence.  Note that HImode constants are never accessed in this way.  */
02758   bool part_of_sequence_p;
02759 } pool_node;
02760 
02761 /* The maximum number of constants that can fit into one pool, since
02762    the pc relative range is 0...1020 bytes and constants are at least 4
02763    bytes long.  */
02764 
02765 #define MAX_POOL_SIZE (1020/4)
02766 static pool_node pool_vector[MAX_POOL_SIZE];
02767 static int pool_size;
02768 static rtx pool_window_label;
02769 static int pool_window_last;
02770 
02771 /* ??? If we need a constant in HImode which is the truncated value of a
02772    constant we need in SImode, we could combine the two entries thus saving
02773    two bytes.  Is this common enough to be worth the effort of implementing
02774    it?  */
02775 
02776 /* ??? This stuff should be done at the same time that we shorten branches.
02777    As it is now, we must assume that all branches are the maximum size, and
02778    this causes us to almost always output constant pools sooner than
02779    necessary.  */
02780 
02781 /* Add a constant to the pool and return its label.  */
02782 
02783 static rtx
02784 add_constant (rtx x, enum machine_mode mode, rtx last_value)
02785 {
02786   int i;
02787   rtx lab, new, ref, newref;
02788 
02789   /* First see if we've already got it.  */
02790   for (i = 0; i < pool_size; i++)
02791     {
02792       if (x->code == pool_vector[i].value->code
02793     && mode == pool_vector[i].mode)
02794   {
02795     if (x->code == CODE_LABEL)
02796       {
02797         if (XINT (x, 3) != XINT (pool_vector[i].value, 3))
02798     continue;
02799       }
02800     if (rtx_equal_p (x, pool_vector[i].value))
02801       {
02802         lab = new = 0;
02803         if (! last_value
02804       || ! i
02805       || ! rtx_equal_p (last_value, pool_vector[i-1].value))
02806     {
02807       new = gen_label_rtx ();
02808       LABEL_REFS (new) = pool_vector[i].label;
02809       pool_vector[i].label = lab = new;
02810     }
02811         if (lab && pool_window_label)
02812     {
02813       newref = gen_rtx_LABEL_REF (VOIDmode, pool_window_label);
02814       ref = pool_vector[pool_window_last].wend;
02815       LABEL_NEXTREF (newref) = ref;
02816       pool_vector[pool_window_last].wend = newref;
02817     }
02818         if (new)
02819     pool_window_label = new;
02820         pool_window_last = i;
02821         return lab;
02822       }
02823   }
02824     }
02825 
02826   /* Need a new one.  */
02827   pool_vector[pool_size].value = x;
02828   if (last_value && rtx_equal_p (last_value, pool_vector[pool_size - 1].value))
02829     {
02830       lab = 0;
02831       pool_vector[pool_size - 1].part_of_sequence_p = true;
02832     }
02833   else
02834     lab = gen_label_rtx ();
02835   pool_vector[pool_size].mode = mode;
02836   pool_vector[pool_size].label = lab;
02837   pool_vector[pool_size].wend = NULL_RTX;
02838   pool_vector[pool_size].part_of_sequence_p = (lab == 0);
02839   if (lab && pool_window_label)
02840     {
02841       newref = gen_rtx_LABEL_REF (VOIDmode, pool_window_label);
02842       ref = pool_vector[pool_window_last].wend;
02843       LABEL_NEXTREF (newref) = ref;
02844       pool_vector[pool_window_last].wend = newref;
02845     }
02846   if (lab)
02847     pool_window_label = lab;
02848   pool_window_last = pool_size;
02849   pool_size++;
02850   return lab;
02851 }
02852 
02853 /* Output the literal table.  START, if nonzero, is the first instruction
02854    this table is needed for, and also indicates that there is at least one
02855    casesi_worker_2 instruction; We have to emit the operand3 labels from
02856    these insns at a 4-byte  aligned position.  BARRIER is the barrier
02857    after which we are to place the table.  */
02858 
02859 static void
02860 dump_table (rtx start, rtx barrier)
02861 {
02862   rtx scan = barrier;
02863   int i;
02864   int need_align = 1;
02865   rtx lab, ref;
02866   int have_df = 0;
02867 
02868   /* Do two passes, first time dump out the HI sized constants.  */
02869 
02870   for (i = 0; i < pool_size; i++)
02871     {
02872       pool_node *p = &pool_vector[i];
02873 
02874       if (p->mode == HImode)
02875   {
02876     if (need_align)
02877       {
02878         scan = emit_insn_after (gen_align_2 (), scan);
02879         need_align = 0;
02880       }
02881     for (lab = p->label; lab; lab = LABEL_REFS (lab))
02882       scan = emit_label_after (lab, scan);
02883     scan = emit_insn_after (gen_consttable_2 (p->value, const0_rtx),
02884           scan);
02885     for (ref = p->wend; ref; ref = LABEL_NEXTREF (ref))
02886       {
02887         lab = XEXP (ref, 0);
02888         scan = emit_insn_after (gen_consttable_window_end (lab), scan);
02889       }
02890   }
02891       else if (p->mode == DFmode)
02892   have_df = 1;
02893     }
02894 
02895   need_align = 1;
02896 
02897   if (start)
02898     {
02899       scan = emit_insn_after (gen_align_4 (), scan);
02900       need_align = 0;
02901       for (; start != barrier; start = NEXT_INSN (start))
02902   if (GET_CODE (start) == INSN
02903       && recog_memoized (start) == CODE_FOR_casesi_worker_2)
02904     {
02905       rtx src = SET_SRC (XVECEXP (PATTERN (start), 0, 0));
02906       rtx lab = XEXP (XVECEXP (src, 0, 3), 0);
02907 
02908       scan = emit_label_after (lab, scan);
02909     }
02910     }
02911   if (TARGET_FMOVD && TARGET_ALIGN_DOUBLE && have_df)
02912     {
02913       rtx align_insn = NULL_RTX;
02914 
02915       scan = emit_label_after (gen_label_rtx (), scan);
02916       scan = emit_insn_after (gen_align_log (GEN_INT (3)), scan);
02917       need_align = 0;
02918 
02919       for (i = 0; i < pool_size; i++)
02920   {
02921     pool_node *p = &pool_vector[i];
02922 
02923     switch (p->mode)
02924       {
02925       case HImode:
02926         break;
02927       case SImode:
02928       case SFmode:
02929         if (align_insn && !p->part_of_sequence_p)
02930     {
02931       for (lab = p->label; lab; lab = LABEL_REFS (lab))
02932         emit_label_before (lab, align_insn);
02933       emit_insn_before (gen_consttable_4 (p->value, const0_rtx),
02934             align_insn);
02935       for (ref = p->wend; ref; ref = LABEL_NEXTREF (ref))
02936         {
02937           lab = XEXP (ref, 0);
02938           emit_insn_before (gen_consttable_window_end (lab),
02939           align_insn);
02940         }
02941       delete_insn (align_insn);
02942       align_insn = NULL_RTX;
02943       continue;
02944     }
02945         else
02946     {
02947       for (lab = p->label; lab; lab = LABEL_REFS (lab))
02948         scan = emit_label_after (lab, scan);
02949       scan = emit_insn_after (gen_consttable_4 (p->value,
02950                   const0_rtx), scan);
02951       need_align = ! need_align;
02952     }
02953         break;
02954       case DFmode:
02955         if (need_align)
02956     {
02957       scan = emit_insn_after (gen_align_log (GEN_INT (3)), scan);
02958       align_insn = scan;
02959       need_align = 0;
02960     }
02961       case DImode:
02962         for (lab = p->label; lab; lab = LABEL_REFS (lab))
02963     scan = emit_label_after (lab, scan);
02964         scan = emit_insn_after (gen_consttable_8 (p->value, const0_rtx),
02965               scan);
02966         break;
02967       default:
02968         abort ();
02969         break;
02970       }
02971 
02972     if (p->mode != HImode)
02973       {
02974         for (ref = p->wend; ref; ref = LABEL_NEXTREF (ref))
02975     {
02976       lab = XEXP (ref, 0);
02977       scan = emit_insn_after (gen_consttable_window_end (lab),
02978             scan);
02979     }
02980       }
02981   }
02982 
02983       pool_size = 0;
02984     }
02985 
02986   for (i = 0; i < pool_size; i++)
02987     {
02988       pool_node *p = &pool_vector[i];
02989 
02990       switch (p->mode)
02991   {
02992   case HImode:
02993     break;
02994   case SImode:
02995   case SFmode:
02996     if (need_align)
02997       {
02998         need_align = 0;
02999         scan = emit_label_after (gen_label_rtx (), scan);
03000         scan = emit_insn_after (gen_align_4 (), scan);
03001       }
03002     for (lab = p->label; lab; lab = LABEL_REFS (lab))
03003       scan = emit_label_after (lab, scan);
03004     scan = emit_insn_after (gen_consttable_4 (p->value, const0_rtx),
03005           scan);
03006     break;
03007   case DFmode:
03008   case DImode:
03009     if (need_align)
03010       {
03011         need_align = 0;
03012         scan = emit_label_after (gen_label_rtx (), scan);
03013         scan = emit_insn_after (gen_align_4 (), scan);
03014       }
03015     for (lab = p->label; lab; lab = LABEL_REFS (lab))
03016       scan = emit_label_after (lab, scan);
03017     scan = emit_insn_after (gen_consttable_8 (p->value, const0_rtx),
03018           scan);
03019     break;
03020   default:
03021     abort ();
03022     break;
03023   }
03024 
03025       if (p->mode != HImode)
03026   {
03027     for (ref = p->wend; ref; ref = LABEL_NEXTREF (ref))
03028       {
03029         lab = XEXP (ref, 0);
03030         scan = emit_insn_after (gen_consttable_window_end (lab), scan);
03031       }
03032   }
03033     }
03034 
03035   scan = emit_insn_after (gen_consttable_end (), scan);
03036   scan = emit_barrier_after (scan);
03037   pool_size = 0;
03038   pool_window_label = NULL_RTX;
03039   pool_window_last = 0;
03040 }
03041 
03042 /* Return nonzero if constant would be an ok source for a
03043    mov.w instead of a mov.l.  */
03044 
03045 static int
03046 hi_const (rtx src)
03047 {
03048   return (GET_CODE (src) == CONST_INT
03049     && INTVAL (src) >= -32768
03050     && INTVAL (src) <= 32767);
03051 }
03052 
03053 /* Nonzero if the insn is a move instruction which needs to be fixed.  */
03054 
03055 /* ??? For a DImode/DFmode moves, we don't need to fix it if each half of the
03056    CONST_DOUBLE input value is CONST_OK_FOR_I08.  For a SFmode move, we don't
03057    need to fix it if the input value is CONST_OK_FOR_I08.  */
03058 
03059 static int
03060 broken_move (rtx insn)
03061 {
03062   if (GET_CODE (insn) == INSN)
03063     {
03064       rtx pat = PATTERN (insn);
03065       if (GET_CODE (pat) == PARALLEL)
03066   pat = XVECEXP (pat, 0, 0);
03067       if (GET_CODE (pat) == SET
03068     /* We can load any 8 bit value if we don't care what the high
03069        order bits end up as.  */
03070     && GET_MODE (SET_DEST (pat)) != QImode
03071     && (CONSTANT_P (SET_SRC (pat))
03072         /* Match mova_const.  */
03073         || (GET_CODE (SET_SRC (pat)) == UNSPEC
03074       && XINT (SET_SRC (pat), 1) == UNSPEC_MOVA
03075       && GET_CODE (XVECEXP (SET_SRC (pat), 0, 0)) == CONST))
03076     && ! (TARGET_SH2E
03077     && GET_CODE (SET_SRC (pat)) == CONST_DOUBLE
03078     && (fp_zero_operand (SET_SRC (pat))
03079         || fp_one_operand (SET_SRC (pat)))
03080     /* ??? If this is a -m4 or -m4-single compilation, in general
03081        we don't know the current setting of fpscr, so disable fldi.
03082        There is an exception if this was a register-register move
03083        before reload - and hence it was ascertained that we have
03084        single precision setting - and in a post-reload optimization
03085        we changed this to do a constant load.  In that case
03086        we don't have an r0 clobber, hence we must use fldi.  */
03087     && (! TARGET_SH4 || TARGET_FMOVD
03088         || (GET_CODE (XEXP (XVECEXP (PATTERN (insn), 0, 2), 0))
03089       == SCRATCH))
03090     && GET_CODE (SET_DEST (pat)) == REG
03091     && FP_REGISTER_P (REGNO (SET_DEST (pat))))
03092     && ! (TARGET_SH2A
03093     && GET_MODE (SET_DEST (pat)) == SImode
03094     && GET_CODE (SET_SRC (pat)) == CONST_INT
03095     && CONST_OK_FOR_I20 (INTVAL (SET_SRC (pat))))
03096     && (GET_CODE (SET_SRC (pat)) != CONST_INT
03097         || ! CONST_OK_FOR_I08 (INTVAL (SET_SRC (pat)))))
03098   return 1;
03099     }
03100 
03101   return 0;
03102 }
03103 
03104 static int
03105 mova_p (rtx insn)
03106 {
03107   return (GET_CODE (insn) == INSN
03108     && GET_CODE (PATTERN (insn)) == SET
03109     && GET_CODE (SET_SRC (PATTERN (insn))) == UNSPEC
03110     && XINT (SET_SRC (PATTERN (insn)), 1) == UNSPEC_MOVA
03111     /* Don't match mova_const.  */
03112     && GET_CODE (XVECEXP (SET_SRC (PATTERN (insn)), 0, 0)) == LABEL_REF);
03113 }
03114 
03115 /* Fix up a mova from a switch that went out of range.  */
03116 static void
03117 fixup_mova (rtx mova)
03118 {
03119   if (! flag_pic)
03120     {
03121       SET_SRC (PATTERN (mova)) = XVECEXP (SET_SRC (PATTERN (mova)), 0, 0);
03122       INSN_CODE (mova) = -1;
03123     }
03124   else
03125     {
03126       rtx worker = mova;
03127       rtx lab = gen_label_rtx ();
03128       rtx wpat, wpat0, wpat1, wsrc, diff;
03129 
03130       do
03131   {
03132     worker = NEXT_INSN (worker);
03133     if (! worker
03134         || GET_CODE (worker) == CODE_LABEL
03135         || GET_CODE (worker) == JUMP_INSN)
03136       abort ();
03137   } while (recog_memoized (worker) != CODE_FOR_casesi_worker_1);
03138       wpat = PATTERN (worker);
03139       wpat0 = XVECEXP (wpat, 0, 0);
03140       wpat1 = XVECEXP (wpat, 0, 1);
03141       wsrc = SET_SRC (wpat0);
03142       PATTERN (worker) = (gen_casesi_worker_2
03143         (SET_DEST (wpat0), XVECEXP (wsrc, 0, 1),
03144          XEXP (XVECEXP (wsrc, 0, 2), 0), lab,
03145          XEXP (wpat1, 0)));
03146       INSN_CODE (worker) = -1;
03147       diff = gen_rtx_MINUS (Pmode, XVECEXP (SET_SRC (PATTERN (mova)), 0, 0),
03148           gen_rtx_LABEL_REF (Pmode, lab));
03149       diff = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, diff), UNSPEC_PIC);
03150       SET_SRC (PATTERN (mova)) = gen_rtx_CONST (Pmode, diff);
03151       INSN_CODE (mova) = -1;
03152     }
03153 }
03154 
03155 /* Find the last barrier from insn FROM which is close enough to hold the
03156    constant pool.  If we can't find one, then create one near the end of
03157    the range.  */
03158 
03159 static rtx
03160 find_barrier (int num_mova, rtx mova, rtx from)
03161 {
03162   int count_si = 0;
03163   int count_hi = 0;
03164   int found_hi = 0;
03165   int found_si = 0;
03166   int found_di = 0;
03167   int hi_align = 2;
03168   int si_align = 2;
03169   int leading_mova = num_mova;
03170   rtx barrier_before_mova = 0, found_barrier = 0, good_barrier = 0;
03171   int si_limit;
03172   int hi_limit;
03173 
03174   /* For HImode: range is 510, add 4 because pc counts from address of
03175      second instruction after this one, subtract 2 for the jump instruction
03176      that we may need to emit before the table, subtract 2 for the instruction
03177      that fills the jump delay slot (in very rare cases, reorg will take an
03178      instruction from after the constant pool or will leave the delay slot
03179      empty).  This gives 510.
03180      For SImode: range is 1020, add 4 because pc counts from address of
03181      second instruction after this one, subtract 2 in case pc is 2 byte
03182      aligned, subtract 2 for the jump instruction that we may need to emit
03183      before the table, subtract 2 for the instruction that fills the jump
03184      delay slot.  This gives 1018.  */
03185 
03186   /* The branch will always be shortened now that the reference address for
03187      forward branches is the successor address, thus we need no longer make
03188      adjustments to the [sh]i_limit for -O0.  */
03189 
03190   si_limit = 1018;
03191   hi_limit = 510;
03192 
03193   while (from && count_si < si_limit && count_hi < hi_limit)
03194     {
03195       int inc = get_attr_length (from);
03196       int new_align = 1;
03197 
03198       if (GET_CODE (from) == CODE_LABEL)
03199   {
03200     if (optimize)
03201       new_align = 1 << label_to_alignment (from);
03202     else if (GET_CODE (prev_nonnote_insn (from)) == BARRIER)
03203       new_align = 1 << barrier_align (from);
03204     else
03205       new_align = 1;
03206     inc = 0;
03207   }
03208 
03209       if (GET_CODE (from) == BARRIER)
03210   {
03211 
03212     found_barrier = from;
03213 
03214     /* If we are at the end of the function, or in front of an alignment
03215        instruction, we need not insert an extra alignment.  We prefer
03216        this kind of barrier.  */
03217     if (barrier_align (from) > 2)
03218       good_barrier = from;
03219   }
03220 
03221       if (broken_move (from))
03222   {
03223     rtx pat, src, dst;
03224     enum machine_mode mode;
03225 
03226     pat = PATTERN (from);
03227     if (GET_CODE (pat) == PARALLEL)
03228       pat = XVECEXP (pat, 0, 0);
03229     src = SET_SRC (pat);
03230     dst = SET_DEST (pat);
03231     mode = GET_MODE (dst);
03232 
03233     /* We must explicitly check the mode, because sometimes the
03234        front end will generate code to load unsigned constants into
03235        HImode targets without properly sign extending them.  */
03236     if (mode == HImode
03237         || (mode == SImode && hi_const (src) && REGNO (dst) != FPUL_REG))
03238       {
03239         found_hi += 2;
03240         /* We put the short constants before the long constants, so
03241      we must count the length of short constants in the range
03242      for the long constants.  */
03243         /* ??? This isn't optimal, but is easy to do.  */
03244         si_limit -= 2;
03245       }
03246     else
03247       {
03248         /* We dump DF/DI constants before SF/SI ones, because
03249      the limit is the same, but the alignment requirements
03250      are higher.  We may waste up to 4 additional bytes
03251      for alignment, and the DF/DI constant may have
03252      another SF/SI constant placed before it.  */
03253         if (TARGET_SHCOMPACT
03254       && ! found_di
03255       && (mode == DFmode || mode == DImode))
03256     {
03257       found_di = 1;
03258       si_limit -= 8;
03259     }
03260         while (si_align > 2 && found_si + si_align - 2 > count_si)
03261     si_align >>= 1;
03262         if (found_si > count_si)
03263     count_si = found_si;
03264         found_si += GET_MODE_SIZE (mode);
03265         if (num_mova)
03266     si_limit -= GET_MODE_SIZE (mode);
03267       }
03268 
03269     /* See the code in machine_dependent_reorg, which has a similar if
03270        statement that generates a new mova insn in many cases.  */
03271     if (GET_CODE (dst) == REG && FP_ANY_REGISTER_P (REGNO (dst)))
03272       inc += 2;
03273   }
03274 
03275       if (mova_p (from))
03276   {
03277     if (! num_mova++)
03278       {
03279         leading_mova = 0;
03280         mova = from;
03281         barrier_before_mova = good_barrier ? good_barrier : found_barrier;
03282       }
03283     if (found_si > count_si)
03284       count_si = found_si;
03285   }
03286       else if (GET_CODE (from) == JUMP_INSN
03287          && (GET_CODE (PATTERN (from)) == ADDR_VEC
03288        || GET_CODE (PATTERN (from)) == ADDR_DIFF_VEC))
03289   {
03290     if (num_mova)
03291       num_mova--;
03292     if (barrier_align (next_real_insn (from)) == align_jumps_log)
03293       {
03294         /* We have just passed the barrier in front of the
03295      ADDR_DIFF_VEC, which is stored in found_barrier.  Since
03296      the ADDR_DIFF_VEC is accessed as data, just like our pool
03297      constants, this is a good opportunity to accommodate what
03298      we have gathered so far.
03299      If we waited any longer, we could end up at a barrier in
03300      front of code, which gives worse cache usage for separated
03301      instruction / data caches.  */
03302         good_barrier = found_barrier;
03303         break;
03304       }
03305     else
03306       {
03307         rtx body = PATTERN (from);
03308         inc = XVECLEN (body, 1) * GET_MODE_SIZE (GET_MODE (body));
03309       }
03310   }
03311       /* For the SH1, we generate alignments even after jumps-around-jumps.  */
03312       else if (GET_CODE (from) == JUMP_INSN
03313          && ! TARGET_SH2
03314          && ! TARGET_SMALLCODE)
03315   new_align = 4;
03316 
03317       if (found_si)
03318   {
03319     count_si += inc;
03320     if (new_align > si_align)
03321       {
03322         si_limit -= (count_si - 1) & (new_align - si_align);
03323         si_align = new_align;
03324       }
03325     count_si = (count_si + new_align - 1) & -new_align;
03326   }
03327       if (found_hi)
03328   {
03329     count_hi += inc;
03330     if (new_align > hi_align)
03331       {
03332         hi_limit -= (count_hi - 1) & (new_align - hi_align);
03333         hi_align = new_align;
03334       }
03335     count_hi = (count_hi + new_align - 1) & -new_align;
03336   }
03337       from = NEXT_INSN (from);
03338     }
03339 
03340   if (num_mova)
03341     {
03342       if (leading_mova)
03343   {
03344     /* Try as we might, the leading mova is out of range.  Change
03345        it into a load (which will become a pcload) and retry.  */
03346     fixup_mova (mova);
03347     return find_barrier (0, 0, mova);
03348   }
03349       else
03350   {
03351     /* Insert the constant pool table before the mova instruction,
03352        to prevent the mova label reference from going out of range.  */
03353     from = mova;
03354     good_barrier = found_barrier = barrier_before_mova;
03355   }
03356     }
03357 
03358   if (found_barrier)
03359     {
03360       if (good_barrier && next_real_insn (found_barrier))
03361   found_barrier = good_barrier;
03362     }
03363   else
03364     {
03365       /* We didn't find a barrier in time to dump our stuff,
03366    so we'll make one.  */
03367       rtx label = gen_label_rtx ();
03368 
03369       /* If we exceeded the range, then we must back up over the last
03370    instruction we looked at.  Otherwise, we just need to undo the
03371    NEXT_INSN at the end of the loop.  */
03372       if (count_hi > hi_limit || count_si > si_limit)
03373   from = PREV_INSN (PREV_INSN (from));
03374       else
03375   from = PREV_INSN (from);
03376 
03377       /* Walk back to be just before any jump or label.
03378    Putting it before a label reduces the number of times the branch
03379    around the constant pool table will be hit.  Putting it before
03380    a jump makes it more likely that the bra delay slot will be
03381    filled.  */
03382       while (GET_CODE (from) == JUMP_INSN || GET_CODE (from) == NOTE
03383        || GET_CODE (from) == CODE_LABEL)
03384   from = PREV_INSN (from);
03385 
03386       from = emit_jump_insn_after (gen_jump (label), from);
03387       JUMP_LABEL (from) = label;
03388       LABEL_NUSES (label) = 1;
03389       found_barrier = emit_barrier_after (from);
03390       emit_label_after (label, found_barrier);
03391     }
03392 
03393   return found_barrier;
03394 }
03395 
03396 /* If the instruction INSN is implemented by a special function, and we can
03397    positively find the register that is used to call the sfunc, and this
03398    register is not used anywhere else in this instruction - except as the
03399    destination of a set, return this register; else, return 0.  */
03400 rtx
03401 sfunc_uses_reg (rtx insn)
03402 {
03403   int i;
03404   rtx pattern, part, reg_part, reg;
03405 
03406   if (GET_CODE (insn) != INSN)
03407     return 0;
03408   pattern = PATTERN (insn);
03409   if (GET_CODE (pattern) != PARALLEL || get_attr_type (insn) != TYPE_SFUNC)
03410     return 0;
03411 
03412   for (reg_part = 0, i = XVECLEN (pattern, 0) - 1; i >= 1; i--)
03413     {
03414       part = XVECEXP (pattern, 0, i);
03415       if (GET_CODE (part) == USE && GET_MODE (XEXP (part, 0)) == SImode)
03416   reg_part = part;
03417     }
03418   if (! reg_part)
03419     return 0;
03420   reg = XEXP (reg_part, 0);
03421   for (i = XVECLEN (pattern, 0) - 1; i >= 0; i--)
03422     {
03423       part = XVECEXP (pattern, 0, i);
03424       if (part == reg_part || GET_CODE (part) == CLOBBER)
03425   continue;
03426       if (reg_mentioned_p (reg, ((GET_CODE (part) == SET
03427           && GET_CODE (SET_DEST (part)) == REG)
03428          ? SET_SRC (part) : part)))
03429   return 0;
03430     }
03431   return reg;
03432 }
03433 
03434 /* See if the only way in which INSN uses REG is by calling it, or by
03435    setting it while calling it.  Set *SET to a SET rtx if the register
03436    is set by INSN.  */
03437 
03438 static int
03439 noncall_uses_reg (rtx reg, rtx insn, rtx *set)
03440 {
03441   rtx pattern, reg2;
03442 
03443   *set = NULL_RTX;
03444 
03445   reg2 = sfunc_uses_reg (insn);
03446   if (reg2 && REGNO (reg2) == REGNO (reg))
03447     {
03448       pattern = single_set (insn);
03449       if (pattern
03450     && GET_CODE (SET_DEST (pattern)) == REG
03451     && REGNO (reg) == REGNO (SET_DEST (pattern)))
03452   *set = pattern;
03453       return 0;
03454     }
03455   if (GET_CODE (insn) != CALL_INSN)
03456     {
03457       /* We don't use rtx_equal_p because we don't care if the mode is
03458    different.  */
03459       pattern = single_set (insn);
03460       if (pattern
03461     && GET_CODE (SET_DEST (pattern)) == REG
03462     && REGNO (reg) == REGNO (SET_DEST (pattern)))
03463   {
03464     rtx par, part;
03465     int i;
03466 
03467     *set = pattern;
03468     par = PATTERN (insn);
03469     if (GET_CODE (par) == PARALLEL)
03470       for (i = XVECLEN (par, 0) - 1; i >= 0; i--)
03471         {
03472     part = XVECEXP (par, 0, i);
03473     if (GET_CODE (part) != SET && reg_mentioned_p (reg, part))
03474       return 1;
03475         }
03476     return reg_mentioned_p (reg, SET_SRC (pattern));
03477   }
03478 
03479       return 1;
03480     }
03481 
03482   pattern = PATTERN (insn);
03483 
03484   if (GET_CODE (pattern) == PARALLEL)
03485     {
03486       int i;
03487 
03488       for (i = XVECLEN (pattern, 0) - 1; i >= 1; i--)
03489   if (reg_mentioned_p (reg, XVECEXP (pattern, 0, i)))
03490     return 1;
03491       pattern = XVECEXP (pattern, 0, 0);
03492     }
03493 
03494   if (GET_CODE (pattern) == SET)
03495     {
03496       if (reg_mentioned_p (reg, SET_DEST (pattern)))
03497   {
03498     /* We don't use rtx_equal_p, because we don't care if the
03499              mode is different.  */
03500     if (GET_CODE (SET_DEST (pattern)) != REG
03501         || REGNO (reg) != REGNO (SET_DEST (pattern)))
03502       return 1;
03503 
03504     *set = pattern;
03505   }
03506 
03507       pattern = SET_SRC (pattern);
03508     }
03509 
03510   if (GET_CODE (pattern) != CALL
03511       || GET_CODE (XEXP (pattern, 0)) != MEM
03512       || ! rtx_equal_p (reg, XEXP (XEXP (pattern, 0), 0)))
03513     return 1;
03514 
03515   return 0;
03516 }
03517 
03518 /* Given a X, a pattern of an insn or a part of it, return a mask of used
03519    general registers.  Bits 0..15 mean that the respective registers
03520    are used as inputs in the instruction.  Bits 16..31 mean that the
03521    registers 0..15, respectively, are used as outputs, or are clobbered.
03522    IS_DEST should be set to 16 if X is the destination of a SET, else to 0.  */
03523 int
03524 regs_used (rtx x, int is_dest)
03525 {
03526   enum rtx_code code;
03527   const char *fmt;
03528   int i, used = 0;
03529 
03530   if (! x)
03531     return used;
03532   code = GET_CODE (x);
03533   switch (code)
03534     {
03535     case REG:
03536       if (REGNO (x) < 16)
03537   return (((1 << HARD_REGNO_NREGS (0, GET_MODE (x))) - 1)
03538     << (REGNO (x) + is_dest));
03539       return 0;
03540     case SUBREG:
03541       {
03542   rtx y = SUBREG_REG (x);
03543 
03544   if (GET_CODE (y) != REG)
03545     break;
03546   if (REGNO (y) < 16)
03547     return (((1 << HARD_REGNO_NREGS (0, GET_MODE (x))) - 1)
03548       << (REGNO (y) +
03549           subreg_regno_offset (REGNO (y),
03550              GET_MODE (y),
03551              SUBREG_BYTE (x),
03552              GET_MODE (x)) + is_dest));
03553   return 0;
03554       }
03555     case SET:
03556       return regs_used (SET_SRC (x), 0) | regs_used (SET_DEST (x), 16);
03557     case RETURN:
03558       /* If there was a return value, it must have been indicated with USE.  */
03559       return 0x00ffff00;
03560     case CLOBBER:
03561       is_dest = 1;
03562       break;
03563     case MEM:
03564       is_dest = 0;
03565       break;
03566     case CALL:
03567       used |= 0x00ff00f0;
03568       break;
03569     default:
03570       break;
03571     }
03572 
03573   fmt = GET_RTX_FORMAT (code);
03574 
03575   for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
03576     {
03577       if (fmt[i] == 'E')
03578   {
03579     register int j;
03580     for (j = XVECLEN (x, i) - 1; j >= 0; j--)
03581       used |= regs_used (XVECEXP (x, i, j), is_dest);
03582   }
03583       else if (fmt[i] == 'e')
03584   used |= regs_used (XEXP (x, i), is_dest);
03585     }
03586   return used;
03587 }
03588 
03589 /* Create an instruction that prevents redirection of a conditional branch
03590    to the destination of the JUMP with address ADDR.
03591    If the branch needs to be implemented as an indirect jump, try to find
03592    a scratch register for it.
03593    If NEED_BLOCK is 0, don't do anything unless we need a scratch register.
03594    If any preceding insn that doesn't fit into a delay slot is good enough,
03595    pass 1.  Pass 2 if a definite blocking insn is needed.
03596    -1 is used internally to avoid deep recursion.
03597    If a blocking instruction is made or recognized, return it.  */
03598 
03599 static rtx
03600 gen_block_redirect (rtx jump, int addr, int need_block)
03601 {
03602   int dead = 0;
03603   rtx prev = prev_nonnote_insn (jump);
03604   rtx dest;
03605 
03606   /* First, check if we already have an instruction that satisfies our need.  */
03607   if (prev && GET_CODE (prev) == INSN && ! INSN_DELETED_P (prev))
03608     {
03609       if (INSN_CODE (prev) == CODE_FOR_indirect_jump_scratch)
03610   return prev;
03611       if (GET_CODE (PATTERN (prev)) == USE
03612     || GET_CODE (PATTERN (prev)) == CLOBBER
03613     || get_attr_in_delay_slot (prev) == IN_DELAY_SLOT_YES)
03614   prev = jump;
03615       else if ((need_block &= ~1) < 0)
03616   return prev;
03617       else if (recog_memoized (prev) == CODE_FOR_block_branch_redirect)
03618   need_block = 0;
03619     }
03620   if (GET_CODE (PATTERN (jump)) == RETURN)
03621     {
03622       if (! need_block)
03623   return prev;
03624       /* Reorg even does nasty things with return insns that cause branches
03625    to go out of range - see find_end_label and callers.  */
03626       return emit_insn_before (gen_block_branch_redirect (const0_rtx) , jump);
03627     }
03628   /* We can't use JUMP_LABEL here because it might be undefined
03629      when not optimizing.  */
03630   dest = XEXP (SET_SRC (PATTERN (jump)), 0);
03631   /* If the branch is out of range, try to find a scratch register for it.  */
03632   if (optimize
03633       && (INSN_ADDRESSES (INSN_UID (dest)) - addr + (unsigned) 4092
03634     > 4092 + 4098))
03635     {
03636       rtx scan;
03637       /* Don't look for the stack pointer as a scratch register,
03638    it would cause trouble if an interrupt occurred.  */
03639       unsigned try = 0x7fff, used;
03640       int jump_left = flag_expensive_optimizations + 1;
03641 
03642       /* It is likely that the most recent eligible instruction is wanted for
03643    the delay slot.  Therefore, find out which registers it uses, and
03644    try to avoid using them.  */
03645 
03646       for (scan = jump; (scan = PREV_INSN (scan)); )
03647   {
03648     enum rtx_code code;
03649 
03650     if (INSN_DELETED_P (scan))
03651       continue;
03652     code = GET_CODE (scan);
03653     if (code == CODE_LABEL || code == JUMP_INSN)
03654       break;
03655     if (code == INSN
03656         && GET_CODE (PATTERN (scan)) != USE
03657         && GET_CODE (PATTERN (scan)) != CLOBBER
03658         && get_attr_in_delay_slot (scan) == IN_DELAY_SLOT_YES)
03659       {
03660         try &= ~regs_used (PATTERN (scan), 0);
03661         break;
03662       }
03663   }
03664       for (used = dead = 0, scan = JUMP_LABEL (jump);
03665      (scan = NEXT_INSN (scan)); )
03666   {
03667     enum rtx_code code;
03668 
03669     if (INSN_DELETED_P (scan))
03670       continue;
03671     code = GET_CODE (scan);
03672     if (INSN_P (scan))
03673       {
03674         used |= regs_used (PATTERN (scan), 0);
03675         if (code == CALL_INSN)
03676     used |= regs_used (CALL_INSN_FUNCTION_USAGE (scan), 0);
03677         dead |= (used >> 16) & ~used;
03678         if (dead & try)
03679     {
03680       dead &= try;
03681       break;
03682     }
03683         if (code == JUMP_INSN)
03684     {
03685       if (jump_left-- && simplejump_p (scan))
03686         scan = JUMP_LABEL (scan);
03687       else
03688         break;
03689     }
03690       }
03691   }
03692       /* Mask out the stack pointer again, in case it was
03693    the only 'free' register we have found.  */
03694       dead &= 0x7fff;
03695     }
03696   /* If the immediate destination is still in range, check for possible
03697      threading with a jump beyond the delay slot insn.
03698      Don't check if we are called recursively; the jump has been or will be
03699      checked in a different invocation then.  */
03700 
03701   else if (optimize && need_block >= 0)
03702     {
03703       rtx next = next_active_insn (next_active_insn (dest));
03704       if (next && GET_CODE (next) == JUMP_INSN
03705     && GET_CODE (PATTERN (next)) == SET
03706     && recog_memoized (next) == CODE_FOR_jump_compact)
03707   {
03708     dest = JUMP_LABEL (next);
03709     if (dest
03710         && (INSN_ADDRESSES (INSN_UID (dest)) - addr + (unsigned) 4092
03711       > 4092 + 4098))
03712       gen_block_redirect (next, INSN_ADDRESSES (INSN_UID (next)), -1);
03713   }
03714     }
03715 
03716   if (dead)
03717     {
03718       rtx reg = gen_rtx_REG (SImode, exact_log2 (dead & -dead));
03719 
03720       /* It would be nice if we could convert the jump into an indirect
03721    jump / far branch right now, and thus exposing all constituent
03722    instructions to further optimization.  However, reorg uses
03723    simplejump_p to determine if there is an unconditional jump where
03724    it should try to schedule instructions from the target of the
03725    branch; simplejump_p fails for indirect jumps even if they have
03726    a JUMP_LABEL.  */
03727       rtx insn = emit_insn_before (gen_indirect_jump_scratch
03728            (reg, GEN_INT (INSN_UID (JUMP_LABEL (jump))))
03729            , jump);
03730       /* ??? We would like this to have the scope of the jump, but that
03731    scope will change when a delay slot insn of an inner scope is added.
03732    Hence, after delay slot scheduling, we'll have to expect
03733    NOTE_INSN_BLOCK_END notes between the indirect_jump_scratch and
03734    the jump.  */
03735 
03736       INSN_LOCATOR (insn) = INSN_LOCATOR (jump);
03737       INSN_CODE (insn) = CODE_FOR_indirect_jump_scratch;
03738       return insn;
03739     }
03740   else if (need_block)
03741     /* We can't use JUMP_LABEL here because it might be undefined
03742        when not optimizing.  */
03743     return emit_insn_before (gen_block_branch_redirect
03744           (GEN_INT (INSN_UID (XEXP (SET_SRC (PATTERN (jump)), 0))))
03745           , jump);
03746   return prev;
03747 }
03748 
03749 #define CONDJUMP_MIN -252
03750 #define CONDJUMP_MAX 262
03751 struct far_branch
03752 {
03753   /* A label (to be placed) in front of the jump
03754      that jumps to our ultimate destination.  */
03755   rtx near_label;
03756   /* Where we are going to insert it if we cannot move the jump any farther,
03757      or the jump itself if we have picked up an existing jump.  */
03758   rtx insert_place;
03759   /* The ultimate destination.  */
03760   rtx far_label;
03761   struct far_branch *prev;
03762   /* If the branch has already been created, its address;
03763      else the address of its first prospective user.  */
03764   int address;
03765 };
03766 
03767 static void gen_far_branch (struct far_branch *);
03768 enum mdep_reorg_phase_e mdep_reorg_phase;
03769 static void
03770 gen_far_branch (struct far_branch *bp)
03771 {
03772   rtx insn = bp->insert_place;
03773   rtx jump;
03774   rtx label = gen_label_rtx ();
03775 
03776   emit_label_after (label, insn);
03777   if (bp->far_label)
03778     {
03779       jump = emit_jump_insn_after (gen_jump (bp->far_label), insn);
03780       LABEL_NUSES (bp->far_label)++;
03781     }
03782   else
03783     jump = emit_jump_insn_after (gen_return (), insn);
03784   /* Emit a barrier so that reorg knows that any following instructions
03785      are not reachable via a fall-through path.
03786      But don't do this when not optimizing, since we wouldn't suppress the
03787      alignment for the barrier then, and could end up with out-of-range
03788      pc-relative loads.  */
03789   if (optimize)
03790     emit_barrier_after (jump);
03791   emit_label_after (bp->near_label, insn);
03792   JUMP_LABEL (jump) = bp->far_label;
03793   if (! invert_jump (insn, label, 1))
03794     abort ();
03795   /* If we are branching around a jump (rather than a return), prevent
03796      reorg from using an insn from the jump target as the delay slot insn -
03797      when reorg did this, it pessimized code (we rather hide the delay slot)
03798      and it could cause branches to go out of range.  */
03799   if (bp->far_label)
03800     (emit_insn_after
03801      (gen_stuff_delay_slot
03802       (GEN_INT (INSN_UID (XEXP (SET_SRC (PATTERN (jump)), 0))),
03803        GEN_INT (recog_memoized (insn) == CODE_FOR_branch_false)),
03804       insn));
03805   /* Prevent reorg from undoing our splits.  */
03806   gen_block_redirect (jump, bp->address += 2, 2);
03807 }
03808 
03809 /* Fix up ADDR_DIFF_VECs.  */
03810 void
03811 fixup_addr_diff_vecs (rtx first)
03812 {
03813   rtx insn;
03814 
03815   for (insn = first; insn; insn = NEXT_INSN (insn))
03816     {
03817       rtx vec_lab, pat, prev, prevpat, x, braf_label;
03818 
03819       if (GET_CODE (insn) != JUMP_INSN
03820     || GET_CODE (PATTERN (insn)) != ADDR_DIFF_VEC)
03821   continue;
03822       pat = PATTERN (insn);
03823       vec_lab = XEXP (XEXP (pat, 0), 0);
03824 
03825       /* Search the matching casesi_jump_2.  */
03826       for (prev = vec_lab; ; prev = PREV_INSN (prev))
03827   {
03828     if (GET_CODE (prev) != JUMP_INSN)
03829       continue;
03830     prevpat = PATTERN (prev);
03831     if (GET_CODE (prevpat) != PARALLEL || XVECLEN (prevpat, 0) != 2)
03832       continue;
03833     x = XVECEXP (prevpat, 0, 1);
03834     if (GET_CODE (x) != USE)
03835       continue;
03836     x = XEXP (x, 0);
03837     if (GET_CODE (x) == LABEL_REF && XEXP (x, 0) == vec_lab)
03838       break;
03839   }
03840       /* FIXME: This is a bug in the optimizer, but it seems harmless
03841    to just avoid panicing.  */
03842       if (!prev)
03843   continue;
03844 
03845       /* Emit the reference label of the braf where it belongs, right after
03846    the casesi_jump_2 (i.e. braf).  */
03847       braf_label = XEXP (XEXP (SET_SRC (XVECEXP (prevpat, 0, 0)), 1), 0);
03848       emit_label_after (braf_label, prev);
03849 
03850       /* Fix up the ADDR_DIF_VEC to be relative
03851    to the reference address of the braf.  */
03852       XEXP (XEXP (pat, 0), 0) = braf_label;
03853     }
03854 }
03855 
03856 /* BARRIER_OR_LABEL is either a BARRIER or a CODE_LABEL immediately following
03857    a barrier.  Return the base 2 logarithm of the desired alignment.  */
03858 int
03859 barrier_align (rtx barrier_or_label)
03860 {
03861   rtx next = next_real_insn (barrier_or_label), pat, prev;
03862   int slot, credit, jump_to_next = 0;
03863 
03864   if (! next)
03865     return 0;
03866 
03867   pat = PATTERN (next);
03868 
03869   if (GET_CODE (pat) == ADDR_DIFF_VEC)
03870     return 2;
03871 
03872   if (GET_CODE (pat) == UNSPEC_VOLATILE && XINT (pat, 1) == UNSPECV_ALIGN)
03873     /* This is a barrier in front of a constant table.  */
03874     return 0;
03875 
03876   prev = prev_real_insn (barrier_or_label);
03877   if (GET_CODE (PATTERN (prev)) == ADDR_DIFF_VEC)
03878     {
03879       pat = PATTERN (prev);
03880       /* If this is a very small table, we want to keep the alignment after
03881    the table to the minimum for proper code alignment.  */
03882       return ((TARGET_SMALLCODE
03883          || ((unsigned) XVECLEN (pat, 1) * GET_MODE_SIZE (GET_MODE (pat))
03884        <= (unsigned) 1 << (CACHE_LOG - 2)))
03885         ? 1 << TARGET_SHMEDIA : align_jumps_log);
03886     }
03887 
03888   if (TARGET_SMALLCODE)
03889     return 0;
03890 
03891   if (! TARGET_SH2 || ! optimize)
03892     return align_jumps_log;
03893 
03894   /* When fixing up pcloads, a constant table might be inserted just before
03895      the basic block that ends with the barrier.  Thus, we can't trust the
03896      instruction lengths before that.  */
03897   if (mdep_reorg_phase > SH_FIXUP_PCLOAD)
03898     {
03899       /* Check if there is an immediately preceding branch to the insn beyond
03900    the barrier.  We must weight the cost of discarding useful information
03901    from the current cache line when executing this branch and there is
03902    an alignment, against that of fetching unneeded insn in front of the
03903    branch target when there is no alignment.  */
03904 
03905       /* There are two delay_slot cases to consider.  One is the simple case
03906    where the preceding branch is to the insn beyond the barrier (simple
03907    delay slot filling), and the other is where the preceding branch has
03908    a delay slot that is a duplicate of the insn after the barrier
03909    (fill_eager_delay_slots) and the branch is to the insn after the insn
03910    after the barrier.  */
03911 
03912       /* PREV is presumed to be the JUMP_INSN for the barrier under
03913    investigation.  Skip to the insn before it.  */
03914       prev = prev_real_insn (prev);
03915 
03916       for (slot = 2, credit = (1 << (CACHE_LOG - 2)) + 2;
03917      credit >= 0 && prev && GET_CODE (prev) == INSN;
03918      prev = prev_real_insn (prev))
03919   {
03920     jump_to_next = 0;
03921     if (GET_CODE (PATTERN (prev)) == USE
03922         || GET_CODE (PATTERN (prev)) == CLOBBER)
03923       continue;
03924     if (GET_CODE (PATTERN (prev)) == SEQUENCE)
03925       {
03926         prev = XVECEXP (PATTERN (prev), 0, 1);
03927         if (INSN_UID (prev) == INSN_UID (next))
03928     {
03929         /* Delay slot was filled with insn at jump target.  */
03930       jump_to_next = 1;
03931       continue;
03932       }
03933       }
03934 
03935     if (slot &&
03936         get_attr_in_delay_slot (prev) == IN_DELAY_SLOT_YES)
03937       slot = 0;
03938     credit -= get_attr_length (prev);
03939   }
03940       if (prev
03941     && GET_CODE (prev) == JUMP_INSN
03942     && JUMP_LABEL (prev))
03943   {
03944     rtx x;
03945     if (jump_to_next
03946         || next_real_insn (JUMP_LABEL (prev)) == next
03947         /* If relax_delay_slots() decides NEXT was redundant
03948      with some previous instruction, it will have
03949      redirected PREV's jump to the following insn.  */
03950         || JUMP_LABEL (prev) == next_nonnote_insn (next)
03951         /* There is no upper bound on redundant instructions
03952      that might have been skipped, but we must not put an
03953      alignment where none had been before.  */
03954         || (x = (NEXT_INSN (NEXT_INSN (PREV_INSN (prev)))),
03955       (INSN_P (x)
03956        && (INSN_CODE (x) == CODE_FOR_block_branch_redirect
03957            || INSN_CODE (x) == CODE_FOR_indirect_jump_scratch
03958            || INSN_CODE (x) == CODE_FOR_stuff_delay_slot))))
03959       {
03960         rtx pat = PATTERN (prev);
03961         if (GET_CODE (pat) == PARALLEL)
03962     pat = XVECEXP (pat, 0, 0);
03963         if (credit - slot >= (GET_CODE (SET_SRC (pat)) == PC ? 2 : 0))
03964     return 0;
03965       }
03966   }
03967     }
03968 
03969   return align_jumps_log;
03970 }
03971 
03972 /* If we are inside a phony loop, almost any kind of label can turn up as the
03973    first one in the loop.  Aligning a braf label causes incorrect switch
03974    destination addresses; we can detect braf labels because they are
03975    followed by a BARRIER.
03976    Applying loop alignment to small constant or switch tables is a waste
03977    of space, so we suppress this too.  */
03978 int
03979 sh_loop_align (rtx label)
03980 {
03981   rtx next = label;
03982 
03983   do
03984     next = next_nonnote_insn (next);
03985   while (next && GET_CODE (next) == CODE_LABEL);
03986 
03987   if (! next
03988       || ! INSN_P (next)
03989       || GET_CODE (PATTERN (next)) == ADDR_DIFF_VEC
03990       || recog_memoized (next) == CODE_FOR_consttable_2)
03991     return 0;
03992 
03993   return align_loops_log;
03994 }
03995 
03996 /* Do a final pass over the function, just before delayed branch
03997    scheduling.  */
03998 
03999 static void
04000 sh_reorg (void)
04001 {
04002   rtx first, insn, mova = NULL_RTX;
04003   int num_mova;
04004   rtx r0_rtx = gen_rtx_REG (Pmode, 0);
04005   rtx r0_inc_rtx = gen_rtx_POST_INC (Pmode, r0_rtx);
04006 
04007   first = get_insns ();
04008 
04009   /* We must split call insns before introducing `mova's.  If we're
04010      optimizing, they'll have already been split.  Otherwise, make
04011      sure we don't split them too late.  */
04012   if (! optimize)
04013     split_all_insns_noflow ();
04014 
04015   if (TARGET_SHMEDIA)
04016     return;
04017 
04018   /* If relaxing, generate pseudo-ops to associate function calls with
04019      the symbols they call.  It does no harm to not generate these
04020      pseudo-ops.  However, when we can generate them, it enables to
04021      linker to potentially relax the jsr to a bsr, and eliminate the
04022      register load and, possibly, the constant pool entry.  */
04023 
04024   mdep_reorg_phase = SH_INSERT_USES_LABELS;
04025   if (TARGET_RELAX)
04026     {
04027       /* Remove all REG_LABEL notes.  We want to use them for our own
04028    purposes.  This works because none of the remaining passes
04029    need to look at them.
04030 
04031    ??? But it may break in the future.  We should use a machine
04032    dependent REG_NOTE, or some other approach entirely.  */
04033       for (insn = first; insn; insn = NEXT_INSN (insn))
04034   {
04035     if (INSN_P (insn))
04036       {
04037         rtx note;
04038 
04039         while ((note = find_reg_note (insn, REG_LABEL, NULL_RTX)) != 0)
04040     remove_note (insn, note);
04041       }
04042   }
04043 
04044       for (insn = first; insn; insn = NEXT_INSN (insn))
04045   {
04046     rtx pattern, reg, link, set, scan, dies, label;
04047     int rescan = 0, foundinsn = 0;
04048 
04049     if (GET_CODE (insn) == CALL_INSN)
04050       {
04051         pattern = PATTERN (insn);
04052 
04053         if (GET_CODE (pattern) == PARALLEL)
04054     pattern = XVECEXP (pattern, 0, 0);
04055         if (GET_CODE (pattern) == SET)
04056     pattern = SET_SRC (pattern);
04057 
04058         if (GET_CODE (pattern) != CALL
04059       || GET_CODE (XEXP (pattern, 0)) != MEM)
04060     continue;
04061 
04062         reg = XEXP (XEXP (pattern, 0), 0);
04063       }
04064     else
04065       {
04066         reg = sfunc_uses_reg (insn);
04067         if (! reg)
04068     continue;
04069       }
04070 
04071     if (GET_CODE (reg) != REG)
04072       continue;
04073 
04074     /* This is a function call via REG.  If the only uses of REG
04075        between the time that it is set and the time that it dies
04076        are in function calls, then we can associate all the
04077        function calls with the setting of REG.  */
04078 
04079     for (link = LOG_LINKS (insn); link; link = XEXP (link, 1))
04080       {
04081         if (REG_NOTE_KIND (link) != 0)
04082     continue;
04083         set = single_set (XEXP (link, 0));
04084         if (set && rtx_equal_p (reg, SET_DEST (set)))
04085     {
04086       link = XEXP (link, 0);
04087       break;
04088     }
04089       }
04090 
04091     if (! link)
04092       {
04093         /* ??? Sometimes global register allocation will have
04094                  deleted the insn pointed to by LOG_LINKS.  Try
04095                  scanning backward to find where the register is set.  */
04096         for (scan = PREV_INSN (insn);
04097        scan && GET_CODE (scan) != CODE_LABEL;
04098        scan = PREV_INSN (scan))
04099     {
04100       if (! INSN_P (scan))
04101         continue;
04102 
04103       if (! reg_mentioned_p (reg, scan))
04104         continue;
04105 
04106       if (noncall_uses_reg (reg, scan, &set))
04107         break;
04108 
04109       if (set)
04110         {
04111           link = scan;
04112           break;
04113         }
04114     }
04115       }
04116 
04117     if (! link)
04118       continue;
04119 
04120     /* The register is set at LINK.  */
04121 
04122     /* We can only optimize the function call if the register is
04123              being set to a symbol.  In theory, we could sometimes
04124              optimize calls to a constant location, but the assembler
04125              and linker do not support that at present.  */
04126     if (GET_CODE (SET_SRC (set)) != SYMBOL_REF
04127         && GET_CODE (SET_SRC (set)) != LABEL_REF)
04128       continue;
04129 
04130     /* Scan forward from LINK to the place where REG dies, and
04131              make sure that the only insns which use REG are
04132              themselves function calls.  */
04133 
04134     /* ??? This doesn't work for call targets that were allocated
04135        by reload, since there may not be a REG_DEAD note for the
04136        register.  */
04137 
04138     dies = NULL_RTX;
04139     for (scan = NEXT_INSN (link); scan; scan = NEXT_INSN (scan))
04140       {
04141         rtx scanset;
04142 
04143         /* Don't try to trace forward past a CODE_LABEL if we haven't
04144      seen INSN yet.  Ordinarily, we will only find the setting insn
04145      in LOG_LINKS if it is in the same basic block.  However,
04146      cross-jumping can insert code labels in between the load and
04147      the call, and can result in situations where a single call
04148      insn may have two targets depending on where we came from.  */
04149 
04150         if (GET_CODE (scan) == CODE_LABEL && ! foundinsn)
04151     break;
04152 
04153         if (! INSN_P (scan))
04154     continue;
04155 
04156         /* Don't try to trace forward past a JUMP.  To optimize
04157                  safely, we would have to check that all the
04158                  instructions at the jump destination did not use REG.  */
04159 
04160         if (GET_CODE (scan) == JUMP_INSN)
04161     break;
04162 
04163         if (! reg_mentioned_p (reg, scan))
04164     continue;
04165 
04166         if (noncall_uses_reg (reg, scan, &scanset))
04167     break;
04168 
04169         if (scan == insn)
04170     foundinsn = 1;
04171 
04172         if (scan != insn
04173       && (GET_CODE (scan) == CALL_INSN || sfunc_uses_reg (scan)))
04174     {
04175       /* There is a function call to this register other
04176                      than the one we are checking.  If we optimize
04177                      this call, we need to rescan again below.  */
04178       rescan = 1;
04179     }
04180 
04181         /* ??? We shouldn't have to worry about SCANSET here.
04182      We should just be able to check for a REG_DEAD note
04183      on a function call.  However, the REG_DEAD notes are
04184      apparently not dependable around libcalls; c-torture
04185      execute/920501-2 is a test case.  If SCANSET is set,
04186      then this insn sets the register, so it must have
04187      died earlier.  Unfortunately, this will only handle
04188      the cases in which the register is, in fact, set in a
04189      later insn.  */
04190 
04191         /* ??? We shouldn't have to use FOUNDINSN here.
04192      However, the LOG_LINKS fields are apparently not
04193      entirely reliable around libcalls;
04194      newlib/libm/math/e_pow.c is a test case.  Sometimes
04195      an insn will appear in LOG_LINKS even though it is
04196      not the most recent insn which sets the register.  */
04197 
04198         if (foundinsn
04199       && (scanset
04200           || find_reg_note (scan, REG_DEAD, reg)))
04201     {
04202       dies = scan;
04203       break;
04204     }
04205       }
04206 
04207     if (! dies)
04208       {
04209         /* Either there was a branch, or some insn used REG
04210                  other than as a function call address.  */
04211         continue;
04212       }
04213 
04214     /* Create a code label, and put it in a REG_LABEL note on
04215              the insn which sets the register, and on each call insn
04216              which uses the register.  In final_prescan_insn we look
04217              for the REG_LABEL notes, and output the appropriate label
04218              or pseudo-op.  */
04219 
04220     label = gen_label_rtx ();
04221     REG_NOTES (link) = gen_rtx_INSN_LIST (REG_LABEL, label,
04222             REG_NOTES (link));
04223     REG_NOTES (insn) = gen_rtx_INSN_LIST (REG_LABEL, label,
04224             REG_NOTES (insn));
04225     if (rescan)
04226       {
04227         scan = link;
04228         do
04229     {
04230       rtx reg2;
04231 
04232       scan = NEXT_INSN (scan);
04233       if (scan != insn
04234           && ((GET_CODE (scan) == CALL_INSN
04235          && reg_mentioned_p (reg, scan))
04236         || ((reg2 = sfunc_uses_reg (scan))
04237             && REGNO (reg2) == REGNO (reg))))
04238         REG_NOTES (scan)
04239           = gen_rtx_INSN_LIST (REG_LABEL, label, REG_NOTES (scan));
04240     }
04241         while (scan != dies);
04242       }
04243   }
04244     }
04245 
04246   if (TARGET_SH2)
04247     fixup_addr_diff_vecs (first);
04248 
04249   if (optimize)
04250     {
04251       mdep_reorg_phase = SH_SHORTEN_BRANCHES0;
04252       shorten_branches (first);
04253     }
04254   /* Scan the function looking for move instructions which have to be
04255      changed to pc-relative loads and insert the literal tables.  */
04256 
04257   mdep_reorg_phase = SH_FIXUP_PCLOAD;
04258   for (insn = first, num_mova = 0; insn; insn = NEXT_INSN (insn))
04259     {
04260       if (mova_p (insn))
04261   {
04262     /* ??? basic block reordering can move a switch table dispatch
04263        below the switch table.  Check if that has happened.
04264        We only have the addresses available when optimizing; but then,
04265        this check shouldn't be needed when not optimizing.  */
04266     rtx label_ref = XVECEXP (SET_SRC (PATTERN (insn)), 0, 0);
04267     if (optimize
04268         && (INSN_ADDRESSES (INSN_UID (insn))
04269       > INSN_ADDRESSES (INSN_UID (XEXP (label_ref, 0)))))
04270       {
04271         /* Change the mova into a load.
04272      broken_move will then return true for it.  */
04273         fixup_mova (insn);
04274       }
04275     else if (! num_mova++)
04276       mova = insn;
04277   }
04278       else if (GET_CODE (insn) == JUMP_INSN
04279          && GET_CODE (PATTERN (insn)) == ADDR_DIFF_VEC
04280          && num_mova)
04281   {
04282     rtx scan;
04283     int total;
04284 
04285     num_mova--;
04286 
04287     /* Some code might have been inserted between the mova and
04288        its ADDR_DIFF_VEC.  Check if the mova is still in range.  */
04289     for (scan = mova, total = 0; scan != insn; scan = NEXT_INSN (scan))
04290       total += get_attr_length (scan);
04291 
04292     /* range of mova is 1020, add 4 because pc counts from address of
04293        second instruction after this one, subtract 2 in case pc is 2
04294        byte aligned.  Possible alignment needed for the ADDR_DIFF_VEC
04295        cancels out with alignment effects of the mova itself.  */
04296     if (total > 1022)
04297       {
04298         /* Change the mova into a load, and restart scanning
04299      there.  broken_move will then return true for mova.  */
04300         fixup_mova (mova);
04301         insn = mova;
04302       }
04303   }
04304       if (broken_move (insn)
04305     || (GET_CODE (insn) == INSN
04306         && recog_memoized (insn) == CODE_FOR_casesi_worker_2))
04307   {
04308     rtx scan;
04309     /* Scan ahead looking for a barrier to stick the constant table
04310        behind.  */
04311     rtx barrier = find_barrier (num_mova, mova, insn);
04312     rtx last_float_move = NULL_RTX, last_float = 0, *last_float_addr = NULL;
04313     int need_aligned_label = 0;
04314 
04315     if (num_mova && ! mova_p (mova))
04316       {
04317         /* find_barrier had to change the first mova into a
04318      pcload; thus, we have to start with this new pcload.  */
04319         insn = mova;
04320         num_mova = 0;
04321       }
04322     /* Now find all the moves between the points and modify them.  */
04323     for (scan = insn; scan != barrier; scan = NEXT_INSN (scan))
04324       {
04325         if (GET_CODE (scan) == CODE_LABEL)
04326     last_float = 0;
04327         if (GET_CODE (scan) == INSN
04328       && recog_memoized (scan) == CODE_FOR_casesi_worker_2)
04329     need_aligned_label = 1;
04330         if (broken_move (scan))
04331     {
04332       rtx *patp = &PATTERN (scan), pat = *patp;
04333       rtx src, dst;
04334       rtx lab;
04335       rtx newsrc;
04336       enum machine_mode mode;
04337 
04338       if (GET_CODE (pat) == PARALLEL)
04339         patp = &XVECEXP (pat, 0, 0), pat = *patp;
04340       src = SET_SRC (pat);
04341       dst = SET_DEST (pat);
04342       mode = GET_MODE (dst);
04343 
04344       if (mode == SImode && hi_const (src)
04345           && REGNO (dst) != FPUL_REG)
04346         {
04347           int offset = 0;
04348 
04349           mode = HImode;
04350           while (GET_CODE (dst) == SUBREG)
04351       {
04352         offset += subreg_regno_offset (REGNO (SUBREG_REG (dst)),
04353                GET_MODE (SUBREG_REG (dst)),
04354                SUBREG_BYTE (dst),
04355                GET_MODE (dst));
04356         dst = SUBREG_REG (dst);
04357       }
04358           dst = gen_rtx_REG (HImode, REGNO (dst) + offset);
04359         }
04360       if (GET_CODE (dst) == REG && FP_ANY_REGISTER_P (REGNO (dst)))
04361         {
04362           /* This must be an insn that clobbers r0.  */
04363           rtx *clobberp = &XVECEXP (PATTERN (scan), 0,
04364             XVECLEN (PATTERN (scan), 0)
04365             - 1);
04366           rtx clobber = *clobberp;
04367 
04368           if (GET_CODE (clobber) != CLOBBER
04369         || ! rtx_equal_p (XEXP (clobber, 0), r0_rtx))
04370       abort ();
04371 
04372           if (last_float
04373         && reg_set_between_p (r0_rtx, last_float_move, scan))
04374       last_float = 0;
04375           if (last_float
04376         && TARGET_SHCOMPACT
04377         && GET_MODE_SIZE (mode) != 4
04378         && GET_MODE_SIZE (GET_MODE (last_float)) == 4)
04379       last_float = 0;
04380           lab = add_constant (src, mode, last_float);
04381           if (lab)
04382       emit_insn_before (gen_mova (lab), scan);
04383           else
04384       {
04385         /* There will be a REG_UNUSED note for r0 on
04386            LAST_FLOAT_MOVE; we have to change it to REG_INC,
04387            lest reorg:mark_target_live_regs will not
04388            consider r0 to be used, and we end up with delay
04389            slot insn in front of SCAN that clobbers r0.  */
04390         rtx note
04391           = find_regno_note (last_float_move, REG_UNUSED, 0);
04392 
04393         /* If we are not optimizing, then there may not be
04394            a note.  */
04395         if (note)
04396           PUT_MODE (note, REG_INC);
04397 
04398         *last_float_addr = r0_inc_rtx;
04399       }
04400           last_float_move = scan;
04401           last_float = src;
04402           newsrc = gen_rtx_MEM (mode,
04403           (((TARGET_SH4 && ! TARGET_FMOVD)
04404             || REGNO (dst) == FPUL_REG)
04405            ? r0_inc_rtx
04406            : r0_rtx));
04407           last_float_addr = &XEXP (newsrc, 0);
04408 
04409           /* Remove the clobber of r0.  */
04410           *clobberp = gen_rtx_CLOBBER (GET_MODE (clobber),
04411                gen_rtx_SCRATCH (Pmode));
04412         }
04413       /* This is a mova needing a label.  Create it.  */
04414       else if (GET_CODE (src) == UNSPEC
04415          && XINT (src, 1) == UNSPEC_MOVA
04416          && GET_CODE (XVECEXP (src, 0, 0)) == CONST)
04417         {
04418           lab = add_constant (XVECEXP (src, 0, 0), mode, 0);
04419           newsrc = gen_rtx_LABEL_REF (VOIDmode, lab);
04420           newsrc = gen_rtx_UNSPEC (SImode,
04421                  gen_rtvec (1, newsrc),
04422                  UNSPEC_MOVA);
04423         }
04424       else
04425         {
04426           lab = add_constant (src, mode, 0);
04427           newsrc = gen_rtx_LABEL_REF (VOIDmode, lab);
04428           newsrc = gen_const_mem (mode, newsrc);
04429         }
04430       *patp = gen_rtx_SET (VOIDmode, dst, newsrc);
04431       INSN_CODE (scan) = -1;
04432     }
04433       }
04434     dump_table (need_aligned_label ? insn : 0, barrier);
04435     insn = barrier;
04436   }
04437     }
04438 
04439   mdep_reorg_phase = SH_SHORTEN_BRANCHES1;
04440   INSN_ADDRESSES_FREE ();
04441   split_branches (first);
04442 
04443   /* The INSN_REFERENCES_ARE_DELAYED in sh.h is problematic because it
04444      also has an effect on the register that holds the address of the sfunc.
04445      Insert an extra dummy insn in front of each sfunc that pretends to
04446      use this register.  */
04447   if (flag_delayed_branch)
04448     {
04449       for (insn = first; insn; insn = NEXT_INSN (insn))
04450   {
04451     rtx reg = sfunc_uses_reg (insn);
04452 
04453     if (! reg)
04454       continue;
04455     emit_insn_before (gen_use_sfunc_addr (reg), insn);
04456   }
04457     }
04458 #if 0
04459   /* fpscr is not actually a user variable, but we pretend it is for the
04460      sake of the previous optimization passes, since we want it handled like
04461      one.  However, we don't have any debugging information for it, so turn
04462      it into a non-user variable now.  */
04463   if (TARGET_SH4)
04464     REG_USERVAR_P (get_fpscr_rtx ()) = 0;
04465 #endif
04466   mdep_reorg_phase = SH_AFTER_MDEP_REORG;
04467 }
04468 
04469 int
04470 get_dest_uid (rtx label, int max_uid)
04471 {
04472   rtx dest = next_real_insn (label);
04473   int dest_uid;
04474   if (! dest)
04475     /* This can happen for an undefined label.  */
04476     return 0;
04477   dest_uid = INSN_UID (dest);
04478   /* If this is a newly created branch redirection blocking instruction,
04479      we cannot index the branch_uid or insn_addresses arrays with its
04480      uid.  But then, we won't need to, because the actual destination is
04481      the following branch.  */
04482   while (dest_uid >= max_uid)
04483     {
04484       dest = NEXT_INSN (dest);
04485       dest_uid = INSN_UID (dest);
04486     }
04487   if (GET_CODE (dest) == JUMP_INSN && GET_CODE (PATTERN (dest)) == RETURN)
04488     return 0;
04489   return dest_uid;
04490 }
04491 
04492 /* Split condbranches that are out of range.  Also add clobbers for
04493    scratch registers that are needed in far jumps.
04494    We do this before delay slot scheduling, so that it can take our
04495    newly created instructions into account.  It also allows us to
04496    find branches with common targets more easily.  */
04497 
04498 static void
04499 split_branches (rtx first)
04500 {
04501   rtx insn;
04502   struct far_branch **uid_branch, *far_branch_list = 0;
04503   int max_uid = get_max_uid ();
04504 
04505   /* Find out which branches are out of range.  */
04506   shorten_branches (first);
04507 
04508   uid_branch = (struct far_branch **) alloca (max_uid * sizeof *uid_branch);
04509   memset ((char *) uid_branch, 0, max_uid * sizeof *uid_branch);
04510 
04511   for (insn = first; insn; insn = NEXT_INSN (insn))
04512     if (! INSN_P (insn))
04513       continue;
04514     else if (INSN_DELETED_P (insn))
04515       {
04516   /* Shorten_branches would split this instruction again,
04517      so transform it into a note.  */
04518   PUT_CODE (insn, NOTE);
04519   NOTE_LINE_NUMBER (insn) = NOTE_INSN_DELETED;
04520   NOTE_SOURCE_FILE (insn) = 0;
04521       }
04522     else if (GET_CODE (insn) == JUMP_INSN
04523        /* Don't mess with ADDR_DIFF_VEC */
04524        && (GET_CODE (PATTERN (insn)) == SET
04525      || GET_CODE (PATTERN (insn)) == RETURN))
04526       {
04527   enum attr_type type = get_attr_type (insn);
04528   if (type == TYPE_CBRANCH)
04529     {
04530       rtx next, beyond;
04531 
04532       if (get_attr_length (insn) > 4)
04533         {
04534     rtx src = SET_SRC (PATTERN (insn));
04535     rtx olabel = XEXP (XEXP (src, 1), 0);
04536     int addr = INSN_ADDRESSES (INSN_UID (insn));
04537     rtx label = 0;
04538     int dest_uid = get_dest_uid (olabel, max_uid);
04539     struct far_branch *bp = uid_branch[dest_uid];
04540 
04541     /* redirect_jump needs a valid JUMP_LABEL, and it might delete
04542        the label if the LABEL_NUSES count drops to zero.  There is
04543        always a jump_optimize pass that sets these values, but it
04544        proceeds to delete unreferenced code, and then if not
04545        optimizing, to un-delete the deleted instructions, thus
04546        leaving labels with too low uses counts.  */
04547     if (! optimize)
04548       {
04549         JUMP_LABEL (insn) = olabel;
04550         LABEL_NUSES (olabel)++;
04551       }
04552     if (! bp)
04553       {
04554         bp = (struct far_branch *) alloca (sizeof *bp);
04555         uid_branch[dest_uid] = bp;
04556         bp->prev = far_branch_list;
04557         far_branch_list = bp;
04558         bp->far_label
04559           = XEXP (XEXP (SET_SRC (PATTERN (insn)), 1), 0);
04560         LABEL_NUSES (bp->far_label)++;
04561       }
04562     else
04563       {
04564         label = bp->near_label;
04565         if (! label && bp->address - addr >= CONDJUMP_MIN)
04566           {
04567       rtx block = bp->insert_place;
04568 
04569       if (GET_CODE (PATTERN (block)) == RETURN)
04570         block = PREV_INSN (block);
04571       else
04572         block = gen_block_redirect (block,
04573                   bp->address, 2);
04574       label = emit_label_after (gen_label_rtx (),
04575               PREV_INSN (block));
04576       bp->near_label = label;
04577           }
04578         else if (label && ! NEXT_INSN (label))
04579           {
04580       if (addr + 2 - bp->address <= CONDJUMP_MAX)
04581         bp->insert_place = insn;
04582       else
04583         gen_far_branch (bp);
04584           }
04585       }
04586     if (! label
04587         || (NEXT_INSN (label) && bp->address - addr < CONDJUMP_MIN))
04588       {
04589         bp->near_label = label = gen_label_rtx ();
04590         bp->insert_place = insn;
04591         bp->address = addr;
04592       }
04593     if (! redirect_jump (insn, label, 1))
04594       abort ();
04595         }
04596       else
04597         {
04598     /* get_attr_length (insn) == 2 */
04599     /* Check if we have a pattern where reorg wants to redirect
04600        the branch to a label from an unconditional branch that
04601        is too far away.  */
04602     /* We can't use JUMP_LABEL here because it might be undefined
04603        when not optimizing.  */
04604     /* A syntax error might cause beyond to be NULL_RTX.  */
04605     beyond
04606       = next_active_insn (XEXP (XEXP (SET_SRC (PATTERN (insn)), 1),
04607               0));
04608 
04609     if (beyond
04610         && (GET_CODE (beyond) == JUMP_INSN
04611       || ((beyond = next_active_insn (beyond))
04612           && GET_CODE (beyond) == JUMP_INSN))
04613         && GET_CODE (PATTERN (beyond)) == SET
04614         && recog_memoized (beyond) == CODE_FOR_jump_compact
04615         && ((INSN_ADDRESSES
04616        (INSN_UID (XEXP (SET_SRC (PATTERN (beyond)), 0)))
04617        - INSN_ADDRESSES (INSN_UID (insn)) + (unsigned) 252)
04618       > 252 + 258 + 2))
04619       gen_block_redirect (beyond,
04620               INSN_ADDRESSES (INSN_UID (beyond)), 1);
04621         }
04622 
04623       next = next_active_insn (insn);
04624 
04625       if ((GET_CODE (next) == JUMP_INSN
04626      || ((next = next_active_insn (next))
04627          && GET_CODE (next) == JUMP_INSN))
04628     && GET_CODE (PATTERN (next)) == SET
04629     && recog_memoized (next) == CODE_FOR_jump_compact
04630     && ((INSN_ADDRESSES
04631          (INSN_UID (XEXP (SET_SRC (PATTERN (next)), 0)))
04632          - INSN_ADDRESSES (INSN_UID (insn)) + (unsigned) 252)
04633         > 252 + 258 + 2))
04634         gen_block_redirect (next, INSN_ADDRESSES (INSN_UID (next)), 1);
04635     }
04636   else if (type == TYPE_JUMP || type == TYPE_RETURN)
04637     {
04638       int addr = INSN_ADDRESSES (INSN_UID (insn));
04639       rtx far_label = 0;
04640       int dest_uid = 0;
04641       struct far_branch *bp;
04642 
04643       if (type == TYPE_JUMP)
04644         {
04645     far_label = XEXP (SET_SRC (PATTERN (insn)), 0);
04646     dest_uid = get_dest_uid (far_label, max_uid);
04647     if (! dest_uid)
04648       {
04649         /* Parse errors can lead to labels outside
04650           the insn stream.  */
04651         if (! NEXT_INSN (far_label))
04652           continue;
04653 
04654         if (! optimize)
04655           {
04656       JUMP_LABEL (insn) = far_label;
04657       LABEL_NUSES (far_label)++;
04658           }
04659         redirect_jump (insn, NULL_RTX, 1);
04660         far_label = 0;
04661       }
04662         }
04663       bp = uid_branch[dest_uid];
04664       if (! bp)
04665         {
04666     bp = (struct far_branch *) alloca (sizeof *bp);
04667     uid_branch[dest_uid] = bp;
04668     bp->prev = far_branch_list;
04669     far_branch_list = bp;
04670     bp->near_label = 0;
04671     bp->far_label = far_label;
04672     if (far_label)
04673       LABEL_NUSES (far_label)++;
04674         }
04675       else if (bp->near_label && ! NEXT_INSN (bp->near_label))
04676         if (addr - bp->address <= CONDJUMP_MAX)
04677     emit_label_after (bp->near_label, PREV_INSN (insn));
04678         else
04679     {
04680       gen_far_branch (bp);
04681       bp->near_label = 0;
04682     }
04683       else
04684         bp->near_label = 0;
04685       bp->address = addr;
04686       bp->insert_place = insn;
04687       if (! far_label)
04688         emit_insn_before (gen_block_branch_redirect (const0_rtx), insn);
04689       else
04690         gen_block_redirect (insn, addr, bp->near_label ? 2 : 0);
04691     }
04692       }
04693   /* Generate all pending far branches,
04694      and free our references to the far labels.  */
04695   while (far_branch_list)
04696     {
04697       if (far_branch_list->near_label
04698     && ! NEXT_INSN (far_branch_list->near_label))
04699   gen_far_branch (far_branch_list);
04700       if (optimize
04701     && far_branch_list->far_label
04702     && ! --LABEL_NUSES (far_branch_list->far_label))
04703   delete_insn (far_branch_list->far_label);
04704       far_branch_list = far_branch_list->prev;
04705     }
04706 
04707   /* Instruction length information is no longer valid due to the new
04708      instructions that have been generated.  */
04709   init_insn_lengths ();
04710 }
04711 
04712 /* Dump out instruction addresses, which is useful for debugging the
04713    constant pool table stuff.
04714 
04715    If relaxing, output the label and pseudo-ops used to link together
04716    calls and the instruction which set the registers.  */
04717 
04718 /* ??? The addresses printed by this routine for insns are nonsense for
04719    insns which are inside of a sequence where none of the inner insns have
04720    variable length.  This is because the second pass of shorten_branches
04721    does not bother to update them.  */
04722 
04723 void
04724 final_prescan_insn (rtx insn, rtx *opvec ATTRIBUTE_UNUSED,
04725         int noperands ATTRIBUTE_UNUSED)
04726 {
04727   if (TARGET_DUMPISIZE)
04728     fprintf (asm_out_file, "\n! at %04x\n", INSN_ADDRESSES (INSN_UID (insn)));
04729 
04730   if (TARGET_RELAX)
04731     {
04732       rtx note;
04733 
04734       note = find_reg_note (insn, REG_LABEL, NULL_RTX);
04735       if (note)
04736   {
04737     rtx pattern;
04738 
04739     pattern = PATTERN (insn);
04740     if (GET_CODE (pattern) == PARALLEL)
04741       pattern = XVECEXP (pattern, 0, 0);
04742     if (GET_CODE (pattern) == CALL
04743         || (GET_CODE (pattern) == SET
04744       && (GET_CODE (SET_SRC (pattern)) == CALL
04745           || get_attr_type (insn) == TYPE_SFUNC)))
04746       asm_fprintf (asm_out_file, "\t.uses %LL%d\n",
04747        CODE_LABEL_NUMBER (XEXP (note, 0)));
04748     else if (GET_CODE (pattern) == SET)
04749       (*targetm.asm_out.internal_label) (asm_out_file, "L",
04750                CODE_LABEL_NUMBER (XEXP (note, 0)));
04751     else
04752       abort ();
04753   }
04754     }
04755 }
04756 
04757 /* Dump out any constants accumulated in the final pass.  These will
04758    only be labels.  */
04759 
04760 const char *
04761 output_jump_label_table (void)
04762 {
04763   int i;
04764 
04765   if (pool_size)
04766     {
04767       fprintf (asm_out_file, "\t.align 2\n");
04768       for (i = 0; i < pool_size; i++)
04769   {
04770     pool_node *p = &pool_vector[i];
04771 
04772     (*targetm.asm_out.internal_label) (asm_out_file, "L",
04773              CODE_LABEL_NUMBER (p->label));
04774     output_asm_insn (".long %O0", &p->value);
04775   }
04776       pool_size = 0;
04777     }
04778 
04779   return "";
04780 }
04781 
04782 /* A full frame looks like:
04783 
04784    arg-5
04785    arg-4
04786    [ if current_function_anonymous_args
04787    arg-3
04788    arg-2
04789    arg-1
04790    arg-0 ]
04791    saved-fp
04792    saved-r10
04793    saved-r11
04794    saved-r12
04795    saved-pr
04796    local-n
04797    ..
04798    local-1
04799    local-0        <- fp points here.  */
04800 
04801 /* Number of bytes pushed for anonymous args, used to pass information
04802    between expand_prologue and expand_epilogue.  */
04803 
04804 /* Adjust the stack by SIZE bytes.  REG holds the rtl of the register to be
04805    adjusted.  If epilogue_p is zero, this is for a prologue; otherwise, it's
04806    for an epilogue and a negative value means that it's for a sibcall
04807    epilogue.  If LIVE_REGS_MASK is nonzero, it points to a HARD_REG_SET of
04808    all the registers that are about to be restored, and hence dead.  */
04809 
04810 static void
04811 output_stack_adjust (int size, rtx reg, int epilogue_p,
04812          HARD_REG_SET *live_regs_mask)
04813 {
04814   rtx (*emit_fn) (rtx) = epilogue_p ? &emit_insn : &frame_insn;
04815   if (size)
04816     {
04817       HOST_WIDE_INT align = STACK_BOUNDARY / BITS_PER_UNIT;
04818 
04819 /* This test is bogus, as output_stack_adjust is used to re-align the
04820    stack.  */
04821 #if 0
04822       if (size % align)
04823   abort ();
04824 #endif
04825 
04826       if (CONST_OK_FOR_ADD (size))
04827   emit_fn (GEN_ADD3 (reg, reg, GEN_INT (size)));
04828       /* Try to do it with two partial adjustments; however, we must make
04829    sure that the stack is properly aligned at all times, in case
04830    an interrupt occurs between the two partial adjustments.  */
04831       else if (CONST_OK_FOR_ADD (size / 2 & -align)
04832          && CONST_OK_FOR_ADD (size - (size / 2 & -align)))
04833   {
04834     emit_fn (GEN_ADD3 (reg, reg, GEN_INT (size / 2 & -align)));
04835     emit_fn (GEN_ADD3 (reg, reg, GEN_INT (size - (size / 2 & -align))));
04836   }
04837       else
04838   {
04839     rtx const_reg;
04840     rtx insn;
04841     int temp = epilogue_p ? 7 : (TARGET_SH5 ? 0 : 1);
04842     int i;
04843 
04844     /* If TEMP is invalid, we could temporarily save a general
04845        register to MACL.  However, there is currently no need
04846        to handle this case, so just abort when we see it.  */
04847     if (epilogue_p < 0
04848         || current_function_interrupt
04849         || ! call_really_used_regs[temp] || fixed_regs[temp])
04850       temp = -1;
04851     if (temp < 0 && ! current_function_interrupt
04852         && (TARGET_SHMEDIA || epilogue_p >= 0))
04853       {
04854         HARD_REG_SET temps;
04855         COPY_HARD_REG_SET (temps, call_used_reg_set);
04856         AND_COMPL_HARD_REG_SET (temps, call_fixed_reg_set);
04857         if (epilogue_p > 0)
04858     {
04859       int nreg = 0;
04860       if (current_function_return_rtx)
04861         {
04862           enum machine_mode mode;
04863           mode = GET_MODE (current_function_return_rtx);
04864           if (BASE_RETURN_VALUE_REG (mode) == FIRST_RET_REG)
04865       nreg = HARD_REGNO_NREGS (FIRST_RET_REG, mode);
04866         }
04867       for (i = 0; i < nreg; i++)
04868         CLEAR_HARD_REG_BIT (temps, FIRST_RET_REG + i);
04869       if (current_function_calls_eh_return)
04870         {
04871           CLEAR_HARD_REG_BIT (temps, EH_RETURN_STACKADJ_REGNO);
04872           for (i = 0; i <= 3; i++)
04873       CLEAR_HARD_REG_BIT (temps, EH_RETURN_DATA_REGNO (i));
04874         }
04875     }
04876         if (TARGET_SHMEDIA && epilogue_p < 0)
04877     for (i = FIRST_TARGET_REG; i <= LAST_TARGET_REG; i++)
04878       CLEAR_HARD_REG_BIT (temps, i);
04879         if (epilogue_p <= 0)
04880     {
04881       for (i = FIRST_PARM_REG;
04882            i < FIRST_PARM_REG + NPARM_REGS (SImode); i++)
04883         CLEAR_HARD_REG_BIT (temps, i);
04884       if (cfun->static_chain_decl != NULL)
04885         CLEAR_HARD_REG_BIT (temps, STATIC_CHAIN_REGNUM);
04886     }
04887         temp = scavenge_reg (&temps);
04888       }
04889     if (temp < 0 && live_regs_mask)
04890       temp = scavenge_reg (live_regs_mask);
04891     if (temp < 0)
04892       {
04893         /* If we reached here, the most likely case is the (sibcall)
04894      epilogue for non SHmedia.  Put a special push/pop sequence
04895      for such case as the last resort.  This looks lengthy but
04896      would not be problem because it seems to be very rare.  */
04897         if (! TARGET_SHMEDIA && epilogue_p)
04898     {
04899       rtx adj_reg, tmp_reg, mem;
04900 
04901       /* ??? There is still the slight possibility that r4 or r5
04902          have been reserved as fixed registers or assigned as
04903          global registers, and they change during an interrupt.
04904          There are possible ways to handle this:
04905          - If we are adjusting the frame pointer (r14), we can do
04906            with a single temp register and an ordinary push / pop
04907            on the stack.
04908          - Grab any call-used or call-saved registers (i.e. not
04909            fixed or globals) for the temps we need.  We might
04910            also grab r14 if we are adjusting the stack pointer.
04911            If we can't find enough available registers, issue
04912            a diagnostic and abort - the user must have reserved
04913            way too many registers.
04914          But since all this is rather unlikely to happen and
04915          would require extra testing, we just abort if r4 / r5
04916          are not available.  */
04917       if (fixed_regs[4] || fixed_regs[5]
04918           || global_regs[4] || global_regs[5])
04919         abort ();
04920 
04921       adj_reg = gen_rtx_REG (GET_MODE (reg), 4);
04922       tmp_reg = gen_rtx_REG (GET_MODE (reg), 5);
04923       emit_move_insn (gen_rtx_MEM (Pmode, reg), adj_reg);
04924       emit_insn (GEN_MOV (adj_reg, GEN_INT (size)));
04925       emit_insn (GEN_ADD3 (adj_reg, adj_reg, reg));
04926       mem = gen_rtx_MEM (Pmode, gen_rtx_PRE_DEC (Pmode, adj_reg));
04927       emit_move_insn (mem, tmp_reg);
04928       emit_move_insn (tmp_reg, gen_rtx_MEM (Pmode, reg));
04929       mem = gen_rtx_MEM (Pmode, gen_rtx_PRE_DEC (Pmode, adj_reg));
04930       emit_move_insn (mem, tmp_reg);
04931       emit_move_insn (reg, adj_reg);
04932       mem = gen_rtx_MEM (Pmode, gen_rtx_POST_INC (Pmode, reg));
04933       emit_move_insn (adj_reg, mem);
04934       mem = gen_rtx_MEM (Pmode, gen_rtx_POST_INC (Pmode, reg));
04935       emit_move_insn (tmp_reg, mem);
04936       return;
04937     }
04938         else
04939     abort ();
04940       }
04941     const_reg = gen_rtx_REG (GET_MODE (reg), temp);
04942 
04943     /* If SIZE is negative, subtract the positive value.
04944        This sometimes allows a constant pool entry to be shared
04945        between prologue and epilogue code.  */
04946     if (size < 0)
04947       {
04948         emit_insn (GEN_MOV (const_reg, GEN_INT (-size)));
04949         insn = emit_fn (GEN_SUB3 (reg, reg, const_reg));
04950       }
04951     else
04952       {
04953         emit_insn (GEN_MOV (const_reg, GEN_INT (size)));
04954         insn = emit_fn (GEN_ADD3 (reg, reg, const_reg));
04955       }
04956     if (! epilogue_p)
04957       REG_NOTES (insn)
04958         = (gen_rtx_EXPR_LIST
04959      (REG_FRAME_RELATED_EXPR,
04960       gen_rtx_SET (VOIDmode, reg,
04961              gen_rtx_PLUS (SImode, reg, GEN_INT (size))),
04962       REG_NOTES (insn)));
04963   }
04964     }
04965 }
04966 
04967 static rtx
04968 frame_insn (rtx x)
04969 {
04970   x = emit_insn (x);
04971   RTX_FRAME_RELATED_P (x) = 1;
04972   return x;
04973 }
04974 
04975 /* Output RTL to push register RN onto the stack.  */
04976 
04977 static rtx
04978 push (int rn)
04979 {
04980   rtx x;
04981   if (rn == FPUL_REG)
04982     x = gen_push_fpul ();
04983   else if (rn == FPSCR_REG)
04984     x = gen_push_fpscr ();
04985   else if ((TARGET_SH4 || TARGET_SH2A_DOUBLE) && TARGET_FMOVD && ! TARGET_FPU_SINGLE
04986      && FP_OR_XD_REGISTER_P (rn))
04987     {
04988       if (FP_REGISTER_P (rn) && (rn - FIRST_FP_REG) & 1)
04989   return NULL_RTX;
04990       x = gen_push_4 (gen_rtx_REG (DFmode, rn));
04991     }
04992   else if (TARGET_SH2E && FP_REGISTER_P (rn))
04993     x = gen_push_e (gen_rtx_REG (SFmode, rn));
04994   else
04995     x = gen_push (gen_rtx_REG (SImode, rn));
04996 
04997   x = frame_insn (x);
04998   REG_NOTES (x)
04999     = gen_rtx_EXPR_LIST (REG_INC,
05000        gen_rtx_REG (SImode, STACK_POINTER_REGNUM), 0);
05001   return x;
05002 }
05003 
05004 /* Output RTL to pop register RN from the stack.  */
05005 
05006 static void
05007 pop (int rn)
05008 {
05009   rtx x;
05010   if (rn == FPUL_REG)
05011     x = gen_pop_fpul ();
05012   else if (rn == FPSCR_REG)
05013     x = gen_pop_fpscr ();
05014   else if ((TARGET_SH4 || TARGET_SH2A_DOUBLE) && TARGET_FMOVD && ! TARGET_FPU_SINGLE
05015      && FP_OR_XD_REGISTER_P (rn))
05016     {
05017       if (FP_REGISTER_P (rn) && (rn - FIRST_FP_REG) & 1)
05018   return;
05019       x = gen_pop_4 (gen_rtx_REG (DFmode, rn));
05020     }
05021   else if (TARGET_SH2E && FP_REGISTER_P (rn))
05022     x = gen_pop_e (gen_rtx_REG (SFmode, rn));
05023   else
05024     x = gen_pop (gen_rtx_REG (SImode, rn));
05025 
05026   x = emit_insn (x);
05027   REG_NOTES (x)
05028     = gen_rtx_EXPR_LIST (REG_INC,
05029        gen_rtx_REG (SImode, STACK_POINTER_REGNUM), 0);
05030 }
05031 
05032 /* Generate code to push the regs specified in the mask.  */
05033 
05034 static void
05035 push_regs (HARD_REG_SET *mask, int interrupt_handler)
05036 {
05037   int i;
05038   int skip_fpscr = 0;
05039 
05040   /* Push PR last; this gives better latencies after the prologue, and
05041      candidates for the return delay slot when there are no general
05042      registers pushed.  */
05043   for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
05044     {
05045       /* If this is an interrupt handler, and the SZ bit varies,
05046    and we have to push any floating point register, we need
05047    to switch to the correct precision first.  */
05048       if (i == FIRST_FP_REG && interrupt_handler && TARGET_FMOVD
05049     && hard_regs_intersect_p (mask, &reg_class_contents[DF_REGS]))
05050   {
05051     HARD_REG_SET unsaved;
05052 
05053     push (FPSCR_REG);
05054     COMPL_HARD_REG_SET (unsaved, *mask);
05055     fpscr_set_from_mem (NORMAL_MODE (FP_MODE), unsaved);
05056     skip_fpscr = 1;
05057   }
05058       if (i != PR_REG
05059     && (i != FPSCR_REG || ! skip_fpscr)
05060     && TEST_HARD_REG_BIT (*mask, i))
05061   push (i);
05062     }
05063   if (TEST_HARD_REG_BIT (*mask, PR_REG))
05064     push (PR_REG);
05065 }
05066 
05067 /* Calculate how much extra space is needed to save all callee-saved
05068    target registers.
05069    LIVE_REGS_MASK is the register mask calculated by calc_live_regs.  */
05070 
05071 static int
05072 shmedia_target_regs_stack_space (HARD_REG_SET *live_regs_mask)
05073 {
05074   int reg;
05075   int stack_space = 0;
05076   int interrupt_handler = sh_cfun_interrupt_handler_p ();
05077 
05078   for (reg = LAST_TARGET_REG; reg >= FIRST_TARGET_REG; reg--)
05079     if ((! call_really_used_regs[reg] || interrupt_handler)
05080         && ! TEST_HARD_REG_BIT (*live_regs_mask, reg))
05081       /* Leave space to save this target register on the stack,
05082    in case target register allocation wants to use it.  */
05083       stack_space += GET_MODE_SIZE (REGISTER_NATURAL_MODE (reg));
05084   return stack_space;
05085 }
05086 
05087 /* Decide whether we should reserve space for callee-save target registers,
05088    in case target register allocation wants to use them.  REGS_SAVED is
05089    the space, in bytes, that is already required for register saves.
05090    LIVE_REGS_MASK is the register mask calculated by calc_live_regs.  */
05091 
05092 static int
05093 shmedia_reserve_space_for_target_registers_p (int regs_saved,
05094                 HARD_REG_SET *live_regs_mask)
05095 {
05096   if (optimize_size)
05097     return 0;
05098   return shmedia_target_regs_stack_space (live_regs_mask) <= regs_saved;
05099 }
05100 
05101 /* Decide how much space to reserve for callee-save target registers
05102    in case target register allocation wants to use them.
05103    LIVE_REGS_MASK is the register mask calculated by calc_live_regs.  */
05104 
05105 static int
05106 shmedia_target_regs_stack_adjust (HARD_REG_SET *live_regs_mask)
05107 {
05108   if (shmedia_space_reserved_for_target_registers)
05109     return shmedia_target_regs_stack_space (live_regs_mask);
05110   else
05111     return 0;
05112 }
05113 
05114 /* Work out the registers which need to be saved, both as a mask and a
05115    count of saved words.  Return the count.
05116 
05117    If doing a pragma interrupt function, then push all regs used by the
05118    function, and if we call another function (we can tell by looking at PR),
05119    make sure that all the regs it clobbers are safe too.  */
05120 
05121 static int
05122 calc_live_regs (HARD_REG_SET *live_regs_mask)
05123 {
05124   unsigned int reg;
05125   int count;
05126   int interrupt_handler;
05127   int pr_live, has_call;
05128 
05129   interrupt_handler = sh_cfun_interrupt_handler_p ();
05130 
05131   CLEAR_HARD_REG_SET (*live_regs_mask);
05132   if ((TARGET_SH4 || TARGET_SH2A_DOUBLE) && TARGET_FMOVD && interrupt_handler
05133       && regs_ever_live[FPSCR_REG])
05134     target_flags &= ~FPU_SINGLE_BIT;
05135   /* If we can save a lot of saves by switching to double mode, do that.  */
05136   else if ((TARGET_SH4 || TARGET_SH2A_DOUBLE) && TARGET_FMOVD && TARGET_FPU_SINGLE)
05137     for (count = 0, reg = FIRST_FP_REG; reg <= LAST_FP_REG; reg += 2)
05138       if (regs_ever_live[reg] && regs_ever_live[reg+1]
05139     && (! call_really_used_regs[reg]
05140         || (interrupt_handler && ! pragma_trapa))
05141     && ++count > 2)
05142   {
05143     target_flags &= ~FPU_SINGLE_BIT;
05144     break;
05145   }
05146   /* PR_MEDIA_REG is a general purpose register, thus global_alloc already
05147      knows how to use it.  That means the pseudo originally allocated for
05148      the initial value can become the PR_MEDIA_REG hard register, as seen for
05149      execute/20010122-1.c:test9.  */
05150   if (TARGET_SHMEDIA)
05151     /* ??? this function is called from initial_elimination_offset, hence we
05152        can't use the result of sh_media_register_for_return here.  */
05153     pr_live = sh_pr_n_sets ();
05154   else
05155     {
05156       rtx pr_initial = has_hard_reg_initial_val (Pmode, PR_REG);
05157       pr_live = (pr_initial
05158      ? (GET_CODE (pr_initial) != REG
05159         || REGNO (pr_initial) != (PR_REG))
05160      : regs_ever_live[PR_REG]);
05161       /* For Shcompact, if not optimizing, we end up with a memory reference
05162    using the return address pointer for __builtin_return_address even
05163    though there is no actual need to put the PR register on the stack.  */
05164       pr_live |= regs_ever_live[RETURN_ADDRESS_POINTER_REGNUM];
05165     }
05166   /* Force PR to be live if the prologue has to call the SHmedia
05167      argument decoder or register saver.  */
05168   if (TARGET_SHCOMPACT
05169       && ((current_function_args_info.call_cookie
05170      & ~ CALL_COOKIE_RET_TRAMP (1))
05171     || current_function_has_nonlocal_label))
05172     pr_live = 1;
05173   has_call = TARGET_SHMEDIA ? ! leaf_function_p () : pr_live;
05174   for (count = 0, reg = FIRST_PSEUDO_REGISTER; reg-- != 0; )
05175     {
05176       if (reg == (TARGET_SHMEDIA ? PR_MEDIA_REG : PR_REG)
05177     ? pr_live
05178     : (interrupt_handler && ! pragma_trapa)
05179     ? (/* Need to save all the regs ever live.  */
05180        (regs_ever_live[reg]
05181         || (call_really_used_regs[reg]
05182       && (! fixed_regs[reg] || reg == MACH_REG || reg == MACL_REG
05183           || reg == PIC_OFFSET_TABLE_REGNUM)
05184       && has_call)
05185         || (has_call && REGISTER_NATURAL_MODE (reg) == SImode
05186       && (GENERAL_REGISTER_P (reg) || TARGET_REGISTER_P (reg))))
05187        && reg != STACK_POINTER_REGNUM && reg != ARG_POINTER_REGNUM
05188        && reg != RETURN_ADDRESS_POINTER_REGNUM
05189        && reg != T_REG && reg != GBR_REG
05190        /* Push fpscr only on targets which have FPU */
05191        && (reg != FPSCR_REG || TARGET_FPU_ANY))
05192     : (/* Only push those regs which are used and need to be saved.  */
05193        (TARGET_SHCOMPACT
05194         && flag_pic
05195         && current_function_args_info.call_cookie
05196         && reg == PIC_OFFSET_TABLE_REGNUM)
05197        || (regs_ever_live[reg] && ! call_really_used_regs[reg])
05198        || (current_function_calls_eh_return
05199      && (reg == EH_RETURN_DATA_REGNO (0)
05200          || reg == EH_RETURN_DATA_REGNO (1)
05201          || reg == EH_RETURN_DATA_REGNO (2)
05202          || reg == EH_RETURN_DATA_REGNO (3)))
05203        || ((reg == MACL_REG || reg == MACH_REG)
05204      && regs_ever_live[reg]
05205      && sh_cfun_attr_renesas_p ())
05206        ))
05207   {
05208     SET_HARD_REG_BIT (*live_regs_mask, reg);
05209     count += GET_MODE_SIZE (REGISTER_NATURAL_MODE (reg));
05210 
05211     if ((TARGET_SH4 || TARGET_SH2A_DOUBLE || TARGET_SH5) && TARGET_FMOVD
05212         && GET_MODE_CLASS (REGISTER_NATURAL_MODE (reg)) == MODE_FLOAT)
05213       {
05214         if (FP_REGISTER_P (reg))
05215     {
05216       if (! TARGET_FPU_SINGLE && ! regs_ever_live[reg ^ 1])
05217         {
05218           SET_HARD_REG_BIT (*live_regs_mask, (reg ^ 1));
05219           count += GET_MODE_SIZE (REGISTER_NATURAL_MODE (reg ^ 1));
05220         }
05221     }
05222         else if (XD_REGISTER_P (reg))
05223     {
05224       /* Must switch to double mode to access these registers.  */
05225       target_flags &= ~FPU_SINGLE_BIT;
05226     }
05227       }
05228   }
05229     }
05230   /* If we have a target register optimization pass after prologue / epilogue
05231      threading, we need to assume all target registers will be live even if
05232      they aren't now.  */
05233   if (flag_branch_target_load_optimize2
05234       && TARGET_SAVE_ALL_TARGET_REGS
05235       && shmedia_space_reserved_for_target_registers)
05236     for (reg = LAST_TARGET_REG; reg >= FIRST_TARGET_REG; reg--)
05237       if ((! call_really_used_regs[reg] || interrupt_handler)
05238     && ! TEST_HARD_REG_BIT (*live_regs_mask, reg))
05239   {
05240     SET_HARD_REG_BIT (*live_regs_mask, reg);
05241     count += GET_MODE_SIZE (REGISTER_NATURAL_MODE (reg));
05242   }
05243   /* If this is an interrupt handler, we don't have any call-clobbered
05244      registers we can conveniently use for target register save/restore.
05245      Make sure we save at least one general purpose register when we need
05246      to save target registers.  */
05247   if (interrupt_handler
05248       && hard_regs_intersect_p (live_regs_mask,
05249         &reg_class_contents[TARGET_REGS])
05250       && ! hard_regs_intersect_p (live_regs_mask,
05251           &reg_class_contents[GENERAL_REGS]))
05252     {
05253       SET_HARD_REG_BIT (*live_regs_mask, R0_REG);
05254       count += GET_MODE_SIZE (REGISTER_NATURAL_MODE (R0_REG));
05255     }
05256 
05257   return count;
05258 }
05259 
05260 /* Code to generate prologue and epilogue sequences */
05261 
05262 /* PUSHED is the number of bytes that are being pushed on the
05263    stack for register saves.  Return the frame size, padded
05264    appropriately so that the stack stays properly aligned.  */
05265 static HOST_WIDE_INT
05266 rounded_frame_size (int pushed)
05267 {
05268   HOST_WIDE_INT size = get_frame_size ();
05269   HOST_WIDE_INT align = STACK_BOUNDARY / BITS_PER_UNIT;
05270 
05271   return ((size + pushed + align - 1) & -align) - pushed;
05272 }
05273 
05274 /* Choose a call-clobbered target-branch register that remains
05275    unchanged along the whole function.  We set it up as the return
05276    value in the prologue.  */
05277 int
05278 sh_media_register_for_return (void)
05279 {
05280   int regno;
05281   int tr0_used;
05282 
05283   if (! current_function_is_leaf)
05284     return -1;
05285   if (lookup_attribute ("interrupt_handler",
05286       DECL_ATTRIBUTES (current_function_decl)))
05287     return -1;
05288 
05289   tr0_used = flag_pic && regs_ever_live[PIC_OFFSET_TABLE_REGNUM];
05290 
05291   for (regno = FIRST_TARGET_REG + tr0_used; regno <= LAST_TARGET_REG; regno++)
05292     if (call_really_used_regs[regno] && ! regs_ever_live[regno])
05293       return regno;
05294 
05295   return -1;
05296 }
05297 
05298 /* The maximum registers we need to save are:
05299    - 62 general purpose registers (r15 is stack pointer, r63 is zero)
05300    - 32 floating point registers (for each pair, we save none,
05301          one single precision value, or a double precision value).
05302    -  8 target registers
05303    -  add 1 entry for a delimiter.  */
05304 #define MAX_SAVED_REGS (62+32+8)
05305 
05306 typedef struct save_entry_s
05307 {
05308   unsigned char reg;
05309   unsigned char mode;
05310   short offset;
05311 } save_entry;
05312 
05313 #define MAX_TEMPS 4
05314 
05315 /* There will be a delimiter entry with VOIDmode both at the start and the
05316    end of a filled in schedule.  The end delimiter has the offset of the
05317    save with the smallest (i.e. most negative) offset.  */
05318 typedef struct save_schedule_s
05319 {
05320   save_entry entries[MAX_SAVED_REGS + 2];
05321   int temps[MAX_TEMPS+1];
05322 } save_schedule;
05323 
05324 /* Fill in SCHEDULE according to LIVE_REGS_MASK.  If RESTORE is nonzero,
05325    use reverse order.  Returns the last entry written to (not counting
05326    the delimiter).  OFFSET_BASE is a number to be added to all offset
05327    entries.  */
05328 
05329 static save_entry *
05330 sh5_schedule_saves (HARD_REG_SET *live_regs_mask, save_schedule *schedule,
05331         int offset_base)
05332 {
05333   int align, i;
05334   save_entry *entry = schedule->entries;
05335   int tmpx = 0;
05336   int offset;
05337 
05338   if (! current_function_interrupt)
05339     for (i = FIRST_GENERAL_REG; tmpx < MAX_TEMPS && i <= LAST_GENERAL_REG; i++)
05340       if (call_really_used_regs[i] && ! fixed_regs[i] && i != PR_MEDIA_REG
05341     && ! FUNCTION_ARG_REGNO_P (i)
05342     && i != FIRST_RET_REG
05343     && ! (cfun->static_chain_decl != NULL && i == STATIC_CHAIN_REGNUM)
05344     && ! (current_function_calls_eh_return
05345     && (i == EH_RETURN_STACKADJ_REGNO
05346         || ((unsigned) i >= EH_RETURN_DATA_REGNO (0)
05347       && (unsigned) i <= EH_RETURN_DATA_REGNO (3)))))
05348   schedule->temps[tmpx++] = i;
05349   entry->reg = -1;
05350   entry->mode = VOIDmode;
05351   entry->offset = offset_base;
05352   entry++;
05353   /* We loop twice: first, we save 8-byte aligned registers in the
05354      higher addresses, that are known to be aligned.  Then, we
05355      proceed to saving 32-bit registers that don't need 8-byte
05356      alignment.
05357      If this is an interrupt function, all registers that need saving
05358      need to be saved in full.  moreover, we need to postpone saving
05359      target registers till we have saved some general purpose registers
05360      we can then use as scratch registers.  */
05361   offset = offset_base;
05362   for (align = 1; align >= 0; align--)
05363     {
05364       for (i = FIRST_PSEUDO_REGISTER - 1; i >= 0; i--)
05365   if (TEST_HARD_REG_BIT (*live_regs_mask, i))
05366     {
05367       enum machine_mode mode = REGISTER_NATURAL_MODE (i);
05368       int reg = i;
05369 
05370       if (current_function_interrupt)
05371         {
05372     if (TARGET_REGISTER_P (i))
05373       continue;
05374     if (GENERAL_REGISTER_P (i))
05375       mode = DImode;
05376         }
05377       if (mode == SFmode && (i % 2) == 1
05378     && ! TARGET_FPU_SINGLE && FP_REGISTER_P (i)
05379     && (TEST_HARD_REG_BIT (*live_regs_mask, (i ^ 1))))
05380         {
05381     mode = DFmode;
05382     i--;
05383     reg--;
05384         }
05385 
05386       /* If we're doing the aligned pass and this is not aligned,
05387          or we're doing the unaligned pass and this is aligned,
05388          skip it.  */
05389       if ((GET_MODE_SIZE (mode) % (STACK_BOUNDARY / BITS_PER_UNIT) == 0)
05390     != align)
05391         continue;
05392 
05393       if (current_function_interrupt
05394     && GENERAL_REGISTER_P (i)
05395     && tmpx < MAX_TEMPS)
05396         schedule->temps[tmpx++] = i;
05397 
05398       offset -= GET_MODE_SIZE (mode);
05399       entry->reg = i;
05400       entry->mode = mode;
05401       entry->offset = offset;
05402       entry++;
05403     }
05404       if (align && current_function_interrupt)
05405   for (i = LAST_TARGET_REG; i >= FIRST_TARGET_REG; i--)
05406     if (TEST_HARD_REG_BIT (*live_regs_mask, i))
05407       {
05408         offset -= GET_MODE_SIZE (DImode);
05409         entry->reg = i;
05410         entry->mode = DImode;
05411         entry->offset = offset;
05412         entry++;
05413       }
05414     }
05415   entry->reg = -1;
05416   entry->mode = VOIDmode;
05417   entry->offset = offset;
05418   schedule->temps[tmpx] = -1;
05419   return entry - 1;
05420 }
05421 
05422 void
05423 sh_expand_prologue (void)
05424 {
05425   HARD_REG_SET live_regs_mask;
05426   int d, i;
05427   int d_rounding = 0;
05428   int save_flags = target_flags;
05429   int pretend_args;
05430 
05431   current_function_interrupt = sh_cfun_interrupt_handler_p ();
05432 
05433   /* We have pretend args if we had an object sent partially in registers
05434      and partially on the stack, e.g. a large structure.  */
05435   pretend_args = current_function_pretend_args_size;
05436   if (TARGET_VARARGS_PRETEND_ARGS (current_function_decl)
05437       && (NPARM_REGS(SImode)
05438     > current_function_args_info.arg_count[(int) SH_ARG_INT]))
05439     pretend_args = 0;
05440   output_stack_adjust (-pretend_args
05441            - current_function_args_info.stack_regs * 8,
05442            stack_pointer_rtx, 0, NULL);
05443 
05444   if (TARGET_SHCOMPACT && flag_pic && current_function_args_info.call_cookie)
05445     /* We're going to use the PIC register to load the address of the
05446        incoming-argument decoder and/or of the return trampoline from
05447        the GOT, so make sure the PIC register is preserved and
05448        initialized.  */
05449     regs_ever_live[PIC_OFFSET_TABLE_REGNUM] = 1;
05450 
05451   if (TARGET_SHCOMPACT
05452       && (current_function_args_info.call_cookie & ~ CALL_COOKIE_RET_TRAMP(1)))
05453     {
05454       int reg;
05455 
05456       /* First, make all registers with incoming arguments that will
05457    be pushed onto the stack live, so that register renaming
05458    doesn't overwrite them.  */
05459       for (reg = 0; reg < NPARM_REGS (SImode); reg++)
05460   if (CALL_COOKIE_STACKSEQ_GET (current_function_args_info.call_cookie)
05461       >= NPARM_REGS (SImode) - reg)
05462     for (; reg < NPARM_REGS (SImode); reg++)
05463       emit_insn (gen_shcompact_preserve_incoming_args
05464            (gen_rtx_REG (SImode, FIRST_PARM_REG + reg)));
05465   else if (CALL_COOKIE_INT_REG_GET
05466      (current_function_args_info.call_cookie, reg) == 1)
05467     emit_insn (gen_shcompact_preserve_incoming_args
05468          (gen_rtx_REG (SImode, FIRST_PARM_REG + reg)));
05469 
05470       emit_move_insn (gen_rtx_REG (Pmode, MACL_REG),
05471           stack_pointer_rtx);
05472       emit_move_insn (gen_rtx_REG (SImode, R0_REG),
05473           GEN_INT (current_function_args_info.call_cookie));
05474       emit_move_insn (gen_rtx_REG (SImode, MACH_REG),
05475           gen_rtx_REG (SImode, R0_REG));
05476     }
05477   else if (TARGET_SHMEDIA)
05478     {
05479       int tr = sh_media_register_for_return ();
05480 
05481       if (tr >= 0)
05482   {
05483     rtx insn = emit_move_insn (gen_rtx_REG (DImode, tr),
05484              gen_rtx_REG (DImode, PR_MEDIA_REG));
05485 
05486     /* ??? We should suppress saving pr when we don't need it, but this
05487        is tricky because of builtin_return_address.  */
05488 
05489     /* If this function only exits with sibcalls, this copy
05490        will be flagged as dead.  */
05491     REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_MAYBE_DEAD,
05492             const0_rtx,
05493             REG_NOTES (insn));
05494   }
05495     }
05496 
05497   /* Emit the code for SETUP_VARARGS.  */
05498   if (current_function_stdarg)
05499     {
05500       if (TARGET_VARARGS_PRETEND_ARGS (current_function_decl))
05501   {
05502     /* Push arg regs as if they'd been provided by caller in stack.  */
05503     for (i = 0; i < NPARM_REGS(SImode); i++)
05504       {
05505         int rn = NPARM_REGS(SImode) + FIRST_PARM_REG - i - 1;
05506         rtx insn;
05507 
05508         if (i >= (NPARM_REGS(SImode)
05509       - current_function_args_info.arg_count[(int) SH_ARG_INT]
05510       ))
05511     break;
05512         insn = push (rn);
05513         RTX_FRAME_RELATED_P (insn) = 0;
05514       }
05515   }
05516     }
05517 
05518   /* If we're supposed to switch stacks at function entry, do so now.  */
05519   if (sp_switch)
05520     emit_insn (gen_sp_switch_1 ());
05521 
05522   d = calc_live_regs (&live_regs_mask);
05523   /* ??? Maybe we could save some switching if we can move a mode switch
05524      that already happens to be at the function start into the prologue.  */
05525   if (target_flags != save_flags && ! current_function_interrupt)
05526     emit_insn (gen_toggle_sz ());
05527 
05528   if (TARGET_SH5)
05529     {
05530       int offset_base, offset;
05531       rtx r0 = NULL_RTX;
05532       int offset_in_r0 = -1;
05533       int sp_in_r0 = 0;
05534       int tregs_space = shmedia_target_regs_stack_adjust (&live_regs_mask);
05535       int total_size, save_size;
05536       save_schedule schedule;
05537       save_entry *entry;
05538       int *tmp_pnt;
05539 
05540       if (call_really_used_regs[R0_REG] && ! fixed_regs[R0_REG]
05541     && ! current_function_interrupt)
05542   r0 = gen_rtx_REG (Pmode, R0_REG);
05543 
05544       /* D is the actual number of bytes that we need for saving registers,
05545    however, in initial_elimination_offset we have committed to using
05546    an additional TREGS_SPACE amount of bytes - in order to keep both
05547    addresses to arguments supplied by the caller and local variables
05548    valid, we must keep this gap.  Place it between the incoming
05549    arguments and the actually saved registers in a bid to optimize
05550    locality of reference.  */
05551       total_size = d + tregs_space;
05552       total_size += rounded_frame_size (total_size);
05553       save_size = total_size - rounded_frame_size (d);
05554       if (save_size % (STACK_BOUNDARY / BITS_PER_UNIT))
05555   d_rounding = ((STACK_BOUNDARY / BITS_PER_UNIT)
05556       - save_size % (STACK_BOUNDARY / BITS_PER_UNIT));
05557 
05558       /* If adjusting the stack in a single step costs nothing extra, do so.
05559    I.e. either if a single addi is enough, or we need a movi anyway,
05560    and we don't exceed the maximum offset range (the test for the
05561    latter is conservative for simplicity).  */
05562       if (TARGET_SHMEDIA
05563     && (CONST_OK_FOR_I10 (-total_size)
05564         || (! CONST_OK_FOR_I10 (-(save_size + d_rounding))
05565       && total_size <= 2044)))
05566   d_rounding = total_size - save_size;
05567 
05568       offset_base = d + d_rounding;
05569 
05570       output_stack_adjust (-(save_size + d_rounding), stack_pointer_rtx,
05571          0, NULL);
05572 
05573       sh5_schedule_saves (&live_regs_mask, &schedule, offset_base);
05574       tmp_pnt = schedule.temps;
05575       for (entry = &schedule.entries[1]; entry->mode != VOIDmode; entry++)
05576         {
05577     enum machine_mode mode = entry->mode;
05578     unsigned int reg = entry->reg;
05579     rtx reg_rtx, mem_rtx, pre_dec = NULL_RTX;
05580     rtx orig_reg_rtx;
05581 
05582     offset = entry->offset;
05583 
05584     reg_rtx = gen_rtx_REG (mode, reg);
05585 
05586     mem_rtx = gen_rtx_MEM (mode,
05587          gen_rtx_PLUS (Pmode,
05588                  stack_pointer_rtx,
05589                  GEN_INT (offset)));
05590 
05591     GO_IF_LEGITIMATE_ADDRESS (mode, XEXP (mem_rtx, 0), try_pre_dec);
05592 
05593     if (! r0)
05594       abort ();
05595     mem_rtx = NULL_RTX;
05596 
05597   try_pre_dec:
05598     do
05599       if (HAVE_PRE_DECREMENT
05600     && (offset_in_r0 - offset == GET_MODE_SIZE (mode)
05601         || mem_rtx == NULL_RTX
05602         || reg == PR_REG || SPECIAL_REGISTER_P (reg)))
05603         {
05604     pre_dec = gen_rtx_MEM (mode,
05605                gen_rtx_PRE_DEC (Pmode, r0));
05606 
05607     GO_IF_LEGITIMATE_ADDRESS (mode, XEXP (pre_dec, 0),
05608             pre_dec_ok);
05609 
05610     pre_dec = NULL_RTX;
05611 
05612     break;
05613 
05614         pre_dec_ok:
05615     mem_rtx = NULL_RTX;
05616     offset += GET_MODE_SIZE (mode);
05617         }
05618     while (0);
05619 
05620     if (mem_rtx != NULL_RTX)
05621       goto addr_ok;
05622 
05623     if (offset_in_r0 == -1)
05624       {
05625         emit_move_insn (r0, GEN_INT (offset));
05626         offset_in_r0 = offset;
05627       }
05628     else if (offset != offset_in_r0)
05629       {
05630         emit_move_insn (r0,
05631             gen_rtx_PLUS
05632             (Pmode, r0,
05633              GEN_INT (offset - offset_in_r0)));
05634         offset_in_r0 += offset - offset_in_r0;
05635       }
05636 
05637     if (pre_dec != NULL_RTX)
05638       {
05639         if (! sp_in_r0)
05640     {
05641       emit_move_insn (r0,
05642           gen_rtx_PLUS
05643           (Pmode, r0, stack_pointer_rtx));
05644       sp_in_r0 = 1;
05645     }
05646 
05647         offset -= GET_MODE_SIZE (mode);
05648         offset_in_r0 -= GET_MODE_SIZE (mode);
05649 
05650         mem_rtx = pre_dec;
05651       }
05652     else if (sp_in_r0)
05653       mem_rtx = gen_rtx_MEM (mode, r0);
05654     else
05655       mem_rtx = gen_rtx_MEM (mode,
05656            gen_rtx_PLUS (Pmode,
05657              stack_pointer_rtx,
05658              r0));
05659 
05660     /* We must not use an r0-based address for target-branch
05661        registers or for special registers without pre-dec
05662        memory addresses, since we store their values in r0
05663        first.  */
05664     if (TARGET_REGISTER_P (reg)
05665         || ((reg == PR_REG || SPECIAL_REGISTER_P (reg))
05666       && mem_rtx != pre_dec))
05667       abort ();
05668 
05669   addr_ok:
05670     orig_reg_rtx = reg_rtx;
05671     if (TARGET_REGISTER_P (reg)
05672         || ((reg == PR_REG || SPECIAL_REGISTER_P (reg))
05673       && mem_rtx != pre_dec))
05674       {
05675         rtx tmp_reg = gen_rtx_REG (GET_MODE (reg_rtx), *tmp_pnt);
05676 
05677         emit_move_insn (tmp_reg, reg_rtx);
05678 
05679         if (REGNO (tmp_reg) == R0_REG)
05680     {
05681       offset_in_r0 = -1;
05682       sp_in_r0 = 0;
05683       if (refers_to_regno_p (R0_REG, R0_REG+1, mem_rtx, (rtx *) 0))
05684         abort ();
05685     }
05686 
05687         if (*++tmp_pnt <= 0)
05688     tmp_pnt = schedule.temps;
05689 
05690         reg_rtx = tmp_reg;
05691       }
05692     {
05693       rtx insn;
05694 
05695       /* Mark as interesting for dwarf cfi generator */
05696       insn = emit_move_insn (mem_rtx, reg_rtx);
05697       RTX_FRAME_RELATED_P (insn) = 1;
05698       /* If we use an intermediate register for the save, we can't
05699          describe this exactly in cfi as a copy of the to-be-saved
05700          register into the temporary register and then the temporary
05701          register on the stack, because the temporary register can
05702          have a different natural size than the to-be-saved register.
05703          Thus, we gloss over the intermediate copy and pretend we do
05704          a direct save from the to-be-saved register.  */
05705       if (REGNO (reg_rtx) != reg)
05706         {
05707     rtx set, note_rtx;
05708 
05709     set = gen_rtx_SET (VOIDmode, mem_rtx, orig_reg_rtx);
05710     note_rtx = gen_rtx_EXPR_LIST (REG_FRAME_RELATED_EXPR, set,
05711                 REG_NOTES (insn));
05712     REG_NOTES (insn) = note_rtx;
05713         }
05714 
05715       if (TARGET_SHCOMPACT && (offset_in_r0 != -1))
05716         {
05717     rtx reg_rtx = gen_rtx_REG (mode, reg);
05718     rtx set, note_rtx;
05719     rtx mem_rtx = gen_rtx_MEM (mode,
05720              gen_rtx_PLUS (Pmode,
05721                stack_pointer_rtx,
05722                GEN_INT (offset)));
05723 
05724     set = gen_rtx_SET (VOIDmode, mem_rtx, reg_rtx);
05725     note_rtx = gen_rtx_EXPR_LIST (REG_FRAME_RELATED_EXPR, set,
05726                 REG_NOTES (insn));
05727     REG_NOTES (insn) = note_rtx;
05728         }
05729     }
05730   }
05731 
05732       if (entry->offset != d_rounding)
05733   abort ();
05734     }
05735   else
05736     push_regs (&live_regs_mask, current_function_interrupt);
05737 
05738   if (flag_pic && regs_ever_live[PIC_OFFSET_TABLE_REGNUM])
05739     {
05740       rtx insn = get_last_insn ();
05741       rtx last = emit_insn (gen_GOTaddr2picreg ());
05742 
05743       /* Mark these insns as possibly dead.  Sometimes, flow2 may
05744    delete all uses of the PIC register.  In this case, let it
05745    delete the initialization too.  */
05746       do
05747   {
05748     insn = NEXT_INSN (insn);
05749 
05750     REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_MAYBE_DEAD,
05751             const0_rtx,
05752             REG_NOTES (insn));
05753   }
05754       while (insn != last);
05755     }
05756 
05757   if (SHMEDIA_REGS_STACK_ADJUST ())
05758     {
05759       emit_move_insn (gen_rtx_REG (Pmode, R0_REG),
05760           function_symbol (TARGET_FPU_ANY
05761                ? "__GCC_push_shmedia_regs"
05762                : "__GCC_push_shmedia_regs_nofpu"));
05763       /* This must NOT go through the PLT, otherwise mach and macl
05764    may be clobbered.  */
05765       emit_insn (gen_shmedia_save_restore_regs_compact
05766      (GEN_INT (-SHMEDIA_REGS_STACK_ADJUST ())));
05767     }
05768 
05769   if (target_flags != save_flags && ! current_function_interrupt)
05770     {
05771       rtx insn = emit_insn (gen_toggle_sz ());
05772 
05773       /* If we're lucky, a mode switch in the function body will
05774    overwrite fpscr, turning this insn dead.  Tell flow this
05775    insn is ok to delete.  */
05776       REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_MAYBE_DEAD,
05777               const0_rtx,
05778               REG_NOTES (insn));
05779     }
05780 
05781   target_flags = save_flags;
05782 
05783   output_stack_adjust (-rounded_frame_size (d) + d_rounding,
05784            stack_pointer_rtx, 0, NULL);
05785 
05786   if (frame_pointer_needed)
05787     frame_insn (GEN_MOV (frame_pointer_rtx, stack_pointer_rtx));
05788 
05789   if (TARGET_SHCOMPACT
05790       && (current_function_args_info.call_cookie & ~ CALL_COOKIE_RET_TRAMP(1)))
05791     {
05792       /* This must NOT go through the PLT, otherwise mach and macl
05793    may be clobbered.  */
05794       emit_move_insn (gen_rtx_REG (Pmode, R0_REG),
05795           function_symbol ("__GCC_shcompact_incoming_args"));
05796       emit_insn (gen_shcompact_incoming_args ());
05797     }
05798 }
05799 
05800 void
05801 sh_expand_epilogue (bool sibcall_p)
05802 {
05803   HARD_REG_SET live_regs_mask;
05804   int d, i;
05805   int d_rounding = 0;
05806 
05807   int save_flags = target_flags;
05808   int frame_size, save_size;
05809   int fpscr_deferred = 0;
05810   int e = sibcall_p ? -1 : 1;
05811 
05812   d = calc_live_regs (&live_regs_mask);
05813 
05814   save_size = d;
05815   frame_size = rounded_frame_size (d);
05816 
05817   if (TARGET_SH5)
05818     {
05819       int tregs_space = shmedia_target_regs_stack_adjust (&live_regs_mask);
05820       int total_size;
05821       if (d % (STACK_BOUNDARY / BITS_PER_UNIT))
05822       d_rounding = ((STACK_BOUNDARY / BITS_PER_UNIT)
05823         - d % (STACK_BOUNDARY / BITS_PER_UNIT));
05824 
05825       total_size = d + tregs_space;
05826       total_size += rounded_frame_size (total_size);
05827       save_size = total_size - frame_size;
05828 
05829       /* If adjusting the stack in a single step costs nothing extra, do so.
05830    I.e. either if a single addi is enough, or we need a movi anyway,
05831    and we don't exceed the maximum offset range (the test for the
05832    latter is conservative for simplicity).  */
05833       if (TARGET_SHMEDIA
05834     && ! frame_pointer_needed
05835     && (CONST_OK_FOR_I10 (total_size)
05836         || (! CONST_OK_FOR_I10 (save_size + d_rounding)
05837       && total_size <= 2044)))
05838   d_rounding = frame_size;
05839 
05840       frame_size -= d_rounding;
05841     }
05842 
05843   if (frame_pointer_needed)
05844     {
05845       /* We must avoid scheduling the epilogue with previous basic blocks
05846    when exception handling is enabled.  See PR/18032.  */
05847       if (flag_exceptions)
05848   emit_insn (gen_blockage ());
05849       output_stack_adjust (frame_size, frame_pointer_rtx, e, &live_regs_mask);
05850 
05851       /* We must avoid moving the stack pointer adjustment past code
05852    which reads from the local frame, else an interrupt could
05853    occur after the SP adjustment and clobber data in the local
05854    frame.  */
05855       emit_insn (gen_blockage ());
05856       emit_insn (GEN_MOV (stack_pointer_rtx, frame_pointer_rtx));
05857     }
05858   else if (frame_size)
05859     {
05860       /* We must avoid moving the stack pointer adjustment past code
05861    which reads from the local frame, else an interrupt could
05862    occur after the SP adjustment and clobber data in the local
05863    frame.  */
05864       emit_insn (gen_blockage ());
05865       output_stack_adjust (frame_size, stack_pointer_rtx, e, &live_regs_mask);
05866     }
05867 
05868   if (SHMEDIA_REGS_STACK_ADJUST ())
05869     {
05870       emit_move_insn (gen_rtx_REG (Pmode, R0_REG),
05871           function_symbol (TARGET_FPU_ANY
05872                ? "__GCC_pop_shmedia_regs"
05873                : "__GCC_pop_shmedia_regs_nofpu"));
05874       /* This must NOT go through the PLT, otherwise mach and macl
05875    may be clobbered.  */
05876       emit_insn (gen_shmedia_save_restore_regs_compact
05877      (GEN_INT (SHMEDIA_REGS_STACK_ADJUST ())));
05878     }
05879 
05880   /* Pop all the registers.  */
05881 
05882   if (target_flags != save_flags && ! current_function_interrupt)
05883     emit_insn (gen_toggle_sz ());
05884   if (TARGET_SH5)
05885     {
05886       int offset_base, offset;
05887       int offset_in_r0 = -1;
05888       int sp_in_r0 = 0;
05889       rtx r0 = gen_rtx_REG (Pmode, R0_REG);
05890       save_schedule schedule;
05891       save_entry *entry;
05892       int *tmp_pnt;
05893 
05894       entry = sh5_schedule_saves (&live_regs_mask, &schedule, d_rounding);
05895       offset_base = -entry[1].offset + d_rounding;
05896       tmp_pnt = schedule.temps;
05897       for (; entry->mode != VOIDmode; entry--)
05898   {
05899     enum machine_mode mode = entry->mode;
05900     int reg = entry->reg;
05901     rtx reg_rtx, mem_rtx, post_inc = NULL_RTX, insn;
05902 
05903     offset = offset_base + entry->offset;
05904     reg_rtx = gen_rtx_REG (mode, reg);
05905 
05906     mem_rtx = gen_rtx_MEM (mode,
05907          gen_rtx_PLUS (Pmode,
05908                  stack_pointer_rtx,
05909                  GEN_INT (offset)));
05910 
05911     GO_IF_LEGITIMATE_ADDRESS (mode, XEXP (mem_rtx, 0), try_post_inc);
05912 
05913     mem_rtx = NULL_RTX;
05914 
05915   try_post_inc:
05916     do
05917       if (HAVE_POST_INCREMENT
05918     && (offset == offset_in_r0
05919         || (offset + GET_MODE_SIZE (mode) != d + d_rounding
05920       && mem_rtx == NULL_RTX)
05921         || reg == PR_REG || SPECIAL_REGISTER_P (reg)))
05922         {
05923     post_inc = gen_rtx_MEM (mode,
05924           gen_rtx_POST_INC (Pmode, r0));
05925 
05926     GO_IF_LEGITIMATE_ADDRESS (mode, XEXP (post_inc, 0),
05927             post_inc_ok);
05928 
05929     post_inc = NULL_RTX;
05930 
05931     break;
05932 
05933         post_inc_ok:
05934     mem_rtx = NULL_RTX;
05935         }
05936     while (0);
05937 
05938     if (mem_rtx != NULL_RTX)
05939       goto addr_ok;
05940 
05941     if (offset_in_r0 == -1)
05942       {
05943         emit_move_insn (r0, GEN_INT (offset));
05944         offset_in_r0 = offset;
05945       }
05946     else if (offset != offset_in_r0)
05947       {
05948         emit_move_insn (r0,
05949             gen_rtx_PLUS
05950             (Pmode, r0,
05951              GEN_INT (offset - offset_in_r0)));
05952         offset_in_r0 += offset - offset_in_r0;
05953       }
05954 
05955     if (post_inc != NULL_RTX)
05956       {
05957         if (! sp_in_r0)
05958     {
05959       emit_move_insn (r0,
05960           gen_rtx_PLUS
05961           (Pmode, r0, stack_pointer_rtx));
05962       sp_in_r0 = 1;
05963     }
05964 
05965         mem_rtx = post_inc;
05966 
05967         offset_in_r0 += GET_MODE_SIZE (mode);
05968       }
05969     else if (sp_in_r0)
05970       mem_rtx = gen_rtx_MEM (mode, r0);
05971     else
05972       mem_rtx = gen_rtx_MEM (mode,
05973            gen_rtx_PLUS (Pmode,
05974              stack_pointer_rtx,
05975              r0));
05976 
05977     if ((reg == PR_REG || SPECIAL_REGISTER_P (reg))
05978         && mem_rtx != post_inc)
05979       abort ();
05980 
05981   addr_ok:
05982     if ((reg == PR_REG || SPECIAL_REGISTER_P (reg))
05983         && mem_rtx != post_inc)
05984       {
05985         insn = emit_move_insn (r0, mem_rtx);
05986         mem_rtx = r0;
05987       }
05988     else if (TARGET_REGISTER_P (reg))
05989       {
05990         rtx tmp_reg = gen_rtx_REG (mode, *tmp_pnt);
05991 
05992         /* Give the scheduler a bit of freedom by using up to
05993      MAX_TEMPS registers in a round-robin fashion.  */
05994         insn = emit_move_insn (tmp_reg, mem_rtx);
05995         mem_rtx = tmp_reg;
05996         if (*++tmp_pnt < 0)
05997     tmp_pnt = schedule.temps;
05998       }
05999 
06000     insn = emit_move_insn (reg_rtx, mem_rtx);
06001     if (reg == PR_MEDIA_REG && sh_media_register_for_return () >= 0)
06002       /* This is dead, unless we return with a sibcall.  */
06003       REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_MAYBE_DEAD,
06004               const0_rtx,
06005               REG_NOTES (insn));
06006   }
06007 
06008       if (entry->offset + offset_base != d + d_rounding)
06009   abort ();
06010     }
06011   else /* ! TARGET_SH5 */
06012     {
06013       save_size = 0;
06014       if (TEST_HARD_REG_BIT (live_regs_mask, PR_REG))
06015   pop (PR_REG);
06016       for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
06017   {
06018     int j = (FIRST_PSEUDO_REGISTER - 1) - i;
06019 
06020     if (j == FPSCR_REG && current_function_interrupt && TARGET_FMOVD
06021         && hard_regs_intersect_p (&live_regs_mask,
06022           &reg_class_contents[DF_REGS]))
06023       fpscr_deferred = 1;
06024     else if (j != PR_REG && TEST_HARD_REG_BIT (live_regs_mask, j))
06025       pop (j);
06026     if (j == FIRST_FP_REG && fpscr_deferred)
06027       pop (FPSCR_REG);
06028 
06029   }
06030     }
06031   if (target_flags != save_flags && ! current_function_interrupt)
06032     emit_insn (gen_toggle_sz ());
06033   target_flags = save_flags;
06034 
06035   output_stack_adjust (current_function_pretend_args_size
06036            + save_size + d_rounding
06037            + current_function_args_info.stack_regs * 8,
06038            stack_pointer_rtx, e, NULL);
06039 
06040   if (current_function_calls_eh_return)
06041     emit_insn (GEN_ADD3 (stack_pointer_rtx, stack_pointer_rtx,
06042        EH_RETURN_STACKADJ_RTX));
06043 
06044   /* Switch back to the normal stack if necessary.  */
06045   if (sp_switch)
06046     emit_insn (gen_sp_switch_2 ());
06047 
06048   /* Tell flow the insn that pops PR isn't dead.  */
06049   /* PR_REG will never be live in SHmedia mode, and we don't need to
06050      USE PR_MEDIA_REG, since it will be explicitly copied to TR0_REG
06051      by the return pattern.  */
06052   if (TEST_HARD_REG_BIT (live_regs_mask, PR_REG))
06053     emit_insn (gen_rtx_USE (VOIDmode, gen_rtx_REG (SImode, PR_REG)));
06054 }
06055 
06056 static int sh_need_epilogue_known = 0;
06057 
06058 int
06059 sh_need_epilogue (void)
06060 {
06061   if (! sh_need_epilogue_known)
06062     {
06063       rtx epilogue;
06064 
06065       start_sequence ();
06066       sh_expand_epilogue (0);
06067       epilogue = get_insns ();
06068       end_sequence ();
06069       sh_need_epilogue_known = (epilogue == NULL ? -1 : 1);
06070     }
06071   return sh_need_epilogue_known > 0;
06072 }
06073 
06074 /* Emit code to change the current function's return address to RA.
06075    TEMP is available as a scratch register, if needed.  */
06076 
06077 void
06078 sh_set_return_address (rtx ra, rtx tmp)
06079 {
06080   HARD_REG_SET live_regs_mask;
06081   int d;
06082   int pr_reg = TARGET_SHMEDIA ? PR_MEDIA_REG : PR_REG;
06083   int pr_offset;
06084 
06085   d = calc_live_regs (&live_regs_mask);
06086 
06087   /* If pr_reg isn't life, we can set it (or the register given in
06088      sh_media_register_for_return) directly.  */
06089   if (! TEST_HARD_REG_BIT (live_regs_mask, pr_reg))
06090     {
06091       rtx rr;
06092 
06093       if (TARGET_SHMEDIA)
06094   {
06095     int rr_regno = sh_media_register_for_return ();
06096 
06097     if (rr_regno < 0)
06098       rr_regno = pr_reg;
06099 
06100     rr = gen_rtx_REG (DImode, rr_regno);
06101   }
06102       else
06103   rr = gen_rtx_REG (SImode, pr_reg);
06104 
06105       emit_insn (GEN_MOV (rr, ra));
06106       /* Tell flow the register for return isn't dead.  */
06107       emit_insn (gen_rtx_USE (VOIDmode, rr));
06108       return;
06109     }
06110 
06111   if (TARGET_SH5)
06112     {
06113       int offset;
06114       save_schedule schedule;
06115       save_entry *entry;
06116 
06117       entry = sh5_schedule_saves (&live_regs_mask, &schedule, 0);
06118       offset = entry[1].offset;
06119       for (; entry->mode != VOIDmode; entry--)
06120   if (entry->reg == pr_reg)
06121     goto found;
06122 
06123       /* We can't find pr register.  */
06124       abort ();
06125 
06126     found:
06127       offset = entry->offset - offset;
06128       pr_offset = (rounded_frame_size (d) + offset
06129        + SHMEDIA_REGS_STACK_ADJUST ());
06130     }
06131   else
06132     pr_offset = rounded_frame_size (d);
06133 
06134   emit_insn (GEN_MOV (tmp, GEN_INT (pr_offset)));
06135   emit_insn (GEN_ADD3 (tmp, tmp, frame_pointer_rtx));
06136 
06137   tmp = gen_rtx_MEM (Pmode, tmp);
06138   emit_insn (GEN_MOV (tmp, ra));
06139 }
06140 
06141 /* Clear variables at function end.  */
06142 
06143 static void
06144 sh_output_function_epilogue (FILE *file ATTRIBUTE_UNUSED,
06145            HOST_WIDE_INT size ATTRIBUTE_UNUSED)
06146 {
06147   trap_exit = pragma_interrupt = pragma_trapa = pragma_nosave_low_regs = 0;
06148   sh_need_epilogue_known = 0;
06149   sp_switch = NULL_RTX;
06150 }
06151 
06152 static rtx
06153 sh_builtin_saveregs (void)
06154 {
06155   /* First unnamed integer register.  */
06156   int first_intreg = current_function_args_info.arg_count[(int) SH_ARG_INT];
06157   /* Number of integer registers we need to save.  */
06158   int n_intregs = MAX (0, NPARM_REGS (SImode) - first_intreg);
06159   /* First unnamed SFmode float reg */
06160   int first_floatreg = current_function_args_info.arg_count[(int) SH_ARG_FLOAT];
06161   /* Number of SFmode float regs to save.  */
06162   int n_floatregs = MAX (0, NPARM_REGS (SFmode) - first_floatreg);
06163   rtx regbuf, fpregs;
06164   int bufsize, regno;
06165   HOST_WIDE_INT alias_set;
06166 
06167   if (TARGET_SH5)
06168     {
06169       if (n_intregs)
06170   {
06171     int pushregs = n_intregs;
06172 
06173     while (pushregs < NPARM_REGS (SImode) - 1
06174      && (CALL_COOKIE_INT_REG_GET
06175       (current_function_args_info.call_cookie,
06176        NPARM_REGS (SImode) - pushregs)
06177          == 1))
06178       {
06179         current_function_args_info.call_cookie
06180     &= ~ CALL_COOKIE_INT_REG (NPARM_REGS (SImode)
06181             - pushregs, 1);
06182         pushregs++;
06183       }
06184 
06185     if (pushregs == NPARM_REGS (SImode))
06186       current_function_args_info.call_cookie
06187         |= (CALL_COOKIE_INT_REG (0, 1)
06188       | CALL_COOKIE_STACKSEQ (pushregs - 1));
06189     else
06190       current_function_args_info.call_cookie
06191         |= CALL_COOKIE_STACKSEQ (pushregs);
06192 
06193     current_function_pretend_args_size += 8 * n_intregs;
06194   }
06195       if (TARGET_SHCOMPACT)
06196   return const0_rtx;
06197     }
06198 
06199   if (! TARGET_SH2E && ! TARGET_SH4 && ! TARGET_SH5)
06200     {
06201       error ("__builtin_saveregs not supported by this subtarget");
06202       return const0_rtx;
06203     }
06204 
06205   if (TARGET_SHMEDIA)
06206     n_floatregs = 0;
06207 
06208   /* Allocate block of memory for the regs.  */
06209   /* ??? If n_intregs + n_floatregs == 0, should we allocate at least 1 byte?
06210      Or can assign_stack_local accept a 0 SIZE argument?  */
06211   bufsize = (n_intregs * UNITS_PER_WORD) + (n_floatregs * UNITS_PER_WORD);
06212 
06213   if (TARGET_SHMEDIA)
06214     regbuf = gen_rtx_MEM (BLKmode,
06215         gen_rtx_REG (Pmode, ARG_POINTER_REGNUM));
06216   else if (n_floatregs & 1)
06217     {
06218       rtx addr;
06219 
06220       regbuf = assign_stack_local (BLKmode, bufsize + UNITS_PER_WORD, 0);
06221       addr = copy_to_mode_reg (Pmode, XEXP (regbuf, 0));
06222       emit_insn (gen_iorsi3 (addr, addr, GEN_INT (UNITS_PER_WORD)));
06223       regbuf = change_address (regbuf, BLKmode, addr);
06224     }
06225   else
06226     regbuf = assign_stack_local (BLKmode, bufsize, 0);
06227   alias_set = get_varargs_alias_set ();
06228   set_mem_alias_set (regbuf, alias_set);
06229 
06230   /* Save int args.
06231      This is optimized to only save the regs that are necessary.  Explicitly
06232      named args need not be saved.  */
06233   if (n_intregs > 0)
06234     move_block_from_reg (BASE_ARG_REG (SImode) + first_intreg,
06235        adjust_address (regbuf, BLKmode,
06236            n_floatregs * UNITS_PER_WORD),
06237        n_intregs);
06238 
06239   if (TARGET_SHMEDIA)
06240     /* Return the address of the regbuf.  */
06241     return XEXP (regbuf, 0);
06242 
06243   /* Save float args.
06244      This is optimized to only save the regs that are necessary.  Explicitly
06245      named args need not be saved.
06246      We explicitly build a pointer to the buffer because it halves the insn
06247      count when not optimizing (otherwise the pointer is built for each reg
06248      saved).
06249      We emit the moves in reverse order so that we can use predecrement.  */
06250 
06251   fpregs = gen_reg_rtx (Pmode);
06252   emit_move_insn (fpregs, XEXP (regbuf, 0));
06253   emit_insn (gen_addsi3 (fpregs, fpregs,
06254        GEN_INT (n_floatregs * UNITS_PER_WORD)));
06255   if (TARGET_SH4 || TARGET_SH2A_DOUBLE)
06256     {
06257       rtx mem;
06258       for (regno = NPARM_REGS (DFmode) - 2; regno >= first_floatreg; regno -= 2)
06259   {
06260     emit_insn (gen_addsi3 (fpregs, fpregs,
06261          GEN_INT (-2 * UNITS_PER_WORD)));
06262     mem = gen_rtx_MEM (DFmode, fpregs);
06263     set_mem_alias_set (mem, alias_set);
06264     emit_move_insn (mem,
06265         gen_rtx_REG (DFmode, BASE_ARG_REG (DFmode) + regno));
06266   }
06267       regno = first_floatreg;
06268       if (regno & 1)
06269   {
06270     emit_insn (gen_addsi3 (fpregs, fpregs, GEN_INT (-UNITS_PER_WORD)));
06271     mem = gen_rtx_MEM (SFmode, fpregs);
06272     set_mem_alias_set (mem, alias_set);
06273     emit_move_insn (mem,
06274         gen_rtx_REG (SFmode, BASE_ARG_REG (SFmode) + regno
06275             - (TARGET_LITTLE_ENDIAN != 0)));
06276   }
06277     }
06278   else
06279     for (regno = NPARM_REGS (SFmode) - 1; regno >= first_floatreg; regno--)
06280       {
06281         rtx mem;
06282 
06283   emit_insn (gen_addsi3 (fpregs, fpregs, GEN_INT (-UNITS_PER_WORD)));
06284   mem = gen_rtx_MEM (SFmode, fpregs);
06285   set_mem_alias_set (mem, alias_set);
06286   emit_move_insn (mem,
06287       gen_rtx_REG (SFmode, BASE_ARG_REG (SFmode) + regno));
06288       }
06289 
06290   /* Return the address of the regbuf.  */
06291   return XEXP (regbuf, 0);
06292 }
06293 
06294 /* Define the `__builtin_va_list' type for the ABI.  */
06295 
06296 static tree
06297 sh_build_builtin_va_list (void)
06298 {
06299   tree f_next_o, f_next_o_limit, f_next_fp, f_next_fp_limit, f_next_stack;
06300   tree record;
06301 
06302   if (TARGET_SH5 || (! TARGET_SH2E && ! TARGET_SH4)
06303       || TARGET_HITACHI || sh_cfun_attr_renesas_p ())
06304     return ptr_type_node;
06305 
06306   record = (*lang_hooks.types.make_type) (RECORD_TYPE);
06307 
06308   f_next_o = build_decl (FIELD_DECL, get_identifier ("__va_next_o"),
06309        ptr_type_node);
06310   f_next_o_limit = build_decl (FIELD_DECL,
06311              get_identifier ("__va_next_o_limit"),
06312              ptr_type_node);
06313   f_next_fp = build_decl (FIELD_DECL, get_identifier ("__va_next_fp"),
06314         ptr_type_node);
06315   f_next_fp_limit = build_decl (FIELD_DECL,
06316         get_identifier ("__va_next_fp_limit"),
06317         ptr_type_node);
06318   f_next_stack = build_decl (FIELD_DECL, get_identifier ("__va_next_stack"),
06319            ptr_type_node);
06320 
06321   DECL_FIELD_CONTEXT (f_next_o) = record;
06322   DECL_FIELD_CONTEXT (f_next_o_limit) = record;
06323   DECL_FIELD_CONTEXT (f_next_fp) = record;
06324   DECL_FIELD_CONTEXT (f_next_fp_limit) = record;
06325   DECL_FIELD_CONTEXT (f_next_stack) = record;
06326 
06327   TYPE_FIELDS (record) = f_next_o;
06328   TREE_CHAIN (f_next_o) = f_next_o_limit;
06329   TREE_CHAIN (f_next_o_limit) = f_next_fp;
06330   TREE_CHAIN (f_next_fp) = f_next_fp_limit;
06331   TREE_CHAIN (f_next_fp_limit) = f_next_stack;
06332 
06333   layout_type (record);
06334 
06335   return record;
06336 }
06337 
06338 /* Implement `va_start' for varargs and stdarg.  */
06339 
06340 void
06341 sh_va_start (tree valist, rtx nextarg)
06342 {
06343   tree f_next_o, f_next_o_limit, f_next_fp, f_next_fp_limit, f_next_stack;
06344   tree next_o, next_o_limit, next_fp, next_fp_limit, next_stack;
06345   tree t, u;
06346   int nfp, nint;
06347 
06348   if (TARGET_SH5)
06349     {
06350       expand_builtin_saveregs ();
06351       std_expand_builtin_va_start (valist, nextarg);
06352       return;
06353     }
06354 
06355   if ((! TARGET_SH2E && ! TARGET_SH4)
06356       || TARGET_HITACHI || sh_cfun_attr_renesas_p ())
06357     {
06358       std_expand_builtin_va_start (valist, nextarg);
06359       return;
06360     }
06361 
06362   f_next_o = TYPE_FIELDS (va_list_type_node);
06363   f_next_o_limit = TREE_CHAIN (f_next_o);
06364   f_next_fp = TREE_CHAIN (f_next_o_limit);
06365   f_next_fp_limit = TREE_CHAIN (f_next_fp);
06366   f_next_stack = TREE_CHAIN (f_next_fp_limit);
06367 
06368   next_o = build (COMPONENT_REF, TREE_TYPE (f_next_o), valist, f_next_o,
06369       NULL_TREE);
06370   next_o_limit = build (COMPONENT_REF, TREE_TYPE (f_next_o_limit),
06371       valist, f_next_o_limit, NULL_TREE);
06372   next_fp = build (COMPONENT_REF, TREE_TYPE (f_next_fp), valist, f_next_fp,
06373        NULL_TREE);
06374   next_fp_limit = build (COMPONENT_REF, TREE_TYPE (f_next_fp_limit),
06375        valist, f_next_fp_limit, NULL_TREE);
06376   next_stack = build (COMPONENT_REF, TREE_TYPE (f_next_stack),
06377           valist, f_next_stack, NULL_TREE);
06378 
06379   /* Call __builtin_saveregs.  */
06380   u = make_tree (ptr_type_node, expand_builtin_saveregs ());
06381   t = build (MODIFY_EXPR, ptr_type_node, next_fp, u);
06382   TREE_SIDE_EFFECTS (t) = 1;
06383   expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);
06384 
06385   nfp = current_function_args_info.arg_count[SH_ARG_FLOAT];
06386   if (nfp < 8)
06387     nfp = 8 - nfp;
06388   else
06389     nfp = 0;
06390   u = fold (build (PLUS_EXPR, ptr_type_node, u,
06391        build_int_cst (NULL_TREE, UNITS_PER_WORD * nfp)));
06392   t = build (MODIFY_EXPR, ptr_type_node, next_fp_limit, u);
06393   TREE_SIDE_EFFECTS (t) = 1;
06394   expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);
06395 
06396   t = build (MODIFY_EXPR, ptr_type_node, next_o, u);
06397   TREE_SIDE_EFFECTS (t) = 1;
06398   expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);
06399 
06400   nint = current_function_args_info.arg_count[SH_ARG_INT];
06401   if (nint < 4)
06402     nint = 4 - nint;
06403   else
06404     nint = 0;
06405   u = fold (build (PLUS_EXPR, ptr_type_node, u,
06406        build_int_cst (NULL_TREE, UNITS_PER_WORD * nint)));
06407   t = build (MODIFY_EXPR, ptr_type_node, next_o_limit, u);
06408   TREE_SIDE_EFFECTS (t) = 1;
06409   expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);
06410 
06411   u = make_tree (ptr_type_node, nextarg);
06412   t = build (MODIFY_EXPR, ptr_type_node, next_stack, u);
06413   TREE_SIDE_EFFECTS (t) = 1;
06414   expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);
06415 }
06416 
06417 /* Implement `va_arg'.  */
06418 
06419 static tree
06420 sh_gimplify_va_arg_expr (tree valist, tree type, tree *pre_p,
06421        tree *post_p ATTRIBUTE_UNUSED)
06422 {
06423   HOST_WIDE_INT size, rsize;
06424   tree tmp, pptr_type_node;
06425   tree addr, lab_over = NULL, result = NULL;
06426   int pass_by_ref = targetm.calls.must_pass_in_stack (TYPE_MODE (type), type);
06427 
06428   if (pass_by_ref)
06429     type = build_pointer_type (type);
06430 
06431   size = int_size_in_bytes (type);
06432   rsize = (size + UNITS_PER_WORD - 1) & -UNITS_PER_WORD;
06433   pptr_type_node = build_pointer_type (ptr_type_node);
06434 
06435   if (! TARGET_SH5 && (TARGET_SH2E || TARGET_SH4)
06436       && ! (TARGET_HITACHI || sh_cfun_attr_renesas_p ()))
06437     {
06438       tree f_next_o, f_next_o_limit, f_next_fp, f_next_fp_limit, f_next_stack;
06439       tree next_o, next_o_limit, next_fp, next_fp_limit, next_stack;
06440       int pass_as_float;
06441       tree lab_false;
06442 
06443       f_next_o = TYPE_FIELDS (va_list_type_node);
06444       f_next_o_limit = TREE_CHAIN (f_next_o);
06445       f_next_fp = TREE_CHAIN (f_next_o_limit);
06446       f_next_fp_limit = TREE_CHAIN (f_next_fp);
06447       f_next_stack = TREE_CHAIN (f_next_fp_limit);
06448 
06449       next_o = build (COMPONENT_REF, TREE_TYPE (f_next_o), valist, f_next_o,
06450           NULL_TREE);
06451       next_o_limit = build (COMPONENT_REF, TREE_TYPE (f_next_o_limit),
06452           valist, f_next_o_limit, NULL_TREE);
06453       next_fp = build (COMPONENT_REF, TREE_TYPE (f_next_fp),
06454            valist, f_next_fp, NULL_TREE);
06455       next_fp_limit = build (COMPONENT_REF, TREE_TYPE (f_next_fp_limit),
06456            valist, f_next_fp_limit, NULL_TREE);
06457       next_stack = build (COMPONENT_REF, TREE_TYPE (f_next_stack),
06458         valist, f_next_stack, NULL_TREE);
06459 
06460       /* Structures with a single member with a distinct mode are passed
06461    like their member.  This is relevant if the latter has a REAL_TYPE
06462    or COMPLEX_TYPE type.  */
06463       if (TREE_CODE (type) == RECORD_TYPE
06464     && TYPE_FIELDS (type)
06465     && TREE_CODE (TYPE_FIELDS (type)) == FIELD_DECL
06466     && (TREE_CODE (TREE_TYPE (TYPE_FIELDS (type))) == REAL_TYPE
06467         || TREE_CODE (TREE_TYPE (TYPE_FIELDS (type))) == COMPLEX_TYPE)
06468           && TREE_CHAIN (TYPE_FIELDS (type)) == NULL_TREE)
06469   type = TREE_TYPE (TYPE_FIELDS (type));
06470 
06471       if (TARGET_SH4)
06472   {
06473     pass_as_float = ((TREE_CODE (type) == REAL_TYPE && size <= 8)
06474          || (TREE_CODE (type) == COMPLEX_TYPE
06475              && TREE_CODE (TREE_TYPE (type)) == REAL_TYPE
06476              && size <= 16));
06477   }
06478       else
06479   {
06480     pass_as_float = (TREE_CODE (type) == REAL_TYPE && size == 4);
06481   }
06482 
06483       addr = create_tmp_var (pptr_type_node, NULL);
06484       lab_false = create_artificial_label ();
06485       lab_over = create_artificial_label ();
06486 
06487       valist = build1 (INDIRECT_REF, ptr_type_node, addr);
06488 
06489       if (pass_as_float)
06490   {
06491     int first_floatreg
06492       = current_function_args_info.arg_count[(int) SH_ARG_FLOAT];
06493     int n_floatregs = MAX (0, NPARM_REGS (SFmode) - first_floatreg);
06494 
06495     tmp = build (GE_EXPR, boolean_type_node, next_fp, next_fp_limit);
06496     tmp = build (COND_EXPR, void_type_node, tmp,
06497            build (GOTO_EXPR, void_type_node, lab_false),
06498            NULL);
06499     gimplify_and_add (tmp, pre_p);
06500 
06501     if (TYPE_ALIGN (type) > BITS_PER_WORD
06502         || (((TREE_CODE (type) == REAL_TYPE && size == 8) || size == 16)
06503       && (n_floatregs & 1)))
06504       {
06505         tmp = fold_convert (ptr_type_node, size_int (UNITS_PER_WORD));
06506         tmp = build (BIT_AND_EXPR, ptr_type_node, next_fp, tmp);
06507         tmp = build (PLUS_EXPR, ptr_type_node, next_fp, tmp);
06508         tmp = build (MODIFY_EXPR, ptr_type_node, next_fp, tmp);
06509         gimplify_and_add (tmp, pre_p);
06510       }
06511 
06512     tmp = build1 (ADDR_EXPR, pptr_type_node, next_fp);
06513     tmp = build (MODIFY_EXPR, void_type_node, addr, tmp);
06514     gimplify_and_add (tmp, pre_p);
06515 
06516 #ifdef FUNCTION_ARG_SCmode_WART
06517     if (TYPE_MODE (type) == SCmode && TARGET_SH4 && TARGET_LITTLE_ENDIAN)
06518       {
06519         tree subtype = TREE_TYPE (type);
06520         tree real, imag;
06521 
06522         imag = std_gimplify_va_arg_expr (valist, subtype, pre_p, NULL);
06523         imag = get_initialized_tmp_var (imag, pre_p, NULL);
06524 
06525         real = std_gimplify_va_arg_expr (valist, subtype, pre_p, NULL);
06526         real = get_initialized_tmp_var (real, pre_p, NULL);
06527 
06528         result = build (COMPLEX_EXPR, type, real, imag);
06529         result = get_initialized_tmp_var (result, pre_p, NULL);
06530       }
06531 #endif /* FUNCTION_ARG_SCmode_WART */
06532 
06533     tmp = build (GOTO_EXPR, void_type_node, lab_over);
06534     gimplify_and_add (tmp, pre_p);
06535 
06536     tmp = build (LABEL_EXPR, void_type_node, lab_false);
06537     gimplify_and_add (tmp, pre_p);
06538 
06539     tmp = build1 (ADDR_EXPR, pptr_type_node, next_stack);
06540     tmp = build (MODIFY_EXPR, void_type_node, addr, tmp);
06541     gimplify_and_add (tmp, pre_p);
06542   }
06543       else
06544   {
06545     tmp = fold_convert (ptr_type_node, size_int (rsize));
06546     tmp = build (PLUS_EXPR, ptr_type_node, next_o, tmp);
06547     tmp = build (GT_EXPR, boolean_type_node, tmp, next_o_limit);
06548     tmp = build (COND_EXPR, void_type_node, tmp,
06549            build (GOTO_EXPR, void_type_node, lab_false),
06550            NULL);
06551     gimplify_and_add (tmp, pre_p);
06552 
06553     tmp = build1 (ADDR_EXPR, pptr_type_node, next_o);
06554     tmp = build (MODIFY_EXPR, void_type_node, addr, tmp);
06555     gimplify_and_add (tmp, pre_p);
06556 
06557     tmp = build (GOTO_EXPR, void_type_node, lab_over);
06558     gimplify_and_add (tmp, pre_p);
06559 
06560     tmp = build (LABEL_EXPR, void_type_node, lab_false);
06561     gimplify_and_add (tmp, pre_p);
06562 
06563     if (size > 4 && ! TARGET_SH4)
06564       {
06565         tmp = build (MODIFY_EXPR, ptr_type_node, next_o, next_o_limit);
06566         gimplify_and_add (tmp, pre_p);
06567       }
06568 
06569     tmp = build1 (ADDR_EXPR, pptr_type_node, next_stack);
06570     tmp = build (MODIFY_EXPR, void_type_node, addr, tmp);
06571     gimplify_and_add (tmp, pre_p);
06572   }
06573 
06574       if (!result)
06575   {
06576     tmp = build (LABEL_EXPR, void_type_node, lab_over);
06577     gimplify_and_add (tmp, pre_p);
06578   }
06579     }
06580 
06581   /* ??? In va-sh.h, there had been code to make values larger than
06582      size 8 indirect.  This does not match the FUNCTION_ARG macros.  */
06583 
06584   tmp = std_gimplify_va_arg_expr (valist, type, pre_p, NULL);
06585   if (result)
06586     {
06587       tmp = build (MODIFY_EXPR, void_type_node, result, tmp);
06588       gimplify_and_add (tmp, pre_p);
06589 
06590       tmp = build (LABEL_EXPR, void_type_node, lab_over);
06591       gimplify_and_add (tmp, pre_p);
06592     }
06593   else
06594     result = tmp;
06595 
06596   if (pass_by_ref)
06597     result = build_fold_indirect_ref (result);
06598 
06599   return result;
06600 }
06601 
06602 bool
06603 sh_promote_prototypes (tree type)
06604 {
06605   if (TARGET_HITACHI)
06606     return 0;
06607   if (! type)
06608     return 1;
06609   return ! sh_attr_renesas_p (type);
06610 }
06611 
06612 /* Whether an argument must be passed by reference.  On SHcompact, we
06613    pretend arguments wider than 32-bits that would have been passed in
06614    registers are passed by reference, so that an SHmedia trampoline
06615    loads them into the full 64-bits registers.  */
06616 
06617 static int
06618 shcompact_byref (CUMULATIVE_ARGS *cum, enum machine_mode mode,
06619      tree type, bool named)
06620 {
06621   unsigned HOST_WIDE_INT size;
06622 
06623   if (type)
06624     size = int_size_in_bytes (type);
06625   else
06626     size = GET_MODE_SIZE (mode);
06627 
06628   if (cum->arg_count[SH_ARG_INT] < NPARM_REGS (SImode)
06629       && (!named
06630     || GET_SH_ARG_CLASS (mode) == SH_ARG_INT
06631     || (GET_SH_ARG_CLASS (mode) == SH_ARG_FLOAT
06632         && cum->arg_count[SH_ARG_FLOAT] >= NPARM_REGS (SFmode)))
06633       && size > 4
06634       && !SHCOMPACT_FORCE_ON_STACK (mode, type)
06635       && !SH5_WOULD_BE_PARTIAL_NREGS (*cum, mode, type, named))
06636     return size;
06637   else
06638     return 0;
06639 }
06640 
06641 static bool
06642 sh_pass_by_reference (CUMULATIVE_ARGS *cum, enum machine_mode mode,
06643           tree type, bool named)
06644 {
06645   if (targetm.calls.must_pass_in_stack (mode, type))
06646     return true;
06647 
06648   /* ??? std_gimplify_va_arg_expr passes NULL for cum.  That function
06649      wants to know about pass-by-reference semantics for incoming
06650      arguments.  */
06651   if (! cum)
06652     return false;
06653 
06654   if (TARGET_SHCOMPACT)
06655     {
06656       cum->byref = shcompact_byref (cum, mode, type, named);
06657       return cum->byref != 0;
06658     }
06659 
06660   return false;
06661 }
06662 
06663 static bool
06664 sh_callee_copies (CUMULATIVE_ARGS *cum, enum machine_mode mode,
06665       tree type, bool named ATTRIBUTE_UNUSED)
06666 {
06667   /* ??? How can it possibly be correct to return true only on the
06668      caller side of the equation?  Is there someplace else in the
06669      sh backend that's magically producing the copies?  */
06670   return (cum->outgoing
06671     && ((mode == BLKmode ? TYPE_ALIGN (type) : GET_MODE_ALIGNMENT (mode))
06672         % SH_MIN_ALIGN_FOR_CALLEE_COPY == 0));
06673 }
06674 
06675 static int
06676 sh_arg_partial_bytes (CUMULATIVE_ARGS *cum, enum machine_mode mode,
06677           tree type, bool named ATTRIBUTE_UNUSED)
06678 {
06679   int words = 0;
06680 
06681   if (!TARGET_SH5
06682       && PASS_IN_REG_P (*cum, mode, type)
06683       && !(TARGET_SH4 || TARGET_SH2A_DOUBLE)
06684       && (ROUND_REG (*cum, mode)
06685     + (mode != BLKmode
06686        ? ROUND_ADVANCE (GET_MODE_SIZE (mode))
06687        : ROUND_ADVANCE (int_size_in_bytes (type)))
06688     > NPARM_REGS (mode)))
06689     words = NPARM_REGS (mode) - ROUND_REG (*cum, mode);
06690 
06691   else if (!TARGET_SHCOMPACT
06692      && SH5_WOULD_BE_PARTIAL_NREGS (*cum, mode, type, named))
06693     words = NPARM_REGS (SImode) - cum->arg_count[SH_ARG_INT];
06694 
06695   return words * UNITS_PER_WORD;
06696 }
06697 
06698 
06699 /* Define where to put the arguments to a function.
06700    Value is zero to push the argument on the stack,
06701    or a hard register in which to store the argument.
06702 
06703    MODE is the argument's machine mode.
06704    TYPE is the data type of the argument (as a tree).
06705     This is null for libcalls where that information may
06706     not be available.
06707    CUM is a variable of type CUMULATIVE_ARGS which gives info about
06708     the preceding args and about the function being called.
06709    NAMED is nonzero if this argument is a named parameter
06710     (otherwise it is an extra parameter matching an ellipsis).
06711 
06712    On SH the first args are normally in registers
06713    and the rest are pushed.  Any arg that starts within the first
06714    NPARM_REGS words is at least partially passed in a register unless
06715    its data type forbids.  */
06716 
06717 
06718 rtx
06719 sh_function_arg (CUMULATIVE_ARGS *ca, enum machine_mode mode,
06720      tree type, int named)
06721 {
06722   if (! TARGET_SH5 && mode == VOIDmode)
06723     return GEN_INT (ca->renesas_abi ? 1 : 0);
06724 
06725   if (! TARGET_SH5
06726       && PASS_IN_REG_P (*ca, mode, type)
06727       && (named || ! (TARGET_HITACHI || ca->renesas_abi)))
06728     {
06729       int regno;
06730 
06731       if (mode == SCmode && TARGET_SH4 && TARGET_LITTLE_ENDIAN
06732     && (! FUNCTION_ARG_SCmode_WART || (ROUND_REG (*ca, mode) & 1)))
06733   {
06734     rtx r1 = gen_rtx_EXPR_LIST (VOIDmode,
06735               gen_rtx_REG (SFmode,
06736                BASE_ARG_REG (mode)
06737                + (ROUND_REG (*ca, mode) ^ 1)),
06738               const0_rtx);
06739     rtx r2 = gen_rtx_EXPR_LIST (VOIDmode,
06740               gen_rtx_REG (SFmode,
06741                BASE_ARG_REG (mode)
06742                + ((ROUND_REG (*ca, mode) + 1) ^ 1)),
06743               GEN_INT (4));
06744     return gen_rtx_PARALLEL(SCmode, gen_rtvec(2, r1, r2));
06745   }
06746 
06747      /* If the alignment of a DF value causes an SF register to be
06748   skipped, we will use that skipped register for the next SF
06749   value.  */
06750       if ((TARGET_HITACHI || ca->renesas_abi)
06751     && ca->free_single_fp_reg
06752     && mode == SFmode)
06753   return gen_rtx_REG (mode, ca->free_single_fp_reg);
06754 
06755       regno = (BASE_ARG_REG (mode) + ROUND_REG (*ca, mode))
06756          ^ (mode == SFmode && TARGET_SH4
06757       && TARGET_LITTLE_ENDIAN != 0
06758       && ! TARGET_HITACHI && ! ca->renesas_abi);
06759       return gen_rtx_REG (mode, regno);
06760 
06761     }
06762 
06763   if (TARGET_SH5)
06764     {
06765       if (mode == VOIDmode && TARGET_SHCOMPACT)
06766   return GEN_INT (ca->call_cookie);
06767 
06768       /* The following test assumes unnamed arguments are promoted to
06769    DFmode.  */
06770       if (mode == SFmode && ca->free_single_fp_reg)
06771   return SH5_PROTOTYPED_FLOAT_ARG (*ca, mode, ca->free_single_fp_reg);
06772 
06773       if ((GET_SH_ARG_CLASS (mode) == SH_ARG_FLOAT)
06774     && (named || ! ca->prototype_p)
06775     && ca->arg_count[(int) SH_ARG_FLOAT] < NPARM_REGS (SFmode))
06776   {
06777     if (! ca->prototype_p && TARGET_SHMEDIA)
06778       return SH5_PROTOTYPELESS_FLOAT_ARG (*ca, mode);
06779 
06780     return SH5_PROTOTYPED_FLOAT_ARG (*ca, mode,
06781              FIRST_FP_PARM_REG
06782              + ca->arg_count[(int) SH_ARG_FLOAT]);
06783   }
06784 
06785       if (ca->arg_count[(int) SH_ARG_INT] < NPARM_REGS (SImode)
06786     && (! TARGET_SHCOMPACT
06787         || (! SHCOMPACT_FORCE_ON_STACK (mode, type)
06788       && ! SH5_WOULD_BE_PARTIAL_NREGS (*ca, mode,
06789                type, named))))
06790   {
06791     return gen_rtx_REG (mode, (FIRST_PARM_REG
06792                + ca->arg_count[(int) SH_ARG_INT]));
06793   }
06794 
06795       return 0;
06796     }
06797 
06798   return 0;
06799 }
06800 
06801 /* Update the data in CUM to advance over an argument
06802    of mode MODE and data type TYPE.
06803    (TYPE is null for libcalls where that information may not be
06804    available.)  */
06805 
06806 void
06807 sh_function_arg_advance (CUMULATIVE_ARGS *ca, enum machine_mode mode,
06808        tree type, int named)
06809 {
06810   if (ca->force_mem)
06811     ca->force_mem = 0;
06812   else if (TARGET_SH5)
06813     {
06814       tree type2 = (ca->byref && type
06815         ? TREE_TYPE (type)
06816         : type);
06817       enum machine_mode mode2 = (ca->byref && type
06818          ? TYPE_MODE (type2)
06819          : mode);
06820       int dwords = ((ca->byref
06821          ? ca->byref
06822          : mode2 == BLKmode
06823          ? int_size_in_bytes (type2)
06824          : GET_MODE_SIZE (mode2)) + 7) / 8;
06825       int numregs = MIN (dwords, NPARM_REGS (SImode)
06826        - ca->arg_count[(int) SH_ARG_INT]);
06827 
06828       if (numregs)
06829   {
06830     ca->arg_count[(int) SH_ARG_INT] += numregs;
06831     if (TARGET_SHCOMPACT
06832         && SHCOMPACT_FORCE_ON_STACK (mode2, type2))
06833       {
06834         ca->call_cookie
06835     |= CALL_COOKIE_INT_REG (ca->arg_count[(int) SH_ARG_INT]
06836           - numregs, 1);
06837         /* N.B. We want this also for outgoing.  */
06838         ca->stack_regs += numregs;
06839       }
06840     else if (ca->byref)
06841       {
06842         if (! ca->outgoing)
06843     ca->stack_regs += numregs;
06844         ca->byref_regs += numregs;
06845         ca->byref = 0;
06846         do
06847     ca->call_cookie
06848       |= CALL_COOKIE_INT_REG (ca->arg_count[(int) SH_ARG_INT]
06849             - numregs, 2);
06850         while (--numregs);
06851         ca->call_cookie
06852     |= CALL_COOKIE_INT_REG (ca->arg_count[(int) SH_ARG_INT]
06853           - 1, 1);
06854       }
06855     else if (dwords > numregs)
06856       {
06857         int pushregs = numregs;
06858 
06859         if (TARGET_SHCOMPACT)
06860     ca->stack_regs += numregs;
06861         while (pushregs < NPARM_REGS (SImode) - 1
06862          && (CALL_COOKIE_INT_REG_GET
06863        (ca->call_cookie,
06864         NPARM_REGS (SImode) - pushregs)
06865        == 1))
06866     {
06867       ca->call_cookie
06868         &= ~ CALL_COOKIE_INT_REG (NPARM_REGS (SImode)
06869                 - pushregs, 1);
06870       pushregs++;
06871     }
06872         if (numregs == NPARM_REGS (SImode))
06873     ca->call_cookie
06874       |= CALL_COOKIE_INT_REG (0, 1)
06875       | CALL_COOKIE_STACKSEQ (numregs - 1);
06876         else
06877     ca->call_cookie
06878       |= CALL_COOKIE_STACKSEQ (numregs);
06879       }
06880   }
06881       if (GET_SH_ARG_CLASS (mode2) == SH_ARG_FLOAT
06882     && (named || ! ca->prototype_p))
06883   {
06884     if (mode2 == SFmode && ca->free_single_fp_reg)
06885       ca->free_single_fp_reg = 0;
06886     else if (ca->arg_count[(int) SH_ARG_FLOAT]
06887        < NPARM_REGS (SFmode))
06888       {
06889         int numfpregs
06890     = MIN ((GET_MODE_SIZE (mode2) + 7) / 8 * 2,
06891            NPARM_REGS (SFmode)
06892            - ca->arg_count[(int) SH_ARG_FLOAT]);
06893 
06894         ca->arg_count[(int) SH_ARG_FLOAT] += numfpregs;
06895 
06896         if (TARGET_SHCOMPACT && ! ca->prototype_p)
06897     {
06898       if (ca->outgoing && numregs > 0)
06899         do
06900           {
06901       ca->call_cookie
06902         |= (CALL_COOKIE_INT_REG
06903             (ca->arg_count[(int) SH_ARG_INT]
06904              - numregs + ((numfpregs - 2) / 2),
06905              4 + (ca->arg_count[(int) SH_ARG_FLOAT]
06906             - numfpregs) / 2));
06907           }
06908         while (numfpregs -= 2);
06909     }
06910         else if (mode2 == SFmode && (named)
06911            && (ca->arg_count[(int) SH_ARG_FLOAT]
06912          < NPARM_REGS (SFmode)))
06913     ca->free_single_fp_reg
06914       = FIRST_FP_PARM_REG - numfpregs
06915       + ca->arg_count[(int) SH_ARG_FLOAT] + 1;
06916       }
06917   }
06918       return;
06919     }
06920 
06921   if ((TARGET_HITACHI || ca->renesas_abi) && TARGET_FPU_DOUBLE)
06922     {
06923       /* Note that we've used the skipped register.  */
06924       if (mode == SFmode && ca->free_single_fp_reg)
06925   {
06926     ca->free_single_fp_reg = 0;
06927     return;
06928   }
06929       /* When we have a DF after an SF, there's an SF register that get
06930    skipped in order to align the DF value.  We note this skipped
06931    register, because the next SF value will use it, and not the
06932    SF that follows the DF.  */
06933       if (mode == DFmode
06934     && ROUND_REG (*ca, DFmode) != ROUND_REG (*ca, SFmode))
06935   {
06936     ca->free_single_fp_reg = (ROUND_REG (*ca, SFmode)
06937             + BASE_ARG_REG (mode));
06938   }
06939     }
06940 
06941   if (! ((TARGET_SH4 || TARGET_SH2A) || ca->renesas_abi)
06942       || PASS_IN_REG_P (*ca, mode, type))
06943     (ca->arg_count[(int) GET_SH_ARG_CLASS (mode)]
06944      = (ROUND_REG (*ca, mode)
06945   + (mode == BLKmode
06946      ? ROUND_ADVANCE (int_size_in_bytes (type))
06947      : ROUND_ADVANCE (GET_MODE_SIZE (mode)))));
06948 }
06949 
06950 /* The Renesas calling convention doesn't quite fit into this scheme since
06951    the address is passed like an invisible argument, but one that is always
06952    passed in memory.  */
06953 static rtx
06954 sh_struct_value_rtx (tree fndecl, int incoming ATTRIBUTE_UNUSED)
06955 {
06956   if (TARGET_HITACHI || sh_attr_renesas_p (fndecl))
06957     return 0;
06958   return gen_rtx_REG (Pmode, 2);
06959 }
06960 
06961 /* Worker function for TARGET_RETURN_IN_MEMORY.  */
06962 
06963 static bool
06964 sh_return_in_memory (tree type, tree fndecl)
06965 {
06966   if (TARGET_SH5)
06967     {
06968       if (TYPE_MODE (type) == BLKmode)
06969   return ((unsigned HOST_WIDE_INT) int_size_in_bytes (type)) > 8;
06970       else
06971   return GET_MODE_SIZE (TYPE_MODE (type)) > 8;
06972     }
06973   else
06974     {
06975       return (TYPE_MODE (type) == BLKmode
06976         || ((TARGET_HITACHI || sh_attr_renesas_p (fndecl))
06977       && TREE_CODE (type) == RECORD_TYPE));
06978     }
06979 }
06980 
06981 /* We actually emit the code in sh_expand_prologue.  We used to use
06982    a static variable to flag that we need to emit this code, but that
06983    doesn't when inlining, when functions are deferred and then emitted
06984    later.  Fortunately, we already have two flags that are part of struct
06985    function that tell if a function uses varargs or stdarg.  */
06986 static void
06987 sh_setup_incoming_varargs (CUMULATIVE_ARGS *ca,
06988          enum machine_mode mode,
06989          tree type,
06990          int *pretend_arg_size,
06991          int second_time ATTRIBUTE_UNUSED)
06992 {
06993   if (! current_function_stdarg)
06994     abort ();
06995   if (TARGET_VARARGS_PRETEND_ARGS (current_function_decl))
06996     {
06997       int named_parm_regs, anon_parm_regs;
06998 
06999       named_parm_regs = (ROUND_REG (*ca, mode)
07000        + (mode == BLKmode
07001           ? ROUND_ADVANCE (int_size_in_bytes (type))
07002           : ROUND_ADVANCE (GET_MODE_SIZE (mode))));
07003       anon_parm_regs = NPARM_REGS (SImode) - named_parm_regs;
07004       if (anon_parm_regs > 0)
07005   *pretend_arg_size = anon_parm_regs * 4;
07006     }
07007 }
07008 
07009 static bool
07010 sh_strict_argument_naming (CUMULATIVE_ARGS *ca ATTRIBUTE_UNUSED)
07011 {
07012   return TARGET_SH5;
07013 }
07014 
07015 static bool
07016 sh_pretend_outgoing_varargs_named (CUMULATIVE_ARGS *ca)
07017 {
07018   return ! (TARGET_HITACHI || ca->renesas_abi) && ! TARGET_SH5;
07019 }
07020 
07021 
07022 /* Define the offset between two registers, one to be eliminated, and
07023    the other its replacement, at the start of a routine.  */
07024 
07025 int
07026 initial_elimination_offset (int from, int to)
07027 {
07028   int regs_saved;
07029   int regs_saved_rounding = 0;
07030   int total_saved_regs_space;
07031   int total_auto_space;
07032   int save_flags = target_flags;
07033   int copy_flags;
07034   HARD_REG_SET live_regs_mask;
07035 
07036   shmedia_space_reserved_for_target_registers = false;
07037   regs_saved = calc_live_regs (&live_regs_mask);
07038   regs_saved += SHMEDIA_REGS_STACK_ADJUST ();
07039 
07040   if (shmedia_reserve_space_for_target_registers_p (regs_saved, &live_regs_mask))
07041     {
07042       shmedia_space_reserved_for_target_registers = true;
07043       regs_saved += shmedia_target_regs_stack_adjust (&live_regs_mask);
07044     }
07045 
07046   if (TARGET_SH5 && regs_saved % (STACK_BOUNDARY / BITS_PER_UNIT))
07047     regs_saved_rounding = ((STACK_BOUNDARY / BITS_PER_UNIT)
07048          - regs_saved % (STACK_BOUNDARY / BITS_PER_UNIT));
07049 
07050   total_auto_space = rounded_frame_size (regs_saved) - regs_saved_rounding;
07051   copy_flags = target_flags;
07052   target_flags = save_flags;
07053 
07054   total_saved_regs_space = regs_saved + regs_saved_rounding;
07055 
07056   if (from == ARG_POINTER_REGNUM && to == FRAME_POINTER_REGNUM)
07057     return total_saved_regs_space + total_auto_space
07058       + current_function_args_info.byref_regs * 8;
07059 
07060   if (from == ARG_POINTER_REGNUM && to == STACK_POINTER_REGNUM)
07061     return total_saved_regs_space + total_auto_space
07062       + current_function_args_info.byref_regs * 8;
07063 
07064   /* Initial gap between fp and sp is 0.  */
07065   if (from == FRAME_POINTER_REGNUM && to == STACK_POINTER_REGNUM)
07066     return 0;
07067 
07068   if (from == RETURN_ADDRESS_POINTER_REGNUM
07069       && (to == FRAME_POINTER_REGNUM || to == STACK_POINTER_REGNUM))
07070     {
07071       if (TARGET_SH5)
07072   {
07073     int n = total_saved_regs_space;
07074     int pr_reg = TARGET_SHMEDIA ? PR_MEDIA_REG : PR_REG;
07075     save_schedule schedule;
07076     save_entry *entry;
07077 
07078     n += total_auto_space;
07079 
07080     /* If it wasn't saved, there's not much we can do.  */
07081     if (! TEST_HARD_REG_BIT (live_regs_mask, pr_reg))
07082       return n;
07083 
07084     target_flags = copy_flags;
07085 
07086     sh5_schedule_saves (&live_regs_mask, &schedule, n);
07087     for (entry = &schedule.entries[1]; entry->mode != VOIDmode; entry++)
07088       if (entry->reg == pr_reg)
07089         {
07090     target_flags = save_flags;
07091     return entry->offset;
07092         }
07093     abort ();
07094   }
07095       else
07096   return total_auto_space;
07097     }
07098 
07099   abort ();
07100 }
07101 
07102 /* Handle machine specific pragmas to be semi-compatible with Renesas
07103    compiler.  */
07104 
07105 void
07106 sh_pr_interrupt (struct cpp_reader *pfile ATTRIBUTE_UNUSED)
07107 {
07108   pragma_interrupt = 1;
07109 }
07110 
07111 void
07112 sh_pr_trapa (struct cpp_reader *pfile ATTRIBUTE_UNUSED)
07113 {
07114   pragma_interrupt = pragma_trapa = 1;
07115 }
07116 
07117 void
07118 sh_pr_nosave_low_regs (struct cpp_reader *pfile ATTRIBUTE_UNUSED)
07119 {
07120   pragma_nosave_low_regs = 1;
07121 }
07122 
07123 /* Generate 'handle_interrupt' attribute for decls */
07124 
07125 static void
07126 sh_insert_attributes (tree node, tree *attributes)
07127 {
07128   if (! pragma_interrupt
07129       || TREE_CODE (node) != FUNCTION_DECL)
07130     return;
07131 
07132   /* We are only interested in fields.  */
07133   if (!DECL_P (node))
07134     return;
07135 
07136   /* Add a 'handle_interrupt' attribute.  */
07137   * attributes = tree_cons (get_identifier ("interrupt_handler"), NULL, * attributes);
07138 
07139   return;
07140 }
07141 
07142 /* Supported attributes:
07143 
07144    interrupt_handler -- specifies this function is an interrupt handler.
07145 
07146    sp_switch -- specifies an alternate stack for an interrupt handler
07147    to run on.
07148 
07149    trap_exit -- use a trapa to exit an interrupt function instead of
07150    an rte instruction.
07151 
07152    renesas -- use Renesas calling/layout conventions (functions and
07153    structures).
07154 
07155 */
07156 
07157 const struct attribute_spec sh_attribute_table[] =
07158 {
07159   /* { name, min_len, max_len, decl_req, type_req, fn_type_req, handler } */
07160   { "interrupt_handler", 0, 0, true,  false, false, sh_handle_interrupt_handler_attribute },
07161   { "sp_switch",         1, 1, true,  false, false, sh_handle_sp_switch_attribute },
07162   { "trap_exit",         1, 1, true,  false, false, sh_handle_trap_exit_attribute },
07163   { "renesas",           0, 0, false, true, false, sh_handle_renesas_attribute },
07164 #ifdef SYMBIAN
07165   /* Symbian support adds three new attributes:
07166      dllexport - for exporting a function/variable that will live in a dll
07167      dllimport - for importing a function/variable from a dll
07168 
07169      Microsoft allows multiple declspecs in one __declspec, separating
07170      them with spaces.  We do NOT support this.  Instead, use __declspec
07171      multiple times.  */
07172   { "dllimport",         0, 0, true,  false, false, sh_symbian_handle_dll_attribute },
07173   { "dllexport",         0, 0, true,  false, false, sh_symbian_handle_dll_attribute },
07174 #endif
07175   { NULL,                0, 0, false, false, false, NULL }
07176 };
07177 
07178 /* Handle an "interrupt_handler" attribute; arguments as in
07179    struct attribute_spec.handler.  */
07180 static tree
07181 sh_handle_interrupt_handler_attribute (tree *node, tree name,
07182                tree args ATTRIBUTE_UNUSED,
07183                int flags ATTRIBUTE_UNUSED,
07184                bool *no_add_attrs)
07185 {
07186   if (TREE_CODE (*node) != FUNCTION_DECL)
07187     {
07188       warning ("%qs attribute only applies to functions",
07189          IDENTIFIER_POINTER (name));
07190       *no_add_attrs = true;
07191     }
07192   else if (TARGET_SHCOMPACT)
07193     {
07194       error ("attribute interrupt_handler is not compatible with -m5-compact");
07195       *no_add_attrs = true;
07196     }
07197 
07198   return NULL_TREE;
07199 }
07200 
07201 /* Handle an "sp_switch" attribute; arguments as in
07202    struct attribute_spec.handler.  */
07203 static tree
07204 sh_handle_sp_switch_attribute (tree *node, tree name, tree args,
07205              int flags ATTRIBUTE_UNUSED, bool *no_add_attrs)
07206 {
07207   if (TREE_CODE (*node) != FUNCTION_DECL)
07208     {
07209