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 }
 };
 
