m32c.c (SYMBOL_FLAG_FUNCVEC_FUNCTION): Define.
authorJayant Sonar <jayants@kpitcummins.com>
Mon, 7 May 2007 23:13:15 +0000 (23:13 +0000)
committerDJ Delorie <dj@gcc.gnu.org>
Mon, 7 May 2007 23:13:15 +0000 (19:13 -0400)
* config/m32c/m32c.c (SYMBOL_FLAG_FUNCVEC_FUNCTION): Define.
(TARGET_ENCODE_SECTION_INFO): Re-define.
(m32c_encode_section_info): New
(function_vector_handler): New
(current_function_special_page_vector): New
(m32c_special_page_vector_p): New.
* config/m32c/m32c-protos.h (m32c_special_page_vector_p):
Prototype.
* config/m32c/jump.md: Added instruction JSRS for functions
with attribute "function_vector".
* doc/extend.texi (function_vector): Added description
for M16C, M32C targets.

From-SVN: r124523

gcc/ChangeLog
gcc/config/m32c/jump.md
gcc/config/m32c/m32c-protos.h
gcc/config/m32c/m32c.c
gcc/doc/extend.texi

index 9d6c0db9e02cf8bb48b663e596ca7eb026e15969..9452c04552462f5f90794844ad2b28d1885609ac 100644 (file)
@@ -1,3 +1,18 @@
+2007-05-07  Jayant Sonar  <jayants@kpitcummins.com>
+
+       * config/m32c/m32c.c (SYMBOL_FLAG_FUNCVEC_FUNCTION): Define.
+       (TARGET_ENCODE_SECTION_INFO): Re-define.
+       (m32c_encode_section_info): New
+       (function_vector_handler): New
+       (current_function_special_page_vector): New
+       (m32c_special_page_vector_p): New.
+       * config/m32c/m32c-protos.h (m32c_special_page_vector_p): 
+       Prototype.
+       * config/m32c/jump.md: Added instruction JSRS for functions 
+       with attribute "function_vector".
+       * doc/extend.texi (function_vector): Added description 
+       for M16C, M32C targets.
+
 2007-05-07  DJ Delorie  <dj@redhat.com>
 
        PR 31794
index 4a358eac40fc91794359bb49573541f3af1c0909..f0983d1532db26c2f9c5f39abb13f065ffdd449c 100644 (file)
   ""
   "*
 switch (which_alternative) {
-  case 0: return \"jsr.a\t%0\";
+  case 0:
+    {
+      HOST_WIDE_INT func_vect_num = 
+      current_function_special_page_vector(XEXP (operands[0], 0));
+      if (func_vect_num)
+        {
+          operands[3] = gen_rtx_CONST_INT (VOIDmode, func_vect_num);
+          return \"jsrs\t%3\";
+        }
+      else
+        return \"jsr.a\t%0\";
+    }
   case 1: return TARGET_A16 ? \"push.w %a0 | jsr.a\tm32c_jsri16\" : \"jsri.a\t%a0\";
   case 2: return \"jsri.a\t%a0\";
 }"
@@ -84,7 +95,18 @@ switch (which_alternative) {
   ""
   "*
 switch (which_alternative) {
-  case 0: return \"jsr.a\t%1\";
+  case 0:
+    {
+      HOST_WIDE_INT func_vect_num = 
+      current_function_special_page_vector(XEXP (operands[1], 0));
+      if (func_vect_num)
+        {
+          operands[4] = gen_rtx_CONST_INT (VOIDmode, func_vect_num);
+          return \"jsrs\t%4\";
+        }
+      else
+        return \"jsr.a\t%1\";
+    }
   case 1: return TARGET_A16 ? \"push.w %a1 | jsr.a\tm32c_jsri16\" : \"jsri.a\t%a1\";
   case 2: return \"jsri.a\t%a1\";
 }"
index 5735ee75867411c79ad603276bce827f8d61ad54..5bbc67cbb323e828bbd15d54919ffb05e94bc44b 100644 (file)
@@ -112,6 +112,7 @@ void m32c_function_arg_advance (CUMULATIVE_ARGS *, MM, tree, int);
 tree m32c_gimplify_va_arg_expr (tree, tree, tree *, tree *);
 void m32c_init_cumulative_args (CUMULATIVE_ARGS *, tree, rtx, tree, int);
 bool m32c_promote_function_return (tree);
+int  m32c_special_page_vector_p (tree);
 
 #endif
 
index de7ce9d7a0f408d0790c1762e0b175cf80046814..dd0bce332994b004d03952af0e70b2a1c6977bce 100644 (file)
@@ -61,6 +61,7 @@ typedef enum
 } Push_Pop_Type;
 
 static tree interrupt_handler (tree *, tree, tree, int, bool *);
+static tree function_vector_handler (tree *, tree, tree, int, bool *);
 static int interrupt_p (tree node);
 static bool m32c_asm_integer (rtx, unsigned int, int);
 static int m32c_comp_type_attributes (tree, tree);
@@ -75,6 +76,9 @@ static bool m32c_strict_argument_naming (CUMULATIVE_ARGS *);
 static rtx m32c_struct_value_rtx (tree, int);
 static rtx m32c_subreg (enum machine_mode, rtx, enum machine_mode, int);
 static int need_to_save (int);
+int current_function_special_page_vector (rtx);
+
+#define SYMBOL_FLAG_FUNCVEC_FUNCTION    (SYMBOL_FLAG_MACH_DEP << 0)
 
 #define streq(a,b) (strcmp ((a), (b)) == 0)
 
@@ -2721,10 +2725,104 @@ interrupt_handler (tree * node ATTRIBUTE_UNUSED,
   return NULL_TREE;
 }
 
+/* Returns TRUE if given tree has the "function_vector" attribute. */
+int
+m32c_special_page_vector_p (tree func)
+{
+  if (TREE_CODE (func) != FUNCTION_DECL)
+    return 0;
+
+  tree list = M32C_ATTRIBUTES (func);
+  while (list)
+    {
+      if (is_attribute_p ("function_vector", TREE_PURPOSE (list)))
+        return 1;
+      list = TREE_CHAIN (list);
+    }
+  return 0;
+}
+
+static tree
+function_vector_handler (tree * node ATTRIBUTE_UNUSED,
+                         tree name ATTRIBUTE_UNUSED,
+                         tree args ATTRIBUTE_UNUSED,
+                         int flags ATTRIBUTE_UNUSED,
+                         bool * no_add_attrs ATTRIBUTE_UNUSED)
+{
+  if (TARGET_R8C)
+    {
+      /* The attribute is not supported for R8C target.  */
+      warning (OPT_Wattributes,
+                "`%s' attribute is not supported for R8C target",
+                IDENTIFIER_POINTER (name));
+      *no_add_attrs = true;
+    }
+  else if (TREE_CODE (*node) != FUNCTION_DECL)
+    {
+      /* The attribute must be applied to functions only.  */
+      warning (OPT_Wattributes,
+                "`%s' attribute applies only to functions",
+                IDENTIFIER_POINTER (name));
+      *no_add_attrs = true;
+    }
+  else if (TREE_CODE (TREE_VALUE (args)) != INTEGER_CST)
+    {
+      /* The argument must be a constant integer.  */
+      warning (OPT_Wattributes,
+                "`%s' attribute argument not an integer constant",
+                IDENTIFIER_POINTER (name));
+      *no_add_attrs = true;
+    }
+  else if (TREE_INT_CST_LOW (TREE_VALUE (args)) < 18
+           || TREE_INT_CST_LOW (TREE_VALUE (args)) > 255)
+    {
+      /* The argument value must be between 18 to 255.  */
+      warning (OPT_Wattributes,
+                "`%s' attribute argument should be between 18 to 255",
+                IDENTIFIER_POINTER (name));
+      *no_add_attrs = true;
+    }
+  return NULL_TREE;
+}
+
+/* If the function is assigned the attribute 'function_vector', it
+   returns the function vector number, otherwise returns zero.  */
+int
+current_function_special_page_vector (rtx x)
+{
+  int num;
+
+  if ((GET_CODE(x) == SYMBOL_REF)
+      && (SYMBOL_REF_FLAGS (x) & SYMBOL_FLAG_FUNCVEC_FUNCTION))
+    {
+      tree t = SYMBOL_REF_DECL (x);
+
+      if (TREE_CODE (t) != FUNCTION_DECL)
+        return 0;
+
+      tree list = M32C_ATTRIBUTES (t);
+      while (list)
+        {
+          if (is_attribute_p ("function_vector", TREE_PURPOSE (list)))
+            {
+              num = TREE_INT_CST_LOW (TREE_VALUE (TREE_VALUE (list)));
+              return num;
+            }
+
+          list = TREE_CHAIN (list);
+        }
+
+      return 0;
+    }
+  else
+    return 0;
+}
+
 #undef TARGET_ATTRIBUTE_TABLE
 #define TARGET_ATTRIBUTE_TABLE m32c_attribute_table
 static const struct attribute_spec m32c_attribute_table[] = {
   {"interrupt", 0, 0, false, false, false, interrupt_handler},
+  {"function_vector", 1, 1, true,  false, false, function_vector_handler},
   {0, 0, 0, 0, 0, 0, 0}
 };
 
@@ -3751,6 +3849,23 @@ m32c_scc_pattern(rtx *operands, RTX_CODE code)
   return buf;
 }
 
+/* Encode symbol attributes of a SYMBOL_REF into its
+   SYMBOL_REF_FLAGS. */
+static void
+m32c_encode_section_info (tree decl, rtx rtl, int first)
+{
+  int extra_flags = 0;
+
+  default_encode_section_info (decl, rtl, first);
+  if (TREE_CODE (decl) == FUNCTION_DECL
+      && m32c_special_page_vector_p (decl))
+
+    extra_flags = SYMBOL_FLAG_FUNCVEC_FUNCTION;
+
+  if (extra_flags)
+    SYMBOL_REF_FLAGS (XEXP (rtl, 0)) |= extra_flags;
+}
+
 /* Returns TRUE if the current function is a leaf, and thus we can
    determine which registers an interrupt function really needs to
    save.  The logic below is mostly about finding the insn sequence
@@ -4164,6 +4279,9 @@ m32c_output_compare (rtx insn, rtx *operands)
   return template + 1;
 }
 
+#undef TARGET_ENCODE_SECTION_INFO
+#define TARGET_ENCODE_SECTION_INFO m32c_encode_section_info
+
 /* The Global `targetm' Variable. */
 
 struct gcc_target targetm = TARGET_INITIALIZER;
index 45a632493dea990746be7f86e73c2c547c105046..1069892a50c745c1bb37c6595c7d62275f93c8c5 100644 (file)
@@ -1972,7 +1972,7 @@ is used.  @xref{C Dialect Options,,Options
 Controlling C Dialect}.
 
 @item function_vector
-@cindex calling functions through the function vector on the H8/300 processors
+@cindex calling functions through the function vector on H8/300, M16C, and M32C processors
 Use this attribute on the H8/300, H8/300H, and H8S to indicate that the specified
 function should be called through the function vector.  Calling a
 function through the function vector will reduce code size, however;
@@ -1982,6 +1982,40 @@ and 64 entries on the H8/300H and H8S) and shares space with the interrupt vecto
 You must use GAS and GLD from GNU binutils version 2.7 or later for
 this attribute to work correctly.
 
+On M16C/M32C targets, the @code{function_vector} attribute declares a
+special page subroutine call function. Use of this attribute reduces
+the code size by 2 bytes for each call generated to the
+subroutine. The argument to the attribute is the vector number entry
+from the special page vector table which contains the 16 low-order
+bits of the subroutine's entry address. Each vector table has special
+page number (18 to 255) which are used in @code{jsrs} instruction.
+Jump addresses of the routines are generated by adding 0x0F0000 (in
+case of M16C targets) or 0xFF0000 (in case of M32C targets), to the 2
+byte addresses set in the vector table. Therefore you need to ensure
+that all the special page vector routines should get mapped within the
+address range 0x0F0000 to 0x0FFFFF (for M16C) and 0xFF0000 to 0xFFFFFF
+(for M32C).
+
+In the following example 2 bytes will be saved for each call to
+function @code{foo}.
+
+@smallexample
+void foo (void) __attribute__((function_vector(0x18)));
+void foo (void)
+@{
+@}
+
+void bar (void)
+@{
+    foo();
+@}
+@end smallexample
+
+If functions are defined in one file and are called in another file,
+then be sure to write this declaration in both files.
+
+This attribute is ignored for R8C target.
+
 @item interrupt
 @cindex interrupt handler functions
 Use this attribute on the ARM, AVR, C4x, CRX, M32C, M32R/D, MS1, and Xstormy16