• Main Page
  • Modules
  • Data Types
  • Files

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