Not committed Adds OS_main attribute feature. Written by Anatoly Sokolov. Apply patch after XMEGA patch. -------------------------------------------------------------------------------- Index: gcc/function.c =================================================================== --- gcc/function.c (revision 133747) +++ gcc/function.c (working copy) @@ -4756,6 +4756,14 @@ } int +prologue_contains (const_rtx insn) +{ + if (contains (insn, &prologue)) + return 1; + return 0; +} + +int prologue_epilogue_contains (const_rtx insn) { if (contains (insn, &prologue)) Index: gcc/rtl.h =================================================================== --- gcc/rtl.h (revision 133747) +++ gcc/rtl.h (working copy) @@ -2128,6 +2128,7 @@ /* In function.c */ extern void reposition_prologue_and_epilogue_notes (void); +extern int prologue_contains (const_rtx); extern int prologue_epilogue_contains (const_rtx); extern int sibcall_epilogue_contains (const_rtx); extern void mark_temp_addr_taken (rtx); --- gcc/config/avr/avr.h.orig 2008-03-31 16:48:03.477537900 -0600 +++ gcc/config/avr/avr.h 2008-03-31 17:07:51.442457900 -0600 @@ -1095,4 +1095,8 @@ struct machine_function GTY(()) /* 'true' - if current function is a task function as specified by the "OS_task" attribute. */ int is_OS_task; + + /* 'true' - if current function is a 'main' function + as specified by the "OS_main" attribute. */ + int is_OS_main; }; --- gcc/config/avr/avr.c.orig Mon Mar 31 19:47:54 2008 +++ gcc/config/avr/avr.c Mon Mar 31 20:50:08 2008 @@ -53,6 +53,7 @@ static int interrupt_function_p (tree); static int signal_function_p (tree); static int nmi_function_p (tree); static int avr_OS_task_function_p (tree); +static int avr_OS_main_function_p (tree); static int avr_regs_to_save (HARD_REG_SET *); static void avr_args (HARD_REG_SET *); static int sequent_regs_live (HARD_REG_SET *); @@ -509,6 +513,19 @@ avr_OS_task_function_p (tree func) 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 the number of hard registers to push/pop in the prologue/epilogue of the current function, and optionally store these registers in SET. */ @@ -527,9 +544,10 @@ avr_regs_to_save (HARD_REG_SET *set) count = 0; /* No need to save any registers if the function never returns or - is have "OS_task" attribute. */ + is have "OS_task" or "OS_main" attribute. */ if (TREE_THIS_VOLATILE (current_function_decl) - || cfun->machine->is_OS_task) + || cfun->machine->is_OS_task + || cfun->machine->is_OS_main) return 0; for (reg = 0; reg < 32; reg++) @@ -646,6 +664,8 @@ expand_prologue (void) rtx pushword = gen_rtx_MEM (HImode, gen_rtx_POST_DEC (HImode, stack_pointer_rtx)); rtx insn; + int method1_length; + int sp_plus_length; last_insn_address = 0; @@ -655,6 +675,7 @@ expand_prologue (void) cfun->machine->is_signal = signal_function_p (current_function_decl); cfun->machine->is_nmi = nmi_function_p (current_function_decl); cfun->machine->is_OS_task = avr_OS_task_function_p (current_function_decl); + cfun->machine->is_OS_main = avr_OS_main_function_p (current_function_decl); /* Prologue: naked. */ if (cfun->machine->is_naked) @@ -669,6 +690,7 @@ expand_prologue (void) && !cfun->machine->is_interrupt && !cfun->machine->is_signal && !cfun->machine->is_OS_task + && !cfun->machine->is_OS_main && live_seq); if (cfun->machine->is_interrupt || cfun->machine->is_signal) @@ -738,7 +760,7 @@ expand_prologue (void) } if (frame_pointer_needed) { - if(!cfun->machine->is_OS_task) + if (!(cfun->machine->is_OS_task || cfun->machine->is_OS_main)) { /* Push frame pointer. */ insn = emit_move_insn (pushword, frame_pointer_rtx); @@ -768,7 +790,7 @@ expand_prologue (void) if (TARGET_TINY_STACK) { if (size < -63 || size > 63) - warning (0, "large frame pointer change (%d) with -mtiny-stack", size); + warning (0, "large frame pointer change (%ld) with -mtiny-stack", size); /* The high byte (r29) doesn't change - prefer 'subi' (1 cycle) over 'sbiw' (2 cycles, same size). */ @@ -780,7 +802,6 @@ expand_prologue (void) myfp = frame_pointer_rtx; } /* Calculate length. */ - int method1_length; method1_length = get_attr_length (gen_move_insn (frame_pointer_rtx, stack_pointer_rtx)); method1_length += @@ -878,6 +899,7 @@ expand_epilogue (void) HARD_REG_SET set; int minimize; HOST_WIDE_INT size = get_frame_size(); + int sp_plus_length; /* epilogue: naked */ if (cfun->machine->is_naked) @@ -893,6 +915,7 @@ expand_epilogue (void) && !cfun->machine->is_interrupt && !cfun->machine->is_signal && !cfun->machine->is_OS_task + && !cfun->machine->is_OS_main && live_seq); if (minimize && (frame_pointer_needed || live_seq > 4)) @@ -955,7 +978,7 @@ expand_epilogue (void) emit_move_insn (stack_pointer_rtx, frame_pointer_rtx); } } - if(!cfun->machine->is_OS_task) + if (!(cfun->machine->is_OS_task || cfun->machine->is_OS_main)) { /* Restore previous frame_pointer. */ emit_insn (gen_pophi (frame_pointer_rtx)); @@ -1787,10 +1810,18 @@ output_movhi (rtx insn, rtx operands[], } /* Use simple load of stack pointer if no interrupts are used or inside main or signal function prologue where they disabled. */ - else if (TARGET_NO_INTERRUPTS + else if ((!AVR_XMEGA && TARGET_NO_INTERRUPTS) || (!AVR_XMEGA - && reload_completed + && reload_completed && cfun->machine->is_signal + && prologue_epilogue_contains (insn)) + || (!AVR_XMEGA + && reload_completed + && cfun->machine->is_OS_main + && prologue_contains (insn)) + || (AVR_XMEGA + && reload_completed + && cfun->machine->is_nmi && prologue_epilogue_contains (insn))) { *l = 2; @@ -4821,6 +4852,7 @@ const struct attribute_spec avr_attribut { "nmi", 0, 0, true, false, false, avr_handle_fndecl_attribute }, { "naked", 0, 0, false, true, true, avr_handle_fntype_attribute }, { "OS_task", 0, 0, false, true, true, avr_handle_fntype_attribute }, + { "OS_main", 0, 0, false, true, true, avr_handle_fntype_attribute }, { NULL, 0, 0, false, false, false, NULL } };