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