m68k-protos.h: Rename m68k_interrupt_function_p to m68k_get_function_kind.
authorKazu Hirata <kazu@codesourcery.com>
Mon, 14 May 2007 13:52:18 +0000 (13:52 +0000)
committerKazu Hirata <kazu@gcc.gnu.org>
Mon, 14 May 2007 13:52:18 +0000 (13:52 +0000)
gcc/
* config/m68k/m68k-protos.h: Rename m68k_interrupt_function_p
to m68k_get_function_kind.  Update its prototype.
* config/m68k/m68k.c (m68k_attribute_table): Add an entry for
interrupt_thread.
(m68k_interrupt_function_p): Return enum m68k_function_type
instead of bool.  Rename to m68k_get_function_kind.
(m68k_handle_fndecl_attribute): Reject interrupt_thread if the
target is not fido.
(m68k_compute_frame_layout): Don't mark any register for save
if an interrupt_thread attribute is specified.
(m68k_hard_regno_rename_ok): Update a use of
m68k_interrupt_function_p.
* config/m68k/m68k.h (EPILOGUE_USES): Update a use of
m68k_interrupt_function_p.
(m68k_function_type): New.
* config/m68k/m68k.md (*return): Output a 'sleep' instruction
for a function with an interrupt_thread attribute.
* doc/extend.texi: Document the interrupt_thread attribute.

gcc/testsuite/
* gcc.target/m68k/interrupt_thread-1.c,
gcc.target/m68k/interrupt_thread-2.c,
gcc.target/m68k/interrupt_thread-3.c: New.
* gcc.target/m68k/m68k.exp: Accept fido.

From-SVN: r124713

gcc/ChangeLog
gcc/config/m68k/m68k-protos.h
gcc/config/m68k/m68k.c
gcc/config/m68k/m68k.h
gcc/config/m68k/m68k.md
gcc/doc/extend.texi
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.target/m68k/m68k.exp

index 46ee450c5fd0cce25e8dc6ebcb32ce0e33773181..d470dabc4e31e29913b1015c8dea9b2e47004384 100644 (file)
@@ -1,3 +1,24 @@
+2007-05-14  Kazu Hirata  <kazu@codesourcery.com>
+
+       * config/m68k/m68k-protos.h: Rename m68k_interrupt_function_p
+       to m68k_get_function_kind.  Update its prototype.
+       * config/m68k/m68k.c (m68k_attribute_table): Add an entry for
+       interrupt_thread.
+       (m68k_interrupt_function_p): Return enum m68k_function_type
+       instead of bool.  Rename to m68k_get_function_kind.
+       (m68k_handle_fndecl_attribute): Reject interrupt_thread if the
+       target is not fido.
+       (m68k_compute_frame_layout): Don't mark any register for save
+       if an interrupt_thread attribute is specified.
+       (m68k_hard_regno_rename_ok): Update a use of
+       m68k_interrupt_function_p.
+       * config/m68k/m68k.h (EPILOGUE_USES): Update a use of
+       m68k_interrupt_function_p.
+       (m68k_function_type): New.
+       * config/m68k/m68k.md (*return): Output a 'sleep' instruction
+       for a function with an interrupt_thread attribute.
+       * doc/extend.texi: Document the interrupt_thread attribute.
+
 2007-05-13  Daniel Berlin  <dberlin@dberlin.org>
 
        Fix PR tree-optimization/31911
 2007-05-13  Daniel Berlin  <dberlin@dberlin.org>
 
        Fix PR tree-optimization/31911
index b3b78a15adb99b904a7028c0f9f230aa8f0d0f24..f5d6c3af76e4dff7654b1866cd92f55197c89916 100644 (file)
@@ -21,7 +21,7 @@ Boston, MA 02110-1301, USA.  */
 /* Define functions defined in aux-output.c and used in templates.  */
 
 #ifdef RTX_CODE
 /* Define functions defined in aux-output.c and used in templates.  */
 
 #ifdef RTX_CODE
-extern bool m68k_interrupt_function_p (tree);
+extern enum m68k_function_kind m68k_get_function_kind (tree);
 extern HOST_WIDE_INT m68k_initial_elimination_offset (int from, int to);
 
 extern void split_di (rtx[], int, rtx[], rtx[]);
 extern HOST_WIDE_INT m68k_initial_elimination_offset (int from, int to);
 
 extern void split_di (rtx[], int, rtx[], rtx[]);
index f975e06fea99d385124d18e013a4d6b2df3ca034..87665596726f734cde3704f8d8b3aad19a3995fb 100644 (file)
@@ -223,6 +223,7 @@ static const struct attribute_spec m68k_attribute_table[] =
 {
   /* { name, min_len, max_len, decl_req, type_req, fn_type_req, handler } */
   { "interrupt_handler", 0, 0, true,  false, false, m68k_handle_fndecl_attribute },
 {
   /* { name, min_len, max_len, decl_req, type_req, fn_type_req, handler } */
   { "interrupt_handler", 0, 0, true,  false, false, m68k_handle_fndecl_attribute },
+  { "interrupt_thread", 0, 0, true,  false, false, m68k_handle_fndecl_attribute },
   { NULL,                0, 0, false, false, false, NULL }
 };
 
   { NULL,                0, 0, false, false, false, NULL }
 };
 
@@ -633,10 +634,12 @@ m68k_cpp_cpu_family (const char *prefix)
   return concat ("__m", prefix, "_family_", m68k_cpu_entry->family, NULL);
 }
 \f
   return concat ("__m", prefix, "_family_", m68k_cpu_entry->family, NULL);
 }
 \f
-/* Return nonzero if FUNC is an interrupt function as specified by the
-   "interrupt_handler" attribute.  */
-bool
-m68k_interrupt_function_p (tree func)
+/* Return m68k_fk_interrupt_handler if FUNC has an "interrupt_handler"
+   attribute and interrupt_thread if FUNC has an "interrupt_thread"
+   attribute.  Otherwise, return m68k_fk_normal_function.  */
+
+enum m68k_function_kind
+m68k_get_function_kind (tree func)
 {
   tree a;
 
 {
   tree a;
 
@@ -644,7 +647,14 @@ m68k_interrupt_function_p (tree func)
     return false;
 
   a = lookup_attribute ("interrupt_handler", DECL_ATTRIBUTES (func));
     return false;
 
   a = lookup_attribute ("interrupt_handler", DECL_ATTRIBUTES (func));
-  return (a != NULL_TREE);
+  if (a != NULL_TREE)
+    return m68k_fk_interrupt_handler;
+
+  a = lookup_attribute ("interrupt_thread", DECL_ATTRIBUTES (func));
+  if (a != NULL_TREE)
+    return m68k_fk_interrupt_thread;
+
+  return m68k_fk_normal_function;
 }
 
 /* Handle an attribute requiring a FUNCTION_DECL; arguments as in
 }
 
 /* Handle an attribute requiring a FUNCTION_DECL; arguments as in
@@ -662,6 +672,19 @@ m68k_handle_fndecl_attribute (tree *node, tree name,
       *no_add_attrs = true;
     }
 
       *no_add_attrs = true;
     }
 
+  if (m68k_get_function_kind (*node) != m68k_fk_normal_function)
+    {
+      error ("multiple interrupt attributes not allowed");
+      *no_add_attrs = true;
+    }
+
+  if (!TARGET_FIDOA
+      && !strcmp (IDENTIFIER_POINTER (name), "interrupt_thread"))
+    {
+      error ("interrupt_thread is available only on fido");
+      *no_add_attrs = true;
+    }
+
   return NULL_TREE;
 }
 
   return NULL_TREE;
 }
 
@@ -670,7 +693,10 @@ m68k_compute_frame_layout (void)
 {
   int regno, saved;
   unsigned int mask;
 {
   int regno, saved;
   unsigned int mask;
-  bool interrupt_handler = m68k_interrupt_function_p (current_function_decl);
+  enum m68k_function_kind func_kind =
+    m68k_get_function_kind (current_function_decl);
+  bool interrupt_handler = func_kind == m68k_fk_interrupt_handler;
+  bool interrupt_thread = func_kind == m68k_fk_interrupt_thread;
 
   /* Only compute the frame once per function.
      Don't cache information until reload has been completed.  */
 
   /* Only compute the frame once per function.
      Don't cache information until reload has been completed.  */
@@ -681,12 +707,15 @@ m68k_compute_frame_layout (void)
   current_frame.size = (get_frame_size () + 3) & -4;
 
   mask = saved = 0;
   current_frame.size = (get_frame_size () + 3) & -4;
 
   mask = saved = 0;
-  for (regno = 0; regno < 16; regno++)
-    if (m68k_save_reg (regno, interrupt_handler))
-      {
-       mask |= 1 << (regno - D0_REG);
-       saved++;
-      }
+
+  /* Interrupt thread does not need to save any register.  */
+  if (!interrupt_thread)
+    for (regno = 0; regno < 16; regno++)
+      if (m68k_save_reg (regno, interrupt_handler))
+       {
+         mask |= 1 << (regno - D0_REG);
+         saved++;
+       }
   current_frame.offset = saved * 4;
   current_frame.reg_no = saved;
   current_frame.reg_mask = mask;
   current_frame.offset = saved * 4;
   current_frame.reg_no = saved;
   current_frame.reg_mask = mask;
@@ -695,12 +724,14 @@ m68k_compute_frame_layout (void)
   mask = saved = 0;
   if (TARGET_HARD_FLOAT)
     {
   mask = saved = 0;
   if (TARGET_HARD_FLOAT)
     {
-      for (regno = 16; regno < 24; regno++)
-       if (m68k_save_reg (regno, interrupt_handler))
-         {
-           mask |= 1 << (regno - FP0_REG);
-           saved++;
-         }
+      /* Interrupt thread does not need to save any register.  */
+      if (!interrupt_thread)
+       for (regno = 16; regno < 24; regno++)
+         if (m68k_save_reg (regno, interrupt_handler))
+           {
+             mask |= 1 << (regno - FP0_REG);
+             saved++;
+           }
       current_frame.foffset = saved * TARGET_FP_REG_SIZE;
       current_frame.offset += current_frame.foffset;
     }
       current_frame.foffset = saved * TARGET_FP_REG_SIZE;
       current_frame.offset += current_frame.foffset;
     }
@@ -4211,7 +4242,8 @@ m68k_hard_regno_rename_ok (unsigned int old_reg ATTRIBUTE_UNUSED,
      saved by the prologue, even if they would normally be
      call-clobbered.  */
 
      saved by the prologue, even if they would normally be
      call-clobbered.  */
 
-  if (m68k_interrupt_function_p (current_function_decl)
+  if ((m68k_get_function_kind (current_function_decl)
+       == m68k_fk_interrupt_handler)
       && !regs_ever_live[new_reg])
     return 0;
 
       && !regs_ever_live[new_reg])
     return 0;
 
index baa5bcb66514cf9c9690b3ca698aae32706f9177..1b19b4c80957072b0d30b8fd90bcbecde62248ee 100644 (file)
@@ -903,8 +903,10 @@ do { if (cc_prev_status.flags & CC_IN_68881)                       \
 #define INCOMING_FRAME_SP_OFFSET 4
 
 /* All registers are live on exit from an interrupt routine.  */
 #define INCOMING_FRAME_SP_OFFSET 4
 
 /* All registers are live on exit from an interrupt routine.  */
-#define EPILOGUE_USES(REGNO) \
-  (reload_completed && m68k_interrupt_function_p (current_function_decl))
+#define EPILOGUE_USES(REGNO)                                   \
+  (reload_completed                                            \
+   && (m68k_get_function_kind (current_function_decl)  \
+       == m68k_fk_interrupt_handler))
 
 /* Describe how we implement __builtin_eh_return.  */
 #define EH_RETURN_DATA_REGNO(N) \
 
 /* Describe how we implement __builtin_eh_return.  */
 #define EH_RETURN_DATA_REGNO(N) \
@@ -1098,6 +1100,13 @@ enum fpu_type
   FPUTYPE_COLDFIRE
 };
 
   FPUTYPE_COLDFIRE
 };
 
+enum m68k_function_kind
+{
+  m68k_fk_normal_function,
+  m68k_fk_interrupt_handler,
+  m68k_fk_interrupt_thread
+};
+
 /* Variables in m68k.c; see there for details.  */
 extern const char *m68k_library_id_string;
 extern int m68k_last_compare_had_fp_operands;
 /* Variables in m68k.c; see there for details.  */
 extern const char *m68k_library_id_string;
 extern int m68k_last_compare_had_fp_operands;
index 78ddf58f71e7d377921b7c1baca314d91670c2a0..19abe624c293c0043313aa0bed5f80352afc5ec1 100644 (file)
   [(return)]
   ""
 {
   [(return)]
   ""
 {
-  if (m68k_interrupt_function_p (current_function_decl))
-    return "rte";
-  else if (current_function_pops_args)
+  switch (m68k_get_function_kind (current_function_decl))
     {
     {
-      operands[0] = GEN_INT (current_function_pops_args);
-      return "rtd %0";
+    case m68k_fk_interrupt_handler:
+      return "rte";
+
+    case m68k_fk_interrupt_thread:
+      return "sleep";
+
+    default:
+      if (current_function_pops_args)
+       {
+         operands[0] = GEN_INT (current_function_pops_args);
+         return "rtd %0";
+       }
+      else
+       return "rts";
     }
     }
-  else
-    return "rts";
 })
 
 (define_insn "*m68k_store_multiple"
 })
 
 (define_insn "*m68k_store_multiple"
index 574bc12776826053f374ba0b847460863128dabf..4a8f67455cccf027844160a1e1ec7f22caddbb04 100644 (file)
@@ -2047,6 +2047,14 @@ indicate that the specified function is an interrupt handler.  The compiler
 will generate function entry and exit sequences suitable for use in an
 interrupt handler when this attribute is present.
 
 will generate function entry and exit sequences suitable for use in an
 interrupt handler when this attribute is present.
 
+@item interrupt_thread
+@cindex interrupt thread functions on fido
+Use this attribute on fido, a subarchitecture of the m68k, to indicate
+that the specified function is an interrupt handler that is designed
+to run as a thread.  The compiler omits generate prologue/epilogue
+sequences and replaces the return instruction with a @code{sleep}
+instruction.  This attribute is available only on fido.
+
 @item kspisusp
 @cindex User stack pointer in interrupts on the Blackfin
 When used together with @code{interrupt_handler}, @code{exception_handler}
 @item kspisusp
 @cindex User stack pointer in interrupts on the Blackfin
 When used together with @code{interrupt_handler}, @code{exception_handler}
index fe908d11df102bc2ec98c5721534027d5b25acbf..0c3111793de653a1c4deb0702f3f3e3c42b32a4e 100644 (file)
@@ -1,3 +1,10 @@
+2007-05-14  Kazu Hirata  <kazu@codesourcery.com>
+
+       * gcc.target/m68k/interrupt_thread-1.c,
+       gcc.target/m68k/interrupt_thread-2.c,
+       gcc.target/m68k/interrupt_thread-3.c: New.
+       * gcc.target/m68k/m68k.exp: Accept fido.
+
 2007-05-13  Dominique d'Humières  <dominiq@lps.ens.fr>
 
        * alloc_comp_basics_1.f90: Fix dg directive.
 2007-05-13  Dominique d'Humières  <dominiq@lps.ens.fr>
 
        * alloc_comp_basics_1.f90: Fix dg directive.
index 9398d109cc606a690116618dd2170460191f868d..872802d958630fdcd9aed7345150bb437b8c0cf2 100644 (file)
@@ -17,7 +17,7 @@
 # GCC testsuite that uses the `dg.exp' driver.
 
 # Exit immediately if this isn't an m68k target.
 # GCC testsuite that uses the `dg.exp' driver.
 
 # Exit immediately if this isn't an m68k target.
-if ![istarget m68k*-*-*] then {
+if { ![istarget m68k*-*-*] && ![istarget fido*-*-*] } then {
   return
 }
 
   return
 }