aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJayant Sonar <jayants@kpitcummins.com>2007-05-07 23:13:15 +0000
committerDJ Delorie <dj@gcc.gnu.org>2007-05-07 19:13:15 -0400
commit5abd2125f012351411df08f07918667ce3e418a9 (patch)
treeb4d7248e78a4d9cbf0ccb466af301868b241de83
parent04055200edcb139e4be7088107191b7a1a9089fa (diff)
downloadgcc-5abd2125f012351411df08f07918667ce3e418a9.zip
gcc-5abd2125f012351411df08f07918667ce3e418a9.tar.gz
gcc-5abd2125f012351411df08f07918667ce3e418a9.tar.bz2
m32c.c (SYMBOL_FLAG_FUNCVEC_FUNCTION): Define.
* 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
-rw-r--r--gcc/ChangeLog15
-rw-r--r--gcc/config/m32c/jump.md26
-rw-r--r--gcc/config/m32c/m32c-protos.h1
-rw-r--r--gcc/config/m32c/m32c.c118
-rw-r--r--gcc/doc/extend.texi36
5 files changed, 193 insertions, 3 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 9d6c0db..9452c04 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -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
diff --git a/gcc/config/m32c/jump.md b/gcc/config/m32c/jump.md
index 4a358ea..f0983d1 100644
--- a/gcc/config/m32c/jump.md
+++ b/gcc/config/m32c/jump.md
@@ -69,7 +69,18 @@
""
"*
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\";
}"
diff --git a/gcc/config/m32c/m32c-protos.h b/gcc/config/m32c/m32c-protos.h
index 5735ee7..5bbc67c 100644
--- a/gcc/config/m32c/m32c-protos.h
+++ b/gcc/config/m32c/m32c-protos.h
@@ -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
diff --git a/gcc/config/m32c/m32c.c b/gcc/config/m32c/m32c.c
index de7ce9d..dd0bce3 100644
--- a/gcc/config/m32c/m32c.c
+++ b/gcc/config/m32c/m32c.c
@@ -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;
diff --git a/gcc/doc/extend.texi b/gcc/doc/extend.texi
index 45a6324..1069892 100644
--- a/gcc/doc/extend.texi
+++ b/gcc/doc/extend.texi
@@ -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