This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[PATCH - SH] trap_exit and sp_switch with interrupt_handler attribute


Hi,

I had posted a patch for gcc3.3 regarding supporting 'trap_exit' and
'sp_switch' attributes with 'interrupt_handler attribute'. With gcc3.4 
onwards due to unit-at-a-time compilation scheme, it is not working with 
optimization (-O2,-O3,-Os). I have modified it to work with gcc3.4 and 
regression tested it with gcc3.4-20040709. This patch also removes 
problem of pragma_interrupt with optimization which declares all functions
below function declared with #pragma_inetrrupt as interrupt handlers.
Ok to apply to gcc3.4 and gcc3.5?

Regards,
Asgari Jinia
KPIT Cummins InfoSystems Ltd.
Pune, India

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Free download of GNU based tool-chains for Renesas' SH and H8 Series.
The following site also offers free technical support to its users. 
Visit http://www.kpitgnutools.com for details. 
Latest versions of KPIT GNU tools are released on June 1, 2004.
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 
======================================================================

ChangeLog:
2004-07-28  Asgari Jinia  <asgarij@kpitcummins.com>

	* config/sh/sh.c (sh_cfun_sp_switch_handler_p): Added.
      Returns true if current function has sp_switch attribute.
	(sh_cfun_trap_exit_p): Added. Returns true if current 
      function has trap_exit attribute.
	(print_operand): Use sh_cfun_trap_exit_p for checking 'trap_exit' 
      attribute.
	(sh_expand_prologue): Use sh_cfun_sp_switch_handler_p for checking 
      'sp_switch' attribute.
	(sh_insert_attributes): Reset pragma_interrupt
	(sh_handle_sp_switch_attribute): Use 'lookup_attribute' function to 
      check interrupt_handler attribute.
	(sh_handle_trap_exit_attribute): Use 'lookup_attribute' function to 
      check interrupt_handler attribute.

======================================
--- gcc-3.4-20040709/gcc/config/sh/sh.c.old	2004-07-28 12:20:42.000000000 +0530
+++ gcc-3.4-20040709/gcc/config/sh/sh.c	2004-07-28 12:41:31.000000000 +0530
@@ -203,8 +203,10 @@ static HOST_WIDE_INT rounded_frame_size 
 static rtx mark_constant_pool_use (rtx);
 const struct attribute_spec sh_attribute_table[];
 static tree sh_handle_interrupt_handler_attribute (tree *, tree, tree, int, bool *);
+static int sh_cfun_sp_switch_handler_p (void);
 static tree sh_handle_sp_switch_attribute (tree *, tree, tree, int, bool *);
 static tree sh_handle_trap_exit_attribute (tree *, tree, tree, int, bool *);
+static int sh_cfun_trap_exit_p (void);
 static tree sh_handle_renesas_attribute (tree *, tree, tree, int, bool *);
 static void sh_output_function_epilogue (FILE *, HOST_WIDE_INT);
 static void sh_insert_attributes (tree, tree *);
@@ -445,7 +447,7 @@ print_operand (FILE *stream, rtx x, int 
       fprintf (stream, "%s", LOCAL_LABEL_PREFIX);
       break;
     case '@':
-      if (trap_exit)
+      if (sh_cfun_trap_exit_p())
 	fprintf (stream, "trapa #%d", trap_exit);
       else if (sh_cfun_interrupt_handler_p ())
 	fprintf (stream, "rte");
@@ -5314,7 +5316,7 @@ sh_expand_prologue (void)
     }
 
   /* If we're supposed to switch stacks at function entry, do so now.  */
-  if (sp_switch)
+  if (sh_cfun_sp_switch_handler_p ())
     emit_insn (gen_sp_switch_1 ());
 
   d = calc_live_regs (&live_regs_mask);
@@ -5818,7 +5820,7 @@ sh_expand_epilogue (bool sibcall_p)
 			 EH_RETURN_STACKADJ_RTX));
 
   /* Switch back to the normal stack if necessary.  */
-  if (sp_switch)
+  if (sh_cfun_sp_switch_handler_p ())
     emit_insn (gen_sp_switch_2 ());
 
   /* Tell flow the insn that pops PR isn't dead.  */
@@ -6825,6 +6827,8 @@ sh_insert_attributes (tree node, tree *a
       || TREE_CODE (node) != FUNCTION_DECL)
     return;
 
+  pragma_interrupt = 0;
+
   /* We are only interested in fields.  */
   if (TREE_CODE_CLASS (TREE_CODE (node)) != 'd')
     return;
@@ -6895,7 +6899,8 @@ sh_handle_sp_switch_attribute (tree *nod
 	       IDENTIFIER_POINTER (name));
       *no_add_attrs = true;
     }
-  else if (!pragma_interrupt)
+  else if (lookup_attribute ("interrupt_handler",
+                              DECL_ATTRIBUTES (*node)) == NULL)
     {
       /* The sp_switch attribute only has meaning for interrupt functions.  */
       warning ("`%s' attribute only applies to interrupt functions",
@@ -6917,6 +6922,25 @@ sh_handle_sp_switch_attribute (tree *nod
 
   return NULL_TREE;
 }
+/* True if __attribute__((sp_switch)), for the current function.  */
+static int
+sh_cfun_sp_switch_handler_p (void)
+{
+  tree t;
+  t = lookup_attribute ("sp_switch",
+                        DECL_ATTRIBUTES (current_function_decl));
+  if (t != NULL_TREE)
+    {
+      sp_switch = gen_rtx_SYMBOL_REF (VOIDmode,
+				      TREE_STRING_POINTER (
+                                      TREE_VALUE(TREE_VALUE (t))));
+      return 1;
+    }
+  else
+    {
+      return 0;
+    }
+}
 
 /* Handle an "trap_exit" attribute; arguments as in
    struct attribute_spec.handler.  */
@@ -6930,7 +6954,8 @@ sh_handle_trap_exit_attribute (tree *nod
 	       IDENTIFIER_POINTER (name));
       *no_add_attrs = true;
     }
-  else if (!pragma_interrupt)
+  else if (lookup_attribute ("interrupt_handler",
+                              DECL_ATTRIBUTES (*node)) == NULL)
     {
       /* The trap_exit attribute only has meaning for interrupt functions.  */
       warning ("`%s' attribute only applies to interrupt functions",
@@ -6952,6 +6977,27 @@ sh_handle_trap_exit_attribute (tree *nod
   return NULL_TREE;
 }
 
+
+/* True if __attribute__((trap_exit)), for the current function.
+   trap_exit is initialized with trap no.  */
+static int
+sh_cfun_trap_exit_p (void)
+{
+  tree t;
+  t = lookup_attribute ("trap_exit",
+                        DECL_ATTRIBUTES (current_function_decl));
+  if (t != NULL_TREE)
+    {
+      trap_exit = TREE_INT_CST_LOW(TREE_VALUE(TREE_VALUE(t)));
+      return 1;
+    }
+  else
+    {
+      return 0;
+    }
+
+}
+
 static tree
 sh_handle_renesas_attribute (tree *node ATTRIBUTE_UNUSED,
 			     tree name ATTRIBUTE_UNUSED,


==========================================
DejaGNU testcase for trap_exit:

--- /dev/null	2002-08-31 05:01:37.000000000 +0530
+++ gcc-3.4-20040709/gcc/testsuite/gcc.dg/trap_exit.c	2004-07-29 14:32:38.000000000 +0530
@@ -0,0 +1,18 @@
+/* Test for trap_exit attributes.  */
+/* Origin: Asgari Jinia <asgarij@kpitcummins.com> */
+/* { dg-do compile {target sh-*-*}} */
+/* { dg-options "-O2 -S" } */
+/* { dg-final { scan-assembler "trapa #32" } } */
+/* { dg-final { scan-assembler "trapa #33" } } */
+void foo(void) __attribute__((interrupt_handler,trap_exit(32)));
+void foo(void)
+{
+
+}
+
+#pragma interrupt
+void bar(void) __attribute__ ((trap_exit(33)));
+void bar(void)
+{
+
+}

==============================================
DejaGNU testcase for sp_switch:

--- /dev/null	2002-08-31 05:01:37.000000000 +0530
+++ gcc-3.4-20040709/gcc/testsuite/gcc.dg/sp_switch.c	2004-07-29 14:32:43.000000000 +0530
@@ -0,0 +1,22 @@
+/* Test for sp_switch attribute.  */
+/* Origin: Asgari Jinia <asgarij@kpitcummins.com> */
+/* { dg-do compile {target sh-*-*}} */
+/* { dg-options "-O2 -S" } */
+/* { dg-final { scan-assembler "mov.l #_alt_stack1,r0" } } */
+/* { dg-final { scan-assembler "mov.l #_alt_stack2,r0" } } */
+
+void *alt_stack1;
+void *alt_stack2;
+
+void foo(void) __attribute__((interrupt_handler,sp_switch("alt_stack1")));
+void foo(void)
+{
+
+}
+
+#pragma interrupt
+void bar(void) __attribute__((sp_switch("alt_stack2")));
+void bar(void)
+{
+
+}


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]