--- ./gcc/config/avr/avr.c.orig 2010-03-05 15:10:10.000000000 +0100 +++ ./gcc/config/avr/avr.c 2010-03-05 15:20:53.000000000 +0100 @@ -72,6 +72,12 @@ static void avr_insert_attributes (tree, tree *); static void avr_asm_init_sections (void); static unsigned int avr_section_type_flags (tree, const char *, int); +static void avr_asm_named_section (const char *name, unsigned int flags, tree decl); +/* Track if code will use .bss and/or .data */ +static int avr_need_clear_bss_p = 0; +static int avr_need_copy_data_p = 0; +static void avr_output_data_section_asm_op (const void*); +static void avr_output_bss_section_asm_op (const void*); static void avr_reorg (void); static void avr_asm_out_ctor (rtx, int); @@ -4782,6 +4788,54 @@ fprintf (asm_out_file, "\t.p2align 1\n"); } +/* ASM_OUTPUT_COMMON */ +/* Track need of __do_clear_bss */ + +void +avr_asm_output_common (FILE *stream, const char *name, + unsigned HOST_WIDE_INT size, + unsigned HOST_WIDE_INT rounded ATTRIBUTE_UNUSED) +{ + avr_need_clear_bss_p = 1; + fputs ("\t.comm ", stream); + assemble_name (stream, name); + fprintf (stream, ",%lu,1\n", (unsigned long) size); +} + +/* ASM_OUTPUT_LOCAL */ +/* Track need of __do_clear_bss */ + +void +avr_asm_output_local (FILE *stream, const char *name, + unsigned HOST_WIDE_INT size, + unsigned HOST_WIDE_INT rounded ATTRIBUTE_UNUSED) +{ + avr_need_clear_bss_p = 1; + fputs ("\t.lcomm ", stream); + assemble_name (stream, name); + fprintf (stream, ",%d\n", (int) size); +} + +/* Unnamed section callback to track need of __do_copy_data */ + +static void +avr_output_data_section_asm_op (const void *data) +{ + avr_need_copy_data_p = 1; + /* Dispatch to default */ + output_section_asm_op (data); +} + +/* Unnamed section callback to track need of __do_clear_bss */ + +static void +avr_output_bss_section_asm_op (const void *data) +{ + avr_need_clear_bss_p = 1; + /* Dispatch to default */ + output_section_asm_op (data); +} + /* Implement TARGET_ASM_INIT_SECTIONS. */ static void @@ -4791,6 +4845,27 @@ avr_output_progmem_section_asm_op, NULL); readonly_data_section = data_section; + + data_section->unnamed.callback = avr_output_data_section_asm_op; + bss_section->unnamed.callback = avr_output_bss_section_asm_op; +} + +/* TARGET_ASM_NAMED_SECTION */ +/* Track need of __do_clear_bss, __do_copy_data for named sections */ + +static void +avr_asm_named_section (const char *name, unsigned int flags, tree decl) +{ + if (!avr_need_copy_data_p) + avr_need_copy_data_p = + (0 == strncmp (name, ".data", 5) + || 0 == strncmp (name, ".rodata", 7) + || 0 == strncmp (name, ".gnu.linkonce.", 14)); + + if (!avr_need_clear_bss_p) + avr_need_clear_bss_p = (0 == strncmp (name, ".bss", 4)); + + default_elf_asm_named_section (name, flags, decl); } static unsigned int @@ -4829,12 +4904,6 @@ fputs ("__tmp_reg__ = 0\n" "__zero_reg__ = 1\n", asm_out_file); - - /* FIXME: output these only if there is anything in the .data / .bss - sections - some code size could be saved by not linking in the - initialization code from libgcc if one or both sections are empty. */ - fputs ("\t.global __do_copy_data\n", asm_out_file); - fputs ("\t.global __do_clear_bss\n", asm_out_file); } /* Outputs to the stdio stream FILE some @@ -4843,6 +4912,16 @@ static void avr_file_end (void) { + /* Output these only if there is anything in the + .data* / .rodata* / .gnu.linkonce.* resp. .bss* + input section(s) - some code size can be saved by not + linking in the initialization code from libgcc if resp. + sections are empty. */ + if (avr_need_copy_data_p) + fputs (".global __do_copy_data\n", asm_out_file); + + if (avr_need_clear_bss_p) + fputs (".global __do_clear_bss\n", asm_out_file); } /* Choose the order in which to allocate hard registers for --- ./gcc/config/avr/avr.h.orig 2010-03-05 15:10:10.000000000 +0100 +++ ./gcc/config/avr/avr.h 2010-03-05 15:20:53.000000000 +0100 @@ -533,29 +533,21 @@ #define ASM_APP_OFF "/* #NOAPP */\n" /* Switch into a generic section. */ -#define TARGET_ASM_NAMED_SECTION default_elf_asm_named_section +#define TARGET_ASM_NAMED_SECTION avr_asm_named_section #define TARGET_ASM_INIT_SECTIONS avr_asm_init_sections #define ASM_OUTPUT_ASCII(FILE, P, SIZE) gas_output_ascii (FILE,P,SIZE) #define IS_ASM_LOGICAL_LINE_SEPARATOR(C, STR) ((C) == '\n' || ((C) == '$')) -#define ASM_OUTPUT_COMMON(STREAM, NAME, SIZE, ROUNDED) \ -do { \ - fputs ("\t.comm ", (STREAM)); \ - assemble_name ((STREAM), (NAME)); \ - fprintf ((STREAM), ",%lu,1\n", (unsigned long)(SIZE)); \ -} while (0) +#define ASM_OUTPUT_COMMON(STREAM, NAME, SIZE, ROUNDED) \ + avr_asm_output_common (STREAM, NAME, SIZE, ROUNDED) -#define ASM_OUTPUT_BSS(FILE, DECL, NAME, SIZE, ROUNDED) \ - asm_output_bss ((FILE), (DECL), (NAME), (SIZE), (ROUNDED)) +#define ASM_OUTPUT_BSS(FILE, DECL, NAME, SIZE, ROUNDED) \ + asm_output_bss ((FILE), (DECL), (NAME), (SIZE), (ROUNDED)) -#define ASM_OUTPUT_LOCAL(STREAM, NAME, SIZE, ROUNDED) \ -do { \ - fputs ("\t.lcomm ", (STREAM)); \ - assemble_name ((STREAM), (NAME)); \ - fprintf ((STREAM), ",%d\n", (int)(SIZE)); \ -} while (0) +#define ASM_OUTPUT_LOCAL(STREAM, NAME, SIZE, ROUNDED) \ + avr_asm_output_local (STREAM, NAME, SIZE, ROUNDED) #undef TYPE_ASM_OP #undef SIZE_ASM_OP --- ./gcc/config/avr/avr-protos.h.orig 2008-06-15 23:32:29.000000000 +0200 +++ ./gcc/config/avr/avr-protos.h 2010-03-05 15:20:53.000000000 +0100 @@ -38,6 +38,8 @@ extern void gas_output_limited_string (FILE *file, const char *str); extern void gas_output_ascii (FILE *file, const char *str, size_t length); extern int avr_hard_regno_rename_ok (unsigned int, unsigned int); +extern void avr_asm_output_common (FILE *stream, const char *name, unsigned HOST_WIDE_INT size, unsigned HOST_WIDE_INT rounded); +extern void avr_asm_output_local (FILE *stream, const char *name, unsigned HOST_WIDE_INT size, unsigned HOST_WIDE_INT rounded); #ifdef TREE_CODE extern void asm_output_external (FILE *file, tree decl, char *name); @@ -123,6 +125,7 @@ extern int compare_eq_p (rtx insn); extern void out_shift_with_cnt (const char *template, rtx insn, rtx operands[], int *len, int t_len); +extern rtx avr_return_addr_rtx (int count, rtx tem); extern int avr_io_address_p (rtx x, int size); extern int avr_peep2_scratch_safe (rtx reg_rtx); #endif /* RTX_CODE */