This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[PATCH]: Add attributes for HC11/HC12 functions
- From: Stephane Carrez <stcarrez at nerim dot fr>
- To: gcc-patches at gcc dot gnu dot org
- Date: Sat, 22 Mar 2003 00:29:48 +0100
- Subject: [PATCH]: Add attributes for HC11/HC12 functions
Hi!
This patch adds two new attributes 'near' and 'far' to have a better control
of which function must be far or near (far means the function uses the 'call/rtc'
calling convention, thus allowing to be put in memory bank window).
Committed on 3_3 and mainline.
Stephane
2003-03-22 Stephane Carrez <stcarrez at nerim dot fr>
* config/m68hc11/m68hc11.h (ASM_DECLARE_FUNCTION_NAME): Fix typo in
writing .interrupt command.
* config/m68hc11/m68hc11.md ("call"): Look at the symbol to see
if it's a far or near function.
("call_value"): Likewise.
* config/m68hc11/m68hc11.c (m68hc11_attribute_table): Add far and
near attributes.
(m68hc11_handle_fntype_attribute): Accept attributes on methods.
(m68hc11_override_options): Ignore -mlong-calls for 68HC11.
(m68hc11_initial_elimination_offset): Set current_function_far
according to attributes.
(expand_prologue): Likewise.
(trap_handler_symbol): New global to keep track of trap handlers.
(m68hc11_encode_section_info): Mark symbol as far if needed; set
trap symbol.
(m68hc11_is_far_symbol): New function.
(m68hc11_is_trap_symbol): New function.
* config/m68hc11/m68hc11-protos.h (m68hc11_is_far_symbol): Declare.
(m68hc11_is_trap_symbol): Declare.
Index: config/m68hc11/m68hc11-protos.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/m68hc11/m68hc11-protos.h,v
retrieving revision 1.24
diff -u -p -r1.24 m68hc11-protos.h
--- config/m68hc11/m68hc11-protos.h 10 Mar 2003 22:10:36 -0000 1.24
+++ config/m68hc11/m68hc11-protos.h 21 Mar 2003 23:18:33 -0000
@@ -141,6 +141,9 @@ extern int m68hc11_function_arg_padding
extern void m68hc11_function_epilogue PARAMS((FILE*,int));
+extern int m68hc11_is_far_symbol PARAMS((rtx));
+extern int m68hc11_is_trap_symbol PARAMS((rtx));
+
#endif /* TREE_CODE */
extern HOST_WIDE_INT m68hc11_min_offset;
Index: config/m68hc11/m68hc11.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/m68hc11/m68hc11.c,v
retrieving revision 1.69
diff -u -p -r1.69 m68hc11.c
--- config/m68hc11/m68hc11.c 16 Mar 2003 21:26:04 -0000 1.69
+++ config/m68hc11/m68hc11.c 21 Mar 2003 23:18:35 -0000
@@ -276,6 +276,7 @@ m68hc11_override_options ()
m68hc11_tmp_regs_class = D_REGS;
if (m68hc11_soft_reg_count == 0 && !TARGET_M6812)
m68hc11_soft_reg_count = "4";
+ target_flags &= ~MASK_LONG_CALLS;
}
/* Configure for a 68hc12 processor. */
@@ -1232,9 +1233,16 @@ const struct attribute_spec m68hc11_attr
/* { name, min_len, max_len, decl_req, type_req, fn_type_req, handler } */
{ "interrupt", 0, 0, false, true, true, m68hc11_handle_fntype_attribute },
{ "trap", 0, 0, false, true, true, m68hc11_handle_fntype_attribute },
+ { "far", 0, 0, false, true, true, m68hc11_handle_fntype_attribute },
+ { "near", 0, 0, false, true, true, m68hc11_handle_fntype_attribute },
{ NULL, 0, 0, false, false, false, NULL }
};
+/* Keep track of the symbol which has a `trap' attribute and which uses
+ the `swi' calling convention. Since there is only one trap, we only
+ record one such symbol. If there are several, a warning is reported. */
+static rtx trap_handler_symbol = 0;
+
/* Handle an attribute requiring a FUNCTION_TYPE, FIELD_DECL or TYPE_DECL;
arguments as in struct attribute_spec.handler. */
static tree
@@ -1246,6 +1254,7 @@ m68hc11_handle_fntype_attribute (node, n
bool *no_add_attrs;
{
if (TREE_CODE (*node) != FUNCTION_TYPE
+ && TREE_CODE (*node) != METHOD_TYPE
&& TREE_CODE (*node) != FIELD_DECL
&& TREE_CODE (*node) != TYPE_DECL)
{
@@ -1268,16 +1277,56 @@ m68hc11_encode_section_info (decl, first
{
tree func_attr;
int trap_handler;
+ int is_far = 0;
rtx rtl;
-
+
if (TREE_CODE (decl) != FUNCTION_DECL)
return;
rtl = DECL_RTL (decl);
func_attr = TYPE_ATTRIBUTES (TREE_TYPE (decl));
+
+
+ if (lookup_attribute ("far", func_attr) != NULL_TREE)
+ is_far = 1;
+ else if (lookup_attribute ("near", func_attr) == NULL_TREE)
+ is_far = TARGET_LONG_CALLS != 0;
+
trap_handler = lookup_attribute ("trap", func_attr) != NULL_TREE;
- SYMBOL_REF_FLAG (XEXP (rtl, 0)) = trap_handler;
+ if (trap_handler && is_far)
+ {
+ warning ("`trap' and `far' attributes are not compatible, ignoring `far'");
+ trap_handler = 0;
+ }
+ if (trap_handler)
+ {
+ if (trap_handler_symbol != 0)
+ warning ("`trap' attribute is already used");
+ else
+ trap_handler_symbol = XEXP (rtl, 0);
+ }
+ SYMBOL_REF_FLAG (XEXP (rtl, 0)) = is_far;
+}
+
+int
+m68hc11_is_far_symbol (sym)
+ rtx sym;
+{
+ if (GET_CODE (sym) == MEM)
+ sym = XEXP (sym, 0);
+
+ return SYMBOL_REF_FLAG (sym);
+}
+
+int
+m68hc11_is_trap_symbol (sym)
+ rtx sym;
+{
+ if (GET_CODE (sym) == MEM)
+ sym = XEXP (sym, 0);
+
+ return trap_handler_symbol != 0 && rtx_equal_p (trap_handler_symbol, sym);
}
@@ -1317,6 +1366,14 @@ m68hc11_initial_elimination_offset (from
/* For a trap handler, we must take into account the registers which
are pushed on the stack during the trap (except the PC). */
func_attr = TYPE_ATTRIBUTES (TREE_TYPE (current_function_decl));
+
+ if (lookup_attribute ("far", func_attr) != 0)
+ current_function_far = 1;
+ else if (lookup_attribute ("near", func_attr) != 0)
+ current_function_far = 0;
+ else
+ current_function_far = TARGET_LONG_CALLS != 0;
+
trap_handler = lookup_attribute ("trap", func_attr) != NULL_TREE;
if (trap_handler && from == ARG_POINTER_REGNUM)
size = 7;
@@ -1611,6 +1668,12 @@ expand_prologue ()
current_function_interrupt = lookup_attribute ("interrupt",
func_attr) != NULL_TREE;
current_function_trap = lookup_attribute ("trap", func_attr) != NULL_TREE;
+ if (lookup_attribute ("far", func_attr) != NULL_TREE)
+ current_function_far = 1;
+ else if (lookup_attribute ("near", func_attr) != NULL_TREE)
+ current_function_far = 0;
+ else
+ current_function_far = TARGET_LONG_CALLS != 0;
/* Get the scratch register to build the frame and push registers.
If the first argument is a 32-bit quantity, the D+X registers
Index: config/m68hc11/m68hc11.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/m68hc11/m68hc11.h,v
retrieving revision 1.67
diff -u -p -r1.67 m68hc11.h
--- config/m68hc11/m68hc11.h 10 Mar 2003 22:10:35 -0000 1.67
+++ config/m68hc11/m68hc11.h 21 Mar 2003 23:18:37 -0000
@@ -1560,7 +1560,7 @@ do {
{ \
fprintf (FILE, "\t.interrupt\t"); \
assemble_name (FILE, NAME); \
- putc ('\b', FILE); \
+ putc ('\n', FILE); \
} \
ASM_DECLARE_RESULT (FILE, DECL_RESULT (DECL)); \
ASM_OUTPUT_LABEL(FILE, NAME); \
Index: config/m68hc11/m68hc11.md
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/m68hc11/m68hc11.md,v
retrieving revision 1.47
diff -u -p -r1.47 m68hc11.md
--- config/m68hc11/m68hc11.md 10 Mar 2003 21:51:02 -0000 1.47
+++ config/m68hc11/m68hc11.md 21 Mar 2003 23:18:39 -0000
@@ -6390,14 +6390,17 @@
""
"*
{
- int far_call = current_function_far;
-
if (GET_CODE (XEXP (operands[0], 0)) == SYMBOL_REF)
{
- if (SYMBOL_REF_FLAG (XEXP (operands[0], 0)) == 1)
+ if (m68hc11_is_far_symbol (operands[0]))
+ {
+ output_asm_insn (\"call\\t%0\", operands);
+ return \"\";
+ }
+ if (m68hc11_is_trap_symbol (operands[0]))
return \"swi\";
else
- return far_call ? \"call\\t%0\" : \"bsr\\t%0\";
+ return \"bsr\\t%0\";
}
else
{
@@ -6412,14 +6415,17 @@
""
"*
{
- int far_call = current_function_far;
-
if (GET_CODE (XEXP (operands[1], 0)) == SYMBOL_REF)
{
- if (SYMBOL_REF_FLAG (XEXP (operands[1], 0)) == 1)
+ if (m68hc11_is_far_symbol (operands[1]))
+ {
+ output_asm_insn (\"call\\t%1\", operands);
+ return \"\";
+ }
+ if (m68hc11_is_trap_symbol (operands[0]))
return \"swi\";
else
- return far_call ? \"call\\t%1\" : \"bsr\\t%1\";
+ return \"bsr\\t%1\";
}
else
{