Index: gcc/config/avr/avr.c =================================================================== --- gcc/config/avr/avr.c (revision 129730) +++ gcc/config/avr/avr.c (working copy) @@ -48,6 +48,8 @@ #define MAX_LD_OFFSET(MODE) (64 - (signed)GET_MODE_SIZE (MODE)) static int avr_naked_function_p (tree); +static int avr_OS_main_function_p (tree); +static int avr_OS_task_function_p (tree); static int interrupt_function_p (tree); static int signal_function_p (tree); static int avr_regs_to_save (HARD_REG_SET *); @@ -400,6 +402,33 @@ return a != NULL_TREE; } +/* Return nonzero if FUNC is a OS_main function. */ + +static int +avr_OS_main_function_p (tree func) +{ + tree a; + + gcc_assert (TREE_CODE (func) == FUNCTION_DECL); + + a = lookup_attribute ("OS_main", TYPE_ATTRIBUTES (TREE_TYPE (func))); + return a != NULL_TREE; +} + +/* Return nonzero if FUNC is a OS_task function. */ + +static int +avr_OS_task_function_p (tree func) +{ + tree a; + + gcc_assert (TREE_CODE (func) == FUNCTION_DECL); + + a = lookup_attribute ("OS_task", TYPE_ATTRIBUTES (TREE_TYPE (func))); + return a != NULL_TREE; +} + + /* Return nonzero if FUNC is an interrupt function as specified by the "interrupt" attribute. */ @@ -445,8 +474,11 @@ CLEAR_HARD_REG_SET (*set); count = 0; - /* No need to save any registers if the function never returns. */ - if (TREE_THIS_VOLATILE (current_function_decl)) + /* No need to save any registers if the function never returns or + is have "OS_main" or OS_task attribute. */ + if (TREE_THIS_VOLATILE (current_function_decl) + || avr_OS_main_function_p (current_function_decl) + || avr_OS_task_function_p (current_function_decl)) return 0; for (reg = 0; reg < 32; reg++) @@ -497,7 +529,6 @@ && ! interrupt_function_p (current_function_decl) && ! signal_function_p (current_function_decl) && ! avr_naked_function_p (current_function_decl) - && ! MAIN_NAME_P (DECL_NAME (current_function_decl)) && ! TREE_THIS_VOLATILE (current_function_decl)); } @@ -666,7 +697,8 @@ int reg; int interrupt_func_p; int signal_func_p; - int main_p; + int OS_main_p; + int OS_task_p; int live_seq; int minimize; @@ -684,9 +716,11 @@ interrupt_func_p = interrupt_function_p (current_function_decl); signal_func_p = signal_function_p (current_function_decl); - main_p = MAIN_NAME_P (DECL_NAME (current_function_decl)); + OS_main_p = avr_OS_main_function_p (current_function_decl); + OS_task_p = avr_OS_task_function_p (current_function_decl); live_seq = sequent_regs_live (); minimize = (TARGET_CALL_PROLOGUES + && !OS_main_p && !OS_task_p && !interrupt_func_p && !signal_func_p && live_seq); if (interrupt_func_p) @@ -704,19 +738,8 @@ AS1 (clr,__zero_reg__) "\n"); prologue_size += 5; } - if (main_p) + if (minimize && (frame_pointer_needed || live_seq > 6)) { - fprintf (file, ("\t" - AS1 (ldi,r28) ",lo8(%s - " HOST_WIDE_INT_PRINT_DEC ")" CR_TAB - AS1 (ldi,r29) ",hi8(%s - " HOST_WIDE_INT_PRINT_DEC ")" CR_TAB - AS2 (out,__SP_H__,r29) CR_TAB - AS2 (out,__SP_L__,r28) "\n"), - avr_init_stack, size, avr_init_stack, size); - - prologue_size += 4; - } - else if (minimize && (frame_pointer_needed || live_seq > 6)) - { fprintf (file, ("\t" AS1 (ldi, r26) ",lo8(" HOST_WIDE_INT_PRINT_DEC ")" CR_TAB AS1 (ldi, r27) ",hi8(" HOST_WIDE_INT_PRINT_DEC ")" CR_TAB), size, size); @@ -754,12 +777,17 @@ } if (frame_pointer_needed) { + if (!OS_main_p && !OS_task_p) + { + fprintf (file, "\t" + AS1 (push,r28) CR_TAB + AS1 (push,r29) "\n"); + prologue_size += 2; + } fprintf (file, "\t" - AS1 (push,r28) CR_TAB - AS1 (push,r29) CR_TAB AS2 (in,r28,__SP_L__) CR_TAB AS2 (in,r29,__SP_H__) "\n"); - prologue_size += 4; + prologue_size += 2; if (size) { fputs ("\t", file); @@ -769,7 +797,7 @@ { prologue_size += out_set_stack_ptr (file, 1, 1); } - else if (signal_func_p) + else if (signal_func_p || OS_main_p) { prologue_size += out_set_stack_ptr (file, 0, 0); } @@ -793,7 +821,8 @@ int reg; int interrupt_func_p; int signal_func_p; - int main_p; + int OS_main_p; + int OS_task_p; int function_size; int live_seq; int minimize; @@ -825,28 +854,15 @@ interrupt_func_p = interrupt_function_p (current_function_decl); signal_func_p = signal_function_p (current_function_decl); - main_p = MAIN_NAME_P (DECL_NAME (current_function_decl)); + OS_main_p = avr_OS_main_function_p (current_function_decl); + OS_task_p = avr_OS_task_function_p (current_function_decl); live_seq = sequent_regs_live (); minimize = (TARGET_CALL_PROLOGUES + && !OS_main_p && !OS_task_p && !interrupt_func_p && !signal_func_p && live_seq); - if (main_p) + if (minimize && (frame_pointer_needed || live_seq > 4)) { - /* Return value from main() is already in the correct registers - (r25:r24) as the exit() argument. */ - if (AVR_MEGA) - { - fputs ("\t" AS1 (jmp,exit) "\n", file); - epilogue_size += 2; - } - else - { - fputs ("\t" AS1 (rjmp,exit) "\n", file); - ++epilogue_size; - } - } - else if (minimize && (frame_pointer_needed || live_seq > 4)) - { fprintf (file, ("\t" AS2 (ldi, r30, %d) CR_TAB), live_seq); ++epilogue_size; if (frame_pointer_needed) @@ -893,10 +909,13 @@ epilogue_size += out_set_stack_ptr (file, -1, -1); } } - fprintf (file, "\t" - AS1 (pop,r29) CR_TAB - AS1 (pop,r28) "\n"); - epilogue_size += 2; + if (!OS_main_p && !OS_task_p) + { + fprintf (file, "\t" + AS1 (pop,r29) CR_TAB + AS1 (pop,r28) "\n"); + epilogue_size += 2; + } } epilogue_size += avr_regs_to_save (&set); @@ -4643,6 +4662,8 @@ interrupt - make a function to be hardware interrupt. After function prologue interrupts are enabled; naked - don't generate function prologue/epilogue and `ret' command. + OS_main - ... + OS_task - ... Only `progmem' attribute valid for type. */ @@ -4653,6 +4674,8 @@ { "signal", 0, 0, true, false, false, avr_handle_fndecl_attribute }, { "interrupt", 0, 0, true, false, false, avr_handle_fndecl_attribute }, { "naked", 0, 0, false, true, true, avr_handle_fntype_attribute }, + { "OS_main", 0, 0, false, true, true, avr_handle_fntype_attribute }, + { "OS_task", 0, 0, false, true, true, avr_handle_fntype_attribute }, { NULL, 0, 0, false, false, false, NULL } };