This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[patch] rx: create interrupt vector aliases by attributes
- From: DJ Delorie <dj at redhat dot com>
- To: gcc-patches at gcc dot gnu dot org
- Date: Wed, 14 Nov 2012 20:47:24 -0500
- Subject: [patch] rx: create interrupt vector aliases by attributes
This patch allows the user to specify a vector number in an interrupt
attribute, allowing for more generic creation of vector tables. Ok?
* doc/extend.texi (Function Attributes): Document RX extensions to
"interrupt" attribute.
* config/rx/rx.c (has_interrupt_vector): New.
(rx_output_function_prologue): If a function has an interrupt
vector assigned, emit a vector-specific alias for it.
(rx_handle_func_attribute): Allow args to attributes.
(rx_attribute_table): Allow the interrupt attribute to take an
argument.
Index: gcc/doc/extend.texi
===================================================================
--- gcc/doc/extend.texi (revision 193523)
+++ gcc/doc/extend.texi (working copy)
@@ -2892,12 +2892,39 @@ void __attribute__ ((interrupt, use_shad
@end smallexample
On RL78, use @code{brk_interrupt} instead of @code{interrupt} for
handlers intended to be used with the @code{BRK} opcode (i.e. those
that must end with @code{RETB} instead of @code{RETI}).
+On RX targets, you can specify an interrupt vector number, which
+causes gcc to emit a vector-specific alias for the function:
+
+@smallexample
+void f () __attribute__((interrupt (15)));
+@end smallexample
+
+In the above example, an additional global symbol
+@code{__gcc_autovector_func_15} would be created to reference this
+function, which can be referenced by some other function or linker
+script to build the vector table:
+
+@smallexample
+extern __gcc_autovector_func_15() __attribute__((weak));
+@{ @dots{} __gcc_autovector_func_15; @dots{} @}
+
+.weak __gcc_autovector_func_15
+.long __gcc_autovector_func_15
+
+PROVIDE(__gcc_autovector_func_15=0)
+LONG (__gcc_autovector_func_15)
+@end smallexample
+
+Note that the PROVIDE must be outside any section block
+(i.e. @code{.text : @{ ... @} }) or else the value will be relocated
+and result in a non-zero address.
+
@item interrupt_handler
@cindex interrupt handler functions on the Blackfin, m68k, H8/300 and SH processors
Use this attribute on the Blackfin, m68k, H8/300, H8/300H, H8S, and SH to
indicate that the specified function is an interrupt handler. The compiler
generates function entry and exit sequences suitable for use in an
interrupt handler when this attribute is present.
Index: gcc/config/rx/rx.c
===================================================================
--- gcc/config/rx/rx.c (revision 193523)
+++ gcc/config/rx/rx.c (working copy)
@@ -1184,12 +1184,44 @@ is_fast_interrupt_func (const_tree decl)
static inline bool
is_interrupt_func (const_tree decl)
{
return has_func_attr (decl, "interrupt");
}
+/* Returns true if the provided function has the "vector" attribute.
+ If true, it also returns the vector in *RET if RET is not NULL. */
+
+static inline bool
+has_interrupt_vector (const_tree decl, int *ret)
+{
+ tree vec_attr;
+ int rv;
+
+ if (decl == NULL_TREE)
+ decl = current_function_decl;
+
+ vec_attr = lookup_attribute ("interrupt", DECL_ATTRIBUTES (decl));
+ if (!vec_attr)
+ return false;
+
+ vec_attr = TREE_VALUE (vec_attr);
+ if (!vec_attr)
+ return false;
+
+ vec_attr = TREE_VALUE (vec_attr);
+ if (!vec_attr)
+ return false;
+
+ if (TREE_CODE (vec_attr) != INTEGER_CST)
+ return false;
+
+ if (ret)
+ *ret = TREE_INT_CST_LOW (vec_attr);
+ return true;
+}
+
/* Returns true if the provided function has the "naked" attribute. */
static inline bool
is_naked_func (const_tree decl)
{
return has_func_attr (decl, "naked");
@@ -1768,12 +1800,27 @@ rx_expand_prologue (void)
}
static void
rx_output_function_prologue (FILE * file,
HOST_WIDE_INT frame_size ATTRIBUTE_UNUSED)
{
+ int v;
+
+ if (has_interrupt_vector (NULL_TREE, &v))
+ {
+ if (0 <= v && v <= 255)
+ {
+ asm_fprintf (file, "\t.global\t__gcc_autovector_func_%d\n", v);
+ asm_fprintf (file, "__gcc_autovector_func_%d:\n", v);
+ }
+ else
+ {
+ error ("interrupt vector %d must be in the range 0..255", v);
+ }
+ }
+
if (is_fast_interrupt_func (NULL_TREE))
asm_fprintf (file, "\t; Note: Fast Interrupt Handler\n");
if (is_interrupt_func (NULL_TREE))
asm_fprintf (file, "\t; Note: Interrupt Handler\n");
@@ -2549,13 +2596,12 @@ rx_handle_func_attribute (tree * node,
tree name,
tree args,
int flags ATTRIBUTE_UNUSED,
bool * no_add_attrs)
{
gcc_assert (DECL_P (* node));
- gcc_assert (args == NULL_TREE);
if (TREE_CODE (* node) != FUNCTION_DECL)
{
warning (OPT_Wattributes, "%qE attribute only applies to functions",
name);
* no_add_attrs = true;
@@ -2572,13 +2618,13 @@ rx_handle_func_attribute (tree * node,
const struct attribute_spec rx_attribute_table[] =
{
/* Name, min_len, max_len, decl_req, type_req, fn_type_req, handler,
affects_type_identity. */
{ "fast_interrupt", 0, 0, true, false, false, rx_handle_func_attribute,
false },
- { "interrupt", 0, 0, true, false, false, rx_handle_func_attribute,
+ { "interrupt", 0, 1, true, false, false, rx_handle_func_attribute,
false },
{ "naked", 0, 0, true, false, false, rx_handle_func_attribute,
false },
{ NULL, 0, 0, false, false, false, NULL, false }
};