This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[PATCH - SH] trap_exit and sp_switch with interrupt_handler attribute
- From: "Asgari J. Jinia" <AsgariJ at KPITCummins dot com>
- To: <gcc-patches at gcc dot gnu dot org>
- Date: Fri, 30 Jul 2004 11:17:46 +0530
- Subject: [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)
+{
+
+}