00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
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
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
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
00078
00079
00080 enum processor_type sh_cpu;
00081
00082
00083
00084
00085 static short *regmode_weight[2];
00086
00087
00088 static int curr_regmode_pressure[2];
00089
00090
00091 static int skip_cycles = 0;
00092
00093
00094
00095 static short cached_can_issue_more;
00096
00097
00098
00099
00100 rtx sh_compare_op0;
00101 rtx sh_compare_op1;
00102
00103
00104
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
00157
00158
00159
00160 enum reg_class reg_class_from_letter[] =
00161 {
00162 ALL_REGS, TARGET_REGS, FPSCR_REGS, DF_REGS,
00163 FP_REGS, FP_REGS, NO_REGS, NO_REGS,
00164 NO_REGS, NO_REGS, SIBCALL_REGS, PR_REGS,
00165 NO_REGS, NO_REGS, NO_REGS, NO_REGS,
00166 NO_REGS, NO_REGS, NO_REGS, T_REGS,
00167 NO_REGS, NO_REGS, FP0_REGS, MAC_REGS,
00168 FPUL_REGS, 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
00277 #undef TARGET_ATTRIBUTE_TABLE
00278 #define TARGET_ATTRIBUTE_TABLE sh_attribute_table
00279
00280
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
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
00321
00322
00323
00324
00325
00326
00327
00328
00329
00330
00331
00332
00333
00334
00335
00336
00337
00338
00339
00340
00341
00342
00343
00344
00345
00346
00347
00348
00349
00350
00351
00352
00353
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
00456 #define INSN_REGMODE_WEIGHT(INSN, MODE) regmode_weight[((MODE) == SImode) ? 0 : 1][INSN_UID (INSN)]
00457
00458
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
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
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
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
00653
00654
00655
00656
00657
00658
00659
00660
00661
00662
00663
00664
00665
00666
00667
00668
00669
00670
00671
00672
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
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
00729
00730
00731
00732
00733
00734
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
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
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
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
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
00933
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
00945
00946
00947
00948
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
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
01022 default:
01023 if (TARGET_SH1)
01024 fputc ('#', stream);
01025 output_addr_const (stream, x);
01026 break;
01027 }
01028 break;
01029 }
01030 }
01031
01032
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
01042
01043
01044
01045
01046
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
01059
01060
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
01068
01069
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
01095
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
01153
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
01167
01168
01169
01170
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
01183
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 ;
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
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
01233
01234 rtx new = change_address (operands[0], mode, 0);
01235 MEM_COPY_ATTRIBUTES (new, operands[0]);
01236 operands[0] = new;
01237 }
01238
01239
01240
01241
01242
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
01300
01301
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
01343
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
01352 switch (code)
01353 {
01354 case NE:
01355
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
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
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
01448
01449
01450
01451
01452
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
01472
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
01507
01508
01509
01510
01511
01512
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
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
01533
01534
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
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
01592 if (dbr_sequence_length ())
01593 print_slot (final_sequence);
01594
01595 this.reg = gen_rtx_REG (SImode, 13);
01596
01597
01598
01599
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
01632
01633
01634 static int lf = 100;
01635
01636
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
01645
01646
01647
01648
01649
01650
01651
01652 if (! TARGET_RELAX)
01653 {
01654 int label = lf++;
01655
01656 rtx op0 = operands[0];
01657
01658
01659
01660
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
01680
01681 case 2:
01682 return logic ? "bt%.\t%l0" : "bf%.\t%l0";
01683
01684
01685
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
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
01718
01719
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
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
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
01773
01774 static void
01775 sh_file_start (void)
01776 {
01777 default_file_start ();
01778
01779 #ifdef SYMBIAN
01780
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
01787
01788
01789
01790
01791
01792
01793 fprintf (asm_out_file, "%s\n", TEXT_SECTION_ASM_OP);
01794 else
01795
01796
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
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
01837
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
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
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
01872
01873
01874
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
01886
01887
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
01903
01904
01905 #define EXT_SHIFT_SIGNED(n) (((n) | 8) == 15)
01906
01907
01908
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
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
01947 return MAX_COST;
01948 }
01949
01950 if (GET_CODE (XEXP (x, 1)) != CONST_INT)
01951 return SH_DYNAMIC_SHIFT_COST;
01952
01953 value = INTVAL (XEXP (x, 1));
01954
01955
01956 if (GET_CODE (x) == ASHIFTRT)
01957 {
01958 int cost = ashiftrt_insns[value];
01959
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
01969
01970 static inline int
01971 andcosts (rtx x)
01972 {
01973 int i;
01974
01975
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
01992 if (i == 0xff || i == 0xffff)
01993 return 1;
01994
01995
01996 if (CONST_OK_FOR_K08 (i))
01997 return 2;
01998
01999
02000 if (CONST_OK_FOR_I08 (i))
02001 return 2;
02002
02003
02004 return 3;
02005 }
02006
02007
02008
02009 static inline int
02010 addsubcosts (rtx x)
02011 {
02012
02013 if (GET_CODE (XEXP (x, 1)) == REG
02014 || GET_CODE (XEXP (x, 1)) == SUBREG)
02015 return 1;
02016
02017
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
02039 default:
02040 return 5;
02041 }
02042
02043
02044
02045 return 3;
02046 }
02047
02048
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
02056
02057
02058
02059
02060
02061
02062 return TARGET_SMALLCODE ? 2 : 3;
02063
02064 if (TARGET_SH2)
02065 {
02066
02067
02068
02069 if (TARGET_SMALLCODE)
02070 return 2;
02071 return 3;
02072 }
02073
02074
02075
02076 if (TARGET_SMALLCODE)
02077 return 5;
02078
02079
02080 return 20;
02081 }
02082
02083
02084
02085
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
02196
02197
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
02208
02209 void
02210 gen_ashift (int type, int n, rtx reg)
02211 {
02212
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
02240
02241 void
02242 gen_ashift_hi (int type, int n, rtx reg)
02243 {
02244
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
02259
02260
02261
02262
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
02280
02281
02282 void
02283 gen_shifty_op (int code, rtx *operands)
02284 {
02285 int value = INTVAL (operands[2]);
02286 int max, i;
02287
02288
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
02302
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
02314
02315
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
02326
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
02336
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
02353
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
02359
02360
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
02395
02396
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
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
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
02446
02447
02448
02449
02450
02451
02452
02453
02454
02455
02456
02457
02458
02459
02460
02461
02462
02463
02464
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
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
02488 if (! mask2)
02489 best_cost = shift_insns[right] + shift_insns[right + left];
02490
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
02497 if (mask2 == ~(lsb2 - 1))
02498 {
02499 int width, first;
02500
02501 for (width = 8; width <= 16; width += 8)
02502 {
02503
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
02520
02521
02522
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
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
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
02582
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
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
02610
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
02672
02673
02674 if (mask & ((HOST_WIDE_INT) 1 << (31 - total_shift)))
02675 mask |= (HOST_WIDE_INT) ~0 << (31 - total_shift);
02676 case 2:
02677
02678
02679 if (currently_expanding_to_rtl
02680 || reload_in_progress || reload_completed)
02681 {
02682 rtx operands[3];
02683
02684
02685
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
02726
02727
02728
02729
02730
02731
02732
02733
02734
02735
02736
02737
02738
02739
02740
02741
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
02755 kind = 0;
02756 best_cost = shift_insns[32 - insize] + ashiftrt_insns[32 - size];
02757 if (size <= 16)
02758 {
02759
02760 cost = shift_insns[16 - insize] + 1 + ashiftrt_insns[16 - size];
02761
02762
02763 if (cost < best_cost)
02764 {
02765 kind = 5;
02766 best_cost = cost;
02767 }
02768 }
02769
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
02782
02783 if (EXT_SHIFT_SIGNED (size - ext))
02784 cost = ext_shift_insns[ext - insize] + ext_shift_insns[size - ext] + 1;
02785
02786
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
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
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
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
02834
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
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
02873
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
02940 while (--i >= 0)
02941 gen_ashift (ASHIFTRT, 1, dest);
02942 break;
02943 }
02944 case 6:
02945 case 7:
02946
02947
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
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
02987
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
03004
03005
03006
03007
03008
03009
03010
03011
03012
03013
03014
03015
03016
03017
03018
03019
03020
03021
03022
03023
03024
03025
03026
03027
03028
03029
03030
03031
03032
03033
03034
03035
03036
03037
03038
03039
03040
03041
03042
03043
03044
03045
03046
03047
03048
03049
03050
03051
03052
03053
03054
03055
03056 typedef struct
03057 {
03058 rtx value;
03059 rtx label;
03060 label_ref_list_t wend;
03061 enum machine_mode mode;
03062
03063
03064
03065 bool part_of_sequence_p;
03066 } pool_node;
03067
03068
03069
03070
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
03081
03082
03083
03084
03085
03086
03087
03088
03089
03090
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
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
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
03166
03167
03168
03169
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
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
03354
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
03367
03368
03369
03370
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
03382
03383 && GET_MODE (SET_DEST (pat)) != QImode
03384 && (CONSTANT_P (SET_SRC (pat))
03385
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
03394
03395
03396
03397
03398
03399
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
03425 && GET_CODE (MOVA_LABELREF (insn)) == LABEL_REF);
03426 }
03427
03428
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
03470
03471
03472
03473 static int
03474 untangle_mova (int *num_mova, rtx *first_mova, rtx new_mova)
03475 {
03476 int n_addr = 0;
03477 int f_target, n_target = 0;
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
03486
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
03517
03518
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
03536
03537
03538
03539
03540
03541
03542
03543
03544
03545
03546
03547
03548
03549
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
03560
03561
03562
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
03575
03576
03577
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
03583
03584
03585
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
03597
03598
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
03616
03617
03618 if (mode == HImode
03619 || (mode == SImode && hi_const (src) && REGNO (dst) != FPUL_REG))
03620 {
03621 found_hi += 2;
03622
03623
03624
03625
03626 si_limit -= 2;
03627 }
03628 else
03629 {
03630
03631
03632
03633
03634
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
03680
03681
03682
03683
03684
03685
03686
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
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
03730
03731 fixup_mova (mova);
03732 return find_barrier (0, 0, mova);
03733 }
03734 else
03735 {
03736
03737
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
03751
03752 rtx label = gen_label_rtx ();
03753
03754
03755
03756
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
03763
03764
03765
03766
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
03782
03783
03784
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
03820
03821
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
03843
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
03884
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
03904
03905
03906
03907
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
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
03975
03976
03977
03978
03979
03980
03981
03982
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
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
04010
04011 return emit_insn_before (gen_block_branch_redirect (const0_rtx) , jump);
04012 }
04013
04014
04015 dest = XEXP (SET_SRC (PATTERN (jump)), 0);
04016
04017 if (optimize
04018 && (INSN_ADDRESSES (INSN_UID (dest)) - addr + (unsigned) 4092
04019 > 4092 + 4098))
04020 {
04021 rtx scan;
04022
04023
04024 unsigned try = 0x7fff, used;
04025 int jump_left = flag_expensive_optimizations + 1;
04026
04027
04028
04029
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
04078
04079 dead &= 0x7fff;
04080 }
04081
04082
04083
04084
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
04106
04107
04108
04109
04110
04111
04112 rtx insn = emit_insn_before (gen_indirect_jump_scratch
04113 (reg, GEN_INT (INSN_UID (JUMP_LABEL (jump))))
04114 , jump);
04115
04116
04117
04118
04119
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
04127
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
04139
04140 rtx near_label;
04141
04142
04143 rtx insert_place;
04144
04145 rtx far_label;
04146 struct far_branch *prev;
04147
04148
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
04171
04172
04173
04174
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
04183
04184
04185
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
04193 gen_block_redirect (jump, bp->address += 2, 2);
04194 }
04195
04196
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
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
04228
04229 if (!prev)
04230 continue;
04231
04232
04233
04234 braf_label = XEXP (XEXP (SET_SRC (XVECEXP (prevpat, 0, 0)), 1), 0);
04235 emit_label_after (braf_label, prev);
04236
04237
04238
04239 XEXP (XEXP (pat, 0), 0) = braf_label;
04240 }
04241 }
04242
04243
04244
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
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
04268
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
04282
04283
04284 if (mdep_reorg_phase > SH_FIXUP_PCLOAD)
04285 {
04286
04287
04288
04289
04290
04291
04292
04293
04294
04295
04296
04297
04298
04299
04300
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
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
04335
04336
04337 || JUMP_LABEL (prev) == next_nonnote_insn (next)
04338
04339
04340
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
04360
04361
04362
04363
04364
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
04384
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
04398
04399
04400 if (! optimize)
04401 split_all_insns_noflow ();
04402
04403 if (TARGET_SHMEDIA)
04404 return;
04405
04406
04407
04408
04409
04410
04411
04412 mdep_reorg_phase = SH_INSERT_USES_LABELS;
04413 if (TARGET_RELAX)
04414 {
04415
04416
04417
04418
04419
04420
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
04463
04464
04465
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
04487
04488
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
04514
04515
04516
04517
04518
04519 if (GET_CODE (SET_SRC (set)) != SYMBOL_REF
04520 && GET_CODE (SET_SRC (set)) != LABEL_REF)
04521 continue;
04522
04523
04524
04525
04526
04527
04528
04529
04530
04531 dies = NULL_RTX;
04532 for (scan = NEXT_INSN (link); scan; scan = NEXT_INSN (scan))
04533 {
04534 rtx scanset;
04535
04536
04537
04538
04539
04540
04541
04542
04543 if (GET_CODE (scan) == CODE_LABEL && ! foundinsn)
04544 break;
04545
04546 if (! INSN_P (scan))
04547 continue;
04548
04549
04550
04551
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
04569
04570
04571 rescan = 1;
04572 }
04573
04574
04575
04576
04577
04578
04579
04580
04581
04582
04583
04584
04585
04586
04587
04588
04589
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
04603
04604 continue;
04605 }
04606
04607
04608
04609
04610
04611
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
04649
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
04659
04660
04661
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
04672
04673
04674
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
04686
04687 for (scan = mova, total = 0; scan != insn; scan = NEXT_INSN (scan))
04688 total += get_attr_length (scan);
04689
04690
04691
04692
04693
04694 if (total > 1022)
04695 {
04696
04697
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
04708
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
04716
04717 insn = mova;
04718 num_mova = 0;
04719 }
04720
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
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
04783
04784
04785
04786
04787 rtx note
04788 = find_regno_note (last_float_move, REG_UNUSED, 0);
04789
04790
04791
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
04807 *clobberp = gen_rtx_CLOBBER (GET_MODE (clobber),
04808 gen_rtx_SCRATCH (Pmode));
04809 }
04810
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
04844
04845
04846
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
04860
04861
04862
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
04876 return 0;
04877 dest_uid = INSN_UID (dest);
04878
04879
04880
04881
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
04893
04894
04895
04896
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
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
04918
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
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
04943
04944
04945
04946
04947
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
05000
05001
05002
05003
05004
05005
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
05051
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
05095
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
05109
05110 init_insn_lengths ();
05111 }
05112
05113
05114
05115
05116
05117
05118
05119
05120
05121
05122
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
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
05167
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
05192
05193
05194
05195
05196
05197
05198
05199
05200
05201
05202
05203
05204
05205
05206
05207
05208
05209
05210
05211
05212
05213
05214
05215
05216
05217
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
05229
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
05237
05238
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
05253
05254
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
05304
05305
05306
05307
05308
05309 gcc_assert (!TARGET_SHMEDIA && epilogue_p);
05310
05311
05312
05313
05314
05315
05316
05317
05318
05319
05320
05321
05322
05323
05324
05325
05326
05327
05328
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
05352
05353
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
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
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
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
05449
05450
05451 for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
05452 {
05453
05454
05455
05456 if (i == FIRST_FP_REG && interrupt_handler && TARGET_FMOVD
05457 && hard_regs_intersect_p (mask, ®_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
05476
05477
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
05490
05491 stack_space += GET_MODE_SIZE (REGISTER_NATURAL_MODE (reg));
05492 return stack_space;
05493 }
05494
05495
05496
05497
05498
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
05510
05511
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
05523
05524
05525
05526
05527
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
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
05561
05562
05563
05564 if (TARGET_SHMEDIA)
05565
05566
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
05576
05577
05578 pr_live |= regs_ever_live[RETURN_ADDRESS_POINTER_REGNUM];
05579 }
05580
05581
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 ? (
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
05606 && (reg != FPSCR_REG || TARGET_FPU_ANY))
05607 : (
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
05642 target_flags &= ~MASK_FPU_SINGLE;
05643 }
05644 }
05645 }
05646 if (nosave_low_regs && reg == R8_REG)
05647 break;
05648 }
05649
05650
05651
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
05663
05664
05665
05666 if (interrupt_handler
05667 && hard_regs_intersect_p (live_regs_mask,
05668 ®_class_contents[TARGET_REGS])
05669 && ! hard_regs_intersect_p (live_regs_mask,
05670 ®_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
05680
05681
05682
05683
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
05694
05695
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
05720
05721
05722
05723
05724
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
05737
05738
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
05746
05747
05748
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
05775
05776
05777
05778
05779
05780
05781
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
05808
05809
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
05857
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
05869
05870
05871
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
05880
05881
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
05910
05911
05912
05913
05914 REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_MAYBE_DEAD,
05915 const0_rtx,
05916 REG_NOTES (insn));
05917 }
05918 }
05919
05920
05921 if (current_function_stdarg)
05922 {
05923 if (TARGET_VARARGS_PRETEND_ARGS (current_function_decl))
05924 {
05925
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
05942 if (sp_switch_attr)
05943 {
05944
05945
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
05955
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
05976
05977
05978
05979
05980
05981
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
05990
05991
05992
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
06090
06091
06092
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
06124 insn = emit_move_insn (mem_rtx, reg_rtx);
06125 RTX_FRAME_RELATED_P (insn) = 1;
06126
06127
06128
06129
06130
06131
06132
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
06171
06172
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
06187
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
06201
06202
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
06220
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
06257
06258
06259
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
06273
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
06280
06281
06282
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
06289
06290
06291
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
06303
06304 emit_insn (gen_shmedia_save_restore_regs_compact
06305 (GEN_INT (SHMEDIA_REGS_STACK_ADJUST ())));
06306 }
06307
06308
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
06419
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
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
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 ®_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
06470 if (lookup_attribute ("sp_switch", DECL_ATTRIBUTES (current_function_decl)))
06471 emit_insn (gen_sp_switch_2 ());
06472
06473
06474
06475
06476
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
06500
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
06513
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
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
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
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
06579 int first_intreg = current_function_args_info.arg_count[(int) SH_ARG_INT];
06580
06581 int n_intregs = MAX (0, NPARM_REGS (SImode) - first_intreg);
06582
06583 int first_floatreg = current_function_args_info.arg_count[(int) SH_ARG_FLOAT];
06584
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
06632
06633
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
06663
06664
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
06673 return XEXP (regbuf, 0);
06674
06675
06676
06677
06678
06679
06680
06681
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
06719 return XEXP (regbuf, 0);
06720 }
06721
06722
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
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
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
06846
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
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
06912
06913
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
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
07063
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
07094
07095
07096
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
07130
07131
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 }
07140
07141 return false;
07142 }
07143
07144 static bool
07145 sh_callee_copies (CUMULATIVE_ARGS *cum, enum machine_mode mode,
07146 tree type, bool named ATTRIBUTE_UNUSED)
07147 {
07148
07149
07150
07151 return (cum->outgoing
07152 && ((mode == BLKmode ? TYPE_ALIGN (type) : GET_MODE_ALIGNMENT (mode))
07153 % SH_MIN_ALIGN_FOR_CALLEE_COPY == 0));
07154 }
07155
07156 static int
07157 sh_arg_partial_bytes (CUMULATIVE_ARGS *cum, enum machine_mode mode,
07158 tree type, bool named ATTRIBUTE_UNUSED)
07159 {
07160 int words = 0;
07161
07162 if (!TARGET_SH5
07163 && PASS_IN_REG_P (*cum, mode, type)
07164 && !(TARGET_SH4 || TARGET_SH2A_DOUBLE)
07165 && (ROUND_REG (*cum, mode)
07166 + (mode != BLKmode
07167 ? ROUND_ADVANCE (GET_MODE_SIZE (mode))
07168 : ROUND_ADVANCE (int_size_in_bytes (type)))
07169 > NPARM_REGS (mode)))
07170 words = NPARM_REGS (mode) - ROUND_REG (*cum, mode);
07171
07172 else if (!TARGET_SHCOMPACT
07173 && SH5_WOULD_BE_PARTIAL_NREGS (*cum, mode, type, named))
07174 words = NPARM_REGS (SImode) - cum->arg_count[SH_ARG_INT];
07175
07176 return words * UNITS_PER_WORD;
07177 }
07178
07179
07180
07181
07182
07183
07184
07185
07186
07187
07188
07189
07190
07191
07192
07193
07194
07195
07196
07197
07198
07199 rtx
07200 sh_function_arg (CUMULATIVE_ARGS *ca, enum machine_mode mode,
07201 tree type, int named)
07202 {
07203 if (! TARGET_SH5 && mode == VOIDmode)
07204 return GEN_INT (ca->renesas_abi ? 1 : 0);
07205
07206 if (! TARGET_SH5
07207 && PASS_IN_REG_P (*ca, mode, type)
07208 && (named || ! (TARGET_HITACHI || ca->renesas_abi)))
07209 {
07210 int regno;
07211
07212 if (mode == SCmode && TARGET_SH4 && TARGET_LITTLE_ENDIAN
07213 && (! FUNCTION_ARG_SCmode_WART || (ROUND_REG (*ca, mode) & 1)))
07214 {
07215 rtx r1 = gen_rtx_EXPR_LIST (VOIDmode,
07216 gen_rtx_REG (SFmode,
07217 BASE_ARG_REG (mode)
07218 + (ROUND_REG (*ca, mode) ^ 1)),
07219 const0_rtx);
07220 rtx r2 = gen_rtx_EXPR_LIST (VOIDmode,
07221 gen_rtx_REG (SFmode,
07222 BASE_ARG_REG (mode)
07223 + ((ROUND_REG (*ca, mode) + 1) ^ 1)),
07224 GEN_INT (4));
07225 return gen_rtx_PARALLEL(SCmode, gen_rtvec(2, r1, r2));
07226 }
07227
07228
07229
07230
07231 if ((TARGET_HITACHI || ca->renesas_abi)
07232 && ca->free_single_fp_reg
07233 && mode == SFmode)
07234 return gen_rtx_REG (mode, ca->free_single_fp_reg);
07235
07236 regno = (BASE_ARG_REG (mode) + ROUND_REG (*ca, mode))
07237 ^ (mode == SFmode && TARGET_SH4
07238 && TARGET_LITTLE_ENDIAN != 0
07239 && ! TARGET_HITACHI && ! ca->renesas_abi);
07240 return gen_rtx_REG (mode, regno);
07241
07242 }
07243
07244 if (TARGET_SH5)
07245 {
07246 if (mode == VOIDmode && TARGET_SHCOMPACT)
07247 return GEN_INT (ca->call_cookie);
07248
07249
07250
07251 if (mode == SFmode && ca->free_single_fp_reg)
07252 return SH5_PROTOTYPED_FLOAT_ARG (*ca, mode, ca->free_single_fp_reg);
07253
07254 if ((GET_SH_ARG_CLASS (mode) == SH_ARG_FLOAT)
07255 && (named || ! ca->prototype_p)
07256 && ca->arg_count[(int) SH_ARG_FLOAT] < NPARM_REGS (SFmode))
07257 {
07258 if (! ca->prototype_p && TARGET_SHMEDIA)
07259 return SH5_PROTOTYPELESS_FLOAT_ARG (*ca, mode);
07260
07261 return SH5_PROTOTYPED_FLOAT_ARG (*ca, mode,
07262 FIRST_FP_PARM_REG
07263 + ca->arg_count[(int) SH_ARG_FLOAT]);
07264 }
07265
07266 if (ca->arg_count[(int) SH_ARG_INT] < NPARM_REGS (SImode)
07267 && (! TARGET_SHCOMPACT
07268 || (! SHCOMPACT_FORCE_ON_STACK (mode, type)
07269 && ! SH5_WOULD_BE_PARTIAL_NREGS (*ca, mode,
07270 type, named))))
07271 {
07272 return gen_rtx_REG (mode, (FIRST_PARM_REG
07273 + ca->arg_count[(int) SH_ARG_INT]));
07274 }
07275
07276 return 0;
07277 }
07278
07279 return 0;
07280 }
07281
07282
07283
07284
07285
07286
07287 void
07288 sh_function_arg_advance (CUMULATIVE_ARGS *ca, enum machine_mode mode,
07289 tree type, int named)
07290 {
07291 if (ca->force_mem)
07292 ca->force_mem = 0;
07293 else if (TARGET_SH5)
07294 {
07295 tree type2 = (ca->byref && type
07296 ? TREE_TYPE (type)
07297 : type);
07298 enum machine_mode mode2 = (ca->byref && type
07299 ? TYPE_MODE (type2)
07300 : mode);
07301 int dwords = ((ca->byref
07302 ? ca->byref
07303 : mode2 == BLKmode
07304 ? int_size_in_bytes (type2)
07305 : GET_MODE_SIZE (mode2)) + 7) / 8;
07306 int numregs = MIN (dwords, NPARM_REGS (SImode)
07307 - ca->arg_count[(int) SH_ARG_INT]);
07308
07309 if (numregs)
07310 {
07311 ca->arg_count[(int) SH_ARG_INT] += numregs;
07312 if (TARGET_SHCOMPACT
07313 && SHCOMPACT_FORCE_ON_STACK (mode2, type2))
07314 {
07315 ca->call_cookie
07316 |= CALL_COOKIE_INT_REG (ca->arg_count[(int) SH_ARG_INT]
07317 - numregs, 1);
07318
07319 ca->stack_regs += numregs;
07320 }
07321 else if (ca->byref)
07322 {
07323 if (! ca->outgoing)
07324 ca->stack_regs += numregs;
07325 ca->byref_regs += numregs;
07326 ca->byref = 0;
07327 do
07328 ca->call_cookie
07329 |= CALL_COOKIE_INT_REG (ca->arg_count[(int) SH_ARG_INT]
07330 - numregs, 2);
07331 while (--numregs);
07332 ca->call_cookie
07333 |= CALL_COOKIE_INT_REG (ca->arg_count[(int) SH_ARG_INT]
07334 - 1, 1);
07335 }
07336 else if (dwords > numregs)
07337 {
07338 int pushregs = numregs;
07339
07340 if (TARGET_SHCOMPACT)
07341 ca->stack_regs += numregs;
07342 while (pushregs < NPARM_REGS (SImode) - 1
07343 && (CALL_COOKIE_INT_REG_GET
07344 (ca->call_cookie,
07345 NPARM_REGS (SImode) - pushregs)
07346 == 1))
07347 {
07348 ca->call_cookie
07349 &= ~ CALL_COOKIE_INT_REG (NPARM_REGS (SImode)
07350 - pushregs, 1);
07351 pushregs++;
07352 }
07353 if (numregs == NPARM_REGS (SImode))
07354 ca->call_cookie
07355 |= CALL_COOKIE_INT_REG (0, 1)
07356 | CALL_COOKIE_STACKSEQ (numregs - 1);
07357 else
07358 ca->call_cookie
07359 |= CALL_COOKIE_STACKSEQ (numregs);
07360 }
07361 }
07362 if (GET_SH_ARG_CLASS (mode2) == SH_ARG_FLOAT
07363 && (named || ! ca->prototype_p))
07364 {
07365 if (mode2 == SFmode && ca->free_single_fp_reg)
07366 ca->free_single_fp_reg = 0;
07367 else if (ca->arg_count[(int) SH_ARG_FLOAT]
07368 < NPARM_REGS (SFmode))
07369 {
07370 int numfpregs
07371 = MIN ((GET_MODE_SIZE (mode2) + 7) / 8 * 2,
07372 NPARM_REGS (SFmode)
07373 - ca->arg_count[(int) SH_ARG_FLOAT]);
07374
07375 ca->arg_count[(int) SH_ARG_FLOAT] += numfpregs;
07376
07377 if (TARGET_SHCOMPACT && ! ca->prototype_p)
07378 {
07379 if (ca->outgoing && numregs > 0)
07380 do
07381 {
07382 ca->call_cookie
07383 |= (CALL_COOKIE_INT_REG
07384 (ca->arg_count[(int) SH_ARG_INT]
07385 - numregs + ((numfpregs - 2) / 2),
07386 4 + (ca->arg_count[(int) SH_ARG_FLOAT]
07387 - numfpregs) / 2));
07388 }
07389 while (numfpregs -= 2);
07390 }
07391 else if (mode2 == SFmode && (named)
07392 && (ca->arg_count[(int) SH_ARG_FLOAT]
07393 < NPARM_REGS (SFmode)))
07394 ca->free_single_fp_reg
07395 = FIRST_FP_PARM_REG - numfpregs
07396 + ca->arg_count[(int) SH_ARG_FLOAT] + 1;
07397 }
07398 }
07399 return;
07400 }
07401
07402 if ((TARGET_HITACHI || ca->renesas_abi) && TARGET_FPU_DOUBLE)
07403 {
07404
07405 if (mode == SFmode && ca->free_single_fp_reg)
07406 {
07407 ca->free_single_fp_reg = 0;
07408 return;
07409 }
07410
07411
07412
07413
07414 if (mode == DFmode
07415 && ROUND_REG (*ca, DFmode) != ROUND_REG (*ca, SFmode))
07416 {
07417 ca->free_single_fp_reg = (ROUND_REG (*ca, SFmode)
07418 + BASE_ARG_REG (mode));
07419 }
07420 }
07421
07422 if (! ((TARGET_SH4 || TARGET_SH2A) || ca->renesas_abi)
07423 || PASS_IN_REG_P (*ca, mode, type))
07424 (ca->arg_count[(int) GET_SH_ARG_CLASS (mode)]
07425 = (ROUND_REG (*ca, mode)
07426 + (mode == BLKmode
07427 ? ROUND_ADVANCE (int_size_in_bytes (type))
07428 : ROUND_ADVANCE (GET_MODE_SIZE (mode)))));
07429 }
07430
07431
07432
07433
07434 static rtx
07435 sh_struct_value_rtx (tree fndecl, int incoming ATTRIBUTE_UNUSED)
07436 {
07437 if (TARGET_HITACHI || sh_attr_renesas_p (fndecl))
07438 return 0;
07439 return gen_rtx_REG (Pmode, 2);
07440 }
07441
07442
07443
07444 static bool
07445 sh_return_in_memory (tree type, tree fndecl)
07446 {
07447 if (TARGET_SH5)
07448 {
07449 if (TYPE_MODE (type) == BLKmode)
07450 return ((unsigned HOST_WIDE_INT) int_size_in_bytes (type)) > 8;
07451 else
07452 return GET_MODE_SIZE (TYPE_MODE (type)) > 8;
07453 }
07454 else
07455 {
07456 return (TYPE_MODE (type) == BLKmode
07457 || ((TARGET_HITACHI || sh_attr_renesas_p (fndecl))
07458 && TREE_CODE (type) == RECORD_TYPE));
07459 }
07460 }
07461
07462
07463
07464
07465
07466
07467 static void
07468 sh_setup_incoming_varargs (CUMULATIVE_ARGS *ca,
07469 enum machine_mode mode,
07470 tree type,
07471 int *pretend_arg_size,
07472 int second_time ATTRIBUTE_UNUSED)
07473 {
07474 gcc_assert (current_function_stdarg);
07475 if (TARGET_VARARGS_PRETEND_ARGS (current_function_decl))
07476 {
07477 int named_parm_regs, anon_parm_regs;
07478
07479 named_parm_regs = (ROUND_REG (*ca, mode)
07480 + (mode == BLKmode
07481 ? ROUND_ADVANCE (int_size_in_bytes (type))
07482 : ROUND_ADVANCE (GET_MODE_SIZE (mode))));
07483 anon_parm_regs = NPARM_REGS (SImode) - named_parm_regs;
07484 if (anon_parm_regs > 0)
07485 *pretend_arg_size = anon_parm_regs * 4;
07486 }
07487 }
07488
07489 static bool
07490 sh_strict_argument_naming (CUMULATIVE_ARGS *ca ATTRIBUTE_UNUSED)
07491 {
07492 return TARGET_SH5;
07493 }
07494
07495 static bool
07496 sh_pretend_outgoing_varargs_named (CUMULATIVE_ARGS *ca)
07497 {
07498 return ! (TARGET_HITACHI || ca->renesas_abi) && ! TARGET_SH5;
07499 }
07500
07501
07502
07503
07504
07505 int
07506 initial_elimination_offset (int from, int to)
07507 {
07508 int regs_saved;
07509 int regs_saved_rounding = 0;
07510 int total_saved_regs_space;
07511 int total_auto_space;
07512 int save_flags = target_flags;
07513 int copy_flags;
07514 HARD_REG_SET live_regs_mask;
07515
07516 shmedia_space_reserved_for_target_registers = false;
07517 regs_saved = calc_live_regs (&live_regs_mask);
07518 regs_saved += SHMEDIA_REGS_STACK_ADJUST ();
07519
07520 if (shmedia_reserve_space_for_target_registers_p (regs_saved, &live_regs_mask))
07521 {
07522 shmedia_space_reserved_for_target_registers = true;
07523 regs_saved += shmedia_target_regs_stack_adjust (&live_regs_mask);
07524 }
07525
07526 if (TARGET_SH5 && regs_saved % (STACK_BOUNDARY / BITS_PER_UNIT))
07527 regs_saved_rounding = ((STACK_BOUNDARY / BITS_PER_UNIT)
07528 - regs_saved % (STACK_BOUNDARY / BITS_PER_UNIT));
07529
07530 total_auto_space = rounded_frame_size (regs_saved) - regs_saved_rounding;
07531 copy_flags = target_flags;
07532 target_flags = save_flags;
07533
07534 total_saved_regs_space = regs_saved + regs_saved_rounding;
07535
07536 if (from == ARG_POINTER_REGNUM && to == HARD_FRAME_POINTER_REGNUM)
07537 return total_saved_regs_space + total_auto_space
07538 + current_function_args_info.byref_regs * 8;
07539
07540 if (from == ARG_POINTER_REGNUM && to == STACK_POINTER_REGNUM)
07541 return total_saved_regs_space + total_auto_space
07542 + current_function_args_info.byref_regs * 8;
07543
07544
07545 if (from == HARD_FRAME_POINTER_REGNUM && to == STACK_POINTER_REGNUM)
07546 return 0;
07547
07548 if (from == FRAME_POINTER_REGNUM && to == STACK_POINTER_REGNUM)
07549 return rounded_frame_size (0);
07550
07551 if (from == FRAME_POINTER_REGNUM && to == HARD_FRAME_POINTER_REGNUM)
07552 return rounded_frame_size (0);
07553
07554 gcc_assert (from == RETURN_ADDRESS_POINTER_REGNUM
07555 && (to == HARD_FRAME_POINTER_REGNUM
07556 || to == STACK_POINTER_REGNUM));
07557 if (TARGET_SH5)
07558 {
07559 int n = total_saved_regs_space;
07560 int pr_reg = TARGET_SHMEDIA ? PR_MEDIA_REG : PR_REG;
07561 save_schedule schedule;
07562 save_entry *entry;
07563
07564 n += total_auto_space;
07565
07566
07567 if (! TEST_HARD_REG_BIT (live_regs_mask, pr_reg))
07568 return n;
07569
07570 target_flags = copy_flags;
07571
07572 sh5_schedule_saves (&live_regs_mask, &schedule, n);
07573 for (entry = &schedule.entries[1]; entry->mode != VOIDmode; entry++)
07574 if (entry->reg == pr_reg)
07575 {
07576 target_flags = save_flags;
07577 return entry->offset;
07578 }
07579 gcc_unreachable ();
07580 }
07581 else
07582 return total_auto_space;
07583 }
07584
07585
07586 static void
07587 sh_insert_attributes (tree node, tree *attributes)
07588 {
07589 tree attrs;
07590
07591 if (TREE_CODE (node) != FUNCTION_DECL)
07592 return;
07593
07594
07595 if (!DECL_P (node))
07596 return;
07597
07598
07599 *sh_deferred_function_attributes_tail = *attributes;
07600 attrs = sh_deferred_function_attributes;
07601 if (!attrs)
07602 return;
07603
07604
07605 if (!lookup_attribute ("interrupt_handler", attrs)
07606 && !lookup_attribute ("interrupt_handler", DECL_ATTRIBUTES (node)))
07607 {
07608
07609
07610 if (lookup_attribute ("trapa_handler", attrs) != NULL_TREE)
07611
07612
07613 attrs
07614 = tree_cons (get_identifier("interrupt_handler"), NULL_TREE, attrs);
07615
07616
07617 else if (lookup_attribute ("sp_switch", attrs)
07618 || lookup_attribute ("trap_exit", attrs)
07619 || lookup_attribute ("nosave_low_regs", attrs))
07620 {
07621 tree *tail;
07622
07623 for (tail = attributes; attrs; attrs = TREE_CHAIN (attrs))
07624 {
07625 if (is_attribute_p ("sp_switch", TREE_PURPOSE (attrs))
07626 || is_attribute_p ("trap_exit", TREE_PURPOSE (attrs))
07627 || is_attribute_p ("nosave_low_regs", TREE_PURPOSE (attrs)))
07628 warning (OPT_Wattributes,
07629 "%qs attribute only applies to interrupt functions",
07630 IDENTIFIER_POINTER (TREE_PURPOSE (attrs)));
07631 else
07632 {
07633 *tail = tree_cons (TREE_PURPOSE (attrs), NULL_TREE,
07634 NULL_TREE);
07635 tail = &TREE_CHAIN (*tail);
07636 }
07637 }
07638 attrs = *attributes;
07639 }
07640 }
07641
07642
07643 *attributes = attrs;
07644
07645
07646 sh_deferred_function_attributes = NULL_TREE;
07647 sh_deferred_function_attributes_tail = &sh_deferred_function_attributes;
07648
07649 return;
07650 }
07651
07652
07653
07654
07655
07656
07657
07658
07659
07660
07661
07662
07663
07664
07665
07666
07667
07668
07669
07670
07671
07672
07673
07674
07675
07676 const struct attribute_spec sh_attribute_table[] =
07677 {
07678
07679 { "interrupt_handler", 0, 0, true, false, false, sh_handle_interrupt_handler_attribute },
07680 { "sp_switch", 1, 1, true, false, false, sh_handle_sp_switch_attribute },
07681 { "trap_exit", 1, 1, true, false, false, sh_handle_trap_exit_attribute },
07682 { "renesas", 0, 0, false, true, false, sh_handle_renesas_attribute },
07683 { "trapa_handler", 0, 0, true, false, false, sh_handle_interrupt_handler_attribute },
07684 { "nosave_low_regs", 0, 0, true, false, false, sh_handle_interrupt_handler_attribute },
07685 #ifdef SYMBIAN
07686
07687
07688
07689
07690
07691
07692
07693 { "dllimport", 0, 0, true, false, false, sh_symbian_handle_dll_attribute },
07694 { "dllexport", 0, 0, true, false, false, sh_symbian_handle_dll_attribute },
07695 #endif
07696 { NULL, 0, 0, false, false, false, NULL }
07697 };
07698
07699
07700
07701 static tree
07702 sh_handle_interrupt_handler_attribute (tree *node, tree name,
07703 tree args ATTRIBUTE_UNUSED,
07704 int flags ATTRIBUTE_UNUSED,
07705 bool *no_add_attrs)
07706 {
07707 if (TREE_CODE (*node) != FUNCTION_DECL)
07708 {
07709 warning (OPT_Wattributes, "%qs attribute only applies to functions",
07710 IDENTIFIER_POINTER (name));
07711 *no_add_attrs = true;
07712 }
07713 else if (TARGET_SHCOMPACT)
07714 {
07715 error ("attribute interrupt_handler is not compatible with -m5-compact");
07716 *no_add_attrs = true;
07717 }
07718
07719 return NULL_TREE;
07720 }
07721
07722
07723
07724 static tree
07725 sh_handle_sp_switch_attribute (tree *node, tree name, tree args,
07726 int flags ATTRIBUTE_UNUSED, bool *no_add_attrs)
07727 {
07728 if (TREE_CODE (*node) != FUNCTION_DECL)
07729 {
07730 warning (OPT_Wattributes, "%qs attribute only applies to functions",
07731 IDENTIFIER_POINTER (name));
07732 *no_add_attrs = true;
07733 }
07734 else if (TREE_CODE (TREE_VALUE (args)) != STRING_CST)
07735 {
07736
07737 warning (OPT_Wattributes, "%qs attribute argument not a string constant",
07738 IDENTIFIER_POINTER (name));
07739 *no_add_attrs = true;
07740 }
07741
07742 return NULL_TREE;
07743 }
07744
07745
07746
07747 static tree
07748 sh_handle_trap_exit_attribute (tree *node, tree name, tree args,
07749 int flags ATTRIBUTE_UNUSED, bool *no_add_attrs)
07750 {
07751 if (TREE_CODE (*node) != FUNCTION_DECL)
07752 {
07753 warning (OPT_Wattributes, "%qs attribute only applies to functions",
07754 IDENTIFIER_POINTER (name));
07755 *no_add_attrs = true;
07756 }
07757
07758
07759 else if (TREE_CODE (TREE_VALUE (args)) != INTEGER_CST)
07760 {
07761
07762 warning (OPT_Wattributes, "%qs attribute argument not an "
07763 "integer constant", IDENTIFIER_POINTER (name));
07764 *no_add_attrs = true;
07765 }
07766
07767 return NULL_TREE;
07768 }
07769
07770 static tree
07771 sh_handle_renesas_attribute (tree *node ATTRIBUTE_UNUSED,
07772 tree name ATTRIBUTE_UNUSED,
07773 tree args ATTRIBUTE_UNUSED,
07774 int flags ATTRIBUTE_UNUSED,
07775 bool *no_add_attrs ATTRIBUTE_UNUSED)
07776 {
07777 return NULL_TREE;
07778 }
07779
07780
07781 int
07782 sh_attr_renesas_p (tree td)
07783 {
07784 if (TARGET_HITACHI)
07785 return 1;
07786 if (td == 0)
07787 return 0;
07788 if (DECL_P (td))
07789 td = TREE_TYPE (td);
07790 if (td == error_mark_node)
07791 return 0;
07792 return (lookup_attribute ("renesas", TYPE_ATTRIBUTES (td))
07793 != NULL_TREE);
07794 }
07795
07796
07797
07798 int
07799 sh_cfun_attr_renesas_p (void)
07800 {
07801 return sh_attr_renesas_p (current_function_decl);
07802 }
07803
07804 int
07805 sh_cfun_interrupt_handler_p (void)
07806 {
07807 return (lookup_attribute ("interrupt_handler",
07808 DECL_ATTRIBUTES (current_function_decl))
07809 != NULL_TREE);
07810 }
07811
07812
07813
07814 static const char *
07815 sh_check_pch_target_flags (int old_flags)
07816 {
07817 if ((old_flags ^ target_flags) & (MASK_SH1 | MASK_SH2 | MASK_SH3
07818 | MASK_SH_E | MASK_HARD_SH4
07819 | MASK_FPU_SINGLE | MASK_SH4))
07820 return _("created and used with different architectures / ABIs");
07821 if ((old_flags ^ target_flags) & MASK_HITACHI)
07822 return _("created and used with different ABIs");
07823 if ((old_flags ^ target_flags) & MASK_LITTLE_ENDIAN)
07824 return _("created and used with different endianness");
07825 return NULL;
07826 }
07827
07828
07829
07830
07831
07832
07833 int
07834 system_reg_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
07835 {
07836 switch (REGNO (op))
07837 {
07838 case PR_REG:
07839 case MACL_REG:
07840 case MACH_REG:
07841 return 1;
07842 }
07843 return 0;
07844 }
07845
07846
07847
07848 int
07849 fp_zero_operand (rtx op)
07850 {
07851 REAL_VALUE_TYPE r;
07852
07853 if (GET_MODE (op) != SFmode)
07854 return 0;
07855
07856 REAL_VALUE_FROM_CONST_DOUBLE (r, op);
07857 return REAL_VALUES_EQUAL (r, dconst0) && ! REAL_VALUE_MINUS_ZERO (r);
07858 }
07859
07860
07861
07862 int
07863 fp_one_operand (rtx op)
07864 {
07865 REAL_VALUE_TYPE r;
07866
07867 if (GET_MODE (op) != SFmode)
07868 return 0;
07869
07870 REAL_VALUE_FROM_CONST_DOUBLE (r, op);
07871 return REAL_VALUES_EQUAL (r, dconst1);
07872 }
07873
07874
07875
07876
07877
07878
07879
07880
07881 int
07882 fldi_ok (void)
07883 {
07884 return ! TARGET_SH4 || TARGET_FMOVD || reload_completed;
07885 }
07886
07887 int
07888 tertiary_reload_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
07889 {
07890 enum rtx_code code = GET_CODE (op);
07891 return code == MEM || (TARGET_SH4 && code == CONST_DOUBLE);
07892 }
07893
07894
07895 int
07896 tls_symbolic_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
07897 {
07898 if (GET_CODE (op) != SYMBOL_REF)
07899 return 0;
07900 return SYMBOL_REF_TLS_MODEL (op);
07901 }
07902
07903
07904
07905 static int
07906 branch_dest (rtx branch)
07907 {
07908 rtx dest = SET_SRC (PATTERN (branch));
07909 int dest_uid;
07910
07911 if (GET_CODE (dest) == IF_THEN_ELSE)
07912 dest = XEXP (dest, 1);
07913 dest = XEXP (dest, 0);
07914 dest_uid = INSN_UID (dest);
07915 return INSN_ADDRESSES (dest_uid);
07916 }
07917
07918
07919
07920
07921 int
07922 reg_unused_after (rtx reg, rtx insn)
07923 {
07924 enum rtx_code code;
07925 rtx set;
07926
07927
07928
07929
07930 set = single_set (insn);
07931 if (set && GET_CODE (SET_DEST (set)) != MEM
07932 && reg_overlap_mentioned_p (reg, SET_DEST (set)))
07933 return 1;
07934
07935 while ((insn = NEXT_INSN (insn)))
07936 {
07937 rtx set;
07938 if (!INSN_P (insn))
07939 continue;
07940
07941 code = GET_CODE (insn);
07942
07943 #if 0
07944
07945
07946
07947
07948 if (code == CODE_LABEL)
07949 return 1;
07950
07951 #endif
07952
07953 if (code == JUMP_INSN)
07954 return 0;
07955
07956
07957
07958
07959
07960 else if (code == INSN && GET_CODE (PATTERN (insn)) == SEQUENCE)
07961 {
07962 int i;
07963 int retval = 0;
07964
07965 for (i = 0; i < XVECLEN (PATTERN (insn), 0); i++)
07966 {
07967 rtx this_insn = XVECEXP (PATTERN (insn), 0, i);
07968 rtx set = single_set (this_insn);
07969
07970 if (GET_CODE (this_insn) == CALL_INSN)
07971 code = CALL_INSN;
07972 else if (GET_CODE (this_insn) == JUMP_INSN)
07973 {
07974 if (INSN_ANNULLED_BRANCH_P (this_insn))
07975 return 0;
07976 code = JUMP_INSN;
07977 }
07978
07979 if (set && reg_overlap_mentioned_p (reg, SET_SRC (set)))
07980 return 0;
07981 if (set && reg_overlap_mentioned_p (reg, SET_DEST (set)))
07982 {
07983 if (GET_CODE (SET_DEST (set)) != MEM)
07984 retval = 1;
07985 else
07986 return 0;
07987 }
07988 if (set == 0
07989 && reg_overlap_mentioned_p (reg, PATTERN (this_insn)))
07990 return 0;
07991 }
07992 if (retval == 1)
07993 return 1;
07994 else if (code == JUMP_INSN)
07995 return 0;
07996 }
07997
07998 set = single_set (insn);
07999 if (set && reg_overlap_mentioned_p (reg, SET_SRC (set)))
08000 return 0;
08001 if (set && reg_overlap_mentioned_p (reg, SET_DEST (set)))
08002 return GET_CODE (SET_DEST (set)) != MEM;
08003 if (set == 0 && reg_overlap_mentioned_p (reg, PATTERN (insn)))
08004 return 0;
08005
08006 if (code == CALL_INSN && call_really_used_regs[REGNO (reg)])
08007 return 1;
08008 }
08009 return 1;
08010 }
08011
08012 #include "ggc.h"
08013
08014 static GTY(()) rtx fpscr_rtx;
08015 rtx
08016 get_fpscr_rtx (void)
08017 {
08018 if (! fpscr_rtx)
08019 {
08020 fpscr_rtx = gen_rtx_REG (PSImode, FPSCR_REG);
08021 REG_USERVAR_P (fpscr_rtx) = 1;
08022 mark_user_reg (fpscr_rtx);
08023 }
08024 if (! reload_completed || mdep_reorg_phase != SH_AFTER_MDEP_REORG)
08025 mark_user_reg (fpscr_rtx);
08026 return fpscr_rtx;
08027 }
08028
08029 static GTY(()) tree fpscr_values;
08030
08031 static void
08032 emit_fpu_switch (rtx scratch, int index)
08033 {
08034 rtx dst, src;
08035
08036 if (fpscr_values == NULL)
08037 {
08038 tree t;
08039
08040 t = build_index_type (integer_one_node);
08041 t = build_array_type (integer_type_node, t);
08042 t = build_decl (VAR_DECL, get_identifier ("__fpscr_values"), t);
08043 DECL_ARTIFICIAL (t) = 1;
08044 DECL_IGNORED_P (t) = 1;
08045 DECL_EXTERNAL (t) = 1;
08046 TREE_STATIC (t) = 1;
08047 TREE_PUBLIC (t) = 1;
08048 TREE_USED (t) = 1;
08049
08050 fpscr_values = t;
08051 }
08052
08053 src = DECL_RTL (fpscr_values);
08054 if (no_new_pseudos)
08055 {
08056 emit_move_insn (scratch, XEXP (src, 0));
08057 if (index != 0)
08058 emit_insn (gen_addsi3 (scratch, scratch, GEN_INT (index * 4)));
08059 src = adjust_automodify_address (src, PSImode, scratch, index * 4);
08060 }
08061 else
08062 src = adjust_address (src, PSImode, index * 4);
08063
08064 dst = get_fpscr_rtx ();
08065 emit_move_insn (dst, src);
08066 }
08067
08068 void
08069 emit_sf_insn (rtx pat)
08070 {
08071 emit_insn (pat);
08072 }
08073
08074 void
08075 emit_df_insn (rtx pat)
08076 {
08077 emit_insn (pat);
08078 }
08079
08080 void
08081 expand_sf_unop (rtx (*fun) (rtx, rtx, rtx), rtx *operands)
08082 {
08083 emit_sf_insn ((*fun) (operands[0], operands[1], get_fpscr_rtx ()));
08084 }
08085
08086 void
08087 expand_sf_binop (rtx (*fun) (rtx, rtx, rtx, rtx), rtx *operands)
08088 {
08089 emit_sf_insn ((*fun) (operands[0], operands[1], operands[2],
08090 get_fpscr_rtx ()));
08091 }
08092
08093 void
08094 expand_df_unop (rtx (*fun) (rtx, rtx, rtx), rtx *operands)
08095 {
08096 emit_df_insn ((*fun) (operands[0], operands[1], get_fpscr_rtx ()));
08097 }
08098
08099 void
08100 expand_df_binop (rtx (*fun) (rtx, rtx, rtx, rtx), rtx *operands)
08101 {
08102 emit_df_insn ((*fun) (operands[0], operands[1], operands[2],
08103 get_fpscr_rtx ()));
08104 }
08105
08106
08107
08108
08109
08110
08111
08112
08113
08114
08115
08116
08117
08118
08119
08120
08121
08122
08123
08124
08125
08126
08127
08128
08129
08130
08131
08132
08133 static void
08134 mark_use (rtx x, rtx *reg_set_block)
08135 {
08136 enum rtx_code code;
08137
08138 if (! x)
08139 return;
08140 code = GET_CODE (x);
08141 switch (code)
08142 {
08143 case REG:
08144 {
08145 int regno = REGNO (x);
08146 int nregs = (regno < FIRST_PSEUDO_REGISTER
08147 ? HARD_REGNO_NREGS (regno, GET_MODE (x))
08148 : 1);
08149 do
08150 {
08151 reg_set_block[regno + nregs - 1] = 0;
08152 }
08153 while (--nregs);
08154 break;
08155 }
08156 case SET:
08157 {
08158 rtx dest = SET_DEST (x);
08159
08160 if (GET_CODE (dest) == SUBREG)
08161 dest = SUBREG_REG (dest);
08162 if (GET_CODE (dest) != REG)
08163 mark_use (dest, reg_set_block);
08164 mark_use (SET_SRC (x), reg_set_block);
08165 break;
08166 }
08167 case CLOBBER:
08168 break;
08169 default:
08170 {
08171 const char *fmt = GET_RTX_FORMAT (code);
08172 int i, j;
08173 for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
08174 {
08175 if (fmt[i] == 'e')
08176 mark_use (XEXP (x, i), reg_set_block);
08177 else if (fmt[i] == 'E')
08178 for (j = XVECLEN (x, i) - 1; j >= 0; j--)
08179 mark_use (XVECEXP (x, i, j), reg_set_block);
08180 }
08181 break;
08182 }
08183 }
08184 }
08185
08186 static rtx get_free_reg (HARD_REG_SET);
08187
08188
08189
08190
08191
08192
08193
08194
08195
08196
08197
08198
08199
08200
08201
08202 static rtx
08203 get_free_reg (HARD_REG_SET regs_live)
08204 {
08205 if (! TEST_HARD_REG_BIT (regs_live, 1))
08206 return gen_rtx_REG (Pmode, 1);
08207
08208
08209
08210 gcc_assert (!TEST_HARD_REG_BIT (regs_live, 7));
08211 return gen_rtx_REG (Pmode, 7);
08212 }
08213
08214
08215
08216 void
08217 fpscr_set_from_mem (int mode, HARD_REG_SET regs_live)
08218 {
08219 enum attr_fp_mode fp_mode = mode;
08220 enum attr_fp_mode norm_mode = ACTUAL_NORMAL_MODE (FP_MODE);
08221 rtx addr_reg = get_free_reg (regs_live);
08222
08223 emit_fpu_switch (addr_reg, fp_mode == norm_mode);
08224 }
08225
08226
08227 #ifndef IS_ASM_LOGICAL_LINE_SEPARATOR
08228 #define IS_ASM_LOGICAL_LINE_SEPARATOR(C) ((C) == ';')
08229 #endif
08230
08231 int
08232 sh_insn_length_adjustment (rtx insn)
08233 {
08234
08235
08236 if (((GET_CODE (insn) == INSN
08237 && GET_CODE (PATTERN (insn)) != USE
08238 && GET_CODE (PATTERN (insn)) != CLOBBER)
08239 || GET_CODE (insn) == CALL_INSN
08240 || (GET_CODE (insn) == JUMP_INSN
08241 && GET_CODE (PATTERN (insn)) != ADDR_DIFF_VEC
08242 && GET_CODE (PATTERN (insn)) != ADDR_VEC))
08243 && GET_CODE (PATTERN (NEXT_INSN (PREV_INSN (insn)))) != SEQUENCE
08244 && get_attr_needs_delay_slot (insn) == NEEDS_DELAY_SLOT_YES)
08245 return 2;
08246
08247
08248
08249 if (sh_cpu == CPU_SH2E
08250 && GET_CODE (insn) == JUMP_INSN
08251 && GET_CODE (PATTERN (insn)) != ADDR_DIFF_VEC
08252 && GET_CODE (PATTERN (insn)) != ADDR_VEC
08253 && get_attr_type (insn) == TYPE_CBRANCH
08254 && GET_CODE (PATTERN (NEXT_INSN (PREV_INSN (insn)))) != SEQUENCE)
08255 return 2;
08256
08257
08258
08259 if (GET_CODE (insn) == INSN)
08260 {
08261 int sum = 0;
08262 rtx body = PATTERN (insn);
08263 const char *template;
08264 char c;
08265 int maybe_label = 1;
08266
08267 if (GET_CODE (body) == ASM_INPUT)
08268 template = XSTR (body, 0);
08269 else if (asm_noperands (body) >= 0)
08270 template
08271 = decode_asm_operands (body, NULL, NULL, NULL, NULL);
08272 else
08273 return 0;
08274 do
08275 {
08276 int ppi_adjust = 0;
08277
08278 do
08279 c = *template++;
08280 while (c == ' ' || c == '\t');
08281
08282
08283
08284 if ((c == 'p' || c == 'P') && strncasecmp ("re", template, 2))
08285 ppi_adjust = 2;
08286
08287
08288 else if ((c == 'r' || c == 'R')
08289 && ! strncasecmp ("epeat", template, 5))
08290 ppi_adjust = 4;
08291 while (c && c != '\n' && ! IS_ASM_LOGICAL_LINE_SEPARATOR (c))
08292 {
08293
08294 if (c == ':' && maybe_label)
08295 {
08296 ppi_adjust = 0;
08297 break;
08298 }
08299 else if (c == '\'' || c == '"')
08300 maybe_label = 0;
08301 c = *template++;
08302 }
08303 sum += ppi_adjust;
08304 maybe_label = c != ':';
08305 }
08306 while (c);
08307 return sum;
08308 }
08309 return 0;
08310 }
08311
08312
08313
08314 int
08315 nonpic_symbol_mentioned_p (rtx x)
08316 {
08317 register const char *fmt;
08318 register int i;
08319
08320 if (GET_CODE (x) == SYMBOL_REF || GET_CODE (x) == LABEL_REF
08321 || GET_CODE (x) == PC)
08322 return 1;
08323
08324
08325
08326 if (GET_CODE (x) == CONST_DOUBLE)
08327 return 0;
08328
08329 if (GET_CODE (x) == UNSPEC
08330 && (XINT (x, 1) == UNSPEC_PIC
08331 || XINT (x, 1) == UNSPEC_GOT
08332 || XINT (x, 1) == UNSPEC_GOTOFF
08333 || XINT (x, 1) == UNSPEC_GOTPLT
08334 || XINT (x, 1) == UNSPEC_GOTTPOFF
08335 || XINT (x, 1) == UNSPEC_DTPOFF
08336 || XINT (x, 1) == UNSPEC_PLT))
08337 return 0;
08338
08339 fmt = GET_RTX_FORMAT (GET_CODE (x));
08340 for (i = GET_RTX_LENGTH (GET_CODE (x)) - 1; i >= 0; i--)
08341 {
08342 if (fmt[i] == 'E')
08343 {
08344 register int j;
08345
08346 for (j = XVECLEN (x, i) - 1; j >= 0; j--)
08347 if (nonpic_symbol_mentioned_p (XVECEXP (x, i, j)))
08348 return 1;
08349 }
08350 else if (fmt[i] == 'e' && nonpic_symbol_mentioned_p (XEXP (x, i)))
08351 return 1;
08352 }
08353
08354 return 0;
08355 }
08356
08357
08358
08359 rtx
08360 legitimize_pic_address (rtx orig, enum machine_mode mode ATTRIBUTE_UNUSED,
08361 rtx reg)
08362 {
08363 if (tls_symbolic_operand (orig, Pmode))
08364 return orig;
08365
08366 if (GET_CODE (orig) == LABEL_REF
08367 || (GET_CODE (orig) == SYMBOL_REF && SYMBOL_REF_LOCAL_P (orig)))
08368 {
08369 if (reg == 0)
08370 reg = gen_reg_rtx (Pmode);
08371
08372 emit_insn (gen_symGOTOFF2reg (reg, orig));
08373 return reg;
08374 }
08375 else if (GET_CODE (orig) == SYMBOL_REF)
08376 {
08377 if (reg == 0)
08378 reg = gen_reg_rtx (Pmode);
08379
08380 emit_insn (gen_symGOT2reg (reg, orig));
08381 return reg;
08382 }
08383 return orig;
08384 }
08385
08386
08387
08388 static rtx
08389 mark_constant_pool_use (rtx x)
08390 {
08391 rtx insn, lab, pattern;
08392
08393 if (x == NULL)
08394 return x;
08395
08396 switch (GET_CODE (x))
08397 {
08398 case LABEL_REF:
08399 x = XEXP (x, 0);
08400 case CODE_LABEL:
08401 break;
08402 default:
08403 return x;
08404 }
08405
08406
08407
08408 lab = x;
08409 for (insn = PREV_INSN (x); insn; insn = PREV_INSN (insn))
08410 {
08411 if (GET_CODE (insn) != CODE_LABEL
08412 || LABEL_REFS (insn) != NEXT_INSN (insn))
08413 break;
08414 lab = insn;
08415 }
08416
08417 for (insn = LABEL_REFS (lab); insn; insn = LABEL_REFS (insn))
08418 INSN_DELETED_P (insn) = 1;
08419
08420
08421 for (insn = NEXT_INSN (x); insn; insn = NEXT_INSN (insn))
08422 {
08423 if (GET_CODE (insn) != INSN)
08424 continue;
08425
08426 pattern = PATTERN (insn);
08427 if (GET_CODE (pattern) != UNSPEC_VOLATILE)
08428 continue;
08429
08430 switch (XINT (pattern, 1))
08431 {
08432 case UNSPECV_CONST2:
08433 case UNSPECV_CONST4:
08434 case UNSPECV_CONST8:
08435 XVECEXP (pattern, 0, 1) = const1_rtx;
08436 break;
08437 case UNSPECV_WINDOW_END:
08438 if (XVECEXP (pattern, 0, 0) == x)
08439 return lab;
08440 break;
08441 case UNSPECV_CONST_END:
08442 return lab;
08443 default:
08444 break;
08445 }
08446 }
08447
08448 return lab;
08449 }
08450
08451
08452
08453
08454 int
08455 sh_can_redirect_branch (rtx branch1, rtx branch2)
08456 {
08457 if (flag_expensive_optimizations && simplejump_p (branch2))
08458 {
08459 rtx dest = XEXP (SET_SRC (single_set (branch2)), 0);
08460 rtx insn;
08461 int distance;
08462
08463 for (distance = 0, insn = NEXT_INSN (branch1);
08464 insn && distance < 256;
08465 insn = PREV_INSN (insn))
08466 {
08467 if (insn == dest)
08468 return 1;
08469 else
08470 distance += get_attr_length (insn);
08471 }
08472 for (distance = 0, insn = NEXT_INSN (branch1);
08473 insn && distance < 256;
08474 insn = NEXT_INSN (insn))
08475 {
08476 if (insn == dest)
08477 return 1;
08478 else
08479 distance += get_attr_length (insn);
08480 }
08481 }
08482 return 0;
08483 }
08484
08485
08486 int
08487 sh_hard_regno_rename_ok (unsigned int old_reg ATTRIBUTE_UNUSED,
08488 unsigned int new_reg)
08489 {
08490
08491
08492
08493
08494 if (sh_cfun_interrupt_handler_p () && !regs_ever_live[new_reg])
08495 return 0;
08496
08497 return 1;
08498 }
08499
08500
08501
08502
08503
08504
08505
08506
08507 static int
08508 sh_adjust_cost (rtx insn, rtx link ATTRIBUTE_UNUSED, rtx dep_insn, int cost)
08509 {
08510 rtx reg, use_pat;
08511
08512 if (TARGET_SHMEDIA)
08513 {
08514
08515
08516 if (REG_NOTE_KIND (link) != 0)
08517 {
08518
08519
08520
08521
08522
08523 if (REG_NOTE_KIND (link) == REG_DEP_ANTI
08524 && GET_CODE (PATTERN (dep_insn)) == SET
08525 && (get_attr_type (dep_insn) == TYPE_PT_MEDIA
08526 || get_attr_type (dep_insn) == TYPE_PTABS_MEDIA)
08527 && get_attr_type (insn) == TYPE_CBRANCH_MEDIA)
08528 {
08529 int orig_cost = cost;
08530 rtx note = find_reg_note (insn, REG_BR_PROB, 0);
08531 rtx target = ((! note
08532 || INTVAL (XEXP (note, 0)) * 2 < REG_BR_PROB_BASE)
08533 ? insn : JUMP_LABEL (insn));
08534
08535
08536 cost--;
08537 do
08538 target = next_active_insn (target);
08539 while (target && ! flow_dependent_p (target, dep_insn)
08540 && --cost > 0);
08541
08542
08543
08544
08545
08546 if (cost > orig_cost - 2)
08547 cost = orig_cost - 2;
08548 }
08549 else
08550 cost = 0;
08551 }
08552
08553 else if (get_attr_is_mac_media (insn)
08554 && get_attr_is_mac_media (dep_insn))
08555 cost = 1;
08556
08557 else if (! reload_completed
08558 && GET_CODE (PATTERN (insn)) == SET
08559 && GET_CODE (SET_SRC (PATTERN (insn))) == FLOAT
08560 && GET_CODE (PATTERN (dep_insn)) == SET
08561 && fp_arith_reg_operand (SET_SRC (PATTERN (dep_insn)), VOIDmode)
08562 && cost < 4)
08563 cost = 4;
08564
08565
08566 else if (get_attr_type (insn) == TYPE_JUMP_MEDIA
08567 && ! flow_dependent_p (insn, dep_insn))
08568 cost--;
08569 }
08570 else if (REG_NOTE_KIND (link) == 0)
08571 {
08572 enum attr_type dep_type, type;
08573
08574 if (recog_memoized (insn) < 0
08575 || recog_memoized (dep_insn) < 0)
08576 return cost;
08577
08578 dep_type = get_attr_type (dep_insn);
08579 if (dep_type == TYPE_FLOAD || dep_type == TYPE_PCFLOAD)
08580 cost--;
08581 if ((dep_type == TYPE_LOAD_SI || dep_type == TYPE_PCLOAD_SI)
08582 && (type = get_attr_type (insn)) != TYPE_CALL
08583 && type != TYPE_SFUNC)
08584 cost--;
08585
08586
08587
08588 if (GET_CODE(insn) == CALL_INSN)
08589 {
08590 rtx call = PATTERN (insn);
08591
08592 if (GET_CODE (call) == PARALLEL)
08593 call = XVECEXP (call, 0 ,0);
08594 if (GET_CODE (call) == SET)
08595 call = SET_SRC (call);
08596 if (GET_CODE (call) == CALL && GET_CODE (XEXP (call, 0)) == MEM
08597
08598 && (GET_CODE (XEXP (XEXP (call, 0), 0)) == UNSPEC
08599 || ! reg_set_p (XEXP (XEXP (call, 0), 0), dep_insn)))
08600 cost = 0;
08601 }
08602
08603
08604
08605
08606
08607
08608 else if (GET_CODE (PATTERN (insn)) == PARALLEL
08609 && XVECLEN (PATTERN (insn), 0) >= 4
08610 && (reg = sfunc_uses_reg (insn)))
08611 {
08612 if (! reg_set_p (reg, dep_insn))
08613 cost -= 4;
08614 }
08615
08616
08617
08618 else if (TARGET_SH4
08619 && get_attr_type (insn) == TYPE_DYN_SHIFT
08620 && get_attr_any_int_load (dep_insn) == ANY_INT_LOAD_YES
08621 && reg_overlap_mentioned_p (SET_DEST (PATTERN (dep_insn)),
08622 XEXP (SET_SRC (single_set (insn)),
08623 1)))
08624 cost++;
08625
08626
08627
08628
08629 else if (cost < 3
08630 && get_attr_insn_class (dep_insn) == INSN_CLASS_LS_GROUP
08631 && get_attr_dfp_comp (insn) == DFP_COMP_YES)
08632 cost = 3;
08633
08634
08635 else if (reload_completed
08636 && get_attr_dfp_comp (dep_insn) == DFP_COMP_YES
08637 && (use_pat = single_set (insn))
08638 && ! regno_use_in (REGNO (SET_DEST (single_set (dep_insn))),
08639 SET_SRC (use_pat)))
08640 cost -= 1;
08641
08642 if (get_attr_any_fp_comp (dep_insn) == ANY_FP_COMP_YES
08643 && get_attr_late_fp_use (insn) == LATE_FP_USE_YES)
08644 cost -= 1;
08645 }
08646
08647
08648 else if (REG_NOTE_KIND (link) == REG_DEP_ANTI
08649 && recog_memoized (dep_insn) >= 0
08650 && get_attr_type (dep_insn) == TYPE_DFP_ARITH
08651
08652
08653 && flow_dependent_p (dep_insn, insn))
08654 cost = 2;
08655
08656
08657 return cost;
08658 }
08659
08660
08661
08662 static int
08663 flow_dependent_p (rtx insn, rtx dep_insn)
08664 {
08665 rtx tmp = PATTERN (insn);
08666
08667 note_stores (PATTERN (dep_insn), flow_dependent_p_1, &tmp);
08668 return tmp == NULL_RTX;
08669 }
08670
08671
08672 static void
08673 flow_dependent_p_1 (rtx x, rtx pat ATTRIBUTE_UNUSED, void *data)
08674 {
08675 rtx * pinsn = (rtx *) data;
08676
08677 if (*pinsn && reg_referenced_p (x, *pinsn))
08678 *pinsn = NULL_RTX;
08679 }
08680
08681
08682
08683
08684
08685 static int
08686 sh_pr_n_sets (void)
08687 {
08688 return REG_N_SETS (TARGET_SHMEDIA ? PR_MEDIA_REG : PR_REG);
08689 }
08690
08691
08692
08693 static rtx
08694 sh_allocate_initial_value (rtx hard_reg)
08695 {
08696 rtx x;
08697
08698 if (REGNO (hard_reg) == (TARGET_SHMEDIA ? PR_MEDIA_REG : PR_REG))
08699 {
08700 if (current_function_is_leaf
08701 && ! sh_pr_n_sets ()
08702 && ! (TARGET_SHCOMPACT
08703 && ((current_function_args_info.call_cookie
08704 & ~ CALL_COOKIE_RET_TRAMP (1))
08705 || current_function_has_nonlocal_label)))
08706 x = hard_reg;
08707 else
08708 x = gen_frame_mem (Pmode, return_address_pointer_rtx);
08709 }
08710 else
08711 x = NULL_RTX;
08712
08713 return x;
08714 }
08715
08716
08717
08718 static int
08719 sh_issue_rate (void)
08720 {
08721 if (TARGET_SUPERSCALAR)
08722 return 2;
08723 else
08724 return 1;
08725 }
08726
08727
08728
08729
08730 static short
08731 find_set_regmode_weight (rtx x, enum machine_mode mode)
08732 {
08733 if (GET_CODE (x) == CLOBBER && register_operand (SET_DEST (x), mode))
08734 return 1;
08735 if (GET_CODE (x) == SET && register_operand (SET_DEST (x), mode))
08736 {
08737 if (GET_CODE (SET_DEST (x)) == REG)
08738 {
08739 if (!reg_mentioned_p (SET_DEST (x), SET_SRC (x)))
08740 return 1;
08741 else
08742 return 0;
08743 }
08744 return 1;
08745 }
08746 return 0;
08747 }
08748
08749
08750 static short
08751 find_insn_regmode_weight (rtx insn, enum machine_mode mode)
08752 {
08753 short reg_weight = 0;
08754 rtx x;
08755
08756
08757 x = PATTERN (insn);
08758 reg_weight += find_set_regmode_weight (x, mode);
08759 if (GET_CODE (x) == PARALLEL)
08760 {
08761 int j;
08762 for (j = XVECLEN (x, 0) - 1; j >= 0; j--)
08763 {
08764 x = XVECEXP (PATTERN (insn), 0, j);
08765 reg_weight += find_set_regmode_weight (x, mode);
08766 }
08767 }
08768
08769 for (x = REG_NOTES (insn); x; x = XEXP (x, 1))
08770 {
08771 if (REG_NOTE_KIND (x) == REG_DEAD || REG_NOTE_KIND (x) == REG_UNUSED)
08772 {
08773 rtx note = XEXP (x, 0);
08774 if (GET_CODE (note) == REG && GET_MODE (note) == mode)
08775 reg_weight--;
08776 }
08777 }
08778 return reg_weight;
08779 }
08780
08781
08782 static void
08783 find_regmode_weight (basic_block b, enum machine_mode mode)
08784 {
08785 rtx insn, next_tail, head, tail;
08786
08787 get_ebb_head_tail (b, b, &head, &tail);
08788 next_tail = NEXT_INSN (tail);
08789
08790 for (insn = head; insn != next_tail; insn = NEXT_INSN (insn))
08791 {
08792
08793 if (!INSN_P (insn))
08794 continue;
08795
08796 if (mode == SFmode)
08797 INSN_REGMODE_WEIGHT (insn, mode) =
08798 find_insn_regmode_weight (insn, mode) + 2 * find_insn_regmode_weight (insn, DFmode);
08799 else if (mode == SImode)
08800 INSN_REGMODE_WEIGHT (insn, mode) =
08801 find_insn_regmode_weight (insn, mode) + 2 * find_insn_regmode_weight (insn, DImode);
08802 }
08803 }
08804
08805
08806 static int
08807 rank_for_reorder (const void *x, const void *y)
08808 {
08809 rtx tmp = *(const rtx *) y;
08810 rtx tmp2 = *(const rtx *) x;
08811
08812
08813 if (SCHED_GROUP_P (tmp) != SCHED_GROUP_P (tmp2))
08814 return SCHED_GROUP_P (tmp2) ? 1 : -1;
08815
08816
08817
08818
08819 return INSN_LUID (tmp) - INSN_LUID (tmp2);
08820 }
08821
08822
08823 static void
08824 swap_reorder (rtx *a, int n)
08825 {
08826 rtx insn = a[n - 1];
08827 int i = n - 2;
08828
08829 while (i >= 0 && rank_for_reorder (a + i, &insn) >= 0)
08830 {
08831 a[i + 1] = a[i];
08832 i -= 1;
08833 }
08834 a[i + 1] = insn;
08835 }
08836
08837 #define SCHED_REORDER(READY, N_READY) \
08838 do \
08839 { \
08840 if ((N_READY) == 2) \
08841 swap_reorder (READY, N_READY); \
08842 else if ((N_READY) > 2) \
08843 qsort (READY, N_READY, sizeof (rtx), rank_for_reorder); \
08844 } \
08845 while (0)
08846
08847
08848
08849 static void
08850 ready_reorder (rtx *ready, int nready)
08851 {
08852 SCHED_REORDER (ready, nready);
08853 }
08854
08855
08856 static void
08857 sh_md_init_global (FILE *dump ATTRIBUTE_UNUSED,
08858 int verbose ATTRIBUTE_UNUSED,
08859 int old_max_uid)
08860 {
08861 basic_block b;
08862
08863 regmode_weight[0] = (short *) xcalloc (old_max_uid, sizeof (short));
08864 regmode_weight[1] = (short *) xcalloc (old_max_uid, sizeof (short));
08865
08866 FOR_EACH_BB_REVERSE (b)
08867 {
08868 find_regmode_weight (b, SImode);
08869 find_regmode_weight (b, SFmode);
08870 }
08871
08872 CURR_REGMODE_PRESSURE (SImode) = 0;
08873 CURR_REGMODE_PRESSURE (SFmode) = 0;
08874
08875 }
08876
08877
08878 static void
08879 sh_md_finish_global (FILE *dump ATTRIBUTE_UNUSED,
08880 int verbose ATTRIBUTE_UNUSED)
08881 {
08882 if (regmode_weight[0])
08883 {
08884 free (regmode_weight[0]);
08885 regmode_weight[0] = NULL;
08886 }
08887 if (regmode_weight[1])
08888 {
08889 free (regmode_weight[1]);
08890 regmode_weight[1] = NULL;
08891 }
08892 }
08893
08894
08895
08896 static int
08897 sh_variable_issue (FILE *dump ATTRIBUTE_UNUSED,
08898 int sched_verbose ATTRIBUTE_UNUSED,
08899 rtx insn,
08900 int can_issue_more)
08901 {
08902 if (GET_CODE (PATTERN (insn)) != USE
08903 && GET_CODE (PATTERN (insn)) != CLOBBER)
08904 cached_can_issue_more = can_issue_more - 1;
08905 else
08906 cached_can_issue_more = can_issue_more;
08907
08908 if (reload_completed)
08909 return cached_can_issue_more;
08910
08911 CURR_REGMODE_PRESSURE (SImode) += INSN_REGMODE_WEIGHT (insn, SImode);
08912 CURR_REGMODE_PRESSURE (SFmode) += INSN_REGMODE_WEIGHT (insn, SFmode);
08913
08914 return cached_can_issue_more;
08915 }
08916
08917 static void
08918 sh_md_init (FILE *dump ATTRIBUTE_UNUSED,
08919 int verbose ATTRIBUTE_UNUSED,
08920 int veclen ATTRIBUTE_UNUSED)
08921 {
08922 CURR_REGMODE_PRESSURE (SImode) = 0;
08923 CURR_REGMODE_PRESSURE (SFmode) = 0;
08924 }
08925
08926
08927
08928
08929 #define R0_MAX_LIFE_REGIONS 2
08930 #define R0_MAX_LIVE_LENGTH 12
08931
08932 #define SIMODE_MAX_WEIGHT 5
08933 #define SFMODE_MAX_WEIGHT 10
08934
08935
08936 static short
08937 high_pressure (enum machine_mode mode)
08938 {
08939
08940
08941 if ((REG_N_SETS (0) - REG_N_DEATHS (0)) >= R0_MAX_LIFE_REGIONS
08942 && REG_LIVE_LENGTH (0) >= R0_MAX_LIVE_LENGTH)
08943 return 1;
08944
08945 if (mode == SFmode)
08946 return (CURR_REGMODE_PRESSURE (SFmode) > SFMODE_MAX_WEIGHT);
08947 else
08948 return (CURR_REGMODE_PRESSURE (SImode) > SIMODE_MAX_WEIGHT);
08949 }
08950
08951
08952 static int
08953 sh_reorder (FILE *dump ATTRIBUTE_UNUSED,
08954 int sched_verbose ATTRIBUTE_UNUSED,
08955 rtx *ready,
08956 int *n_readyp,
08957 int clock_var ATTRIBUTE_UNUSED)
08958 {
08959 if (reload_completed)
08960 return sh_issue_rate ();
08961
08962 if (high_pressure (SFmode) || high_pressure (SImode))
08963 {
08964 ready_reorder (ready, *n_readyp);
08965 }
08966
08967 return sh_issue_rate ();
08968 }
08969
08970
08971 static int
08972 sh_reorder2 (FILE *dump ATTRIBUTE_UNUSED,
08973 int sched_verbose ATTRIBUTE_UNUSED,
08974 rtx *ready ATTRIBUTE_UNUSED,
08975 int *n_readyp ATTRIBUTE_UNUSED,
08976 int clock_var ATTRIBUTE_UNUSED)
08977 {
08978 if (reload_completed)
08979 return cached_can_issue_more;
08980
08981 if (high_pressure(SFmode) || high_pressure (SImode))
08982 skip_cycles = 1;
08983
08984 return cached_can_issue_more;
08985 }
08986
08987
08988
08989
08990
08991
08992
08993 #define MAX_SKIPS 8
08994
08995 static int
08996 sh_dfa_new_cycle (FILE *sched_dump ATTRIBUTE_UNUSED,
08997 int sched_verbose ATTRIBUTE_UNUSED,
08998 rtx insn ATTRIBUTE_UNUSED,
08999 int last_clock_var,
09000 int clock_var,
09001 int *sort_p)
09002 {
09003 if (reload_completed)
09004 return 0;
09005
09006 if (skip_cycles)
09007 {
09008 if ((clock_var - last_clock_var) < MAX_SKIPS)
09009 {
09010 *sort_p = 0;
09011 return 1;
09012 }
09013
09014 if ((clock_var - last_clock_var) == MAX_SKIPS)
09015 {
09016 *sort_p = 1;
09017 return 1;
09018 }
09019 }
09020
09021 skip_cycles = 0;
09022
09023 return 0;
09024 }
09025
09026
09027
09028 static bool
09029 sh_cannot_modify_jumps_p (void)
09030 {
09031 return (TARGET_SHMEDIA && (reload_in_progress || reload_completed));
09032 }
09033
09034 static int
09035 sh_target_reg_class (void)
09036 {
09037 return TARGET_SHMEDIA ? TARGET_REGS : NO_REGS;
09038 }
09039
09040 static bool
09041 sh_optimize_target_register_callee_saved (bool after_prologue_epilogue_gen)
09042 {
09043 HARD_REG_SET dummy;
09044 rtx insn;
09045
09046 if (! shmedia_space_reserved_for_target_registers)
09047 return 0;
09048 if (after_prologue_epilogue_gen && ! TARGET_SAVE_ALL_TARGET_REGS)
09049 return 0;
09050 if (calc_live_regs (&dummy) >= 6 * 8)
09051 return 1;
09052
09053
09054 for (insn = get_insns(); insn; insn = NEXT_INSN (insn))
09055 {
09056 if (GET_CODE (insn) == NOTE
09057 && NOTE_LINE_NUMBER (insn) == NOTE_INSN_LOOP_BEG)
09058 {
09059 int labels = 0;
09060
09061 do
09062 {
09063 insn = NEXT_INSN (insn);
09064 if ((GET_CODE (insn) == NOTE
09065 && NOTE_LINE_NUMBER (insn) == NOTE_INSN_LOOP_BEG)
09066 || GET_CODE (insn) == CALL_INSN
09067 || (GET_CODE (insn) == CODE_LABEL && ++labels > 4))
09068 return 1;
09069 }
09070 while (GET_CODE (insn) != NOTE
09071 || NOTE_LINE_NUMBER (insn) != NOTE_INSN_LOOP_END);
09072 }
09073 }
09074 return 0;
09075 }
09076
09077 static bool
09078 sh_ms_bitfield_layout_p (tree record_type ATTRIBUTE_UNUSED)
09079 {
09080 return (TARGET_SH5 || TARGET_HITACHI || sh_attr_renesas_p (record_type));
09081 }
09082
09083
09084
09085
09086
09087
09088
09089
09090
09091
09092
09093
09094
09095
09096
09097
09098
09099 void
09100 sh_initialize_trampoline (rtx tramp, rtx fnaddr, rtx cxt)
09101 {
09102 rtx tramp_mem = gen_frame_mem (BLKmode, tramp);
09103
09104 if (TARGET_SHMEDIA64)
09105 {
09106 rtx tramp_templ;
09107 int fixed_len;
09108
09109 rtx movi1 = GEN_INT (0xcc000010);
09110 rtx shori1 = GEN_INT (0xc8000010);
09111 rtx src, dst;
09112
09113
09114
09115
09116
09117
09118
09119
09120 if (cxt == virtual_stack_vars_rtx && frame_offset < 0x20000)
09121 {
09122
09123
09124 rtx mask = force_reg (DImode, GEN_INT (0x3fffc00));
09125 rtx insn = gen_rtx_MINUS (DImode, cxt, tramp);
09126 insn = gen_rtx_ASHIFT (DImode, insn, GEN_INT (10-2));
09127 insn = gen_rtx_AND (DImode, insn, mask);
09128
09129 insn = gen_rtx_IOR (DImode, insn, gen_int_mode (0xec000010, SImode));
09130 insn = force_operand (insn, NULL_RTX);
09131 insn = gen_lowpart (SImode, insn);
09132 emit_move_insn (change_address (tramp_mem, SImode, NULL_RTX), insn);
09133 insn = gen_rtx_LSHIFTRT (DImode, fnaddr, GEN_INT (38));
09134 insn = gen_rtx_AND (DImode, insn, mask);
09135 insn = force_operand (gen_rtx_IOR (DImode, movi1, insn), NULL_RTX);
09136 insn = gen_lowpart (SImode, insn);
09137 emit_move_insn (adjust_address (tramp_mem, SImode, 4), insn);
09138 insn = gen_rtx_LSHIFTRT (DImode, fnaddr, GEN_INT (22));
09139 insn = gen_rtx_AND (DImode, insn, mask);
09140 insn = force_operand (gen_rtx_IOR (DImode, shori1, insn), NULL_RTX);
09141 insn = gen_lowpart (SImode, insn);
09142 emit_move_insn (adjust_address (tramp_mem, SImode, 8), insn);
09143 insn = gen_rtx_LSHIFTRT (DImode, fnaddr, GEN_INT (6));
09144 insn = gen_rtx_AND (DImode, insn, mask);
09145 insn = force_operand (gen_rtx_IOR (DImode, shori1, insn), NULL_RTX);
09146 insn = gen_lowpart (SImode, insn);
09147 emit_move_insn (adjust_address (tramp_mem, SImode, 12), insn);
09148 insn = gen_rtx_ASHIFT (DImode, fnaddr, GEN_INT (10));
09149 insn = gen_rtx_AND (DImode, insn, mask);
09150 insn = force_operand (gen_rtx_IOR (DImode, shori1, insn), NULL_RTX);
09151 insn = gen_lowpart (SImode, insn);
09152 emit_move_insn (adjust_address (tramp_mem, SImode, 16), insn);
09153 emit_move_insn (adjust_address (tramp_mem, SImode, 20),
09154 GEN_INT (0x6bf10600));
09155 emit_move_insn (adjust_address (tramp_mem, SImode, 24),
09156 GEN_INT (0x4415fc10));
09157 emit_move_insn (adjust_address (tramp_mem, SImode, 28),
09158 GEN_INT (0x4401fff0));
09159 emit_insn (gen_ic_invalidate_line (tramp));
09160 return;
09161 }
09162 tramp_templ = gen_rtx_SYMBOL_REF (Pmode,"__GCC_nested_trampoline");
09163 fixed_len = TRAMPOLINE_SIZE - 2 * GET_MODE_SIZE (Pmode);
09164
09165 tramp_templ = gen_datalabel_ref (tramp_templ);
09166 dst = tramp_mem;
09167 src = gen_const_mem (BLKmode, tramp_templ);
09168 set_mem_align (dst, 256);
09169 set_mem_align (src, 64);
09170 emit_block_move (dst, src, GEN_INT (fixed_len), BLOCK_OP_NORMAL);
09171
09172 emit_move_insn (adjust_address (tramp_mem, Pmode, fixed_len), fnaddr);
09173 emit_move_insn (adjust_address (tramp_mem, Pmode,
09174 fixed_len + GET_MODE_SIZE (Pmode)),
09175 cxt);
09176 emit_insn (gen_ic_invalidate_line (tramp));
09177 return;
09178 }
09179 else if (TARGET_SHMEDIA)
09180 {
09181
09182
09183 rtx quad0 = gen_reg_rtx (DImode), cxtload = gen_reg_rtx (DImode);
09184 rtx quad1 = gen_reg_rtx (DImode), quad2 = gen_reg_rtx (DImode);
09185
09186
09187 rtx movishori
09188 = force_reg (V2HImode, (simplify_gen_subreg
09189 (V2HImode, GEN_INT (0x4330432), SImode, 0)));
09190 rtx ptabs = force_reg (DImode, GEN_INT (0x6bf10600));
09191 rtx blink = force_reg (DImode, GEN_INT (0x4401fff0));
09192
09193 tramp = force_reg (Pmode, tramp);
09194 fnaddr = force_reg (SImode, fnaddr);
09195 cxt = force_reg (SImode, cxt);
09196 emit_insn (gen_mshflo_w_x (gen_rtx_SUBREG (V4HImode, quad0, 0),
09197 gen_rtx_SUBREG (V2HImode, fnaddr, 0),
09198 movishori));
09199 emit_insn (gen_rotrdi3_mextr (quad0, quad0,
09200 GEN_INT (TARGET_LITTLE_ENDIAN ? 24 : 56)));
09201 emit_insn (gen_ashldi3_media (quad0, quad0, const2_rtx));
09202 emit_move_insn (change_address (tramp_mem, DImode, NULL_RTX), quad0);
09203 emit_insn (gen_mshflo_w_x (gen_rtx_SUBREG (V4HImode, cxtload, 0),
09204 gen_rtx_SUBREG (V2HImode, cxt, 0),
09205 movishori));
09206 emit_insn (gen_rotrdi3_mextr (cxtload, cxtload,
09207 GEN_INT (TARGET_LITTLE_ENDIAN ? 24 : 56)));
09208 emit_insn (gen_ashldi3_media (cxtload, cxtload, const2_rtx));
09209 if (TARGET_LITTLE_ENDIAN)
09210 {
09211 emit_insn (gen_mshflo_l_di (quad1, ptabs, cxtload));
09212 emit_insn (gen_mextr4 (quad2, cxtload, blink));
09213 }
09214 else
09215 {
09216 emit_insn (gen_mextr4 (quad1, cxtload, ptabs));
09217 emit_insn (gen_mshflo_l_di (quad2, blink, cxtload));
09218 }
09219 emit_move_insn (adjust_address (tramp_mem, DImode, 8), quad1);
09220 emit_move_insn (adjust_address (tramp_mem, DImode, 16), quad2);
09221 emit_insn (gen_ic_invalidate_line (tramp));
09222 return;
09223 }
09224 else if (TARGET_SHCOMPACT)
09225 {
09226 emit_insn (gen_initialize_trampoline (tramp, cxt, fnaddr));
09227 return;
09228 }
09229 emit_move_insn (change_address (tramp_mem, SImode, NULL_RTX),
09230 gen_int_mode (TARGET_LITTLE_ENDIAN ? 0xd301d202 : 0xd202d301,
09231 SImode));
09232 emit_move_insn (adjust_address (tramp_mem, SImode, 4),
09233 gen_int_mode (TARGET_LITTLE_ENDIAN ? 0x0009422b : 0x422b0009,
09234 SImode));
09235 emit_move_insn (adjust_address (tramp_mem, SImode, 8), cxt);
09236 emit_move_insn (adjust_address (tramp_mem, SImode, 12), fnaddr);
09237 if (TARGET_HARVARD)
09238 {
09239 if (TARGET_USERMODE)
09240 emit_library_call (function_symbol (NULL, "__ic_invalidate",
09241 FUNCTION_ORDINARY),
09242 0, VOIDmode, 1, tramp, SImode);
09243 else
09244 emit_insn (gen_ic_invalidate_line (tramp));
09245 }
09246 }
09247
09248
09249
09250
09251
09252
09253
09254 static bool
09255 sh_function_ok_for_sibcall (tree decl, tree exp ATTRIBUTE_UNUSED)
09256 {
09257 return (1
09258 && (! TARGET_SHCOMPACT
09259 || current_function_args_info.stack_regs == 0)
09260 && ! sh_cfun_interrupt_handler_p ()
09261 && (! flag_pic
09262 || (decl && ! TREE_PUBLIC (decl))
09263 || (decl && DECL_VISIBILITY (decl) != VISIBILITY_DEFAULT)));
09264 }
09265
09266
09267
09268 struct builtin_description
09269 {
09270 const enum insn_code icode;
09271 const char *const name;
09272 int signature;
09273 };
09274
09275
09276
09277
09278 static const char signature_args[][4] =
09279 {
09280 #define SH_BLTIN_V2SI2 0
09281 { 4, 4 },
09282 #define SH_BLTIN_V4HI2 1
09283 { 4, 4 },
09284 #define SH_BLTIN_V2SI3 2
09285 { 4, 4, 4 },
09286 #define SH_BLTIN_V4HI3 3
09287 { 4, 4, 4 },
09288 #define SH_BLTIN_V8QI3 4
09289 { 4, 4, 4 },
09290 #define SH_BLTIN_MAC_HISI 5
09291 { 1, 4, 4, 1 },
09292 #define SH_BLTIN_SH_HI 6
09293 { 4, 4, 1 },
09294 #define SH_BLTIN_SH_SI 7
09295 { 4, 4, 1 },
09296 #define SH_BLTIN_V4HI2V2SI 8
09297 { 4, 4, 4 },
09298 #define SH_BLTIN_V4HI2V8QI 9
09299 { 4, 4, 4 },
09300 #define SH_BLTIN_SISF 10
09301 { 4, 2 },
09302 #define SH_BLTIN_LDUA_L 11
09303 { 2, 10 },
09304 #define SH_BLTIN_LDUA_Q 12
09305 { 1, 10 },
09306 #define SH_BLTIN_STUA_L 13
09307 { 0, 10, 2 },
09308 #define SH_BLTIN_STUA_Q 14
09309 { 0, 10, 1 },
09310 #define SH_BLTIN_LDUA_L64 15
09311 { 2, 9 },
09312 #define SH_BLTIN_LDUA_Q64 16
09313 { 1, 9 },
09314 #define SH_BLTIN_STUA_L64 17
09315 { 0, 9, 2 },
09316 #define SH_BLTIN_STUA_Q64 18
09317 { 0, 9, 1 },
09318 #define SH_BLTIN_NUM_SHARED_SIGNATURES 19
09319 #define SH_BLTIN_2 19
09320 #define SH_BLTIN_SU 19
09321 { 1, 2 },
09322 #define SH_BLTIN_3 20
09323 #define SH_BLTIN_SUS 20
09324 { 2, 2, 1 },
09325 #define SH_BLTIN_PSSV 21
09326 { 0, 8, 2, 2 },
09327 #define SH_BLTIN_XXUU 22
09328 #define SH_BLTIN_UUUU 22
09329 { 1, 1, 1, 1 },
09330 #define SH_BLTIN_PV 23
09331 { 0, 8 },
09332 };
09333
09334
09335
09336
09337
09338
09339 static const struct builtin_description bdesc[] =
09340 {
09341 { CODE_FOR_absv2si2, "__builtin_absv2si2", SH_BLTIN_V2SI2 },
09342 { CODE_FOR_absv4hi2, "__builtin_absv4hi2", SH_BLTIN_V4HI2 },
09343 { CODE_FOR_addv2si3, "__builtin_addv2si3", SH_BLTIN_V2SI3 },
09344 { CODE_FOR_addv4hi3, "__builtin_addv4hi3", SH_BLTIN_V4HI3 },
09345 { CODE_FOR_ssaddv2si3,"__builtin_ssaddv2si3", SH_BLTIN_V2SI3 },
09346 { CODE_FOR_usaddv8qi3,"__builtin_usaddv8qi3", SH_BLTIN_V8QI3 },
09347 { CODE_FOR_ssaddv4hi3,"__builtin_ssaddv4hi3", SH_BLTIN_V4HI3 },
09348 { CODE_FOR_alloco_i, "__builtin_sh_media_ALLOCO", SH_BLTIN_PV },
09349 { CODE_FOR_negcmpeqv8qi,"__builtin_sh_media_MCMPEQ_B", SH_BLTIN_V8QI3 },
09350 { CODE_FOR_negcmpeqv2si,"__builtin_sh_media_MCMPEQ_L", SH_BLTIN_V2SI3 },
09351 { CODE_FOR_negcmpeqv4hi,"__builtin_sh_media_MCMPEQ_W", SH_BLTIN_V4HI3 },
09352 { CODE_FOR_negcmpgtuv8qi,"__builtin_sh_media_MCMPGT_UB", SH_BLTIN_V8QI3 },
09353 { CODE_FOR_negcmpgtv2si,"__builtin_sh_media_MCMPGT_L", SH_BLTIN_V2SI3 },
09354 { CODE_FOR_negcmpgtv4hi,"__builtin_sh_media_MCMPGT_W", SH_BLTIN_V4HI3 },
09355 { CODE_FOR_mcmv, "__builtin_sh_media_MCMV", SH_BLTIN_UUUU },
09356 { CODE_FOR_mcnvs_lw, "__builtin_sh_media_MCNVS_LW", SH_BLTIN_3 },
09357 { CODE_FOR_mcnvs_wb, "__builtin_sh_media_MCNVS_WB", SH_BLTIN_V4HI2V8QI },
09358 { CODE_FOR_mcnvs_wub, "__builtin_sh_media_MCNVS_WUB", SH_BLTIN_V4HI2V8QI },
09359 { CODE_FOR_mextr1, "__builtin_sh_media_MEXTR1", SH_BLTIN_V8QI3 },
09360 { CODE_FOR_mextr2, "__builtin_sh_media_MEXTR2", SH_BLTIN_V8QI3 },
09361 { CODE_FOR_mextr3, "__builtin_sh_media_MEXTR3", SH_BLTIN_V8QI3 },
09362 { CODE_FOR_mextr4, "__builtin_sh_media_MEXTR4", SH_BLTIN_V8QI3 },
09363 { CODE_FOR_mextr5, "__builtin_sh_media_MEXTR5", SH_BLTIN_V8QI3 },
09364 { CODE_FOR_mextr6, "__builtin_sh_media_MEXTR6", SH_BLTIN_V8QI3 },
09365 { CODE_FOR_mextr7, "__builtin_sh_media_MEXTR7", SH_BLTIN_V8QI3 },
09366 { CODE_FOR_mmacfx_wl, "__builtin_sh_media_MMACFX_WL", SH_BLTIN_MAC_HISI },
09367 { CODE_FOR_mmacnfx_wl,"__builtin_sh_media_MMACNFX_WL", SH_BLTIN_MAC_HISI },
09368 { CODE_FOR_mulv2si3, "__builtin_mulv2si3", SH_BLTIN_V2SI3, },
09369 { CODE_FOR_mulv4hi3, "__builtin_mulv4hi3", SH_BLTIN_V4HI3 },
09370 { CODE_FOR_mmulfx_l, "__builtin_sh_media_MMULFX_L", SH_BLTIN_V2SI3 },
09371 { CODE_FOR_mmulfx_w, "__builtin_sh_media_MMULFX_W", SH_BLTIN_V4HI3 },
09372 { CODE_FOR_mmulfxrp_w,"__builtin_sh_media_MMULFXRP_W", SH_BLTIN_V4HI3 },
09373 { CODE_FOR_mmulhi_wl, "__builtin_sh_media_MMULHI_WL", SH_BLTIN_V4HI2V2SI },
09374 { CODE_FOR_mmullo_wl, "__builtin_sh_media_MMULLO_WL", SH_BLTIN_V4HI2V2SI },
09375 { CODE_FOR_mmulsum_wq,"__builtin_sh_media_MMULSUM_WQ", SH_BLTIN_XXUU },
09376 { CODE_FOR_mperm_w, "__builtin_sh_media_MPERM_W", SH_BLTIN_SH_HI },
09377 { CODE_FOR_msad_ubq, "__builtin_sh_media_MSAD_UBQ", SH_BLTIN_XXUU },
09378 { CODE_FOR_mshalds_l, "__builtin_sh_media_MSHALDS_L", SH_BLTIN_SH_SI },
09379 { CODE_FOR_mshalds_w, "__builtin_sh_media_MSHALDS_W", SH_BLTIN_SH_HI },
09380 { CODE_FOR_ashrv2si3, "__builtin_ashrv2si3", SH_BLTIN_SH_SI },
09381 { CODE_FOR_ashrv4hi3, "__builtin_ashrv4hi3", SH_BLTIN_SH_HI },
09382 { CODE_FOR_mshards_q, "__builtin_sh_media_MSHARDS_Q", SH_BLTIN_SUS },
09383 { CODE_FOR_mshfhi_b, "__builtin_sh_media_MSHFHI_B", SH_BLTIN_V8QI3 },
09384 { CODE_FOR_mshfhi_l, "__builtin_sh_media_MSHFHI_L", SH_BLTIN_V2SI3 },
09385 { CODE_FOR_mshfhi_w, "__builtin_sh_media_MSHFHI_W", SH_BLTIN_V4HI3 },
09386 { CODE_FOR_mshflo_b, "__builtin_sh_media_MSHFLO_B", SH_BLTIN_V8QI3 },
09387 { CODE_FOR_mshflo_l, "__builtin_sh_media_MSHFLO_L", SH_BLTIN_V2SI3 },
09388 { CODE_FOR_mshflo_w, "__builtin_sh_media_MSHFLO_W", SH_BLTIN_V4HI3 },
09389 { CODE_FOR_ashlv2si3, "__builtin_ashlv2si3", SH_BLTIN_SH_SI },
09390 { CODE_FOR_ashlv4hi3, "__builtin_ashlv4hi3", SH_BLTIN_SH_HI },
09391 { CODE_FOR_lshrv2si3, "__builtin_lshrv2si3", SH_BLTIN_SH_SI },
09392 { CODE_FOR_lshrv4hi3, "__builtin_lshrv4hi3", SH_BLTIN_SH_HI },
09393 { CODE_FOR_subv2si3, "__builtin_subv2si3", SH_BLTIN_V2SI3 },
09394 { CODE_FOR_subv4hi3, "__builtin_subv4hi3", SH_BLTIN_V4HI3 },
09395 { CODE_FOR_sssubv2si3,"__builtin_sssubv2si3", SH_BLTIN_V2SI3 },
09396 { CODE_FOR_ussubv8qi3,"__builtin_ussubv8qi3", SH_BLTIN_V8QI3 },
09397 { CODE_FOR_sssubv4hi3,"__builtin_sssubv4hi3", SH_BLTIN_V4HI3 },
09398 { CODE_FOR_fcosa_s, "__builtin_sh_media_FCOSA_S", SH_BLTIN_SISF },
09399 { CODE_FOR_fsina_s, "__builtin_sh_media_FSINA_S", SH_BLTIN_SISF },
09400 { CODE_FOR_fipr, "__builtin_sh_media_FIPR_S", SH_BLTIN_3 },
09401 { CODE_FOR_ftrv, "__builtin_sh_media_FTRV_S", SH_BLTIN_3 },
09402 { CODE_FOR_mac_media, "__builtin_sh_media_FMAC_S", SH_BLTIN_3 },
09403 { CODE_FOR_sqrtdf2, "__builtin_sh_media_FSQRT_D", SH_BLTIN_2 },
09404 { CODE_FOR_sqrtsf2, "__builtin_sh_media_FSQRT_S", SH_BLTIN_2 },
09405 { CODE_FOR_fsrra_s, "__builtin_sh_media_FSRRA_S", SH_BLTIN_2 },
09406 { CODE_FOR_ldhi_l, "__builtin_sh_media_LDHI_L", SH_BLTIN_LDUA_L },
09407 { CODE_FOR_ldhi_q, "__builtin_sh_media_LDHI_Q", SH_BLTIN_LDUA_Q },
09408 { CODE_FOR_ldlo_l, "__builtin_sh_media_LDLO_L", SH_BLTIN_LDUA_L },
09409 { CODE_FOR_ldlo_q, "__builtin_sh_media_LDLO_Q", SH_BLTIN_LDUA_Q },
09410 { CODE_FOR_sthi_l, "__builtin_sh_media_STHI_L", SH_BLTIN_STUA_L },
09411 { CODE_FOR_sthi_q, "__builtin_sh_media_STHI_Q", SH_BLTIN_STUA_Q },
09412 { CODE_FOR_stlo_l, "__builtin_sh_media_STLO_L", SH_BLTIN_STUA_L },
09413 { CODE_FOR_stlo_q, "__builtin_sh_media_STLO_Q", SH_BLTIN_STUA_Q },
09414 { CODE_FOR_ldhi_l64, "__builtin_sh_media_LDHI_L", SH_BLTIN_LDUA_L64 },
09415 { CODE_FOR_ldhi_q64, "__builtin_sh_media_LDHI_Q", SH_BLTIN_LDUA_Q64 },
09416 { CODE_FOR_ldlo_l64, "__builtin_sh_media_LDLO_L", SH_BLTIN_LDUA_L64 },
09417 { CODE_FOR_ldlo_q64, "__builtin_sh_media_LDLO_Q", SH_BLTIN_LDUA_Q64 },
09418 { CODE_FOR_sthi_l64, "__builtin_sh_media_STHI_L", SH_BLTIN_STUA_L64 },
09419 { CODE_FOR_sthi_q64, "__builtin_sh_media_STHI_Q", SH_BLTIN_STUA_Q64 },
09420 { CODE_FOR_stlo_l64, "__builtin_sh_media_STLO_L", SH_BLTIN_STUA_L64 },
09421 { CODE_FOR_stlo_q64, "__builtin_sh_media_STLO_Q", SH_BLTIN_STUA_Q64 },
09422 { CODE_FOR_nsb, "__builtin_sh_media_NSB", SH_BLTIN_SU },
09423 { CODE_FOR_byterev, "__builtin_sh_media_BYTEREV", SH_BLTIN_2 },
09424 { CODE_FOR_prefetch, "__builtin_sh_media_PREFO", SH_BLTIN_PSSV },
09425 };
09426
09427 static void
09428 sh_media_init_builtins (void)
09429 {
09430 tree shared[SH_BLTIN_NUM_SHARED_SIGNATURES];
09431 const struct builtin_description *d;
09432
09433 memset (shared, 0, sizeof shared);
09434 for (d = bdesc; d - bdesc < (int) ARRAY_SIZE (bdesc); d++)
09435 {
09436 tree type, arg_type = 0;
09437 int signature = d->signature;
09438 int i;
09439
09440 if (signature < SH_BLTIN_NUM_SHARED_SIGNATURES && shared[signature])
09441 type = shared[signature];
09442 else
09443 {
09444 int has_result = signature_args[signature][0] != 0;
09445
09446 if ((signature_args[signature][1] & 8)
09447 && (((signature_args[signature][1] & 1) && TARGET_SHMEDIA32)
09448 || ((signature_args[signature][1] & 2) && TARGET_SHMEDIA64)))
09449 continue;
09450 if (! TARGET_FPU_ANY
09451 && FLOAT_MODE_P (insn_data[d->icode].operand[0].mode))
09452 continue;
09453 type = void_list_node;
09454 for (i = 3; ; i--)
09455 {
09456 int arg = signature_args[signature][i];
09457 int opno = i - 1 + has_result;
09458
09459 if (arg & 8)
09460 arg_type = ptr_type_node;
09461 else if (arg)
09462 arg_type = (*lang_hooks.types.type_for_mode)
09463 (insn_data[d->icode].operand[opno].mode,
09464 (arg & 1));
09465 else if (i)
09466 continue;
09467 else
09468 arg_type = void_type_node;
09469 if (i == 0)
09470 break;
09471 type = tree_cons (NULL_TREE, arg_type, type);
09472 }
09473 type = build_function_type (arg_type, type);
09474 if (signature < SH_BLTIN_NUM_SHARED_SIGNATURES)
09475 shared[signature] = type;
09476 }
09477 lang_hooks.builtin_function (d->name, type, d - bdesc, BUILT_IN_MD,
09478 NULL, NULL_TREE);
09479 }
09480 }
09481
09482
09483 bool
09484 sh_vector_mode_supported_p (enum machine_mode mode)
09485 {
09486 if (TARGET_FPU_ANY
09487 && ((mode == V2SFmode)
09488 || (mode == V4SFmode)
09489 || (mode == V16SFmode)))
09490 return true;
09491
09492 else if (TARGET_SHMEDIA
09493 && ((mode == V8QImode)
09494 || (mode == V2HImode)
09495 || (mode == V4HImode)
09496 || (mode == V2SImode)))
09497 return true;
09498
09499 return false;
09500 }
09501
09502
09503
09504 int
09505 sh_dwarf_calling_convention (tree func)
09506 {
09507 if (sh_attr_renesas_p (func))
09508 return DW_CC_GNU_renesas_sh;
09509
09510 return DW_CC_normal;
09511 }
09512
09513 static void
09514 sh_init_builtins (void)
09515 {
09516 if (TARGET_SHMEDIA)
09517 sh_media_init_builtins ();
09518 }
09519
09520
09521
09522
09523
09524
09525
09526 static rtx
09527 sh_expand_builtin (tree exp, rtx target, rtx subtarget ATTRIBUTE_UNUSED,
09528 enum machine_mode mode ATTRIBUTE_UNUSED, int ignore)
09529 {
09530 tree fndecl = TREE_OPERAND (TREE_OPERAND (exp, 0), 0);
09531 tree arglist = TREE_OPERAND (exp, 1);
09532 unsigned int fcode = DECL_FUNCTION_CODE (fndecl);
09533 const struct builtin_description *d = &bdesc[fcode];
09534 enum insn_code icode = d->icode;
09535 int signature = d->signature;
09536 enum machine_mode tmode = VOIDmode;
09537 int nop = 0, i;
09538 rtx op[4];
09539 rtx pat = 0;
09540
09541 if (signature_args[signature][0])
09542 {
09543 if (ignore)
09544 return 0;
09545
09546 tmode = insn_data[icode].operand[0].mode;
09547 if (! target
09548 || GET_MODE (target) != tmode
09549 || ! (*insn_data[icode].operand[0].predicate) (target, tmode))
09550 target = gen_reg_rtx (tmode);
09551 op[nop++] = target;
09552 }
09553 else
09554 target = 0;
09555
09556 for (i = 1; i <= 3; i++, nop++)
09557 {
09558 tree arg;
09559 enum machine_mode opmode, argmode;
09560 tree optype;
09561
09562 if (! signature_args[signature][i])
09563 break;
09564 arg = TREE_VALUE (arglist);
09565 if (arg == error_mark_node)
09566 return const0_rtx;
09567 arglist = TREE_CHAIN (arglist);
09568 if (signature_args[signature][i] & 8)
09569 {
09570 opmode = ptr_mode;
09571 optype = ptr_type_node;
09572 }
09573 else
09574 {
09575 opmode = insn_data[icode].operand[nop].mode;
09576 optype = (*lang_hooks.types.type_for_mode) (opmode, 0);
09577 }
09578 argmode = TYPE_MODE (TREE_TYPE (arg));
09579 if (argmode != opmode)
09580 arg = build1 (NOP_EXPR, optype, arg);
09581 op[nop] = expand_expr (arg, NULL_RTX, opmode, 0);
09582 if (! (*insn_data[icode].operand[nop].predicate) (op[nop], opmode))
09583 op[nop] = copy_to_mode_reg (opmode, op[nop]);
09584 }
09585
09586 switch (nop)
09587 {
09588 case 1:
09589 pat = (*insn_data[d->icode].genfun) (op[0]);
09590 break;
09591 case 2:
09592 pat = (*insn_data[d->icode].genfun) (op[0], op[1]);
09593 break;
09594 case 3:
09595 pat = (*insn_data[d->icode].genfun) (op[0], op[1], op[2]);
09596 break;
09597 case 4:
09598 pat = (*insn_data[d->icode].genfun) (op[0], op[1], op[2], op[3]);
09599 break;
09600 default:
09601 gcc_unreachable ();
09602 }
09603 if (! pat)
09604 return 0;
09605 emit_insn (pat);
09606 return target;
09607 }
09608
09609 void
09610 sh_expand_unop_v2sf (enum rtx_code code, rtx op0, rtx op1)
09611 {
09612 rtx sel0 = const0_rtx;
09613 rtx sel1 = const1_rtx;
09614 rtx (*fn) (rtx, rtx, rtx, rtx, rtx) = gen_unary_sf_op;
09615 rtx op = gen_rtx_fmt_e (code, SFmode, op1);
09616
09617 emit_insn ((*fn) (op0, op1, op, sel0, sel0));
09618 emit_insn ((*fn) (op0, op1, op, sel1, sel1));
09619 }
09620
09621 void
09622 sh_expand_binop_v2sf (enum rtx_code code, rtx op0, rtx op1, rtx op2)
09623 {
09624 rtx sel0 = const0_rtx;
09625 rtx sel1 = const1_rtx;
09626 rtx (*fn) (rtx, rtx, rtx, rtx, rtx, rtx, rtx, rtx)
09627 = gen_binary_sf_op;
09628 rtx op = gen_rtx_fmt_ee (code, SFmode, op1, op2);
09629
09630 emit_insn ((*fn) (op0, op1, op2, op, sel0, sel0, sel0, sel1));
09631 emit_insn ((*fn) (op0, op1, op2, op, sel1, sel1, sel1, sel0));
09632 }
09633
09634
09635
09636 bool
09637 sh_cannot_change_mode_class (enum machine_mode from, enum machine_mode to,
09638 enum reg_class class)
09639 {
09640
09641
09642 if (to == SFmode && VECTOR_MODE_P (from) && GET_MODE_INNER (from) == SFmode)
09643 return (reg_classes_intersect_p (GENERAL_REGS, class));
09644
09645 if (GET_MODE_SIZE (from) != GET_MODE_SIZE (to))
09646 {
09647 if (TARGET_LITTLE_ENDIAN)
09648 {
09649 if (GET_MODE_SIZE (to) < 8 || GET_MODE_SIZE (from) < 8)
09650 return reg_classes_intersect_p (DF_REGS, class);
09651 }
09652 else
09653 {
09654 if (GET_MODE_SIZE (from) < 8)
09655 return reg_classes_intersect_p (DF_HI_REGS, class);
09656 }
09657 }
09658 return 0;
09659 }
09660
09661
09662
09663
09664
09665 void
09666 sh_mark_label (rtx address, int nuses)
09667 {
09668 if (GOTOFF_P (address))
09669 {
09670
09671 address = XEXP (address, 0);
09672 if (GET_CODE (address) == PLUS)
09673 address = XEXP (address, 0);
09674 address = XVECEXP (address, 0, 0);
09675 }
09676 if (GET_CODE (address) == LABEL_REF
09677 && GET_CODE (XEXP (address, 0)) == CODE_LABEL)
09678 LABEL_NUSES (XEXP (address, 0)) += nuses;
09679 }
09680
09681
09682
09683
09684
09685
09686
09687
09688 int
09689 sh_register_move_cost (enum machine_mode mode,
09690 enum reg_class srcclass, enum reg_class dstclass)
09691 {
09692 if (dstclass == T_REGS || dstclass == PR_REGS)
09693 return 10;
09694
09695 if (dstclass == MAC_REGS && srcclass == MAC_REGS)
09696 return 4;
09697
09698 if (mode == SImode && ! TARGET_SHMEDIA && TARGET_FMOVD
09699 && REGCLASS_HAS_FP_REG (srcclass)
09700 && REGCLASS_HAS_FP_REG (dstclass))
09701 return 4;
09702
09703 if (REGCLASS_HAS_FP_REG (dstclass) && srcclass == T_REGS)
09704 return ((TARGET_HARD_SH4 && !optimize_size) ? 10 : 7);
09705
09706 if ((REGCLASS_HAS_FP_REG (dstclass) && srcclass == MAC_REGS)
09707 || (dstclass == MAC_REGS && REGCLASS_HAS_FP_REG (srcclass)))
09708 return 9;
09709
09710 if ((REGCLASS_HAS_FP_REG (dstclass)
09711 && REGCLASS_HAS_GENERAL_REG (srcclass))
09712 || (REGCLASS_HAS_GENERAL_REG (dstclass)
09713 && REGCLASS_HAS_FP_REG (srcclass)))
09714 return ((TARGET_SHMEDIA ? 4 : TARGET_FMOVD ? 8 : 12)
09715 * ((GET_MODE_SIZE (mode) + 7) / 8U));
09716
09717 if ((dstclass == FPUL_REGS
09718 && REGCLASS_HAS_GENERAL_REG (srcclass))
09719 || (srcclass == FPUL_REGS
09720 && REGCLASS_HAS_GENERAL_REG (dstclass)))
09721 return 5;
09722
09723 if ((dstclass == FPUL_REGS
09724 && (srcclass == PR_REGS || srcclass == MAC_REGS || srcclass == T_REGS))
09725 || (srcclass == FPUL_REGS
09726 && (dstclass == PR_REGS || dstclass == MAC_REGS)))
09727 return 7;
09728
09729 if ((srcclass == TARGET_REGS && ! REGCLASS_HAS_GENERAL_REG (dstclass))
09730 || ((dstclass) == TARGET_REGS && ! REGCLASS_HAS_GENERAL_REG (srcclass)))
09731 return 20;
09732
09733
09734 if (TARGET_SHMEDIA
09735 && ((srcclass) == TARGET_REGS || (srcclass) == SIBCALL_REGS))
09736 {
09737 if (sh_gettrcost >= 0)
09738 return sh_gettrcost;
09739 else if (!TARGET_PT_FIXED)
09740 return 100;
09741 }
09742
09743 if ((srcclass == FPSCR_REGS && ! REGCLASS_HAS_GENERAL_REG (dstclass))
09744 || (dstclass == FPSCR_REGS && ! REGCLASS_HAS_GENERAL_REG (srcclass)))
09745 return 4;
09746
09747 if (TARGET_SHMEDIA
09748 || (TARGET_FMOVD
09749 && ! REGCLASS_HAS_GENERAL_REG (srcclass)
09750 && ! REGCLASS_HAS_GENERAL_REG (dstclass)))
09751 return 2 * ((GET_MODE_SIZE (mode) + 7) / 8U);
09752
09753 return 2 * ((GET_MODE_SIZE (mode) + 3) / 4U);
09754 }
09755
09756 static rtx emit_load_ptr (rtx, rtx);
09757
09758 static rtx
09759 emit_load_ptr (rtx reg, rtx addr)
09760 {
09761 rtx mem = gen_const_mem (ptr_mode, addr);
09762
09763 if (Pmode != ptr_mode)
09764 mem = gen_rtx_SIGN_EXTEND (Pmode, mem);
09765 return emit_move_insn (reg, mem);
09766 }
09767
09768 static void
09769 sh_output_mi_thunk (FILE *file, tree thunk_fndecl ATTRIBUTE_UNUSED,
09770 HOST_WIDE_INT delta, HOST_WIDE_INT vcall_offset,
09771 tree function)
09772 {
09773 CUMULATIVE_ARGS cum;
09774 int structure_value_byref = 0;
09775 rtx this, this_value, sibcall, insns, funexp;
09776 tree funtype = TREE_TYPE (function);
09777 int simple_add = CONST_OK_FOR_ADD (delta);
09778 int did_load = 0;
09779 rtx scratch0, scratch1, scratch2;
09780 unsigned i;
09781
09782 reload_completed = 1;
09783 epilogue_completed = 1;
09784 no_new_pseudos = 1;
09785 current_function_uses_only_leaf_regs = 1;
09786 reset_block_changes ();
09787
09788 emit_note (NOTE_INSN_PROLOGUE_END);
09789
09790
09791
09792
09793
09794 INIT_CUMULATIVE_ARGS (cum, funtype, NULL_RTX, 0, 1);
09795 #ifndef PCC_STATIC_STRUCT_RETURN
09796 if (aggregate_value_p (TREE_TYPE (TREE_TYPE (function)), function))
09797 structure_value_byref = 1;
09798 #endif
09799 if (structure_value_byref && sh_struct_value_rtx (function, 0) == 0)
09800 {
09801 tree ptype = build_pointer_type (TREE_TYPE (funtype));
09802
09803 FUNCTION_ARG_ADVANCE (cum, Pmode, ptype, 1);
09804 }
09805 this = FUNCTION_ARG (cum, Pmode, ptr_type_node, 1);
09806
09807
09808
09809
09810
09811
09812
09813 if (! call_used_regs[0] || fixed_regs[0])
09814 error ("r0 needs to be available as a call-clobbered register");
09815 scratch0 = scratch1 = scratch2 = gen_rtx_REG (Pmode, 0);
09816 if (! TARGET_SH5)
09817 {
09818 if (call_used_regs[1] && ! fixed_regs[1])
09819 scratch1 = gen_rtx_REG (ptr_mode, 1);
09820
09821
09822 if (call_used_regs[3] && ! fixed_regs[3])
09823 scratch2 = gen_rtx_REG (Pmode, 3);
09824 }
09825 else if (TARGET_SHMEDIA)
09826 {
09827 for (i = FIRST_GENERAL_REG; i <= LAST_GENERAL_REG; i++)
09828 if (i != REGNO (scratch0) &&
09829 call_used_regs[i] && ! fixed_regs[i] && ! FUNCTION_ARG_REGNO_P (i))
09830 {
09831 scratch1 = gen_rtx_REG (ptr_mode, i);
09832 break;
09833 }
09834 if (scratch1 == scratch0)
09835 error ("Need a second call-clobbered general purpose register");
09836 for (i = FIRST_TARGET_REG; i <= LAST_TARGET_REG; i++)
09837 if (call_used_regs[i] && ! fixed_regs[i])
09838 {
09839 scratch2 = gen_rtx_REG (Pmode, i);
09840 break;
09841 }
09842 if (scratch2 == scratch0)
09843 error ("Need a call-clobbered target register");
09844 }
09845
09846 this_value = plus_constant (this, delta);
09847 if (vcall_offset
09848 && (simple_add || scratch0 != scratch1)
09849 && strict_memory_address_p (ptr_mode, this_value))
09850 {
09851 emit_load_ptr (scratch0, this_value);
09852 did_load = 1;
09853 }
09854
09855 if (!delta)
09856 ;
09857 else if (simple_add)
09858 emit_move_insn (this, this_value);
09859 else
09860 {
09861 emit_move_insn (scratch1, GEN_INT (delta));
09862 emit_insn (gen_add2_insn (this, scratch1));
09863 }
09864
09865 if (vcall_offset)
09866 {
09867 rtx offset_addr;
09868
09869 if (!did_load)
09870 emit_load_ptr (scratch0, this);
09871
09872 offset_addr = plus_constant (scratch0, vcall_offset);
09873 if (strict_memory_address_p (ptr_mode, offset_addr))
09874 ;
09875 else if (! TARGET_SH5 && scratch0 != scratch1)
09876 {
09877
09878
09879
09880
09881 emit_move_insn (scratch1, GEN_INT (vcall_offset));
09882 offset_addr = gen_rtx_PLUS (Pmode, scratch0, scratch1);
09883 }
09884 else if (CONST_OK_FOR_ADD (vcall_offset))
09885 {
09886 emit_insn (gen_add2_insn (scratch0, GEN_INT (vcall_offset)));
09887 offset_addr = scratch0;
09888 }
09889 else if (scratch0 != scratch1)
09890 {
09891 emit_move_insn (scratch1, GEN_INT (vcall_offset));
09892 emit_insn (gen_add2_insn (scratch0, scratch1));
09893 offset_addr = scratch0;
09894 }
09895 else
09896 gcc_unreachable ();
09897 emit_load_ptr (scratch0, offset_addr);
09898
09899 if (Pmode != ptr_mode)
09900 scratch0 = gen_rtx_TRUNCATE (ptr_mode, scratch0);
09901 emit_insn (gen_add2_insn (this, scratch0));
09902 }
09903
09904
09905 if (! TREE_USED (function))
09906 {
09907 assemble_external (function);
09908 TREE_USED (function) = 1;
09909 }
09910 funexp = XEXP (DECL_RTL (function), 0);
09911
09912
09913 #if 0
09914 if (TARGET_SH1 && ! flag_weak)
09915 sibcall = gen_sibcalli_thunk (funexp, const0_rtx);
09916 else
09917 #endif
09918 if (TARGET_SH2 && flag_pic)
09919 {
09920 sibcall = gen_sibcall_pcrel (funexp, const0_rtx);
09921 XEXP (XVECEXP (sibcall, 0, 2), 0) = scratch2;
09922 }
09923 else
09924 {
09925 if (TARGET_SHMEDIA && flag_pic)
09926 {
09927 funexp = gen_sym2PIC (funexp);
09928 PUT_MODE (funexp, Pmode);
09929 }
09930 emit_move_insn (scratch2, funexp);
09931 funexp = gen_rtx_MEM (FUNCTION_MODE, scratch2);
09932 sibcall = gen_sibcall (funexp, const0_rtx, NULL_RTX);
09933 }
09934 sibcall = emit_call_insn (sibcall);
09935 SIBLING_CALL_P (sibcall) = 1;
09936 use_reg (&CALL_INSN_FUNCTION_USAGE (sibcall), this);
09937 emit_barrier ();
09938
09939
09940
09941
09942
09943 insn_locators_initialize ();
09944 insns = get_insns ();
09945
09946 if (optimize > 0)
09947 {
09948
09949 bitmap_obstack_initialize (NULL);
09950 bitmap_obstack_initialize (®_obstack);
09951 if (! cfun->cfg)
09952 init_flow ();
09953 rtl_register_cfg_hooks ();
09954 init_rtl_bb_info (ENTRY_BLOCK_PTR);
09955 init_rtl_bb_info (EXIT_BLOCK_PTR);
09956 ENTRY_BLOCK_PTR->flags |= BB_RTL;
09957 EXIT_BLOCK_PTR->flags |= BB_RTL;
09958 find_basic_blocks (insns);
09959
09960 if (flag_schedule_insns_after_reload)
09961 {
09962 life_analysis (PROP_FINAL);
09963
09964 split_all_insns (1);
09965
09966 schedule_insns ();
09967 }
09968
09969 else if (flag_pic)
09970 split_all_insns_noflow ();
09971 }
09972
09973 sh_reorg ();
09974
09975 if (optimize > 0 && flag_delayed_branch)
09976 dbr_schedule (insns);
09977
09978 shorten_branches (insns);
09979 final_start_function (insns, file, 1);
09980 final (insns, file, 1);
09981 final_end_function ();
09982
09983 if (optimize > 0)
09984 {
09985
09986 free_basic_block_vars ();
09987
09988
09989 bitmap_obstack_release (®_obstack);
09990 bitmap_obstack_release (NULL);
09991 }
09992
09993 reload_completed = 0;
09994 epilogue_completed = 0;
09995 no_new_pseudos = 0;
09996 }
09997
09998 rtx
09999 function_symbol (rtx target, const char *name, enum sh_function_kind kind)
10000 {
10001 rtx sym;
10002
10003
10004
10005
10006 if (kind != FUNCTION_ORDINARY)
10007 name = IDENTIFIER_POINTER (get_identifier (name));
10008 sym = gen_rtx_SYMBOL_REF (Pmode, name);
10009 SYMBOL_REF_FLAGS (sym) = SYMBOL_FLAG_FUNCTION;
10010 if (flag_pic)
10011 switch (kind)
10012 {
10013 case FUNCTION_ORDINARY:
10014 break;
10015 case SFUNC_GOT:
10016 {
10017 rtx reg = target ? target : gen_reg_rtx (Pmode);
10018
10019 emit_insn (gen_symGOT2reg (reg, sym));
10020 sym = reg;
10021 break;
10022 }
10023 case SFUNC_STATIC:
10024 {
10025
10026
10027
10028
10029
10030 rtx reg = target ? target : gen_reg_rtx (Pmode);
10031
10032 emit_insn (gen_symGOTOFF2reg (reg, sym));
10033 sym = reg;
10034 break;
10035 }
10036 }
10037 if (target && sym != target)
10038 {
10039 emit_move_insn (target, sym);
10040 return target;
10041 }
10042 return sym;
10043 }
10044
10045
10046 static int
10047 scavenge_reg (HARD_REG_SET *s)
10048 {
10049 int r;
10050 for (r = FIRST_GENERAL_REG; r <= LAST_GENERAL_REG; r++)
10051 if (TEST_HARD_REG_BIT (*s, r))
10052 return r;
10053 return -1;
10054 }
10055
10056 rtx
10057 sh_get_pr_initial_val (void)
10058 {
10059 rtx val;
10060
10061
10062
10063
10064 if (TARGET_SHCOMPACT
10065 && ((current_function_args_info.call_cookie
10066 & ~ CALL_COOKIE_RET_TRAMP (1))
10067 || current_function_has_nonlocal_label))
10068 return gen_frame_mem (SImode, return_address_pointer_rtx);
10069
10070
10071
10072
10073
10074
10075
10076
10077
10078
10079
10080
10081 val
10082 = get_hard_reg_initial_val (Pmode, TARGET_SHMEDIA ? PR_MEDIA_REG : PR_REG);
10083 if (TARGET_SH1)
10084 return gen_rtx_UNSPEC (SImode, gen_rtvec (1, val), UNSPEC_RA);
10085 return val;
10086 }
10087
10088 int
10089 sh_expand_t_scc (enum rtx_code code, rtx target)
10090 {
10091 rtx result = target;
10092 HOST_WIDE_INT val;
10093
10094 if (GET_CODE (sh_compare_op0) != REG || REGNO (sh_compare_op0) != T_REG
10095 || GET_CODE (sh_compare_op1) != CONST_INT)
10096 return 0;
10097 if (GET_CODE (result) != REG)
10098 result = gen_reg_rtx (SImode);
10099 val = INTVAL (sh_compare_op1);
10100 if ((code == EQ && val == 1) || (code == NE && val == 0))
10101 emit_insn (gen_movt (result));
10102 else if ((code == EQ && val == 0) || (code == NE && val == 1))
10103 {
10104 emit_insn (gen_rtx_CLOBBER (VOIDmode, result));
10105 emit_insn (gen_subc (result, result, result));
10106 emit_insn (gen_addsi3 (result, result, const1_rtx));
10107 }
10108 else if (code == EQ || code == NE)
10109 emit_insn (gen_move_insn (result, GEN_INT (code == NE)));
10110 else
10111 return 0;
10112 if (result != target)
10113 emit_move_insn (target, result);
10114 return 1;
10115 }
10116
10117
10118 static rtx
10119 extract_sfunc_addr (rtx insn)
10120 {
10121 rtx pattern, part = NULL_RTX;
10122 int len, i;
10123
10124 pattern = PATTERN (insn);
10125 len = XVECLEN (pattern, 0);
10126 for (i = 0; i < len; i++)
10127 {
10128 part = XVECEXP (pattern, 0, i);
10129 if (GET_CODE (part) == USE && GET_MODE (XEXP (part, 0)) == Pmode
10130 && GENERAL_REGISTER_P (true_regnum (XEXP (part, 0))))
10131 return XEXP (part, 0);
10132 }
10133 gcc_assert (GET_CODE (XVECEXP (pattern, 0, 0)) == UNSPEC_VOLATILE);
10134 return XVECEXP (XVECEXP (pattern, 0, 0), 0, 1);
10135 }
10136
10137
10138
10139
10140
10141
10142 int
10143 check_use_sfunc_addr (rtx insn, rtx reg)
10144 {
10145
10146 while ((insn = NEXT_INSN (insn)))
10147 {
10148 if (GET_CODE (insn) == CODE_LABEL || GET_CODE (insn) == JUMP_INSN)
10149 break;
10150 if (! INSN_P (insn))
10151 continue;
10152
10153 if (GET_CODE (PATTERN (insn)) == SEQUENCE)
10154 insn = XVECEXP (PATTERN (insn), 0, 0);
10155 if (GET_CODE (PATTERN (insn)) != PARALLEL
10156 || get_attr_type (insn) != TYPE_SFUNC)
10157 continue;
10158 return rtx_equal_p (extract_sfunc_addr (insn), reg);
10159 }
10160 gcc_unreachable ();
10161 }
10162
10163
10164
10165
10166
10167
10168 static GTY(()) rtx sh_fsca_sf2int_rtx;
10169
10170 rtx
10171 sh_fsca_sf2int (void)
10172 {
10173 if (! sh_fsca_sf2int_rtx)
10174 {
10175 REAL_VALUE_TYPE rv;
10176
10177 real_from_string (&rv, "10430.378350470453");
10178 sh_fsca_sf2int_rtx = const_double_from_real_value (rv, SFmode);
10179 }
10180
10181 return sh_fsca_sf2int_rtx;
10182 }
10183
10184
10185
10186
10187
10188
10189 static GTY(()) rtx sh_fsca_df2int_rtx;
10190
10191 rtx
10192 sh_fsca_df2int (void)
10193 {
10194 if (! sh_fsca_df2int_rtx)
10195 {
10196 REAL_VALUE_TYPE rv;
10197
10198 real_from_string (&rv, "10430.378350470453");
10199 sh_fsca_df2int_rtx = const_double_from_real_value (rv, DFmode);
10200 }
10201
10202 return sh_fsca_df2int_rtx;
10203 }
10204
10205
10206
10207
10208
10209
10210 static GTY(()) rtx sh_fsca_int2sf_rtx;
10211
10212 rtx
10213 sh_fsca_int2sf (void)
10214 {
10215 if (! sh_fsca_int2sf_rtx)
10216 {
10217 REAL_VALUE_TYPE rv;
10218
10219 real_from_string (&rv, "9.587379924285257e-5");
10220 sh_fsca_int2sf_rtx = const_double_from_real_value (rv, SFmode);
10221 }
10222
10223 return sh_fsca_int2sf_rtx;
10224 }
10225
10226
10227
10228 void
10229 sh_init_cumulative_args (CUMULATIVE_ARGS * pcum,
10230 tree fntype,
10231 rtx libname ATTRIBUTE_UNUSED,
10232 tree fndecl,
10233 signed int n_named_args,
10234 enum machine_mode mode)
10235 {
10236 pcum->arg_count [(int) SH_ARG_FLOAT] = 0;
10237 pcum->free_single_fp_reg = 0;
10238 pcum->stack_regs = 0;
10239 pcum->byref_regs = 0;
10240 pcum->byref = 0;
10241 pcum->outgoing = (n_named_args == -1) ? 0 : 1;
10242
10243
10244 pcum->renesas_abi = sh_attr_renesas_p (fntype) ? 1 : 0;
10245
10246 if (fntype)
10247 {
10248 pcum->force_mem = ((TARGET_HITACHI || pcum->renesas_abi)
10249 && aggregate_value_p (TREE_TYPE (fntype), fndecl));
10250 pcum->prototype_p = TYPE_ARG_TYPES (fntype) ? TRUE : FALSE;
10251 pcum->arg_count [(int) SH_ARG_INT]
10252 = TARGET_SH5 && aggregate_value_p (TREE_TYPE (fntype), fndecl);
10253
10254 pcum->call_cookie
10255 = CALL_COOKIE_RET_TRAMP (TARGET_SHCOMPACT
10256 && pcum->arg_count [(int) SH_ARG_INT] == 0
10257 && (TYPE_MODE (TREE_TYPE (fntype)) == BLKmode
10258 ? int_size_in_bytes (TREE_TYPE (fntype))
10259 : GET_MODE_SIZE (TYPE_MODE (TREE_TYPE (fntype)))) > 4
10260 && (BASE_RETURN_VALUE_REG (TYPE_MODE (TREE_TYPE (fntype)))
10261 == FIRST_RET_REG));
10262 }
10263 else
10264 {
10265 pcum->arg_count [(int) SH_ARG_INT] = 0;
10266 pcum->prototype_p = FALSE;
10267 if (mode != VOIDmode)
10268 {
10269 pcum->call_cookie =
10270 CALL_COOKIE_RET_TRAMP (TARGET_SHCOMPACT
10271 && GET_MODE_SIZE (mode) > 4
10272 && BASE_RETURN_VALUE_REG (mode) == FIRST_RET_REG);
10273
10274
10275
10276
10277
10278
10279
10280
10281
10282 pcum->force_mem =
10283 (TARGET_DEFAULT & MASK_HITACHI)
10284 && (mode == BLKmode
10285 || (GET_MODE_SIZE (mode) > 4
10286 && !(mode == DFmode
10287 && TARGET_FPU_DOUBLE)));
10288 }
10289 else
10290 {
10291 pcum->call_cookie = 0;
10292 pcum->force_mem = FALSE;
10293 }
10294 }
10295 }
10296
10297
10298
10299
10300 static int
10301 hard_regs_intersect_p (HARD_REG_SET *a, HARD_REG_SET *b)
10302 {
10303 HARD_REG_SET c;
10304 COPY_HARD_REG_SET (c, *a);
10305 AND_HARD_REG_SET (c, *b);
10306 GO_IF_HARD_REG_SUBSET (c, reg_class_contents[(int) NO_REGS], lose);
10307 return 1;
10308 lose:
10309 return 0;
10310 }
10311
10312 #ifdef TARGET_ADJUST_UNROLL_MAX
10313 static int
10314 sh_adjust_unroll_max (struct loop * loop, int insn_count,
10315 int max_unrolled_insns, int strength_reduce_p,
10316 int unroll_type)
10317 {
10318
10319 if (TARGET_ADJUST_UNROLL && TARGET_SHMEDIA)
10320 {
10321
10322
10323
10324 rtx insn;
10325 int n_labels = 0, n_calls = 0, n_exit_dest = 0, n_inner_loops = -1;
10326 int n_barriers = 0;
10327 rtx dest;
10328 int i;
10329 rtx exit_dest[8];
10330 int threshold;
10331 int unroll_benefit = 0, mem_latency = 0;
10332 int base_cost, best_cost, cost;
10333 int factor, best_factor;
10334 int n_dest;
10335 unsigned max_iterations = 32767;
10336 int n_iterations;
10337 int need_precond = 0, precond = 0;
10338 basic_block * bbs = get_loop_body (loop);
10339 struct niter_desc *desc;
10340
10341
10342
10343
10344
10345
10346
10347 i = loop->num_nodes - 1;
10348 for (insn = BB_HEAD (bbs[i]); ; )
10349 {
10350 if (GET_CODE (insn) == CODE_LABEL)
10351 n_labels++;
10352 else if (GET_CODE (insn) == CALL_INSN)
10353 n_calls++;
10354 else if (GET_CODE (insn) == NOTE
10355 && NOTE_LINE_NUMBER (insn) == NOTE_INSN_LOOP_BEG)
10356 n_inner_loops++;
10357 else if (GET_CODE (insn) == BARRIER)
10358 n_barriers++;
10359 if (insn != BB_END (bbs[i]))
10360 insn = NEXT_INSN (insn);
10361 else if (--i >= 0)
10362 insn = BB_HEAD (bbs[i]);
10363 else
10364 break;
10365 }
10366 free (bbs);
10367
10368
10369 if (n_labels <= 1)
10370 return max_unrolled_insns;
10371 if (n_inner_loops > 0)
10372 return 0;
10373 for (dest = loop->exit_labels; dest && n_exit_dest < 8;
10374 dest = LABEL_NEXTREF (dest))
10375 {
10376 for (i = n_exit_dest - 1;
10377 i >= 0 && XEXP (dest, 0) != XEXP (exit_dest[i], 0); i--);
10378 if (i < 0)
10379 exit_dest[n_exit_dest++] = dest;
10380 }
10381
10382
10383
10384 if (n_calls + n_exit_dest >= 7)
10385 return max_unrolled_insns;
10386
10387
10388
10389
10390 #if 0
10391 if (strength_reduce_p
10392 && (unroll_type == LPT_UNROLL_RUNTIME
10393 || unroll_type == LPT_UNROLL_CONSTANT
10394 || unroll_type == LPT_PEEL_COMPLETELY))
10395 {
10396 struct loop_ivs *ivs = LOOP_IVS (loop);
10397 struct iv_class *bl;
10398
10399
10400
10401 unroll_benefit = 1;
10402
10403 for (bl = ivs->list; bl; bl = bl->next)
10404 {
10405 rtx increment = biv_total_increment (bl);
10406 struct induction *v;
10407
10408 if (increment && GET_CODE (increment) == CONST_INT)
10409 {
10410 unroll_benefit++;
10411 for (v = bl->giv; v; v = v->next_iv)
10412 {
10413 if (! v->ignore && v->same == 0
10414 && GET_CODE (v->mult_val) == CONST_INT)
10415 unroll_benefit++;
10416
10417
10418
10419
10420 while (v->giv_type == DEST_ADDR)
10421 {
10422 rtx mem = PATTERN (v->insn);
10423 tree mem_expr, type, size_tree;
10424
10425 if (GET_CODE (SET_SRC (mem)) == MEM)
10426 mem = SET_SRC (mem);
10427 else if (GET_CODE (SET_DEST (mem)) == MEM)
10428 mem = SET_DEST (mem);
10429 else
10430 break;
10431 mem_expr = MEM_EXPR (mem);
10432 if (! mem_expr)
10433 break;
10434 type = TREE_TYPE (mem_expr);
10435 if (TREE_CODE (type) != ARRAY_TYPE
10436 || ! TYPE_SIZE (type) || ! TYPE_SIZE_UNIT (type))
10437 break;
10438 size_tree = fold_build2 (TRUNC_DIV_EXPR,
10439 bitsizetype,
10440 TYPE_SIZE (type),
10441 TYPE_SIZE_UNIT (type));
10442 if (TREE_CODE (size_tree) == INTEGER_CST
10443 && ! TREE_INT_CST_HIGH (size_tree)
10444 && TREE_INT_CST_LOW (size_tree) < max_iterations)
10445 max_iterations = TREE_INT_CST_LOW (size_tree);
10446 break;
10447 }
10448 }
10449 }
10450 }
10451 }
10452 #else
10453
10454 unroll_benefit = 1;
10455 #endif
10456
10457 desc = get_simple_loop_desc (loop);
10458 n_iterations = desc->const_iter ? desc->niter : 0;
10459 max_iterations
10460 = max_iterations < desc->niter_max ? max_iterations : desc->niter_max;
10461
10462 if (! strength_reduce_p || ! n_iterations)
10463 need_precond = 1;
10464 if (! n_iterations)
10465 {
10466 n_iterations
10467 = max_iterations < 3 ? max_iterations : max_iterations * 3 / 4;
10468 if (! n_iterations)
10469 return 0;
10470 }
10471 #if 0
10472 while (unroll_benefit > 1)
10473 {
10474
10475
10476
10477
10478
10479
10480
10481
10482
10483
10484
10485
10486
10487
10488
10489 rtx set, last_set;
10490
10491 insn = next_active_insn (loop->start);
10492 last_set = single_set (insn);
10493 if (! last_set)
10494 break;
10495 if (GET_CODE (SET_SRC (last_set)) == MEM)
10496 mem_latency += 2;
10497 for (insn = NEXT_INSN (insn); insn != end; insn = NEXT_INSN (insn))
10498 {
10499 if (! INSN_P (insn))
10500 continue;
10501 if (GET_CODE (insn) == JUMP_INSN)
10502 break;
10503 if (! reg_referenced_p (SET_DEST (last_set), PATTERN (insn)))
10504 {
10505
10506 struct loop_ivs *ivs = LOOP_IVS (loop);
10507 struct iv_class *bl;
10508 struct induction *v;
10509 for (bl = ivs->list; bl; bl = bl->next)
10510 {
10511 if (bl->biv->insn == insn)
10512 goto is_biv;
10513 for (v = bl->giv; v; v = v->next_iv)
10514 if (v->insn == insn)
10515 goto is_giv;
10516 }
10517 mem_latency--;
10518 is_biv:
10519 is_giv:
10520 continue;
10521 }
10522 set = single_set (insn);
10523 if (! set)
10524 continue;
10525 if (GET_CODE (SET_SRC (set)) == MEM)
10526 mem_latency += 2;
10527 last_set = set;
10528 }
10529 if (mem_latency < 0)
10530 mem_latency = 0;
10531 else if (mem_latency > unroll_benefit - 1)
10532 mem_latency = unroll_benefit - 1;
10533 break;
10534 }
10535 #endif
10536 if (n_labels + (unroll_benefit + n_labels * 8) / n_iterations
10537 <= unroll_benefit)
10538 return max_unrolled_insns;
10539
10540 n_dest = n_labels + n_calls + n_exit_dest;
10541 base_cost = n_dest <= 8 ? 0 : n_dest - 7;
10542 best_cost = 0;
10543 best_factor = 1;
10544 if (n_barriers * 2 > n_labels - 1)
10545 n_barriers = (n_labels - 1) / 2;
10546 for (factor = 2; factor <= 8; factor++)
10547 {
10548
10549 if (! (factor & (factor-1)))
10550 precond += 4;
10551
10552 else if (need_precond)
10553 continue;
10554 n_dest = ((unroll_type != LPT_PEEL_COMPLETELY)
10555 + (n_labels - 1) * factor + n_calls + n_exit_dest
10556 - (n_barriers * factor >> 1)
10557 + need_precond);
10558 cost
10559 = ((n_dest <= 8 ? 0 : n_dest - 7)
10560 - base_cost * factor
10561 - ((factor > 2 ? unroll_benefit - mem_latency : unroll_benefit)
10562 * (factor - (unroll_type != LPT_PEEL_COMPLETELY)))
10563 + ((unroll_benefit + 1 + (n_labels - 1) * factor)
10564 / n_iterations));
10565 if (need_precond)
10566 cost += (precond + unroll_benefit * factor / 2) / n_iterations;
10567 if (cost < best_cost)
10568 {
10569 best_cost = cost;
10570 best_factor = factor;
10571 }
10572 }
10573 threshold = best_factor * insn_count;
10574 if (max_unrolled_insns > threshold)
10575 max_unrolled_insns = threshold;
10576 }
10577 return max_unrolled_insns;
10578 }
10579 #endif
10580
10581
10582
10583
10584
10585
10586
10587
10588
10589
10590
10591
10592
10593
10594
10595
10596 rtx
10597 replace_n_hard_rtx (rtx x, rtx *replacements, int n_replacements, int modify)
10598 {
10599 int i, j;
10600 const char *fmt;
10601
10602
10603
10604 if (x != 0 && GET_CODE (x) == CONST_DOUBLE)
10605 return x;
10606
10607 for (i = n_replacements - 1; i >= 0 ; i--)
10608 if (x == replacements[i*2] && GET_MODE (x) == GET_MODE (replacements[i*2+1]))
10609 return replacements[i*2+1];
10610
10611
10612 if (x == 0)
10613 return 0;
10614
10615 if (GET_CODE (x) == SUBREG)
10616 {
10617 rtx new = replace_n_hard_rtx (SUBREG_REG (x), replacements,
10618 n_replacements, modify);
10619
10620 if (GET_CODE (new) == CONST_INT)
10621 {
10622 x = simplify_subreg (GET_MODE (x), new,
10623 GET_MODE (SUBREG_REG (x)),
10624 SUBREG_BYTE (x));
10625 if (! x)
10626 abort ();
10627 }
10628 else if (modify)
10629 SUBREG_REG (x) = new;
10630
10631 return x;
10632 }
10633 else if (GET_CODE (x) == REG)
10634 {
10635 unsigned regno = REGNO (x);
10636 unsigned nregs = (regno < FIRST_PSEUDO_REGISTER
10637 ? HARD_REGNO_NREGS (regno, GET_MODE (x)) : 1);
10638 rtx result = NULL_RTX;
10639
10640 for (i = n_replacements - 1; i >= 0; i--)
10641 {
10642 rtx from = replacements[i*2];
10643 rtx to = replacements[i*2+1];
10644 unsigned from_regno, from_nregs, to_regno, new_regno;
10645
10646 if (GET_CODE (from) != REG)
10647 continue;
10648 from_regno = REGNO (from);
10649 from_nregs = (from_regno < FIRST_PSEUDO_REGISTER
10650 ? HARD_REGNO_NREGS (from_regno, GET_MODE (from)) : 1);
10651 if (regno < from_regno + from_nregs && regno + nregs > from_regno)
10652 {
10653 if (regno < from_regno
10654 || regno + nregs > from_regno + nregs
10655 || GET_CODE (to) != REG
10656 || result)
10657 return NULL_RTX;
10658 to_regno = REGNO (to);
10659 if (to_regno < FIRST_PSEUDO_REGISTER)
10660 {
10661 new_regno = regno + to_regno - from_regno;
10662 if ((unsigned) HARD_REGNO_NREGS (new_regno, GET_MODE (x))
10663 != nregs)
10664 return NULL_RTX;
10665 result = gen_rtx_REG (GET_MODE (x), new_regno);
10666 }
10667 else if (GET_MODE (x) <= GET_MODE (to))
10668 result = gen_lowpart_common (GET_MODE (x), to);
10669 else
10670 result = gen_lowpart_SUBREG (GET_MODE (x), to);
10671 }
10672 }
10673 return result ? result : x;
10674 }
10675 else if (GET_CODE (x) == ZERO_EXTEND)
10676 {
10677 rtx new = replace_n_hard_rtx (XEXP (x, 0), replacements,
10678 n_replacements, modify);
10679
10680 if (GET_CODE (new) == CONST_INT)
10681 {
10682 x = simplify_unary_operation (ZERO_EXTEND, GET_MODE (x),
10683 new, GET_MODE (XEXP (x, 0)));
10684 if (! x)
10685 abort ();
10686 }
10687 else if (modify)
10688 XEXP (x, 0) = new;
10689
10690 return x;
10691 }
10692
10693 fmt = GET_RTX_FORMAT (GET_CODE (x));
10694 for (i = GET_RTX_LENGTH (GET_CODE (x)) - 1; i >= 0; i--)
10695 {
10696 rtx new;
10697
10698 if (fmt[i] == 'e')
10699 {
10700 new = replace_n_hard_rtx (XEXP (x, i), replacements,
10701 n_replacements, modify);
10702 if (!new)
10703 return NULL_RTX;
10704 if (modify)
10705 XEXP (x, i) = new;
10706 }
10707 else if (fmt[i] == 'E')
10708 for (j = XVECLEN (x, i) - 1; j >= 0; j--)
10709 {
10710 new = replace_n_hard_rtx (XVECEXP (x, i, j), replacements,
10711 n_replacements, modify);
10712 if (!new)
10713 return NULL_RTX;
10714 if (modify)
10715 XVECEXP (x, i, j) = new;
10716 }
10717 }
10718
10719 return x;
10720 }
10721
10722 rtx
10723 sh_gen_truncate (enum machine_mode mode, rtx x, int need_sign_ext)
10724 {
10725 enum rtx_code code = TRUNCATE;
10726
10727 if (GET_CODE (x) == ZERO_EXTEND || GET_CODE (x) == SIGN_EXTEND)
10728 {
10729 rtx inner = XEXP (x, 0);
10730 enum machine_mode inner_mode = GET_MODE (inner);
10731
10732 if (inner_mode == mode)
10733 return inner;
10734 else if (GET_MODE_SIZE (inner_mode) >= GET_MODE_SIZE (mode))
10735 x = inner;
10736 else if (GET_MODE_SIZE (inner_mode) < GET_MODE_SIZE (mode)
10737 && (! need_sign_ext || GET_CODE (x) == SIGN_EXTEND))
10738 {
10739 code = GET_CODE (x);
10740 x = inner;
10741 }
10742 }
10743 return gen_rtx_fmt_e (code, mode, x);
10744 }
10745
10746
10747
10748 int
10749 shmedia_cleanup_truncate (rtx *p, void *n_changes)
10750 {
10751 rtx x = *p, reg;
10752
10753 if (GET_CODE (x) != TRUNCATE)
10754 return 0;
10755 reg = XEXP (x, 0);
10756 if (GET_MODE_SIZE (GET_MODE (reg)) > 8 && GET_CODE (reg) == REG)
10757 {
10758 enum machine_mode reg_mode = GET_MODE (reg);
10759 XEXP (x, 0) = simplify_subreg (DImode, reg, reg_mode,
10760 subreg_lowpart_offset (DImode, reg_mode));
10761 *(int*) n_changes += 1;
10762 return -1;
10763 }
10764 return 0;
10765 }
10766
10767
10768
10769
10770
10771
10772
10773 static int
10774 sh_contains_memref_p_1 (rtx *loc, void *data ATTRIBUTE_UNUSED)
10775 {
10776 return (GET_CODE (*loc) == MEM);
10777 }
10778
10779
10780 int
10781 sh_contains_memref_p (rtx insn)
10782 {
10783 return for_each_rtx (&PATTERN (insn), &sh_contains_memref_p_1, NULL);
10784 }
10785
10786
10787
10788 rtx
10789 shmedia_prepare_call_address (rtx fnaddr, int is_sibcall)
10790 {
10791 int is_sym;
10792
10793 fnaddr = XEXP (fnaddr, 0);
10794 is_sym = GET_CODE (fnaddr) == SYMBOL_REF;
10795 if (flag_pic && is_sym)
10796 {
10797 if (! SYMBOL_REF_LOCAL_P (fnaddr))
10798 {
10799 rtx reg = gen_reg_rtx (Pmode);
10800
10801
10802
10803 if (is_sibcall)
10804 emit_insn (gen_symGOT2reg (reg, fnaddr));
10805 else
10806 emit_insn (gen_symGOTPLT2reg (reg, fnaddr));
10807 fnaddr = reg;
10808 }
10809 else
10810 {
10811 fnaddr = gen_sym2PIC (fnaddr);
10812 PUT_MODE (fnaddr, Pmode);
10813 }
10814 }
10815
10816
10817
10818
10819
10820 if (!TARGET_PT_FIXED
10821 && (!is_sym || TARGET_INVALID_SYMBOLS)
10822 && (!REG_P (fnaddr) || ! TARGET_REGISTER_P (REGNO (fnaddr))))
10823 {
10824 rtx tr = gen_reg_rtx (PDImode);
10825
10826 emit_insn (gen_ptabs (tr, fnaddr));
10827 fnaddr = tr;
10828 }
10829 else if (! target_reg_operand (fnaddr, Pmode))
10830 fnaddr = copy_to_mode_reg (Pmode, fnaddr);
10831 return fnaddr;
10832 }
10833
10834 enum reg_class
10835 sh_secondary_reload (bool in_p, rtx x, enum reg_class class,
10836 enum machine_mode mode, secondary_reload_info *sri)
10837 {
10838 if (in_p)
10839 {
10840 if (REGCLASS_HAS_FP_REG (class)
10841 && ! TARGET_SHMEDIA
10842 && immediate_operand ((x), mode)
10843 && ! ((fp_zero_operand (x) || fp_one_operand (x))
10844 && mode == SFmode && fldi_ok ()))
10845 switch (mode)
10846 {
10847 case SFmode:
10848 sri->icode = CODE_FOR_reload_insf__frn;
10849 return NO_REGS;
10850 case DFmode:
10851 sri->icode = CODE_FOR_reload_indf__frn;
10852 return NO_REGS;
10853 case SImode:
10854
10855
10856 return FPUL_REGS;
10857 default:
10858 abort ();
10859 }
10860 if (class == FPUL_REGS
10861 && ((GET_CODE (x) == REG
10862 && (REGNO (x) == MACL_REG || REGNO (x) == MACH_REG
10863 || REGNO (x) == T_REG))
10864 || GET_CODE (x) == PLUS))
10865 return GENERAL_REGS;
10866 if (class == FPUL_REGS && immediate_operand (x, mode))
10867 {
10868 if (GET_CODE (x) == CONST_INT && CONST_OK_FOR_I08 (INTVAL (x)))
10869 return GENERAL_REGS;
10870 sri->icode = CODE_FOR_reload_insi__i_fpul;
10871 return NO_REGS;
10872 }
10873 if (class == FPSCR_REGS
10874 && ((GET_CODE (x) == REG && REGNO (x) >= FIRST_PSEUDO_REGISTER)
10875 || (GET_CODE (x) == MEM && GET_CODE (XEXP (x, 0)) == PLUS)))
10876 return GENERAL_REGS;
10877 if (REGCLASS_HAS_FP_REG (class)
10878 && TARGET_SHMEDIA
10879 && immediate_operand (x, mode)
10880 && x != CONST0_RTX (GET_MODE (x))
10881 && GET_MODE (x) != V4SFmode)
10882 return GENERAL_REGS;
10883 if ((mode == QImode || mode == HImode)
10884 && TARGET_SHMEDIA && inqhi_operand (x, mode))
10885 {
10886 sri->icode = ((mode == QImode)
10887 ? CODE_FOR_reload_inqi : CODE_FOR_reload_inhi);
10888 return NO_REGS;
10889 }
10890 if (TARGET_SHMEDIA && class == GENERAL_REGS
10891 && (GET_CODE (x) == LABEL_REF || PIC_DIRECT_ADDR_P (x)))
10892 return TARGET_REGS;
10893 }
10894
10895 if (((REGCLASS_HAS_FP_REG (class)
10896 && (GET_CODE (x) == REG
10897 && (GENERAL_OR_AP_REGISTER_P (REGNO (x))
10898 || (FP_REGISTER_P (REGNO (x)) && mode == SImode
10899 && TARGET_FMOVD))))
10900 || (REGCLASS_HAS_GENERAL_REG (class)
10901 && GET_CODE (x) == REG
10902 && FP_REGISTER_P (REGNO (x))))
10903 && ! TARGET_SHMEDIA
10904 && (mode == SFmode || mode == SImode))
10905 return FPUL_REGS;
10906 if ((class == FPUL_REGS
10907 || (REGCLASS_HAS_FP_REG (class)
10908 && ! TARGET_SHMEDIA && mode == SImode))
10909 && (GET_CODE (x) == MEM
10910 || (GET_CODE (x) == REG
10911 && (REGNO (x) >= FIRST_PSEUDO_REGISTER
10912 || REGNO (x) == T_REG
10913 || system_reg_operand (x, VOIDmode)))))
10914 {
10915 if (class == FPUL_REGS)
10916 return GENERAL_REGS;
10917 return FPUL_REGS;
10918 }
10919 if ((class == TARGET_REGS
10920 || (TARGET_SHMEDIA && class == SIBCALL_REGS))
10921 && !EXTRA_CONSTRAINT_Csy (x)
10922 && (GET_CODE (x) != REG || ! GENERAL_REGISTER_P (REGNO (x))))
10923 return GENERAL_REGS;
10924 if ((class == MAC_REGS || class == PR_REGS)
10925 && GET_CODE (x) == REG && ! GENERAL_REGISTER_P (REGNO (x))
10926 && class != REGNO_REG_CLASS (REGNO (x)))
10927 return GENERAL_REGS;
10928 if (class != GENERAL_REGS && GET_CODE (x) == REG
10929 && TARGET_REGISTER_P (REGNO (x)))
10930 return GENERAL_REGS;
10931 return NO_REGS;
10932 }
10933
10934 enum sh_divide_strategy_e sh_div_strategy = SH_DIV_STRATEGY_DEFAULT;
10935
10936 #include "gt-sh.h"