[rx] New interrupt/vector attributes
diff mbox

Message ID 201405280037.s4S0b221026028@greed.delorie.com
State New
Headers show

Commit Message

DJ Delorie May 28, 2014, 12:37 a.m. UTC
This patch adds an RX-specific "vector" attribute as well as extending
the "interrupt" attribute.  With this change, gcc will pass additional
information to the linker to auto-generate interrupt tables and other
vector tables.  Also fixed a minor bug in adjust_insn_length.
Committed.

	* config/rx/rx.c (add_vector_labels): New.
	(rx_output_function_prologue): Call it.
	(rx_handle_func_attribute): Don't require empty arguments.
	(rx_handle_vector_attribute): New.
	(rx_attribute_table): Add "vector" attribute.
	* doc/extend.texi (interrupt, vector): Document new/changed
	RX-specific attributes.

	* config/rx/rx.c (rx_adjust_insn_length): Skip for non-insns.

 2014-05-27  Eric Botcazou  <ebotcazou@adacore.com>
 
 	* double-int.c (div_and_round_double) <ROUND_DIV_EXPR>: Use the proper
 	predicate to detect a negative quotient.
 
 2014-05-27  Eric Botcazou  <ebotcazou@adacore.com>

Patch
diff mbox

Index: doc/extend.texi
===================================================================
--- doc/extend.texi	(revision 210994)
+++ doc/extend.texi	(working copy)
@@ -3086,12 +3086,34 @@  interrupt handler.
 @end table
 
 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 may specify one or more vector numbers as arguments
+to the attribute, as well as naming an alternate table name.
+Parameters are handled sequentially, so one handler can be assigned to
+multiple entries in multiple tables.  One may also pass the magic
+string @code{"$default"} which causes the function to be used for any
+unfilled slots in the current table.
+
+This example shows a simple assignment of a function to one vector in
+the default table (note that preprocessor macros may be used for
+chip-specific symbolic vector names):
+@smallexample
+void __attribute__ ((interrupt (5))) txd1_handler ();
+@end smallexample
+
+This example assigns a function to two slots in the default table
+(using preprocessor macros defined elsewhere) and makes it the default
+for the @code{dct} table:
+@smallexample
+void __attribute__ ((interrupt (RXD1_VECT,RXD2_VECT,"dct","$default")))
+	txd1_handler ();
+@end smallexample
+
 @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.
@@ -4288,12 +4310,19 @@  This is useful, for example, when the fu
 inline assembly.
 
 When applied to a member function of a C++ class template, the
 attribute also means that the function is instantiated if the
 class itself is instantiated.
 
+@item vector
+@cindex @code{vector} attibute
+This RX attribute is similar to the @code{attribute}, including its
+parameters, but does not make the function an interrupt-handler type
+function (i.e. it retains the normal C function calling ABI).  See the
+@code{interrupt} attribute for a description of its arguments.
+
 @item version_id
 @cindex @code{version_id} attribute
 This IA-64 HP-UX attribute, attached to a global variable or function, renames a
 symbol to contain a version string, thus allowing for function level
 versioning.  HP-UX system header files may use function level versioning
 for some system calls.
Index: config/rx/rx.c
===================================================================
--- config/rx/rx.c	(revision 210994)
+++ config/rx/rx.c	(working copy)
@@ -1807,15 +1807,74 @@  rx_expand_prologue (void)
 	gen_safe_add (stack_pointer_rtx, frame_pointer_rtx, NULL_RTX,
 		      true);
     }
 }
 
 static void
+add_vector_labels (FILE *file, const char *aname)
+{
+  tree vec_attr;
+  tree val_attr;
+  const char *vname = "vect";
+  const char *s;
+  int vnum;
+
+  /* This node is for the vector/interrupt tag itself */
+  vec_attr = lookup_attribute (aname, DECL_ATTRIBUTES (current_function_decl));
+  if (!vec_attr)
+    return;
+
+  /* Now point it at the first argument */
+  vec_attr = TREE_VALUE (vec_attr);
+
+  /* Iterate through the arguments.  */
+  while (vec_attr)
+    {
+      val_attr = TREE_VALUE (vec_attr);
+      switch (TREE_CODE (val_attr))
+	{
+	case STRING_CST:
+	  s = TREE_STRING_POINTER (val_attr);
+	  goto string_id_common;
+
+	case IDENTIFIER_NODE:
+	  s = IDENTIFIER_POINTER (val_attr);
+
+	string_id_common:
+	  if (strcmp (s, "$default") == 0)
+	    {
+	      fprintf (file, "\t.global\t$tableentry$default$%s\n", vname);
+	      fprintf (file, "$tableentry$default$%s:\n", vname);
+	    }
+	  else
+	    vname = s;
+	  break;
+
+	case INTEGER_CST:
+	  vnum = TREE_INT_CST_LOW (val_attr);
+
+	  fprintf (file, "\t.global\t$tableentry$%d$%s\n", vnum, vname);
+	  fprintf (file, "$tableentry$%d$%s:\n", vnum, vname);
+	  break;
+
+	default:
+	  ;
+	}
+
+      vec_attr = TREE_CHAIN (vec_attr);
+    }
+
+}
+
+static void
 rx_output_function_prologue (FILE * file,
 			     HOST_WIDE_INT frame_size ATTRIBUTE_UNUSED)
 {
+  add_vector_labels (file, "interrupt");
+  add_vector_labels (file, "vector");
+
   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");
 
@@ -2599,13 +2658,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;
@@ -2615,23 +2673,47 @@  rx_handle_func_attribute (tree * node,
 
   /* FIXME: We ought to check that the interrupt and exception
      handler attributes have been applied to void functions.  */
   return NULL_TREE;
 }
 
+/* Check "vector" attribute.  */
+
+static tree
+rx_handle_vector_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;
+    }
+
+  return NULL_TREE;
+}
+
 /* Table of RX specific attributes.  */
 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 },
+  { "vector",         1, -1, true, false, false, rx_handle_vector_attribute,
+    false },
   { NULL,             0, 0, false, false, false, NULL, false }
 };
 
 /* Implement TARGET_OVERRIDE_OPTIONS_AFTER_CHANGE.  */
 
 static void
@@ -3152,12 +3234,15 @@  int
 rx_adjust_insn_length (rtx insn, int current_length)
 {
   rtx extend, mem, offset;
   bool zero;
   int factor;
 
+  if (!INSN_P (insn))
+    return current_length;
+
   switch (INSN_CODE (insn))
     {
     default:
       return current_length;
 
     case CODE_FOR_plussi3_zero_extendhi: