Mercurial > hg > CbC > CbC_gcc
comparison gcc/config/sh/sh.c @ 67:f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
author | nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp> |
---|---|
date | Tue, 22 Mar 2011 17:18:12 +0900 |
parents | b7f97abdc517 |
children | 04ced10e8804 |
comparison
equal
deleted
inserted
replaced
65:65488c3d617d | 67:f6334be47118 |
---|---|
35 #include "function.h" | 35 #include "function.h" |
36 #include "regs.h" | 36 #include "regs.h" |
37 #include "hard-reg-set.h" | 37 #include "hard-reg-set.h" |
38 #include "output.h" | 38 #include "output.h" |
39 #include "insn-attr.h" | 39 #include "insn-attr.h" |
40 #include "toplev.h" | 40 #include "diagnostic-core.h" |
41 #include "recog.h" | 41 #include "recog.h" |
42 #include "integrate.h" | 42 #include "integrate.h" |
43 #include "dwarf2.h" | 43 #include "dwarf2.h" |
44 #include "tm_p.h" | 44 #include "tm_p.h" |
45 #include "target.h" | 45 #include "target.h" |
179 static int mova_p (rtx); | 179 static int mova_p (rtx); |
180 static rtx find_barrier (int, rtx, rtx); | 180 static rtx find_barrier (int, rtx, rtx); |
181 static int noncall_uses_reg (rtx, rtx, rtx *); | 181 static int noncall_uses_reg (rtx, rtx, rtx *); |
182 static rtx gen_block_redirect (rtx, int, int); | 182 static rtx gen_block_redirect (rtx, int, int); |
183 static void sh_reorg (void); | 183 static void sh_reorg (void); |
184 static void sh_option_override (void); | |
185 static void sh_option_init_struct (struct gcc_options *); | |
186 static void sh_option_default_params (void); | |
184 static void output_stack_adjust (int, rtx, int, HARD_REG_SET *, bool); | 187 static void output_stack_adjust (int, rtx, int, HARD_REG_SET *, bool); |
185 static rtx frame_insn (rtx); | 188 static rtx frame_insn (rtx); |
186 static rtx push (int); | 189 static rtx push (int); |
187 static void pop (int); | 190 static void pop (int); |
188 static void push_regs (HARD_REG_SET *, int); | 191 static void push_regs (HARD_REG_SET *, int); |
196 static tree sh2a_handle_function_vector_handler_attribute (tree *, tree, | 199 static tree sh2a_handle_function_vector_handler_attribute (tree *, tree, |
197 tree, int, bool *); | 200 tree, int, bool *); |
198 static tree sh_handle_sp_switch_attribute (tree *, tree, tree, int, bool *); | 201 static tree sh_handle_sp_switch_attribute (tree *, tree, tree, int, bool *); |
199 static tree sh_handle_trap_exit_attribute (tree *, tree, tree, int, bool *); | 202 static tree sh_handle_trap_exit_attribute (tree *, tree, tree, int, bool *); |
200 static tree sh_handle_renesas_attribute (tree *, tree, tree, int, bool *); | 203 static tree sh_handle_renesas_attribute (tree *, tree, tree, int, bool *); |
204 static void sh_print_operand (FILE *, rtx, int); | |
205 static void sh_print_operand_address (FILE *, rtx); | |
206 static bool sh_print_operand_punct_valid_p (unsigned char code); | |
207 static bool sh_asm_output_addr_const_extra (FILE *file, rtx x); | |
201 static void sh_output_function_epilogue (FILE *, HOST_WIDE_INT); | 208 static void sh_output_function_epilogue (FILE *, HOST_WIDE_INT); |
202 static void sh_insert_attributes (tree, tree *); | 209 static void sh_insert_attributes (tree, tree *); |
203 static const char *sh_check_pch_target_flags (int); | 210 static const char *sh_check_pch_target_flags (int); |
211 static int sh_register_move_cost (enum machine_mode, reg_class_t, reg_class_t); | |
204 static int sh_adjust_cost (rtx, rtx, rtx, int); | 212 static int sh_adjust_cost (rtx, rtx, rtx, int); |
205 static int sh_issue_rate (void); | 213 static int sh_issue_rate (void); |
206 static int sh_dfa_new_cycle (FILE *, int, rtx, int, int, int *sort_p); | 214 static int sh_dfa_new_cycle (FILE *, int, rtx, int, int, int *sort_p); |
207 static short find_set_regmode_weight (rtx, enum machine_mode); | 215 static short find_set_regmode_weight (rtx, enum machine_mode); |
208 static short find_insn_regmode_weight (rtx, enum machine_mode); | 216 static short find_insn_regmode_weight (rtx, enum machine_mode); |
220 static int sh_variable_issue (FILE *, int, rtx, int); | 228 static int sh_variable_issue (FILE *, int, rtx, int); |
221 | 229 |
222 static bool sh_function_ok_for_sibcall (tree, tree); | 230 static bool sh_function_ok_for_sibcall (tree, tree); |
223 | 231 |
224 static bool sh_cannot_modify_jumps_p (void); | 232 static bool sh_cannot_modify_jumps_p (void); |
225 static enum reg_class sh_target_reg_class (void); | 233 static reg_class_t sh_target_reg_class (void); |
226 static bool sh_optimize_target_register_callee_saved (bool); | 234 static bool sh_optimize_target_register_callee_saved (bool); |
227 static bool sh_ms_bitfield_layout_p (const_tree); | 235 static bool sh_ms_bitfield_layout_p (const_tree); |
228 | 236 |
229 static void sh_init_builtins (void); | 237 static void sh_init_builtins (void); |
230 static tree sh_builtin_decl (unsigned, bool); | 238 static tree sh_builtin_decl (unsigned, bool); |
243 static bool sh_cannot_copy_insn_p (rtx); | 251 static bool sh_cannot_copy_insn_p (rtx); |
244 static bool sh_rtx_costs (rtx, int, int, int *, bool); | 252 static bool sh_rtx_costs (rtx, int, int, int *, bool); |
245 static int sh_address_cost (rtx, bool); | 253 static int sh_address_cost (rtx, bool); |
246 static int sh_pr_n_sets (void); | 254 static int sh_pr_n_sets (void); |
247 static rtx sh_allocate_initial_value (rtx); | 255 static rtx sh_allocate_initial_value (rtx); |
256 static reg_class_t sh_preferred_reload_class (rtx, reg_class_t); | |
257 static reg_class_t sh_secondary_reload (bool, rtx, reg_class_t, | |
258 enum machine_mode, | |
259 struct secondary_reload_info *); | |
248 static bool sh_legitimate_address_p (enum machine_mode, rtx, bool); | 260 static bool sh_legitimate_address_p (enum machine_mode, rtx, bool); |
249 static rtx sh_legitimize_address (rtx, rtx, enum machine_mode); | 261 static rtx sh_legitimize_address (rtx, rtx, enum machine_mode); |
262 static rtx sh_delegitimize_address (rtx); | |
250 static int shmedia_target_regs_stack_space (HARD_REG_SET *); | 263 static int shmedia_target_regs_stack_space (HARD_REG_SET *); |
251 static int shmedia_reserve_space_for_target_registers_p (int, HARD_REG_SET *); | 264 static int shmedia_reserve_space_for_target_registers_p (int, HARD_REG_SET *); |
252 static int shmedia_target_regs_stack_adjust (HARD_REG_SET *); | 265 static int shmedia_target_regs_stack_adjust (HARD_REG_SET *); |
253 static int scavenge_reg (HARD_REG_SET *s); | 266 static int scavenge_reg (HARD_REG_SET *s); |
254 struct save_schedule_s; | 267 struct save_schedule_s; |
255 static struct save_entry_s *sh5_schedule_saves (HARD_REG_SET *, | 268 static struct save_entry_s *sh5_schedule_saves (HARD_REG_SET *, |
256 struct save_schedule_s *, int); | 269 struct save_schedule_s *, int); |
257 | 270 |
258 static rtx sh_struct_value_rtx (tree, int); | 271 static rtx sh_struct_value_rtx (tree, int); |
259 static rtx sh_function_value (const_tree, const_tree, bool); | 272 static rtx sh_function_value (const_tree, const_tree, bool); |
273 static bool sh_function_value_regno_p (const unsigned int); | |
260 static rtx sh_libcall_value (enum machine_mode, const_rtx); | 274 static rtx sh_libcall_value (enum machine_mode, const_rtx); |
261 static bool sh_return_in_memory (const_tree, const_tree); | 275 static bool sh_return_in_memory (const_tree, const_tree); |
262 static rtx sh_builtin_saveregs (void); | 276 static rtx sh_builtin_saveregs (void); |
263 static void sh_setup_incoming_varargs (CUMULATIVE_ARGS *, enum machine_mode, tree, int *, int); | 277 static void sh_setup_incoming_varargs (CUMULATIVE_ARGS *, enum machine_mode, tree, int *, int); |
264 static bool sh_strict_argument_naming (CUMULATIVE_ARGS *); | 278 static bool sh_strict_argument_naming (CUMULATIVE_ARGS *); |
276 const_tree, bool); | 290 const_tree, bool); |
277 static bool sh_callee_copies (CUMULATIVE_ARGS *, enum machine_mode, | 291 static bool sh_callee_copies (CUMULATIVE_ARGS *, enum machine_mode, |
278 const_tree, bool); | 292 const_tree, bool); |
279 static int sh_arg_partial_bytes (CUMULATIVE_ARGS *, enum machine_mode, | 293 static int sh_arg_partial_bytes (CUMULATIVE_ARGS *, enum machine_mode, |
280 tree, bool); | 294 tree, bool); |
295 static void sh_function_arg_advance (CUMULATIVE_ARGS *, enum machine_mode, | |
296 const_tree, bool); | |
297 static rtx sh_function_arg (CUMULATIVE_ARGS *, enum machine_mode, | |
298 const_tree, bool); | |
281 static bool sh_scalar_mode_supported_p (enum machine_mode); | 299 static bool sh_scalar_mode_supported_p (enum machine_mode); |
282 static int sh_dwarf_calling_convention (const_tree); | 300 static int sh_dwarf_calling_convention (const_tree); |
283 static void sh_encode_section_info (tree, rtx, int); | 301 static void sh_encode_section_info (tree, rtx, int); |
284 static int sh2a_function_vector_p (tree); | 302 static int sh2a_function_vector_p (tree); |
285 static void sh_trampoline_init (rtx, tree, rtx); | 303 static void sh_trampoline_init (rtx, tree, rtx); |
286 static rtx sh_trampoline_adjust_address (rtx); | 304 static rtx sh_trampoline_adjust_address (rtx); |
305 static void sh_conditional_register_usage (void); | |
287 | 306 |
288 static const struct attribute_spec sh_attribute_table[] = | 307 static const struct attribute_spec sh_attribute_table[] = |
289 { | 308 { |
290 /* { name, min_len, max_len, decl_req, type_req, fn_type_req, handler } */ | 309 /* { name, min_len, max_len, decl_req, type_req, fn_type_req, handler } */ |
291 { "interrupt_handler", 0, 0, true, false, false, sh_handle_interrupt_handler_attribute }, | 310 { "interrupt_handler", 0, 0, true, false, false, sh_handle_interrupt_handler_attribute }, |
307 { "dllimport", 0, 0, true, false, false, sh_symbian_handle_dll_attribute }, | 326 { "dllimport", 0, 0, true, false, false, sh_symbian_handle_dll_attribute }, |
308 { "dllexport", 0, 0, true, false, false, sh_symbian_handle_dll_attribute }, | 327 { "dllexport", 0, 0, true, false, false, sh_symbian_handle_dll_attribute }, |
309 #endif | 328 #endif |
310 { NULL, 0, 0, false, false, false, NULL } | 329 { NULL, 0, 0, false, false, false, NULL } |
311 }; | 330 }; |
331 | |
332 /* Set default optimization options. */ | |
333 static const struct default_options sh_option_optimization_table[] = | |
334 { | |
335 { OPT_LEVELS_1_PLUS, OPT_fomit_frame_pointer, NULL, 1 }, | |
336 { OPT_LEVELS_1_PLUS_SPEED_ONLY, OPT_mdiv_, "inv:minlat", 1 }, | |
337 { OPT_LEVELS_SIZE, OPT_mdiv_, SH_DIV_STR_FOR_SIZE, 1 }, | |
338 { OPT_LEVELS_0_ONLY, OPT_mdiv_, "", 1 }, | |
339 { OPT_LEVELS_SIZE, OPT_mcbranchdi, NULL, 0 }, | |
340 /* We can't meaningfully test TARGET_SHMEDIA here, because -m | |
341 options haven't been parsed yet, hence we'd read only the | |
342 default. sh_target_reg_class will return NO_REGS if this is | |
343 not SHMEDIA, so it's OK to always set | |
344 flag_branch_target_load_optimize. */ | |
345 { OPT_LEVELS_2_PLUS, OPT_fbranch_target_load_optimize, NULL, 1 }, | |
346 { OPT_LEVELS_NONE, 0, NULL, 0 } | |
347 }; | |
312 | 348 |
313 /* Initialize the GCC target structure. */ | 349 /* Initialize the GCC target structure. */ |
314 #undef TARGET_ATTRIBUTE_TABLE | 350 #undef TARGET_ATTRIBUTE_TABLE |
315 #define TARGET_ATTRIBUTE_TABLE sh_attribute_table | 351 #define TARGET_ATTRIBUTE_TABLE sh_attribute_table |
316 | 352 |
318 #undef TARGET_ASM_UNALIGNED_HI_OP | 354 #undef TARGET_ASM_UNALIGNED_HI_OP |
319 #define TARGET_ASM_UNALIGNED_HI_OP "\t.uaword\t" | 355 #define TARGET_ASM_UNALIGNED_HI_OP "\t.uaword\t" |
320 #undef TARGET_ASM_UNALIGNED_SI_OP | 356 #undef TARGET_ASM_UNALIGNED_SI_OP |
321 #define TARGET_ASM_UNALIGNED_SI_OP "\t.ualong\t" | 357 #define TARGET_ASM_UNALIGNED_SI_OP "\t.ualong\t" |
322 | 358 |
323 /* These are NULLed out on non-SH5 in OVERRIDE_OPTIONS. */ | 359 /* These are NULLed out on non-SH5 in TARGET_OPTION_OVERRIDE. */ |
324 #undef TARGET_ASM_UNALIGNED_DI_OP | 360 #undef TARGET_ASM_UNALIGNED_DI_OP |
325 #define TARGET_ASM_UNALIGNED_DI_OP "\t.uaquad\t" | 361 #define TARGET_ASM_UNALIGNED_DI_OP "\t.uaquad\t" |
326 #undef TARGET_ASM_ALIGNED_DI_OP | 362 #undef TARGET_ASM_ALIGNED_DI_OP |
327 #define TARGET_ASM_ALIGNED_DI_OP "\t.quad\t" | 363 #define TARGET_ASM_ALIGNED_DI_OP "\t.quad\t" |
328 | 364 |
365 #undef TARGET_OPTION_OVERRIDE | |
366 #define TARGET_OPTION_OVERRIDE sh_option_override | |
367 #undef TARGET_OPTION_OPTIMIZATION_TABLE | |
368 #define TARGET_OPTION_OPTIMIZATION_TABLE sh_option_optimization_table | |
369 #undef TARGET_OPTION_INIT_STRUCT | |
370 #define TARGET_OPTION_INIT_STRUCT sh_option_init_struct | |
371 #undef TARGET_OPTION_DEFAULT_PARAMS | |
372 #define TARGET_OPTION_DEFAULT_PARAMS sh_option_default_params | |
373 | |
374 #undef TARGET_PRINT_OPERAND | |
375 #define TARGET_PRINT_OPERAND sh_print_operand | |
376 #undef TARGET_PRINT_OPERAND_ADDRESS | |
377 #define TARGET_PRINT_OPERAND_ADDRESS sh_print_operand_address | |
378 #undef TARGET_PRINT_OPERAND_PUNCT_VALID_P | |
379 #define TARGET_PRINT_OPERAND_PUNCT_VALID_P sh_print_operand_punct_valid_p | |
380 #undef TARGET_ASM_OUTPUT_ADDR_CONST_EXTRA | |
381 #define TARGET_ASM_OUTPUT_ADDR_CONST_EXTRA sh_asm_output_addr_const_extra | |
382 | |
329 #undef TARGET_ASM_FUNCTION_EPILOGUE | 383 #undef TARGET_ASM_FUNCTION_EPILOGUE |
330 #define TARGET_ASM_FUNCTION_EPILOGUE sh_output_function_epilogue | 384 #define TARGET_ASM_FUNCTION_EPILOGUE sh_output_function_epilogue |
331 | 385 |
332 #undef TARGET_ASM_OUTPUT_MI_THUNK | 386 #undef TARGET_ASM_OUTPUT_MI_THUNK |
333 #define TARGET_ASM_OUTPUT_MI_THUNK sh_output_mi_thunk | 387 #define TARGET_ASM_OUTPUT_MI_THUNK sh_output_mi_thunk |
342 | 396 |
343 #undef TARGET_DEFAULT_TARGET_FLAGS | 397 #undef TARGET_DEFAULT_TARGET_FLAGS |
344 #define TARGET_DEFAULT_TARGET_FLAGS TARGET_DEFAULT | 398 #define TARGET_DEFAULT_TARGET_FLAGS TARGET_DEFAULT |
345 #undef TARGET_HANDLE_OPTION | 399 #undef TARGET_HANDLE_OPTION |
346 #define TARGET_HANDLE_OPTION sh_handle_option | 400 #define TARGET_HANDLE_OPTION sh_handle_option |
401 | |
402 #undef TARGET_REGISTER_MOVE_COST | |
403 #define TARGET_REGISTER_MOVE_COST sh_register_move_cost | |
347 | 404 |
348 #undef TARGET_INSERT_ATTRIBUTES | 405 #undef TARGET_INSERT_ATTRIBUTES |
349 #define TARGET_INSERT_ATTRIBUTES sh_insert_attributes | 406 #define TARGET_INSERT_ATTRIBUTES sh_insert_attributes |
350 | 407 |
351 #undef TARGET_SCHED_ADJUST_COST | 408 #undef TARGET_SCHED_ADJUST_COST |
408 #define TARGET_SCHED_REORDER2 sh_reorder2 | 465 #define TARGET_SCHED_REORDER2 sh_reorder2 |
409 | 466 |
410 #undef TARGET_SCHED_INIT | 467 #undef TARGET_SCHED_INIT |
411 #define TARGET_SCHED_INIT sh_md_init | 468 #define TARGET_SCHED_INIT sh_md_init |
412 | 469 |
470 #undef TARGET_DELEGITIMIZE_ADDRESS | |
471 #define TARGET_DELEGITIMIZE_ADDRESS sh_delegitimize_address | |
472 | |
413 #undef TARGET_LEGITIMIZE_ADDRESS | 473 #undef TARGET_LEGITIMIZE_ADDRESS |
414 #define TARGET_LEGITIMIZE_ADDRESS sh_legitimize_address | 474 #define TARGET_LEGITIMIZE_ADDRESS sh_legitimize_address |
415 | 475 |
416 #undef TARGET_CANNOT_MODIFY_JUMPS_P | 476 #undef TARGET_CANNOT_MODIFY_JUMPS_P |
417 #define TARGET_CANNOT_MODIFY_JUMPS_P sh_cannot_modify_jumps_p | 477 #define TARGET_CANNOT_MODIFY_JUMPS_P sh_cannot_modify_jumps_p |
459 #undef TARGET_PROMOTE_FUNCTION_MODE | 519 #undef TARGET_PROMOTE_FUNCTION_MODE |
460 #define TARGET_PROMOTE_FUNCTION_MODE sh_promote_function_mode | 520 #define TARGET_PROMOTE_FUNCTION_MODE sh_promote_function_mode |
461 | 521 |
462 #undef TARGET_FUNCTION_VALUE | 522 #undef TARGET_FUNCTION_VALUE |
463 #define TARGET_FUNCTION_VALUE sh_function_value | 523 #define TARGET_FUNCTION_VALUE sh_function_value |
524 #undef TARGET_FUNCTION_VALUE_REGNO_P | |
525 #define TARGET_FUNCTION_VALUE_REGNO_P sh_function_value_regno_p | |
464 #undef TARGET_LIBCALL_VALUE | 526 #undef TARGET_LIBCALL_VALUE |
465 #define TARGET_LIBCALL_VALUE sh_libcall_value | 527 #define TARGET_LIBCALL_VALUE sh_libcall_value |
466 #undef TARGET_STRUCT_VALUE_RTX | 528 #undef TARGET_STRUCT_VALUE_RTX |
467 #define TARGET_STRUCT_VALUE_RTX sh_struct_value_rtx | 529 #define TARGET_STRUCT_VALUE_RTX sh_struct_value_rtx |
468 #undef TARGET_RETURN_IN_MEMORY | 530 #undef TARGET_RETURN_IN_MEMORY |
482 #define TARGET_PASS_BY_REFERENCE sh_pass_by_reference | 544 #define TARGET_PASS_BY_REFERENCE sh_pass_by_reference |
483 #undef TARGET_CALLEE_COPIES | 545 #undef TARGET_CALLEE_COPIES |
484 #define TARGET_CALLEE_COPIES sh_callee_copies | 546 #define TARGET_CALLEE_COPIES sh_callee_copies |
485 #undef TARGET_ARG_PARTIAL_BYTES | 547 #undef TARGET_ARG_PARTIAL_BYTES |
486 #define TARGET_ARG_PARTIAL_BYTES sh_arg_partial_bytes | 548 #define TARGET_ARG_PARTIAL_BYTES sh_arg_partial_bytes |
549 #undef TARGET_FUNCTION_ARG | |
550 #define TARGET_FUNCTION_ARG sh_function_arg | |
551 #undef TARGET_FUNCTION_ARG_ADVANCE | |
552 #define TARGET_FUNCTION_ARG_ADVANCE sh_function_arg_advance | |
487 | 553 |
488 #undef TARGET_BUILD_BUILTIN_VA_LIST | 554 #undef TARGET_BUILD_BUILTIN_VA_LIST |
489 #define TARGET_BUILD_BUILTIN_VA_LIST sh_build_builtin_va_list | 555 #define TARGET_BUILD_BUILTIN_VA_LIST sh_build_builtin_va_list |
490 #undef TARGET_EXPAND_BUILTIN_VA_START | 556 #undef TARGET_EXPAND_BUILTIN_VA_START |
491 #define TARGET_EXPAND_BUILTIN_VA_START sh_va_start | 557 #define TARGET_EXPAND_BUILTIN_VA_START sh_va_start |
526 | 592 |
527 #endif /* SYMBIAN */ | 593 #endif /* SYMBIAN */ |
528 | 594 |
529 #undef TARGET_SECONDARY_RELOAD | 595 #undef TARGET_SECONDARY_RELOAD |
530 #define TARGET_SECONDARY_RELOAD sh_secondary_reload | 596 #define TARGET_SECONDARY_RELOAD sh_secondary_reload |
597 | |
598 #undef TARGET_PREFERRED_RELOAD_CLASS | |
599 #define TARGET_PREFERRED_RELOAD_CLASS sh_preferred_reload_class | |
600 | |
601 #undef TARGET_CONDITIONAL_REGISTER_USAGE | |
602 #define TARGET_CONDITIONAL_REGISTER_USAGE sh_conditional_register_usage | |
531 | 603 |
532 #undef TARGET_LEGITIMATE_ADDRESS_P | 604 #undef TARGET_LEGITIMATE_ADDRESS_P |
533 #define TARGET_LEGITIMATE_ADDRESS_P sh_legitimate_address_p | 605 #define TARGET_LEGITIMATE_ADDRESS_P sh_legitimate_address_p |
534 | 606 |
535 #undef TARGET_TRAMPOLINE_INIT | 607 #undef TARGET_TRAMPOLINE_INIT |
661 default: | 733 default: |
662 return true; | 734 return true; |
663 } | 735 } |
664 } | 736 } |
665 | 737 |
666 /* Set default optimization options. */ | 738 /* Implement TARGET_OPTION_INIT_STRUCT. */ |
667 void | 739 static void |
668 sh_optimization_options (int level ATTRIBUTE_UNUSED, int size ATTRIBUTE_UNUSED) | 740 sh_option_init_struct (struct gcc_options *opts) |
669 { | 741 { |
670 if (level) | 742 /* We can't meaningfully test TARGET_SH2E / TARGET_IEEE |
671 { | 743 here, so leave it to TARGET_OPTION_OVERRIDE to set |
672 if (!size) | 744 flag_finite_math_only. We set it to 2 here so we know if the user |
673 sh_div_str = "inv:minlat"; | 745 explicitly requested this to be on or off. */ |
674 } | 746 opts->x_flag_finite_math_only = 2; |
675 if (size) | 747 } |
676 { | 748 |
677 target_flags |= MASK_SMALLCODE; | 749 /* Implement TARGET_OPTION_DEFAULT_PARAMS. */ |
678 sh_div_str = SH_DIV_STR_FOR_SIZE ; | 750 static void |
679 } | 751 sh_option_default_params (void) |
680 else | 752 { |
681 TARGET_CBRANCHDI4 = 1; | 753 set_default_param_value (PARAM_SIMULTANEOUS_PREFETCHES, 2); |
682 /* We can't meaningfully test TARGET_SHMEDIA here, because -m options | 754 } |
683 haven't been parsed yet, hence we'd read only the default. | 755 |
684 sh_target_reg_class will return NO_REGS if this is not SHMEDIA, so | 756 /* Implement TARGET_OPTION_OVERRIDE macro. Validate and override |
685 it's OK to always set flag_branch_target_load_optimize. */ | 757 various options, and do some machine dependent initialization. */ |
686 if (level > 1) | 758 static void |
687 { | 759 sh_option_override (void) |
688 flag_branch_target_load_optimize = 1; | |
689 if (!size) | |
690 target_flags |= MASK_SAVE_ALL_TARGET_REGS; | |
691 } | |
692 /* Likewise, we can't meaningfully test TARGET_SH2E / TARGET_IEEE | |
693 here, so leave it to OVERRIDE_OPTIONS to set | |
694 flag_finite_math_only. We set it to 2 here so we know if the user | |
695 explicitly requested this to be on or off. */ | |
696 flag_finite_math_only = 2; | |
697 /* If flag_schedule_insns is 1, we set it to 2 here so we know if | |
698 the user explicitly requested this to be on or off. */ | |
699 if (flag_schedule_insns > 0) | |
700 flag_schedule_insns = 2; | |
701 | |
702 set_param_value ("simultaneous-prefetches", 2); | |
703 } | |
704 | |
705 /* Implement OVERRIDE_OPTIONS macro. Validate and override various | |
706 options, and do some machine dependent initialization. */ | |
707 void | |
708 sh_override_options (void) | |
709 { | 760 { |
710 int regno; | 761 int regno; |
711 | 762 |
712 SUBTARGET_OVERRIDE_OPTIONS; | 763 SUBTARGET_OVERRIDE_OPTIONS; |
764 if (optimize > 1 && !optimize_size) | |
765 target_flags |= MASK_SAVE_ALL_TARGET_REGS; | |
713 if (flag_finite_math_only == 2) | 766 if (flag_finite_math_only == 2) |
714 flag_finite_math_only | 767 flag_finite_math_only |
715 = !flag_signaling_nans && TARGET_SH2E && ! TARGET_IEEE; | 768 = !flag_signaling_nans && TARGET_SH2E && ! TARGET_IEEE; |
716 if (TARGET_SH2E && !flag_finite_math_only) | 769 if (TARGET_SH2E && !flag_finite_math_only) |
717 target_flags |= MASK_IEEE; | 770 target_flags |= MASK_IEEE; |
880 spill failures for R0 in reload. See PR 22553 and the thread | 933 spill failures for R0 in reload. See PR 22553 and the thread |
881 on gcc-patches | 934 on gcc-patches |
882 <http://gcc.gnu.org/ml/gcc-patches/2005-10/msg00816.html>. */ | 935 <http://gcc.gnu.org/ml/gcc-patches/2005-10/msg00816.html>. */ |
883 else if (flag_exceptions) | 936 else if (flag_exceptions) |
884 { | 937 { |
885 if (flag_schedule_insns == 1) | 938 if (flag_schedule_insns && global_options_set.x_flag_schedule_insns) |
886 warning (0, "ignoring -fschedule-insns because of exception handling bug"); | 939 warning (0, "ignoring -fschedule-insns because of exception handling bug"); |
887 flag_schedule_insns = 0; | 940 flag_schedule_insns = 0; |
888 } | 941 } |
889 else if (flag_schedule_insns == 2) | 942 else if (flag_schedule_insns |
943 && !global_options_set.x_flag_schedule_insns) | |
890 flag_schedule_insns = 0; | 944 flag_schedule_insns = 0; |
891 } | 945 } |
892 | 946 |
893 if ((target_flags_explicit & MASK_ACCUMULATE_OUTGOING_ARGS) == 0) | 947 if ((target_flags_explicit & MASK_ACCUMULATE_OUTGOING_ARGS) == 0) |
894 target_flags |= MASK_ACCUMULATE_OUTGOING_ARGS; | 948 target_flags |= MASK_ACCUMULATE_OUTGOING_ARGS; |
942 SH1: 32 bit alignment is faster, because instructions are always | 996 SH1: 32 bit alignment is faster, because instructions are always |
943 fetched as a pair from a longword boundary. | 997 fetched as a pair from a longword boundary. |
944 SH2 .. SH5 : align to cache line start. */ | 998 SH2 .. SH5 : align to cache line start. */ |
945 if (align_functions == 0) | 999 if (align_functions == 0) |
946 align_functions | 1000 align_functions |
947 = TARGET_SMALLCODE ? FUNCTION_BOUNDARY/8 : (1 << CACHE_LOG); | 1001 = optimize_size ? FUNCTION_BOUNDARY/8 : (1 << CACHE_LOG); |
948 /* The linker relaxation code breaks when a function contains | 1002 /* The linker relaxation code breaks when a function contains |
949 alignments that are larger than that at the start of a | 1003 alignments that are larger than that at the start of a |
950 compilation unit. */ | 1004 compilation unit. */ |
951 if (TARGET_RELAX) | 1005 if (TARGET_RELAX) |
952 { | 1006 { |
960 align_functions = min_align; | 1014 align_functions = min_align; |
961 } | 1015 } |
962 | 1016 |
963 if (sh_fixed_range_str) | 1017 if (sh_fixed_range_str) |
964 sh_fix_range (sh_fixed_range_str); | 1018 sh_fix_range (sh_fixed_range_str); |
1019 | |
1020 /* This target defaults to strict volatile bitfields. */ | |
1021 if (flag_strict_volatile_bitfields < 0) | |
1022 flag_strict_volatile_bitfields = 1; | |
965 } | 1023 } |
966 | 1024 |
967 /* Print the operand address in x to the stream. */ | 1025 /* Print the operand address in x to the stream. */ |
968 | 1026 |
969 void | 1027 static void |
970 print_operand_address (FILE *stream, rtx x) | 1028 sh_print_operand_address (FILE *stream, rtx x) |
971 { | 1029 { |
972 switch (GET_CODE (x)) | 1030 switch (GET_CODE (x)) |
973 { | 1031 { |
974 case REG: | 1032 case REG: |
975 case SUBREG: | 1033 case SUBREG: |
1043 'W' print the position of a single bit cleared. | 1101 'W' print the position of a single bit cleared. |
1044 't' print a memory address which is a register. | 1102 't' print a memory address which is a register. |
1045 'u' prints the lowest 16 bits of CONST_INT, as an unsigned value. | 1103 'u' prints the lowest 16 bits of CONST_INT, as an unsigned value. |
1046 'o' output an operator. */ | 1104 'o' output an operator. */ |
1047 | 1105 |
1048 void | 1106 static void |
1049 print_operand (FILE *stream, rtx x, int code) | 1107 sh_print_operand (FILE *stream, rtx x, int code) |
1050 { | 1108 { |
1051 int regno; | 1109 int regno; |
1052 enum machine_mode mode; | 1110 enum machine_mode mode; |
1053 | 1111 |
1054 switch (code) | 1112 switch (code) |
1118 fputs (reg_names[regno], (stream)); | 1176 fputs (reg_names[regno], (stream)); |
1119 } | 1177 } |
1120 else if (MEM_P (x)) | 1178 else if (MEM_P (x)) |
1121 { | 1179 { |
1122 x = adjust_address (x, SImode, 4 * LSW); | 1180 x = adjust_address (x, SImode, 4 * LSW); |
1123 print_operand_address (stream, XEXP (x, 0)); | 1181 sh_print_operand_address (stream, XEXP (x, 0)); |
1124 } | 1182 } |
1125 else | 1183 else |
1126 { | 1184 { |
1127 rtx sub = NULL_RTX; | 1185 rtx sub = NULL_RTX; |
1128 | 1186 |
1130 if (mode == VOIDmode) | 1188 if (mode == VOIDmode) |
1131 mode = DImode; | 1189 mode = DImode; |
1132 if (GET_MODE_SIZE (mode) >= 8) | 1190 if (GET_MODE_SIZE (mode) >= 8) |
1133 sub = simplify_subreg (SImode, x, mode, 4 * LSW); | 1191 sub = simplify_subreg (SImode, x, mode, 4 * LSW); |
1134 if (sub) | 1192 if (sub) |
1135 print_operand (stream, sub, 0); | 1193 sh_print_operand (stream, sub, 0); |
1136 else | 1194 else |
1137 output_operand_lossage ("invalid operand to %%R"); | 1195 output_operand_lossage ("invalid operand to %%R"); |
1138 } | 1196 } |
1139 break; | 1197 break; |
1140 case 'S': | 1198 case 'S': |
1145 fputs (reg_names[regno], (stream)); | 1203 fputs (reg_names[regno], (stream)); |
1146 } | 1204 } |
1147 else if (MEM_P (x)) | 1205 else if (MEM_P (x)) |
1148 { | 1206 { |
1149 x = adjust_address (x, SImode, 4 * MSW); | 1207 x = adjust_address (x, SImode, 4 * MSW); |
1150 print_operand_address (stream, XEXP (x, 0)); | 1208 sh_print_operand_address (stream, XEXP (x, 0)); |
1151 } | 1209 } |
1152 else | 1210 else |
1153 { | 1211 { |
1154 rtx sub = NULL_RTX; | 1212 rtx sub = NULL_RTX; |
1155 | 1213 |
1157 if (mode == VOIDmode) | 1215 if (mode == VOIDmode) |
1158 mode = DImode; | 1216 mode = DImode; |
1159 if (GET_MODE_SIZE (mode) >= 8) | 1217 if (GET_MODE_SIZE (mode) >= 8) |
1160 sub = simplify_subreg (SImode, x, mode, 4 * MSW); | 1218 sub = simplify_subreg (SImode, x, mode, 4 * MSW); |
1161 if (sub) | 1219 if (sub) |
1162 print_operand (stream, sub, 0); | 1220 sh_print_operand (stream, sub, 0); |
1163 else | 1221 else |
1164 output_operand_lossage ("invalid operand to %%S"); | 1222 output_operand_lossage ("invalid operand to %%S"); |
1165 } | 1223 } |
1166 break; | 1224 break; |
1167 case 'T': | 1225 case 'T': |
1173 break; | 1231 break; |
1174 case MEM: | 1232 case MEM: |
1175 if (GET_CODE (XEXP (x, 0)) != PRE_DEC | 1233 if (GET_CODE (XEXP (x, 0)) != PRE_DEC |
1176 && GET_CODE (XEXP (x, 0)) != POST_INC) | 1234 && GET_CODE (XEXP (x, 0)) != POST_INC) |
1177 x = adjust_address (x, SImode, 4); | 1235 x = adjust_address (x, SImode, 4); |
1178 print_operand_address (stream, XEXP (x, 0)); | 1236 sh_print_operand_address (stream, XEXP (x, 0)); |
1179 break; | 1237 break; |
1180 default: | 1238 default: |
1181 break; | 1239 break; |
1182 } | 1240 } |
1183 break; | 1241 break; |
1187 x = XEXP (x, 0); | 1245 x = XEXP (x, 0); |
1188 switch (GET_CODE (x)) | 1246 switch (GET_CODE (x)) |
1189 { | 1247 { |
1190 case REG: | 1248 case REG: |
1191 case SUBREG: | 1249 case SUBREG: |
1192 print_operand (stream, x, 0); | 1250 sh_print_operand (stream, x, 0); |
1193 break; | 1251 break; |
1194 default: | 1252 default: |
1195 break; | 1253 break; |
1196 } | 1254 } |
1197 break; | 1255 break; |
1246 case 'U': | 1304 case 'U': |
1247 switch (GET_CODE (x)) | 1305 switch (GET_CODE (x)) |
1248 { | 1306 { |
1249 case REG: | 1307 case REG: |
1250 case SUBREG: | 1308 case SUBREG: |
1251 print_operand (stream, x, 0); | 1309 sh_print_operand (stream, x, 0); |
1252 fputs (", 0", stream); | 1310 fputs (", 0", stream); |
1253 break; | 1311 break; |
1254 | 1312 |
1255 case PLUS: | 1313 case PLUS: |
1256 print_operand (stream, XEXP (x, 0), 0); | 1314 sh_print_operand (stream, XEXP (x, 0), 0); |
1257 fputs (", ", stream); | 1315 fputs (", ", stream); |
1258 print_operand (stream, XEXP (x, 1), 0); | 1316 sh_print_operand (stream, XEXP (x, 1), 0); |
1259 break; | 1317 break; |
1260 | 1318 |
1261 default: | 1319 default: |
1262 gcc_unreachable (); | 1320 gcc_unreachable (); |
1263 } | 1321 } |
1396 break; | 1454 break; |
1397 } | 1455 } |
1398 break; | 1456 break; |
1399 } | 1457 } |
1400 } | 1458 } |
1459 | |
1460 static bool | |
1461 sh_print_operand_punct_valid_p (unsigned char code) | |
1462 { | |
1463 return (code == '.' || code == '#' || code == '@' || code == ',' | |
1464 || code == '$' || code == '\'' || code == '>'); | |
1465 } | |
1466 | |
1467 /* Implement TARGET_ASM_OUTPUT_ADDR_CONST_EXTRA. */ | |
1468 | |
1469 static bool | |
1470 sh_asm_output_addr_const_extra (FILE *file, rtx x) | |
1471 { | |
1472 if (GET_CODE (x) == UNSPEC) | |
1473 { | |
1474 switch (XINT (x, 1)) | |
1475 { | |
1476 case UNSPEC_DATALABEL: | |
1477 fputs ("datalabel ", file); | |
1478 output_addr_const (file, XVECEXP (x, 0, 0)); | |
1479 break; | |
1480 case UNSPEC_PIC: | |
1481 /* GLOBAL_OFFSET_TABLE or local symbols, no suffix. */ | |
1482 output_addr_const (file, XVECEXP (x, 0, 0)); | |
1483 break; | |
1484 case UNSPEC_GOT: | |
1485 output_addr_const (file, XVECEXP (x, 0, 0)); | |
1486 fputs ("@GOT", file); | |
1487 break; | |
1488 case UNSPEC_GOTOFF: | |
1489 output_addr_const (file, XVECEXP (x, 0, 0)); | |
1490 fputs ("@GOTOFF", file); | |
1491 break; | |
1492 case UNSPEC_PLT: | |
1493 output_addr_const (file, XVECEXP (x, 0, 0)); | |
1494 fputs ("@PLT", file); | |
1495 break; | |
1496 case UNSPEC_GOTPLT: | |
1497 output_addr_const (file, XVECEXP (x, 0, 0)); | |
1498 fputs ("@GOTPLT", file); | |
1499 break; | |
1500 case UNSPEC_DTPOFF: | |
1501 output_addr_const (file, XVECEXP (x, 0, 0)); | |
1502 fputs ("@DTPOFF", file); | |
1503 break; | |
1504 case UNSPEC_GOTTPOFF: | |
1505 output_addr_const (file, XVECEXP (x, 0, 0)); | |
1506 fputs ("@GOTTPOFF", file); | |
1507 break; | |
1508 case UNSPEC_TPOFF: | |
1509 output_addr_const (file, XVECEXP (x, 0, 0)); | |
1510 fputs ("@TPOFF", file); | |
1511 break; | |
1512 case UNSPEC_CALLER: | |
1513 { | |
1514 char name[32]; | |
1515 /* LPCS stands for Label for PIC Call Site. */ | |
1516 targetm.asm_out.generate_internal_label (name, "LPCS", | |
1517 INTVAL (XVECEXP (x, 0, 0))); | |
1518 assemble_name (file, name); | |
1519 } | |
1520 break; | |
1521 case UNSPEC_EXTRACT_S16: | |
1522 case UNSPEC_EXTRACT_U16: | |
1523 { | |
1524 rtx val, shift; | |
1525 | |
1526 val = XVECEXP (x, 0, 0); | |
1527 shift = XVECEXP (x, 0, 1); | |
1528 fputc ('(', file); | |
1529 if (shift != const0_rtx) | |
1530 fputc ('(', file); | |
1531 if (GET_CODE (val) == CONST | |
1532 || GET_RTX_CLASS (GET_CODE (val)) != RTX_OBJ) | |
1533 { | |
1534 fputc ('(', file); | |
1535 output_addr_const (file, val); | |
1536 fputc (')', file); | |
1537 } | |
1538 else | |
1539 output_addr_const (file, val); | |
1540 if (shift != const0_rtx) | |
1541 { | |
1542 fputs (" >> ", file); | |
1543 output_addr_const (file, shift); | |
1544 fputc (')', file); | |
1545 } | |
1546 fputs (" & 65535)", file); | |
1547 } | |
1548 break; | |
1549 case UNSPEC_SYMOFF: | |
1550 output_addr_const (file, XVECEXP (x, 0, 0)); | |
1551 fputc ('-', file); | |
1552 if (GET_CODE (XVECEXP (x, 0, 1)) == CONST) | |
1553 { | |
1554 fputc ('(', file); | |
1555 output_addr_const (file, XVECEXP (x, 0, 1)); | |
1556 fputc (')', file); | |
1557 } | |
1558 else | |
1559 output_addr_const (file, XVECEXP (x, 0, 1)); | |
1560 break; | |
1561 case UNSPEC_PCREL_SYMOFF: | |
1562 output_addr_const (file, XVECEXP (x, 0, 0)); | |
1563 fputs ("-(", file); | |
1564 output_addr_const (file, XVECEXP (x, 0, 1)); | |
1565 fputs ("-.)", file); | |
1566 break; | |
1567 default: | |
1568 return false; | |
1569 } | |
1570 return true; | |
1571 } | |
1572 else | |
1573 return false; | |
1574 } | |
1401 | 1575 |
1402 | 1576 |
1403 /* Encode symbol attributes of a SYMBOL_REF into its | 1577 /* Encode symbol attributes of a SYMBOL_REF into its |
1404 SYMBOL_REF_FLAGS. */ | 1578 SYMBOL_REF_FLAGS. */ |
1405 static void | 1579 static void |
1495 force_into (XEXP (operands[0], 0), r4); | 1669 force_into (XEXP (operands[0], 0), r4); |
1496 force_into (XEXP (operands[1], 0), r5); | 1670 force_into (XEXP (operands[1], 0), r5); |
1497 emit_insn (gen_block_move_real_i4 (func_addr_rtx)); | 1671 emit_insn (gen_block_move_real_i4 (func_addr_rtx)); |
1498 return 1; | 1672 return 1; |
1499 } | 1673 } |
1500 else if (! TARGET_SMALLCODE) | 1674 else if (! optimize_size) |
1501 { | 1675 { |
1502 const char *entry_name; | 1676 const char *entry_name; |
1503 rtx func_addr_rtx = gen_reg_rtx (Pmode); | 1677 rtx func_addr_rtx = gen_reg_rtx (Pmode); |
1504 int dwords; | 1678 int dwords; |
1505 rtx r4 = gen_rtx_REG (SImode, 4); | 1679 rtx r4 = gen_rtx_REG (SImode, 4); |
1534 return 1; | 1708 return 1; |
1535 } | 1709 } |
1536 | 1710 |
1537 /* This is the same number of bytes as a memcpy call, but to a different | 1711 /* This is the same number of bytes as a memcpy call, but to a different |
1538 less common function name, so this will occasionally use more space. */ | 1712 less common function name, so this will occasionally use more space. */ |
1539 if (! TARGET_SMALLCODE) | 1713 if (! optimize_size) |
1540 { | 1714 { |
1541 rtx func_addr_rtx = gen_reg_rtx (Pmode); | 1715 rtx func_addr_rtx = gen_reg_rtx (Pmode); |
1542 int final_switch, while_loop; | 1716 int final_switch, while_loop; |
1543 rtx r4 = gen_rtx_REG (SImode, 4); | 1717 rtx r4 = gen_rtx_REG (SImode, 4); |
1544 rtx r5 = gen_rtx_REG (SImode, 5); | 1718 rtx r5 = gen_rtx_REG (SImode, 5); |
2915 add the cost of the operand, but disregard the latter when inside loops | 3089 add the cost of the operand, but disregard the latter when inside loops |
2916 and loop invariant code motion is still to follow. | 3090 and loop invariant code motion is still to follow. |
2917 Using a multiply first and splitting it later if it's a loss | 3091 Using a multiply first and splitting it later if it's a loss |
2918 doesn't work because of different sign / zero extension semantics | 3092 doesn't work because of different sign / zero extension semantics |
2919 of multiplies vs. shifts. */ | 3093 of multiplies vs. shifts. */ |
2920 return TARGET_SMALLCODE ? 2 : 3; | 3094 return optimize_size ? 2 : 3; |
2921 | 3095 |
2922 if (TARGET_SH2) | 3096 if (TARGET_SH2) |
2923 { | 3097 { |
2924 /* We have a mul insn, so we can never take more than the mul and the | 3098 /* We have a mul insn, so we can never take more than the mul and the |
2925 read of the mac reg, but count more because of the latency and extra | 3099 read of the mac reg, but count more because of the latency and extra |
2926 reg usage. */ | 3100 reg usage. */ |
2927 if (TARGET_SMALLCODE) | 3101 if (optimize_size) |
2928 return 2; | 3102 return 2; |
2929 return 3; | 3103 return 3; |
2930 } | 3104 } |
2931 | 3105 |
2932 /* If we're aiming at small code, then just count the number of | 3106 /* If we're aiming at small code, then just count the number of |
2933 insns in a multiply call sequence. */ | 3107 insns in a multiply call sequence. */ |
2934 if (TARGET_SMALLCODE) | 3108 if (optimize_size) |
2935 return 5; | 3109 return 5; |
2936 | 3110 |
2937 /* Otherwise count all the insns in the routine we'd be calling too. */ | 3111 /* Otherwise count all the insns in the routine we'd be calling too. */ |
2938 return 20; | 3112 return 20; |
2939 } | 3113 } |
4600 } | 4774 } |
4601 } | 4775 } |
4602 /* For the SH1, we generate alignments even after jumps-around-jumps. */ | 4776 /* For the SH1, we generate alignments even after jumps-around-jumps. */ |
4603 else if (JUMP_P (from) | 4777 else if (JUMP_P (from) |
4604 && ! TARGET_SH2 | 4778 && ! TARGET_SH2 |
4605 && ! TARGET_SMALLCODE) | 4779 && ! optimize_size) |
4606 new_align = 4; | 4780 new_align = 4; |
4607 | 4781 |
4608 /* There is a possibility that a bf is transformed into a bf/s by the | 4782 /* There is a possibility that a bf is transformed into a bf/s by the |
4609 delay slot scheduler. */ | 4783 delay slot scheduler. */ |
4610 if (JUMP_P (from) && !JUMP_TABLE_DATA_P (from) | 4784 if (JUMP_P (from) && !JUMP_TABLE_DATA_P (from) |
5198 if (GET_CODE (PATTERN (prev)) == ADDR_DIFF_VEC) | 5372 if (GET_CODE (PATTERN (prev)) == ADDR_DIFF_VEC) |
5199 { | 5373 { |
5200 pat = PATTERN (prev); | 5374 pat = PATTERN (prev); |
5201 /* If this is a very small table, we want to keep the alignment after | 5375 /* If this is a very small table, we want to keep the alignment after |
5202 the table to the minimum for proper code alignment. */ | 5376 the table to the minimum for proper code alignment. */ |
5203 return ((TARGET_SMALLCODE | 5377 return ((optimize_size |
5204 || ((unsigned) XVECLEN (pat, 1) * GET_MODE_SIZE (GET_MODE (pat)) | 5378 || ((unsigned) XVECLEN (pat, 1) * GET_MODE_SIZE (GET_MODE (pat)) |
5205 <= (unsigned) 1 << (CACHE_LOG - 2))) | 5379 <= (unsigned) 1 << (CACHE_LOG - 2))) |
5206 ? 1 << TARGET_SHMEDIA : align_jumps_log); | 5380 ? 1 << TARGET_SHMEDIA : align_jumps_log); |
5207 } | 5381 } |
5208 | 5382 |
5209 if (TARGET_SMALLCODE) | 5383 if (optimize_size) |
5210 return 0; | 5384 return 0; |
5211 | 5385 |
5212 if (! TARGET_SH2 || ! optimize) | 5386 if (! TARGET_SH2 || ! optimize) |
5213 return align_jumps_log; | 5387 return align_jumps_log; |
5214 | 5388 |
6383 } | 6557 } |
6384 } | 6558 } |
6385 | 6559 |
6386 /* Push banked registers last to improve delay slot opportunities. */ | 6560 /* Push banked registers last to improve delay slot opportunities. */ |
6387 if (interrupt_handler) | 6561 if (interrupt_handler) |
6388 for (i = FIRST_BANKED_REG; i <= LAST_BANKED_REG; i++) | 6562 { |
6389 if (TEST_HARD_REG_BIT (*mask, i)) | 6563 bool use_movml = false; |
6390 push (i); | 6564 |
6565 if (TARGET_SH2A) | |
6566 { | |
6567 unsigned int count = 0; | |
6568 | |
6569 for (i = FIRST_BANKED_REG; i <= LAST_BANKED_REG; i++) | |
6570 if (TEST_HARD_REG_BIT (*mask, i)) | |
6571 count++; | |
6572 else | |
6573 break; | |
6574 | |
6575 /* Use movml when all banked registers are pushed. */ | |
6576 if (count == LAST_BANKED_REG - FIRST_BANKED_REG + 1) | |
6577 use_movml = true; | |
6578 } | |
6579 | |
6580 if (use_movml) | |
6581 { | |
6582 rtx x, mem, reg, set; | |
6583 rtx sp_reg = gen_rtx_REG (SImode, STACK_POINTER_REGNUM); | |
6584 | |
6585 /* We must avoid scheduling multiple store insn with another | |
6586 insns. */ | |
6587 emit_insn (gen_blockage ()); | |
6588 x = gen_movml_push_banked (sp_reg); | |
6589 x = frame_insn (x); | |
6590 for (i = FIRST_BANKED_REG; i <= LAST_BANKED_REG; i++) | |
6591 { | |
6592 mem = gen_rtx_MEM (SImode, plus_constant (sp_reg, i * 4)); | |
6593 reg = gen_rtx_REG (SImode, i); | |
6594 add_reg_note (x, REG_CFA_OFFSET, gen_rtx_SET (SImode, mem, reg)); | |
6595 } | |
6596 | |
6597 set = gen_rtx_SET (SImode, sp_reg, plus_constant (sp_reg, - 32)); | |
6598 add_reg_note (x, REG_CFA_ADJUST_CFA, set); | |
6599 emit_insn (gen_blockage ()); | |
6600 } | |
6601 else | |
6602 for (i = FIRST_BANKED_REG; i <= LAST_BANKED_REG; i++) | |
6603 if (TEST_HARD_REG_BIT (*mask, i)) | |
6604 push (i); | |
6605 } | |
6391 | 6606 |
6392 /* Don't push PR register for an ISR with RESBANK attribute assigned. */ | 6607 /* Don't push PR register for an ISR with RESBANK attribute assigned. */ |
6393 if (TEST_HARD_REG_BIT (*mask, PR_REG) && !sh_cfun_resbank_handler_p ()) | 6608 if (TEST_HARD_REG_BIT (*mask, PR_REG) && !sh_cfun_resbank_handler_p ()) |
6394 push (PR_REG); | 6609 push (PR_REG); |
6395 } | 6610 } |
6773 HARD_REG_SET live_regs_mask; | 6988 HARD_REG_SET live_regs_mask; |
6774 int d, i; | 6989 int d, i; |
6775 int d_rounding = 0; | 6990 int d_rounding = 0; |
6776 int save_flags = target_flags; | 6991 int save_flags = target_flags; |
6777 int pretend_args; | 6992 int pretend_args; |
6993 int stack_usage; | |
6778 tree sp_switch_attr | 6994 tree sp_switch_attr |
6779 = lookup_attribute ("sp_switch", DECL_ATTRIBUTES (current_function_decl)); | 6995 = lookup_attribute ("sp_switch", DECL_ATTRIBUTES (current_function_decl)); |
6780 | 6996 |
6781 current_function_interrupt = sh_cfun_interrupt_handler_p (); | 6997 current_function_interrupt = sh_cfun_interrupt_handler_p (); |
6782 | 6998 |
6785 pretend_args = crtl->args.pretend_args_size; | 7001 pretend_args = crtl->args.pretend_args_size; |
6786 if (TARGET_VARARGS_PRETEND_ARGS (current_function_decl) | 7002 if (TARGET_VARARGS_PRETEND_ARGS (current_function_decl) |
6787 && (NPARM_REGS(SImode) | 7003 && (NPARM_REGS(SImode) |
6788 > crtl->args.info.arg_count[(int) SH_ARG_INT])) | 7004 > crtl->args.info.arg_count[(int) SH_ARG_INT])) |
6789 pretend_args = 0; | 7005 pretend_args = 0; |
6790 /* Dwarf2 module doesn't expect frame related insns here. */ | 7006 |
6791 output_stack_adjust (-pretend_args | 7007 output_stack_adjust (-pretend_args |
6792 - crtl->args.info.stack_regs * 8, | 7008 - crtl->args.info.stack_regs * 8, |
6793 stack_pointer_rtx, 0, NULL, false); | 7009 stack_pointer_rtx, 0, NULL, true); |
7010 stack_usage = pretend_args + crtl->args.info.stack_regs * 8; | |
6794 | 7011 |
6795 if (TARGET_SHCOMPACT && flag_pic && crtl->args.info.call_cookie) | 7012 if (TARGET_SHCOMPACT && flag_pic && crtl->args.info.call_cookie) |
6796 /* We're going to use the PIC register to load the address of the | 7013 /* We're going to use the PIC register to load the address of the |
6797 incoming-argument decoder and/or of the return trampoline from | 7014 incoming-argument decoder and/or of the return trampoline from |
6798 the GOT, so make sure the PIC register is preserved and | 7015 the GOT, so make sure the PIC register is preserved and |
6841 { | 7058 { |
6842 /* Push arg regs as if they'd been provided by caller in stack. */ | 7059 /* Push arg regs as if they'd been provided by caller in stack. */ |
6843 for (i = 0; i < NPARM_REGS(SImode); i++) | 7060 for (i = 0; i < NPARM_REGS(SImode); i++) |
6844 { | 7061 { |
6845 int rn = NPARM_REGS(SImode) + FIRST_PARM_REG - i - 1; | 7062 int rn = NPARM_REGS(SImode) + FIRST_PARM_REG - i - 1; |
6846 rtx insn; | |
6847 | 7063 |
6848 if (i >= (NPARM_REGS(SImode) | 7064 if (i >= (NPARM_REGS(SImode) |
6849 - crtl->args.info.arg_count[(int) SH_ARG_INT] | 7065 - crtl->args.info.arg_count[(int) SH_ARG_INT] |
6850 )) | 7066 )) |
6851 break; | 7067 break; |
6852 insn = push (rn); | 7068 push (rn); |
7069 stack_usage += GET_MODE_SIZE (SImode); | |
6853 } | 7070 } |
6854 } | 7071 } |
6855 } | 7072 } |
6856 | 7073 |
6857 /* If we're supposed to switch stacks at function entry, do so now. */ | 7074 /* If we're supposed to switch stacks at function entry, do so now. */ |
6920 | 7137 |
6921 offset_base = d + d_rounding; | 7138 offset_base = d + d_rounding; |
6922 | 7139 |
6923 output_stack_adjust (-(save_size + d_rounding), stack_pointer_rtx, | 7140 output_stack_adjust (-(save_size + d_rounding), stack_pointer_rtx, |
6924 0, NULL, true); | 7141 0, NULL, true); |
7142 stack_usage += save_size + d_rounding; | |
6925 | 7143 |
6926 sh5_schedule_saves (&live_regs_mask, &schedule, offset_base); | 7144 sh5_schedule_saves (&live_regs_mask, &schedule, offset_base); |
6927 tmp_pnt = schedule.temps; | 7145 tmp_pnt = schedule.temps; |
6928 for (entry = &schedule.entries[1]; entry->mode != VOIDmode; entry++) | 7146 for (entry = &schedule.entries[1]; entry->mode != VOIDmode; entry++) |
6929 { | 7147 { |
7071 } | 7289 } |
7072 | 7290 |
7073 gcc_assert (entry->offset == d_rounding); | 7291 gcc_assert (entry->offset == d_rounding); |
7074 } | 7292 } |
7075 else | 7293 else |
7076 push_regs (&live_regs_mask, current_function_interrupt); | 7294 { |
7295 push_regs (&live_regs_mask, current_function_interrupt); | |
7296 stack_usage += d; | |
7297 } | |
7077 | 7298 |
7078 if (flag_pic && df_regs_ever_live_p (PIC_OFFSET_TABLE_REGNUM)) | 7299 if (flag_pic && df_regs_ever_live_p (PIC_OFFSET_TABLE_REGNUM)) |
7079 emit_insn (gen_GOTaddr2picreg ()); | 7300 emit_insn (gen_GOTaddr2picreg ()); |
7080 | 7301 |
7081 if (SHMEDIA_REGS_STACK_ADJUST ()) | 7302 if (SHMEDIA_REGS_STACK_ADJUST ()) |
7095 | 7316 |
7096 target_flags = save_flags; | 7317 target_flags = save_flags; |
7097 | 7318 |
7098 output_stack_adjust (-rounded_frame_size (d) + d_rounding, | 7319 output_stack_adjust (-rounded_frame_size (d) + d_rounding, |
7099 stack_pointer_rtx, 0, NULL, true); | 7320 stack_pointer_rtx, 0, NULL, true); |
7321 stack_usage += rounded_frame_size (d) - d_rounding; | |
7100 | 7322 |
7101 if (frame_pointer_needed) | 7323 if (frame_pointer_needed) |
7102 frame_insn (GEN_MOV (hard_frame_pointer_rtx, stack_pointer_rtx)); | 7324 frame_insn (GEN_MOV (hard_frame_pointer_rtx, stack_pointer_rtx)); |
7103 | 7325 |
7104 if (TARGET_SHCOMPACT | 7326 if (TARGET_SHCOMPACT |
7108 may be clobbered. */ | 7330 may be clobbered. */ |
7109 function_symbol (gen_rtx_REG (Pmode, R0_REG), | 7331 function_symbol (gen_rtx_REG (Pmode, R0_REG), |
7110 "__GCC_shcompact_incoming_args", SFUNC_GOT); | 7332 "__GCC_shcompact_incoming_args", SFUNC_GOT); |
7111 emit_insn (gen_shcompact_incoming_args ()); | 7333 emit_insn (gen_shcompact_incoming_args ()); |
7112 } | 7334 } |
7335 | |
7336 if (flag_stack_usage) | |
7337 current_function_static_stack_size = stack_usage; | |
7113 } | 7338 } |
7114 | 7339 |
7115 void | 7340 void |
7116 sh_expand_epilogue (bool sibcall_p) | 7341 sh_expand_epilogue (bool sibcall_p) |
7117 { | 7342 { |
7212 tmp_pnt = schedule.temps; | 7437 tmp_pnt = schedule.temps; |
7213 for (; entry->mode != VOIDmode; entry--) | 7438 for (; entry->mode != VOIDmode; entry--) |
7214 { | 7439 { |
7215 enum machine_mode mode = (enum machine_mode) entry->mode; | 7440 enum machine_mode mode = (enum machine_mode) entry->mode; |
7216 int reg = entry->reg; | 7441 int reg = entry->reg; |
7217 rtx reg_rtx, mem_rtx, post_inc = NULL_RTX, insn; | 7442 rtx reg_rtx, mem_rtx, post_inc = NULL_RTX; |
7218 | 7443 |
7219 offset = offset_base + entry->offset; | 7444 offset = offset_base + entry->offset; |
7220 reg_rtx = gen_rtx_REG (mode, reg); | 7445 reg_rtx = gen_rtx_REG (mode, reg); |
7221 | 7446 |
7222 mem_rtx = gen_frame_mem (mode, | 7447 mem_rtx = gen_frame_mem (mode, |
7285 | 7510 |
7286 addr_ok: | 7511 addr_ok: |
7287 if ((reg == PR_REG || SPECIAL_REGISTER_P (reg)) | 7512 if ((reg == PR_REG || SPECIAL_REGISTER_P (reg)) |
7288 && mem_rtx != post_inc) | 7513 && mem_rtx != post_inc) |
7289 { | 7514 { |
7290 insn = emit_move_insn (r0, mem_rtx); | 7515 emit_move_insn (r0, mem_rtx); |
7291 mem_rtx = r0; | 7516 mem_rtx = r0; |
7292 } | 7517 } |
7293 else if (TARGET_REGISTER_P (reg)) | 7518 else if (TARGET_REGISTER_P (reg)) |
7294 { | 7519 { |
7295 rtx tmp_reg = gen_rtx_REG (mode, *tmp_pnt); | 7520 rtx tmp_reg = gen_rtx_REG (mode, *tmp_pnt); |
7296 | 7521 |
7297 /* Give the scheduler a bit of freedom by using up to | 7522 /* Give the scheduler a bit of freedom by using up to |
7298 MAX_TEMPS registers in a round-robin fashion. */ | 7523 MAX_TEMPS registers in a round-robin fashion. */ |
7299 insn = emit_move_insn (tmp_reg, mem_rtx); | 7524 emit_move_insn (tmp_reg, mem_rtx); |
7300 mem_rtx = tmp_reg; | 7525 mem_rtx = tmp_reg; |
7301 if (*++tmp_pnt < 0) | 7526 if (*++tmp_pnt < 0) |
7302 tmp_pnt = schedule.temps; | 7527 tmp_pnt = schedule.temps; |
7303 } | 7528 } |
7304 | 7529 |
7305 insn = emit_move_insn (reg_rtx, mem_rtx); | 7530 emit_move_insn (reg_rtx, mem_rtx); |
7306 } | 7531 } |
7307 | 7532 |
7308 gcc_assert (entry->offset + offset_base == d + d_rounding); | 7533 gcc_assert (entry->offset + offset_base == d + d_rounding); |
7309 } | 7534 } |
7310 else /* ! TARGET_SH5 */ | 7535 else /* ! TARGET_SH5 */ |
7324 | 7549 |
7325 /* Banked registers are popped first to avoid being scheduled in the | 7550 /* Banked registers are popped first to avoid being scheduled in the |
7326 delay slot. RTE switches banks before the ds instruction. */ | 7551 delay slot. RTE switches banks before the ds instruction. */ |
7327 if (current_function_interrupt) | 7552 if (current_function_interrupt) |
7328 { | 7553 { |
7329 for (i = LAST_BANKED_REG; i >= FIRST_BANKED_REG; i--) | 7554 bool use_movml = false; |
7330 if (TEST_HARD_REG_BIT (live_regs_mask, i)) | 7555 |
7331 pop (i); | 7556 if (TARGET_SH2A) |
7557 { | |
7558 unsigned int count = 0; | |
7559 | |
7560 for (i = FIRST_BANKED_REG; i <= LAST_BANKED_REG; i++) | |
7561 if (TEST_HARD_REG_BIT (live_regs_mask, i)) | |
7562 count++; | |
7563 else | |
7564 break; | |
7565 | |
7566 /* Use movml when all banked register are poped. */ | |
7567 if (count == LAST_BANKED_REG - FIRST_BANKED_REG + 1) | |
7568 use_movml = true; | |
7569 } | |
7570 | |
7571 if (use_movml) | |
7572 { | |
7573 rtx sp_reg = gen_rtx_REG (SImode, STACK_POINTER_REGNUM); | |
7574 | |
7575 /* We must avoid scheduling multiple load insn with another | |
7576 insns. */ | |
7577 emit_insn (gen_blockage ()); | |
7578 emit_insn (gen_movml_pop_banked (sp_reg)); | |
7579 emit_insn (gen_blockage ()); | |
7580 } | |
7581 else | |
7582 for (i = LAST_BANKED_REG; i >= FIRST_BANKED_REG; i--) | |
7583 if (TEST_HARD_REG_BIT (live_regs_mask, i)) | |
7584 pop (i); | |
7332 | 7585 |
7333 last_reg = FIRST_PSEUDO_REGISTER - LAST_BANKED_REG - 1; | 7586 last_reg = FIRST_PSEUDO_REGISTER - LAST_BANKED_REG - 1; |
7334 } | 7587 } |
7335 else | 7588 else |
7336 last_reg = FIRST_PSEUDO_REGISTER; | 7589 last_reg = FIRST_PSEUDO_REGISTER; |
7634 | 7887 |
7635 static tree | 7888 static tree |
7636 sh_build_builtin_va_list (void) | 7889 sh_build_builtin_va_list (void) |
7637 { | 7890 { |
7638 tree f_next_o, f_next_o_limit, f_next_fp, f_next_fp_limit, f_next_stack; | 7891 tree f_next_o, f_next_o_limit, f_next_fp, f_next_fp_limit, f_next_stack; |
7639 tree record; | 7892 tree record, type_decl; |
7640 | 7893 |
7641 if (TARGET_SH5 || (! TARGET_SH2E && ! TARGET_SH4) | 7894 if (TARGET_SH5 || (! TARGET_SH2E && ! TARGET_SH4) |
7642 || TARGET_HITACHI || sh_cfun_attr_renesas_p ()) | 7895 || TARGET_HITACHI || sh_cfun_attr_renesas_p ()) |
7643 return ptr_type_node; | 7896 return ptr_type_node; |
7644 | 7897 |
7645 record = (*lang_hooks.types.make_type) (RECORD_TYPE); | 7898 record = (*lang_hooks.types.make_type) (RECORD_TYPE); |
7899 type_decl = build_decl (BUILTINS_LOCATION, | |
7900 TYPE_DECL, get_identifier ("__va_list_tag"), record); | |
7646 | 7901 |
7647 f_next_o = build_decl (BUILTINS_LOCATION, | 7902 f_next_o = build_decl (BUILTINS_LOCATION, |
7648 FIELD_DECL, get_identifier ("__va_next_o"), | 7903 FIELD_DECL, get_identifier ("__va_next_o"), |
7649 ptr_type_node); | 7904 ptr_type_node); |
7650 f_next_o_limit = build_decl (BUILTINS_LOCATION, | 7905 f_next_o_limit = build_decl (BUILTINS_LOCATION, |
7666 DECL_FIELD_CONTEXT (f_next_o_limit) = record; | 7921 DECL_FIELD_CONTEXT (f_next_o_limit) = record; |
7667 DECL_FIELD_CONTEXT (f_next_fp) = record; | 7922 DECL_FIELD_CONTEXT (f_next_fp) = record; |
7668 DECL_FIELD_CONTEXT (f_next_fp_limit) = record; | 7923 DECL_FIELD_CONTEXT (f_next_fp_limit) = record; |
7669 DECL_FIELD_CONTEXT (f_next_stack) = record; | 7924 DECL_FIELD_CONTEXT (f_next_stack) = record; |
7670 | 7925 |
7926 TYPE_STUB_DECL (record) = type_decl; | |
7927 TYPE_NAME (record) = type_decl; | |
7671 TYPE_FIELDS (record) = f_next_o; | 7928 TYPE_FIELDS (record) = f_next_o; |
7672 TREE_CHAIN (f_next_o) = f_next_o_limit; | 7929 DECL_CHAIN (f_next_o) = f_next_o_limit; |
7673 TREE_CHAIN (f_next_o_limit) = f_next_fp; | 7930 DECL_CHAIN (f_next_o_limit) = f_next_fp; |
7674 TREE_CHAIN (f_next_fp) = f_next_fp_limit; | 7931 DECL_CHAIN (f_next_fp) = f_next_fp_limit; |
7675 TREE_CHAIN (f_next_fp_limit) = f_next_stack; | 7932 DECL_CHAIN (f_next_fp_limit) = f_next_stack; |
7676 | 7933 |
7677 layout_type (record); | 7934 layout_type (record); |
7678 | 7935 |
7679 return record; | 7936 return record; |
7680 } | 7937 } |
7702 std_expand_builtin_va_start (valist, nextarg); | 7959 std_expand_builtin_va_start (valist, nextarg); |
7703 return; | 7960 return; |
7704 } | 7961 } |
7705 | 7962 |
7706 f_next_o = TYPE_FIELDS (va_list_type_node); | 7963 f_next_o = TYPE_FIELDS (va_list_type_node); |
7707 f_next_o_limit = TREE_CHAIN (f_next_o); | 7964 f_next_o_limit = DECL_CHAIN (f_next_o); |
7708 f_next_fp = TREE_CHAIN (f_next_o_limit); | 7965 f_next_fp = DECL_CHAIN (f_next_o_limit); |
7709 f_next_fp_limit = TREE_CHAIN (f_next_fp); | 7966 f_next_fp_limit = DECL_CHAIN (f_next_fp); |
7710 f_next_stack = TREE_CHAIN (f_next_fp_limit); | 7967 f_next_stack = DECL_CHAIN (f_next_fp_limit); |
7711 | 7968 |
7712 next_o = build3 (COMPONENT_REF, TREE_TYPE (f_next_o), valist, f_next_o, | 7969 next_o = build3 (COMPONENT_REF, TREE_TYPE (f_next_o), valist, f_next_o, |
7713 NULL_TREE); | 7970 NULL_TREE); |
7714 next_o_limit = build3 (COMPONENT_REF, TREE_TYPE (f_next_o_limit), | 7971 next_o_limit = build3 (COMPONENT_REF, TREE_TYPE (f_next_o_limit), |
7715 valist, f_next_o_limit, NULL_TREE); | 7972 valist, f_next_o_limit, NULL_TREE); |
7764 static tree | 8021 static tree |
7765 find_sole_member (tree type) | 8022 find_sole_member (tree type) |
7766 { | 8023 { |
7767 tree field, member = NULL_TREE; | 8024 tree field, member = NULL_TREE; |
7768 | 8025 |
7769 for (field = TYPE_FIELDS (type); field; field = TREE_CHAIN (field)) | 8026 for (field = TYPE_FIELDS (type); field; field = DECL_CHAIN (field)) |
7770 { | 8027 { |
7771 if (TREE_CODE (field) != FIELD_DECL) | 8028 if (TREE_CODE (field) != FIELD_DECL) |
7772 continue; | 8029 continue; |
7773 if (!DECL_SIZE (field)) | 8030 if (!DECL_SIZE (field)) |
7774 return NULL_TREE; | 8031 return NULL_TREE; |
7807 int pass_as_float; | 8064 int pass_as_float; |
7808 tree lab_false; | 8065 tree lab_false; |
7809 tree member; | 8066 tree member; |
7810 | 8067 |
7811 f_next_o = TYPE_FIELDS (va_list_type_node); | 8068 f_next_o = TYPE_FIELDS (va_list_type_node); |
7812 f_next_o_limit = TREE_CHAIN (f_next_o); | 8069 f_next_o_limit = DECL_CHAIN (f_next_o); |
7813 f_next_fp = TREE_CHAIN (f_next_o_limit); | 8070 f_next_fp = DECL_CHAIN (f_next_o_limit); |
7814 f_next_fp_limit = TREE_CHAIN (f_next_fp); | 8071 f_next_fp_limit = DECL_CHAIN (f_next_fp); |
7815 f_next_stack = TREE_CHAIN (f_next_fp_limit); | 8072 f_next_stack = DECL_CHAIN (f_next_fp_limit); |
7816 | 8073 |
7817 next_o = build3 (COMPONENT_REF, TREE_TYPE (f_next_o), valist, f_next_o, | 8074 next_o = build3 (COMPONENT_REF, TREE_TYPE (f_next_o), valist, f_next_o, |
7818 NULL_TREE); | 8075 NULL_TREE); |
7819 next_o_limit = build3 (COMPONENT_REF, TREE_TYPE (f_next_o_limit), | 8076 next_o_limit = build3 (COMPONENT_REF, TREE_TYPE (f_next_o_limit), |
7820 valist, f_next_o_limit, NULL_TREE); | 8077 valist, f_next_o_limit, NULL_TREE); |
7863 | 8120 |
7864 addr = create_tmp_var (pptr_type_node, NULL); | 8121 addr = create_tmp_var (pptr_type_node, NULL); |
7865 lab_false = create_artificial_label (UNKNOWN_LOCATION); | 8122 lab_false = create_artificial_label (UNKNOWN_LOCATION); |
7866 lab_over = create_artificial_label (UNKNOWN_LOCATION); | 8123 lab_over = create_artificial_label (UNKNOWN_LOCATION); |
7867 | 8124 |
7868 valist = build1 (INDIRECT_REF, ptr_type_node, addr); | 8125 valist = build_simple_mem_ref (addr); |
7869 | 8126 |
7870 if (pass_as_float) | 8127 if (pass_as_float) |
7871 { | 8128 { |
7872 tree next_fp_tmp = create_tmp_var (TREE_TYPE (f_next_fp), NULL); | 8129 tree next_fp_tmp = create_tmp_var (TREE_TYPE (f_next_fp), NULL); |
7873 tree cmp; | 8130 tree cmp; |
8016 } | 8273 } |
8017 | 8274 |
8018 static enum machine_mode | 8275 static enum machine_mode |
8019 sh_promote_function_mode (const_tree type, enum machine_mode mode, | 8276 sh_promote_function_mode (const_tree type, enum machine_mode mode, |
8020 int *punsignedp, const_tree funtype, | 8277 int *punsignedp, const_tree funtype, |
8021 int for_return ATTRIBUTE_UNUSED) | 8278 int for_return) |
8022 { | 8279 { |
8023 if (sh_promote_prototypes (funtype)) | 8280 if (sh_promote_prototypes (funtype)) |
8024 return promote_mode (type, mode, punsignedp); | 8281 return promote_mode (type, mode, punsignedp); |
8025 else | 8282 else |
8026 return mode; | 8283 return default_promote_function_mode (type, mode, punsignedp, funtype, |
8284 for_return); | |
8027 } | 8285 } |
8028 | 8286 |
8029 static bool | 8287 static bool |
8030 sh_promote_prototypes (const_tree type) | 8288 sh_promote_prototypes (const_tree type) |
8031 { | 8289 { |
8139 On SH the first args are normally in registers | 8397 On SH the first args are normally in registers |
8140 and the rest are pushed. Any arg that starts within the first | 8398 and the rest are pushed. Any arg that starts within the first |
8141 NPARM_REGS words is at least partially passed in a register unless | 8399 NPARM_REGS words is at least partially passed in a register unless |
8142 its data type forbids. */ | 8400 its data type forbids. */ |
8143 | 8401 |
8144 | 8402 static rtx |
8145 rtx | |
8146 sh_function_arg (CUMULATIVE_ARGS *ca, enum machine_mode mode, | 8403 sh_function_arg (CUMULATIVE_ARGS *ca, enum machine_mode mode, |
8147 tree type, int named) | 8404 const_tree type, bool named) |
8148 { | 8405 { |
8149 if (! TARGET_SH5 && mode == VOIDmode) | 8406 if (! TARGET_SH5 && mode == VOIDmode) |
8150 return GEN_INT (ca->renesas_abi ? 1 : 0); | 8407 return GEN_INT (ca->renesas_abi ? 1 : 0); |
8151 | 8408 |
8152 if (! TARGET_SH5 | 8409 if (! TARGET_SH5 |
8228 /* Update the data in CUM to advance over an argument | 8485 /* Update the data in CUM to advance over an argument |
8229 of mode MODE and data type TYPE. | 8486 of mode MODE and data type TYPE. |
8230 (TYPE is null for libcalls where that information may not be | 8487 (TYPE is null for libcalls where that information may not be |
8231 available.) */ | 8488 available.) */ |
8232 | 8489 |
8233 void | 8490 static void |
8234 sh_function_arg_advance (CUMULATIVE_ARGS *ca, enum machine_mode mode, | 8491 sh_function_arg_advance (CUMULATIVE_ARGS *ca, enum machine_mode mode, |
8235 tree type, int named) | 8492 const_tree type, bool named) |
8236 { | 8493 { |
8237 if (ca->force_mem) | 8494 if (ca->force_mem) |
8238 ca->force_mem = 0; | 8495 ca->force_mem = 0; |
8239 else if (TARGET_SH5) | 8496 else if (TARGET_SH5) |
8240 { | 8497 { |
8241 tree type2 = (ca->byref && type | 8498 const_tree type2 = (ca->byref && type |
8242 ? TREE_TYPE (type) | 8499 ? TREE_TYPE (type) |
8243 : type); | 8500 : type); |
8244 enum machine_mode mode2 = (ca->byref && type | 8501 enum machine_mode mode2 = (ca->byref && type |
8245 ? TYPE_MODE (type2) | 8502 ? TYPE_MODE (type2) |
8246 : mode); | 8503 : mode); |
8247 int dwords = ((ca->byref | 8504 int dwords = ((ca->byref |
8248 ? ca->byref | 8505 ? ca->byref |
8421 sh_libcall_value (enum machine_mode mode, const_rtx fun ATTRIBUTE_UNUSED) | 8678 sh_libcall_value (enum machine_mode mode, const_rtx fun ATTRIBUTE_UNUSED) |
8422 { | 8679 { |
8423 return gen_rtx_REG (mode, BASE_RETURN_VALUE_REG (mode)); | 8680 return gen_rtx_REG (mode, BASE_RETURN_VALUE_REG (mode)); |
8424 } | 8681 } |
8425 | 8682 |
8426 /* Worker function for FUNCTION_VALUE_REGNO_P. */ | 8683 /* Return true if N is a possible register number of function value. */ |
8427 | 8684 |
8428 bool | 8685 static bool |
8429 sh_function_value_regno_p (const unsigned int regno) | 8686 sh_function_value_regno_p (const unsigned int regno) |
8430 { | 8687 { |
8431 return ((regno) == FIRST_RET_REG | 8688 return ((regno) == FIRST_RET_REG |
8432 || (TARGET_SH2E && (regno) == FIRST_FP_RET_REG) | 8689 || (TARGET_SH2E && (regno) == FIRST_FP_RET_REG) |
8433 || (TARGET_SHMEDIA_FPU && (regno) == FIRST_FP_RET_REG)); | 8690 || (TARGET_SHMEDIA_FPU && (regno) == FIRST_FP_RET_REG)); |
9738 | 9995 |
9739 return false; | 9996 return false; |
9740 | 9997 |
9741 win: | 9998 win: |
9742 return true; | 9999 return true; |
10000 } | |
10001 | |
10002 /* In the name of slightly smaller debug output, and to cater to | |
10003 general assembler lossage, recognize various UNSPEC sequences | |
10004 and turn them back into a direct symbol reference. */ | |
10005 | |
10006 static rtx | |
10007 sh_delegitimize_address (rtx orig_x) | |
10008 { | |
10009 rtx x, y; | |
10010 | |
10011 orig_x = delegitimize_mem_from_attrs (orig_x); | |
10012 | |
10013 x = orig_x; | |
10014 if (MEM_P (x)) | |
10015 x = XEXP (x, 0); | |
10016 if (GET_CODE (x) == CONST) | |
10017 { | |
10018 y = XEXP (x, 0); | |
10019 if (GET_CODE (y) == UNSPEC) | |
10020 { | |
10021 if (XINT (y, 1) == UNSPEC_GOT | |
10022 || XINT (y, 1) == UNSPEC_GOTOFF) | |
10023 return XVECEXP (y, 0, 0); | |
10024 else if (TARGET_SHMEDIA | |
10025 && (XINT (y, 1) == UNSPEC_EXTRACT_S16 | |
10026 || XINT (y, 1) == UNSPEC_EXTRACT_U16)) | |
10027 { | |
10028 rtx offset = XVECEXP (y, 0, 1); | |
10029 | |
10030 x = gen_rtx_PLUS (Pmode, XVECEXP (y, 0, 0), offset); | |
10031 if (MEM_P (orig_x)) | |
10032 x = replace_equiv_address_nv (orig_x, x); | |
10033 return x; | |
10034 } | |
10035 } | |
10036 } | |
10037 | |
10038 return orig_x; | |
9743 } | 10039 } |
9744 | 10040 |
9745 /* Mark the use of a constant in the literal table. If the constant | 10041 /* Mark the use of a constant in the literal table. If the constant |
9746 has multiple labels, make it unique. */ | 10042 has multiple labels, make it unique. */ |
9747 static rtx | 10043 static rtx |
10496 sh_cannot_modify_jumps_p (void) | 10792 sh_cannot_modify_jumps_p (void) |
10497 { | 10793 { |
10498 return (TARGET_SHMEDIA && (reload_in_progress || reload_completed)); | 10794 return (TARGET_SHMEDIA && (reload_in_progress || reload_completed)); |
10499 } | 10795 } |
10500 | 10796 |
10501 static enum reg_class | 10797 static reg_class_t |
10502 sh_target_reg_class (void) | 10798 sh_target_reg_class (void) |
10503 { | 10799 { |
10504 return TARGET_SHMEDIA ? TARGET_REGS : NO_REGS; | 10800 return TARGET_SHMEDIA ? TARGET_REGS : NO_REGS; |
10505 } | 10801 } |
10506 | 10802 |
11284 | 11580 |
11285 /* If SECONDARY*_RELOAD_CLASS says something about the src/dst pair, regclass | 11581 /* If SECONDARY*_RELOAD_CLASS says something about the src/dst pair, regclass |
11286 uses this information. Hence, the general register <-> floating point | 11582 uses this information. Hence, the general register <-> floating point |
11287 register information here is not used for SFmode. */ | 11583 register information here is not used for SFmode. */ |
11288 | 11584 |
11289 int | 11585 static int |
11290 sh_register_move_cost (enum machine_mode mode, | 11586 sh_register_move_cost (enum machine_mode mode, |
11291 enum reg_class srcclass, enum reg_class dstclass) | 11587 reg_class_t srcclass, reg_class_t dstclass) |
11292 { | 11588 { |
11293 if (dstclass == T_REGS || dstclass == PR_REGS) | 11589 if (dstclass == T_REGS || dstclass == PR_REGS) |
11294 return 10; | 11590 return 10; |
11295 | 11591 |
11296 if (dstclass == MAC_REGS && srcclass == MAC_REGS) | 11592 if (dstclass == MAC_REGS && srcclass == MAC_REGS) |
11397 #endif /* not PCC_STATIC_STRUCT_RETURN */ | 11693 #endif /* not PCC_STATIC_STRUCT_RETURN */ |
11398 if (structure_value_byref && sh_struct_value_rtx (function, 0) == 0) | 11694 if (structure_value_byref && sh_struct_value_rtx (function, 0) == 0) |
11399 { | 11695 { |
11400 tree ptype = build_pointer_type (TREE_TYPE (funtype)); | 11696 tree ptype = build_pointer_type (TREE_TYPE (funtype)); |
11401 | 11697 |
11402 FUNCTION_ARG_ADVANCE (cum, Pmode, ptype, 1); | 11698 sh_function_arg_advance (&cum, Pmode, ptype, true); |
11403 } | 11699 } |
11404 this_rtx = FUNCTION_ARG (cum, Pmode, ptr_type_node, 1); | 11700 this_rtx = sh_function_arg (&cum, Pmode, ptr_type_node, true); |
11405 | 11701 |
11406 /* For SHcompact, we only have r0 for a scratch register: r1 is the | 11702 /* For SHcompact, we only have r0 for a scratch register: r1 is the |
11407 static chain pointer (even if you can't have nested virtual functions | 11703 static chain pointer (even if you can't have nested virtual functions |
11408 right now, someone might implement them sometime), and the rest of the | 11704 right now, someone might implement them sometime), and the rest of the |
11409 registers are used for argument passing, are callee-saved, or reserved. */ | 11705 registers are used for argument passing, are callee-saved, or reserved. */ |
11429 { | 11725 { |
11430 scratch1 = gen_rtx_REG (ptr_mode, i); | 11726 scratch1 = gen_rtx_REG (ptr_mode, i); |
11431 break; | 11727 break; |
11432 } | 11728 } |
11433 if (scratch1 == scratch0) | 11729 if (scratch1 == scratch0) |
11434 error ("Need a second call-clobbered general purpose register"); | 11730 error ("need a second call-clobbered general purpose register"); |
11435 for (i = FIRST_TARGET_REG; i <= LAST_TARGET_REG; i++) | 11731 for (i = FIRST_TARGET_REG; i <= LAST_TARGET_REG; i++) |
11436 if (call_used_regs[i] && ! fixed_regs[i]) | 11732 if (call_used_regs[i] && ! fixed_regs[i]) |
11437 { | 11733 { |
11438 scratch2 = gen_rtx_REG (Pmode, i); | 11734 scratch2 = gen_rtx_REG (Pmode, i); |
11439 break; | 11735 break; |
11440 } | 11736 } |
11441 if (scratch2 == scratch0) | 11737 if (scratch2 == scratch0) |
11442 error ("Need a call-clobbered target register"); | 11738 error ("need a call-clobbered target register"); |
11443 } | 11739 } |
11444 | 11740 |
11445 this_value = plus_constant (this_rtx, delta); | 11741 this_value = plus_constant (this_rtx, delta); |
11446 if (vcall_offset | 11742 if (vcall_offset |
11447 && (simple_add || scratch0 != scratch1) | 11743 && (simple_add || scratch0 != scratch1) |
11821 | 12117 |
11822 if (fntype) | 12118 if (fntype) |
11823 { | 12119 { |
11824 pcum->force_mem = ((TARGET_HITACHI || pcum->renesas_abi) | 12120 pcum->force_mem = ((TARGET_HITACHI || pcum->renesas_abi) |
11825 && aggregate_value_p (TREE_TYPE (fntype), fndecl)); | 12121 && aggregate_value_p (TREE_TYPE (fntype), fndecl)); |
11826 pcum->prototype_p = TYPE_ARG_TYPES (fntype) ? TRUE : FALSE; | 12122 pcum->prototype_p = prototype_p (fntype); |
11827 pcum->arg_count [(int) SH_ARG_INT] | 12123 pcum->arg_count [(int) SH_ARG_INT] |
11828 = TARGET_SH5 && aggregate_value_p (TREE_TYPE (fntype), fndecl); | 12124 = TARGET_SH5 && aggregate_value_p (TREE_TYPE (fntype), fndecl); |
11829 | 12125 |
11830 pcum->call_cookie | 12126 pcum->call_cookie |
11831 = CALL_COOKIE_RET_TRAMP (TARGET_SHCOMPACT | 12127 = CALL_COOKIE_RET_TRAMP (TARGET_SHCOMPACT |
12135 else if (! target_reg_operand (fnaddr, Pmode)) | 12431 else if (! target_reg_operand (fnaddr, Pmode)) |
12136 fnaddr = copy_to_mode_reg (Pmode, fnaddr); | 12432 fnaddr = copy_to_mode_reg (Pmode, fnaddr); |
12137 return fnaddr; | 12433 return fnaddr; |
12138 } | 12434 } |
12139 | 12435 |
12140 enum reg_class | 12436 /* Implement TARGET_PREFERRED_RELOAD_CLASS. */ |
12141 sh_secondary_reload (bool in_p, rtx x, enum reg_class rclass, | 12437 |
12438 static reg_class_t | |
12439 sh_preferred_reload_class (rtx x, reg_class_t rclass) | |
12440 { | |
12441 if (rclass == NO_REGS | |
12442 && TARGET_SHMEDIA | |
12443 && (CONST_DOUBLE_P (x) | |
12444 || GET_CODE (x) == SYMBOL_REF | |
12445 || PIC_ADDR_P (x))) | |
12446 return GENERAL_REGS; | |
12447 | |
12448 return rclass; | |
12449 } | |
12450 | |
12451 /* Implement TARGET_SECONDARY_RELOAD. */ | |
12452 | |
12453 static reg_class_t | |
12454 sh_secondary_reload (bool in_p, rtx x, reg_class_t rclass_i, | |
12142 enum machine_mode mode, secondary_reload_info *sri) | 12455 enum machine_mode mode, secondary_reload_info *sri) |
12143 { | 12456 { |
12457 enum reg_class rclass = (enum reg_class) rclass_i; | |
12458 | |
12144 if (in_p) | 12459 if (in_p) |
12145 { | 12460 { |
12146 if (REGCLASS_HAS_FP_REG (rclass) | 12461 if (REGCLASS_HAS_FP_REG (rclass) |
12147 && ! TARGET_SHMEDIA | 12462 && ! TARGET_SHMEDIA |
12148 && immediate_operand ((x), mode) | 12463 && immediate_operand ((x), mode) |
12237 && TARGET_REGISTER_P (REGNO (x))) | 12552 && TARGET_REGISTER_P (REGNO (x))) |
12238 return GENERAL_REGS; | 12553 return GENERAL_REGS; |
12239 return NO_REGS; | 12554 return NO_REGS; |
12240 } | 12555 } |
12241 | 12556 |
12557 static void | |
12558 sh_conditional_register_usage (void) | |
12559 { | |
12560 int regno; | |
12561 for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno ++) | |
12562 if (! VALID_REGISTER_P (regno)) | |
12563 fixed_regs[regno] = call_used_regs[regno] = 1; | |
12564 /* R8 and R9 are call-clobbered on SH5, but not on earlier SH ABIs. */ | |
12565 if (TARGET_SH5) | |
12566 { | |
12567 call_used_regs[FIRST_GENERAL_REG + 8] | |
12568 = call_used_regs[FIRST_GENERAL_REG + 9] = 1; | |
12569 call_really_used_regs[FIRST_GENERAL_REG + 8] | |
12570 = call_really_used_regs[FIRST_GENERAL_REG + 9] = 1; | |
12571 } | |
12572 if (TARGET_SHMEDIA) | |
12573 { | |
12574 regno_reg_class[FIRST_GENERAL_REG] = GENERAL_REGS; | |
12575 CLEAR_HARD_REG_SET (reg_class_contents[FP0_REGS]); | |
12576 regno_reg_class[FIRST_FP_REG] = FP_REGS; | |
12577 } | |
12578 if (flag_pic) | |
12579 { | |
12580 fixed_regs[PIC_OFFSET_TABLE_REGNUM] = 1; | |
12581 call_used_regs[PIC_OFFSET_TABLE_REGNUM] = 1; | |
12582 } | |
12583 /* Renesas saves and restores mac registers on call. */ | |
12584 if (TARGET_HITACHI && ! TARGET_NOMACSAVE) | |
12585 { | |
12586 call_really_used_regs[MACH_REG] = 0; | |
12587 call_really_used_regs[MACL_REG] = 0; | |
12588 } | |
12589 for (regno = FIRST_FP_REG + (TARGET_LITTLE_ENDIAN != 0); | |
12590 regno <= LAST_FP_REG; regno += 2) | |
12591 SET_HARD_REG_BIT (reg_class_contents[DF_HI_REGS], regno); | |
12592 if (TARGET_SHMEDIA) | |
12593 { | |
12594 for (regno = FIRST_TARGET_REG; regno <= LAST_TARGET_REG; regno ++) | |
12595 if (! fixed_regs[regno] && call_really_used_regs[regno]) | |
12596 SET_HARD_REG_BIT (reg_class_contents[SIBCALL_REGS], regno); | |
12597 } | |
12598 else | |
12599 for (regno = FIRST_GENERAL_REG; regno <= LAST_GENERAL_REG; regno++) | |
12600 if (! fixed_regs[regno] && call_really_used_regs[regno]) | |
12601 SET_HARD_REG_BIT (reg_class_contents[SIBCALL_REGS], regno); | |
12602 } | |
12603 | |
12604 | |
12242 enum sh_divide_strategy_e sh_div_strategy = SH_DIV_STRATEGY_DEFAULT; | 12605 enum sh_divide_strategy_e sh_div_strategy = SH_DIV_STRATEGY_DEFAULT; |
12243 | 12606 |
12244 #include "gt-sh.h" | 12607 #include "gt-sh.h" |