diff options
author | dj <dj@138bc75d-0d04-0410-961f-82ee72b054a4> | 2007-05-07 23:13:15 +0000 |
---|---|---|
committer | dj <dj@138bc75d-0d04-0410-961f-82ee72b054a4> | 2007-05-07 23:13:15 +0000 |
commit | 2efce110783b2f1073797af48bf5b1e900ba7943 (patch) | |
tree | b4d7248e78a4d9cbf0ccb466af301868b241de83 /gcc/config/m32c | |
parent | cfe58735e51b2616f9ec3b105c9c00e37ab280cb (diff) | |
download | gcc-2efce110783b2f1073797af48bf5b1e900ba7943.tar.gz |
* 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.
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@124523 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/config/m32c')
-rw-r--r-- | gcc/config/m32c/jump.md | 26 | ||||
-rw-r--r-- | gcc/config/m32c/m32c-protos.h | 1 | ||||
-rw-r--r-- | gcc/config/m32c/m32c.c | 118 |
3 files changed, 143 insertions, 2 deletions
diff --git a/gcc/config/m32c/jump.md b/gcc/config/m32c/jump.md index 4a358eac40f..f0983d1532d 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 5735ee75867..5bbc67cbb32 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 de7ce9d7a0f..dd0bce33299 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; |