mirror of
git://gcc.gnu.org/git/gcc.git
synced 2025-01-26 00:14:54 +08:00
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>
|
||||
|
||||
PR 31794
|
||||
|
@ -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\";
|
||||
}"
|
||||
|
@ -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
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user