Mercurial > hg > CbC > CbC_gcc
diff gcc/config/avr/avr.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 |
line wrap: on
line diff
--- a/gcc/config/avr/avr.c Tue May 25 18:58:51 2010 +0900 +++ b/gcc/config/avr/avr.c Tue Mar 22 17:18:12 2011 +0900 @@ -34,7 +34,7 @@ #include "tree.h" #include "output.h" #include "expr.h" -#include "toplev.h" +#include "diagnostic-core.h" #include "obstack.h" #include "function.h" #include "recog.h" @@ -48,6 +48,7 @@ /* Maximal allowed offset for an address in the LD command */ #define MAX_LD_OFFSET(MODE) (64 - (signed)GET_MODE_SIZE (MODE)) +static void avr_option_override (void); static int avr_naked_function_p (tree); static int interrupt_function_p (tree); static int signal_function_p (tree); @@ -58,7 +59,7 @@ static int sequent_regs_live (void); static const char *ptrreg_to_str (int); static const char *cond_string (enum rtx_code); -static int avr_num_arg_regs (enum machine_mode, tree); +static int avr_num_arg_regs (enum machine_mode, const_tree); static RTX_CODE compare_condition (rtx insn); static rtx avr_legitimize_address (rtx, rtx, enum machine_mode); @@ -72,6 +73,7 @@ static bool avr_legitimate_address_p (enum machine_mode, rtx, bool); static void avr_asm_function_end_prologue (FILE *); static void avr_asm_function_begin_epilogue (FILE *); +static bool avr_cannot_modify_jumps_p (void); static rtx avr_function_value (const_tree, const_tree, bool); static void avr_insert_attributes (tree, tree *); static void avr_asm_init_sections (void); @@ -80,6 +82,8 @@ static void avr_reorg (void); static void avr_asm_out_ctor (rtx, int); static void avr_asm_out_dtor (rtx, int); +static int avr_register_move_cost (enum machine_mode, reg_class_t, reg_class_t); +static int avr_memory_move_cost (enum machine_mode, reg_class_t, bool); static int avr_operand_rtx_cost (rtx, enum machine_mode, enum rtx_code, bool); static bool avr_rtx_costs (rtx, int, int, int *, bool); static int avr_address_cost (rtx, bool); @@ -90,6 +94,12 @@ static unsigned int avr_case_values_threshold (void); static bool avr_frame_pointer_required_p (void); static bool avr_can_eliminate (const int, const int); +static bool avr_class_likely_spilled_p (reg_class_t c); +static rtx avr_function_arg (CUMULATIVE_ARGS *, enum machine_mode, + const_tree, bool); +static void avr_function_arg_advance (CUMULATIVE_ARGS *, enum machine_mode, + const_tree, bool); +static void avr_help (void); /* Allocate registers from r25 to r8 for parameters for function calls. */ #define FIRST_CUM_REG 26 @@ -126,6 +136,13 @@ { "OS_main", 0, 0, false, true, true, avr_handle_fntype_attribute }, { NULL, 0, 0, false, false, false, NULL } }; + +/* Implement TARGET_OPTION_OPTIMIZATION_TABLE. */ +static const struct default_options avr_option_optimization_table[] = + { + { OPT_LEVELS_1_PLUS, OPT_fomit_frame_pointer, NULL, 1 }, + { OPT_LEVELS_NONE, 0, NULL, 0 } + }; /* Initialize the GCC target structure. */ #undef TARGET_ASM_ALIGNED_HI_OP @@ -159,12 +176,20 @@ #define TARGET_INSERT_ATTRIBUTES avr_insert_attributes #undef TARGET_SECTION_TYPE_FLAGS #define TARGET_SECTION_TYPE_FLAGS avr_section_type_flags +#undef TARGET_REGISTER_MOVE_COST +#define TARGET_REGISTER_MOVE_COST avr_register_move_cost +#undef TARGET_MEMORY_MOVE_COST +#define TARGET_MEMORY_MOVE_COST avr_memory_move_cost #undef TARGET_RTX_COSTS #define TARGET_RTX_COSTS avr_rtx_costs #undef TARGET_ADDRESS_COST #define TARGET_ADDRESS_COST avr_address_cost #undef TARGET_MACHINE_DEPENDENT_REORG #define TARGET_MACHINE_DEPENDENT_REORG avr_reorg +#undef TARGET_FUNCTION_ARG +#define TARGET_FUNCTION_ARG avr_function_arg +#undef TARGET_FUNCTION_ARG_ADVANCE +#define TARGET_FUNCTION_ARG_ADVANCE avr_function_arg_advance #undef TARGET_LEGITIMIZE_ADDRESS #define TARGET_LEGITIMIZE_ADDRESS avr_legitimize_address @@ -191,10 +216,25 @@ #undef TARGET_CAN_ELIMINATE #define TARGET_CAN_ELIMINATE avr_can_eliminate +#undef TARGET_CLASS_LIKELY_SPILLED_P +#define TARGET_CLASS_LIKELY_SPILLED_P avr_class_likely_spilled_p + +#undef TARGET_OPTION_OVERRIDE +#define TARGET_OPTION_OVERRIDE avr_option_override + +#undef TARGET_OPTION_OPTIMIZATION_TABLE +#define TARGET_OPTION_OPTIMIZATION_TABLE avr_option_optimization_table + +#undef TARGET_CANNOT_MODIFY_JUMPS_P +#define TARGET_CANNOT_MODIFY_JUMPS_P avr_cannot_modify_jumps_p + +#undef TARGET_HELP +#define TARGET_HELP avr_help + struct gcc_target targetm = TARGET_INITIALIZER; -void -avr_override_options (void) +static void +avr_option_override (void) { const struct mcu_type_s *t; @@ -206,10 +246,8 @@ if (!t->name) { - fprintf (stderr, "unknown MCU '%s' specified\nKnown MCU names:\n", - avr_mcu_name); - for (t = avr_mcu_types; t->name; t++) - fprintf (stderr," %s\n", t->name); + error ("unrecognized argument to -mmcu= option: %qs", avr_mcu_name); + inform (input_location, "See --target-help for supported MCUs"); } avr_current_device = t; @@ -222,6 +260,42 @@ init_machine_status = avr_init_machine_status; } +/* Implement TARGET_HELP */ +/* Report extra information for --target-help */ + +static void +avr_help (void) +{ + const struct mcu_type_s *t; + const char * const indent = " "; + int len; + + /* Give a list of MCUs that are accepted by -mmcu=* . + Note that MCUs supported by the compiler might differ from + MCUs supported by binutils. */ + + len = strlen (indent); + printf ("Known MCU names:\n%s", indent); + + /* Print a blank-separated list of all supported MCUs */ + + for (t = avr_mcu_types; t->name; t++) + { + printf ("%s ", t->name); + len += 1 + strlen (t->name); + + /* Break long lines */ + + if (len > 66 && (t+1)->name) + { + printf ("\n%s", indent); + len = strlen (indent); + } + } + + printf ("\n\n"); +} + /* return register class from register number. */ static const enum reg_class reg_class_tab[]={ @@ -243,8 +317,7 @@ static struct machine_function * avr_init_machine_status (void) { - return ((struct machine_function *) - ggc_alloc_cleared (sizeof (struct machine_function))); + return ggc_alloc_cleared_machine_function (); } /* Return register class for register R. */ @@ -410,7 +483,7 @@ /* Return contents of MEM at frame pointer + stack size + 1 (+2 if 3 byte PC). This is return address of function. */ rtx -avr_return_addr_rtx (int count, const_rtx tem) +avr_return_addr_rtx (int count, rtx tem) { rtx r; @@ -739,6 +812,9 @@ } } } + + if (flag_stack_usage) + current_function_static_stack_size = cfun->machine->stack_usage; } /* Output summary at end of function prologue. */ @@ -952,6 +1028,27 @@ fprintf (file, "/* epilogue start */\n"); } + +/* Implement TARGET_CANNOT_MODITY_JUMPS_P */ + +static bool +avr_cannot_modify_jumps_p (void) +{ + + /* Naked Functions must not have any instructions after + their epilogue, see PR42240 */ + + if (reload_completed + && cfun->machine + && cfun->machine->is_naked) + { + return true; + } + + return false; +} + + /* Return nonzero if X (an RTX) is a legitimate memory address on the target machine for a memory operand of mode MODE. */ @@ -1137,7 +1234,7 @@ output_addr_const (file, XEXP (x,0)); fprintf (file,"+" HOST_WIDE_INT_PRINT_DEC ")", 2 * INTVAL (XEXP (x,1))); if (AVR_3_BYTE_PC) - if (warning ( 0, "Pointer offset from symbol maybe incorrect.")) + if (warning (0, "pointer offset from symbol maybe incorrect")) { output_addr_const (stderr, addr); fprintf(stderr,"\n"); @@ -1530,20 +1627,14 @@ { cum->nregs = 18; cum->regno = FIRST_CUM_REG; - if (!libname && fntype) - { - int stdarg = (TYPE_ARG_TYPES (fntype) != 0 - && (TREE_VALUE (tree_last (TYPE_ARG_TYPES (fntype))) - != void_type_node)); - if (stdarg) - cum->nregs = 0; - } + if (!libname && stdarg_p (fntype)) + cum->nregs = 0; } /* Returns the number of registers to allocate for a function argument. */ static int -avr_num_arg_regs (enum machine_mode mode, tree type) +avr_num_arg_regs (enum machine_mode mode, const_tree type) { int size; @@ -1561,9 +1652,9 @@ /* Controls whether a function argument is passed in a register, and which register. */ -rtx -function_arg (CUMULATIVE_ARGS *cum, enum machine_mode mode, tree type, - int named ATTRIBUTE_UNUSED) +static rtx +avr_function_arg (CUMULATIVE_ARGS *cum, enum machine_mode mode, + const_tree type, bool named ATTRIBUTE_UNUSED) { int bytes = avr_num_arg_regs (mode, type); @@ -1576,9 +1667,9 @@ /* Update the summarizer variable CUM to advance past an argument in the argument list. */ -void -function_arg_advance (CUMULATIVE_ARGS *cum, enum machine_mode mode, tree type, - int named ATTRIBUTE_UNUSED) +static void +avr_function_arg_advance (CUMULATIVE_ARGS *cum, enum machine_mode mode, + const_tree type, bool named ATTRIBUTE_UNUSED) { int bytes = avr_num_arg_regs (mode, type); @@ -4233,6 +4324,8 @@ /* Work out if byte or word move is needed. Odd byte rotates need QImode. Word move if no scratch is needed, otherwise use size of scratch. */ enum machine_mode move_mode = QImode; + int move_size, offset, size; + if (num & 0xf) move_mode = QImode; else if ((mode == SImode && !same_reg) || !overlapped) @@ -4248,11 +4341,11 @@ if (GET_MODE (scratch) == HImode && move_mode == QImode) scratch = simplify_gen_subreg (move_mode, scratch, HImode, 0); - int move_size = GET_MODE_SIZE (move_mode); + move_size = GET_MODE_SIZE (move_mode); /* Number of bytes/words to rotate. */ - int offset = (num >> 3) / move_size; + offset = (num >> 3) / move_size; /* Number of moves needed. */ - int size = GET_MODE_SIZE (mode) / move_size; + size = GET_MODE_SIZE (mode) / move_size; /* Himode byte swap is special case to avoid a scratch register. */ if (mode == HImode && same_reg) { @@ -4269,12 +4362,15 @@ } else { +#define MAX_SIZE 8 /* GET_MODE_SIZE (DImode) / GET_MODE_SIZE (QImode) */ /* Create linked list of moves to determine move order. */ struct { rtx src, dst; int links; - } move[size + 8]; - + } move[MAX_SIZE + 8]; + int blocked, moves; + + gcc_assert (size <= MAX_SIZE); /* Generate list of subreg moves. */ for (i = 0; i < size; i++) { @@ -4300,8 +4396,8 @@ break; } - int blocked = -1; - int moves = 0; + blocked = -1; + moves = 0; /* Go through move list and perform non-conflicting moves. As each non-overlapping move is made, it may remove other conflicts so the process is repeated until no conflicts remain. */ @@ -4313,18 +4409,21 @@ src already. */ for (i = 0; i < size; i++) if (move[i].src != NULL_RTX) - if (move[i].links == -1 || move[move[i].links].src == NULL_RTX) - { - moves++; - /* Ignore NOP moves to self. */ - if (!rtx_equal_p (move[i].dst, move[i].src)) - emit_move_insn (move[i].dst, move[i].src); - - /* Remove conflict from list. */ - move[i].src = NULL_RTX; - } - else - blocked = i; + { + if (move[i].links == -1 + || move[move[i].links].src == NULL_RTX) + { + moves++; + /* Ignore NOP moves to self. */ + if (!rtx_equal_p (move[i].dst, move[i].src)) + emit_move_insn (move[i].dst, move[i].src); + + /* Remove conflict from list. */ + move[i].src = NULL_RTX; + } + else + blocked = i; + } /* Check for deadlock. This is when no moves occurred and we have at least one blocked move. */ @@ -4764,8 +4863,8 @@ assigned to registers of class CLASS would likely be spilled because registers of CLASS are needed for spill registers. */ -bool -class_likely_spilled_p (int c) +static bool +avr_class_likely_spilled_p (reg_class_t c) { return (c != ALL_REGS && c != ADDW_REGS); } @@ -5039,6 +5138,32 @@ } +/* Implement `TARGET_REGISTER_MOVE_COST' */ + +static int +avr_register_move_cost (enum machine_mode mode ATTRIBUTE_UNUSED, + reg_class_t from, reg_class_t to) +{ + return (from == STACK_REG ? 6 + : to == STACK_REG ? 12 + : 2); +} + + +/* Implement `TARGET_MEMORY_MOVE_COST' */ + +static int +avr_memory_move_cost (enum machine_mode mode, reg_class_t rclass ATTRIBUTE_UNUSED, + bool in ATTRIBUTE_UNUSED) +{ + return (mode == QImode ? 2 + : mode == HImode ? 4 + : mode == SImode ? 8 + : mode == SFmode ? 8 + : 16); +} + + /* Mutually recursive subroutine of avr_rtx_cost for calculating the cost of an RTX operand given its context. X is the rtx of the operand, MODE is its mode, and OUTER is the rtx_code of this @@ -5827,16 +5952,6 @@ return gen_rtx_REG (BLKmode, RET_REGISTER + 2 - offs); } -/* Places additional restrictions on the register class to - use when it is necessary to copy value X into a register - in class CLASS. */ - -enum reg_class -preferred_reload_class (rtx x ATTRIBUTE_UNUSED, enum reg_class rclass) -{ - return rclass; -} - int test_hard_reg_class (enum reg_class rclass, rtx x) {