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
This commit is contained in:
parent
04055200ed
commit
5abd2125f0
|
@ -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>
|
2007-05-07 DJ Delorie <dj@redhat.com>
|
||||||
|
|
||||||
PR 31794
|
PR 31794
|
||||||
|
|
|
@ -69,7 +69,18 @@
|
||||||
""
|
""
|
||||||
"*
|
"*
|
||||||
switch (which_alternative) {
|
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 1: return TARGET_A16 ? \"push.w %a0 | jsr.a\tm32c_jsri16\" : \"jsri.a\t%a0\";
|
||||||
case 2: return \"jsri.a\t%a0\";
|
case 2: return \"jsri.a\t%a0\";
|
||||||
}"
|
}"
|
||||||
|
@ -84,7 +95,18 @@ switch (which_alternative) {
|
||||||
""
|
""
|
||||||
"*
|
"*
|
||||||
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 1: return TARGET_A16 ? \"push.w %a1 | jsr.a\tm32c_jsri16\" : \"jsri.a\t%a1\";
|
||||||
case 2: return \"jsri.a\t%a1\";
|
case 2: return \"jsri.a\t%a1\";
|
||||||
}"
|
}"
|
||||||
|
|
|
@ -112,6 +112,7 @@ void m32c_function_arg_advance (CUMULATIVE_ARGS *, MM, tree, int);
|
||||||
tree m32c_gimplify_va_arg_expr (tree, tree, tree *, tree *);
|
tree m32c_gimplify_va_arg_expr (tree, tree, tree *, tree *);
|
||||||
void m32c_init_cumulative_args (CUMULATIVE_ARGS *, tree, rtx, tree, int);
|
void m32c_init_cumulative_args (CUMULATIVE_ARGS *, tree, rtx, tree, int);
|
||||||
bool m32c_promote_function_return (tree);
|
bool m32c_promote_function_return (tree);
|
||||||
|
int m32c_special_page_vector_p (tree);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
|
@ -61,6 +61,7 @@ typedef enum
|
||||||
} Push_Pop_Type;
|
} Push_Pop_Type;
|
||||||
|
|
||||||
static tree interrupt_handler (tree *, tree, tree, int, bool *);
|
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 int interrupt_p (tree node);
|
||||||
static bool m32c_asm_integer (rtx, unsigned int, int);
|
static bool m32c_asm_integer (rtx, unsigned int, int);
|
||||||
static int m32c_comp_type_attributes (tree, tree);
|
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_struct_value_rtx (tree, int);
|
||||||
static rtx m32c_subreg (enum machine_mode, rtx, enum machine_mode, int);
|
static rtx m32c_subreg (enum machine_mode, rtx, enum machine_mode, int);
|
||||||
static int need_to_save (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)
|
#define streq(a,b) (strcmp ((a), (b)) == 0)
|
||||||
|
|
||||||
|
@ -2721,10 +2725,104 @@ interrupt_handler (tree * node ATTRIBUTE_UNUSED,
|
||||||
return NULL_TREE;
|
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
|
#undef TARGET_ATTRIBUTE_TABLE
|
||||||
#define TARGET_ATTRIBUTE_TABLE m32c_attribute_table
|
#define TARGET_ATTRIBUTE_TABLE m32c_attribute_table
|
||||||
static const struct attribute_spec m32c_attribute_table[] = {
|
static const struct attribute_spec m32c_attribute_table[] = {
|
||||||
{"interrupt", 0, 0, false, false, false, interrupt_handler},
|
{"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}
|
{0, 0, 0, 0, 0, 0, 0}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -3751,6 +3849,23 @@ m32c_scc_pattern(rtx *operands, RTX_CODE code)
|
||||||
return buf;
|
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
|
/* Returns TRUE if the current function is a leaf, and thus we can
|
||||||
determine which registers an interrupt function really needs to
|
determine which registers an interrupt function really needs to
|
||||||
save. The logic below is mostly about finding the insn sequence
|
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;
|
return template + 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#undef TARGET_ENCODE_SECTION_INFO
|
||||||
|
#define TARGET_ENCODE_SECTION_INFO m32c_encode_section_info
|
||||||
|
|
||||||
/* The Global `targetm' Variable. */
|
/* The Global `targetm' Variable. */
|
||||||
|
|
||||||
struct gcc_target targetm = TARGET_INITIALIZER;
|
struct gcc_target targetm = TARGET_INITIALIZER;
|
||||||
|
|
|
@ -1972,7 +1972,7 @@ is used. @xref{C Dialect Options,,Options
|
||||||
Controlling C Dialect}.
|
Controlling C Dialect}.
|
||||||
|
|
||||||
@item function_vector
|
@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
|
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 should be called through the function vector. Calling a
|
||||||
function through the function vector will reduce code size, however;
|
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
|
You must use GAS and GLD from GNU binutils version 2.7 or later for
|
||||||
this attribute to work correctly.
|
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
|
@item interrupt
|
||||||
@cindex interrupt handler functions
|
@cindex interrupt handler functions
|
||||||
Use this attribute on the ARM, AVR, C4x, CRX, M32C, M32R/D, MS1, and Xstormy16
|
Use this attribute on the ARM, AVR, C4x, CRX, M32C, M32R/D, MS1, and Xstormy16
|
||||||
|
|
Loading…
Reference in New Issue