summaryrefslogtreecommitdiff
path: root/gcc/config/microblaze
diff options
context:
space:
mode:
authoreager <eager@138bc75d-0d04-0410-961f-82ee72b054a4>2014-05-17 15:12:38 +0000
committereager <eager@138bc75d-0d04-0410-961f-82ee72b054a4>2014-05-17 15:12:38 +0000
commit0f718e59b1cffee9e7ac04fdd0be3725f072c61c (patch)
treeb594c0ab7cce86755578cc61bfda61439424797a /gcc/config/microblaze
parente0b7b952168ac1106771da549cf11878d0391f57 (diff)
downloadgcc-0f718e59b1cffee9e7ac04fdd0be3725f072c61c.tar.gz
ChangeLog:
2014-05-17 Ajit Agarwal <ajitkum@xilinx.com> * config/microblaze/microblaze.c (break_handler): New Declaration. (microblaze_break_function_p,microblaze_is_break_handler) : New functions. (compute_frame_size): use of microblaze_break_function_p. Add the test of break_handler. (microblaze_function_prologue) : Add the test of variable break_handler. Check the fnname by BREAK_HANDLER_NAME. (microblaze_function_epilogue) : Add the test of break_handler. (microblaze_globalize_label) : Add the test of break_handler. Check the name by BREAK_HANDLER_NAME. * config/microblaze/microblaze.h (BREAK_HANDLER_NAME) : New macro * config/microblaze/microblaze.md : (*<optab>,<optab>_internal): Add microblaze_is_break_handler () test. (call_internal1,call_value_intern) : Use of microblaze_break_function_p. Use of SYMBOL_REF_DECL. * config/microblaze/microblaze-protos.h (microblaze_break_function_p,microblaze_is_break_handler) : New Declaration. * testsuite/gcc.target/microblaze/others/break_handler.c : New. * doc/extend.texi( MicroBlaze break_handler Functions): Document new MicroBlaze break_handler functions. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@210559 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/config/microblaze')
-rw-r--r--gcc/config/microblaze/microblaze-protos.h4
-rw-r--r--gcc/config/microblaze/microblaze.c40
-rw-r--r--gcc/config/microblaze/microblaze.h5
-rw-r--r--gcc/config/microblaze/microblaze.md28
4 files changed, 63 insertions, 14 deletions
diff --git a/gcc/config/microblaze/microblaze-protos.h b/gcc/config/microblaze/microblaze-protos.h
index b03e9e126c0..f3cc0991ae0 100644
--- a/gcc/config/microblaze/microblaze-protos.h
+++ b/gcc/config/microblaze/microblaze-protos.h
@@ -40,10 +40,12 @@ extern void print_operand_address (FILE *, rtx);
extern void init_cumulative_args (CUMULATIVE_ARGS *,tree, rtx);
extern bool microblaze_legitimate_address_p (enum machine_mode, rtx, bool);
extern int microblaze_is_interrupt_variant (void);
+extern int microblaze_is_break_handler (void);
+extern int microblaze_break_function_p (tree func);
extern rtx microblaze_return_addr (int, rtx);
extern int simple_memory_operand (rtx, enum machine_mode);
extern int double_memory_operand (rtx, enum machine_mode);
-
+extern void microblaze_order_regs_for_local_alloc (void);
extern int microblaze_regno_ok_for_base_p (int, int);
extern HOST_WIDE_INT microblaze_initial_elimination_offset (int, int);
extern void microblaze_declare_object (FILE *, const char *, const char *,
diff --git a/gcc/config/microblaze/microblaze.c b/gcc/config/microblaze/microblaze.c
index ba8109bc123..b12b7bf047f 100644
--- a/gcc/config/microblaze/microblaze.c
+++ b/gcc/config/microblaze/microblaze.c
@@ -209,6 +209,7 @@ enum reg_class microblaze_regno_to_class[] =
and epilogue and use appropriate interrupt return.
save_volatiles - Similar to interrupt handler, but use normal return. */
int interrupt_handler;
+int break_handler;
int fast_interrupt;
int save_volatiles;
@@ -217,6 +218,8 @@ const struct attribute_spec microblaze_attribute_table[] = {
affects_type_identity */
{"interrupt_handler", 0, 0, true, false, false, NULL,
false },
+ {"break_handler", 0, 0, true, false, false, NULL,
+ false },
{"fast_interrupt", 0, 0, true, false, false, NULL,
false },
{"save_volatiles" , 0, 0, true, false, false, NULL,
@@ -1866,7 +1869,18 @@ microblaze_fast_interrupt_function_p (tree func)
a = lookup_attribute ("fast_interrupt", DECL_ATTRIBUTES (func));
return a != NULL_TREE;
}
+int
+microblaze_break_function_p (tree func)
+{
+ tree a;
+ if (!func)
+ return 0;
+ if (TREE_CODE (func) != FUNCTION_DECL)
+ return 0;
+ a = lookup_attribute ("break_handler", DECL_ATTRIBUTES (func));
+ return a != NULL_TREE;
+}
/* Return true if FUNC is an interrupt function which uses
normal return, indicated by the "save_volatiles" attribute. */
@@ -1891,6 +1905,11 @@ microblaze_is_interrupt_variant (void)
{
return (interrupt_handler || fast_interrupt);
}
+int
+microblaze_is_break_handler (void)
+{
+ return break_handler;
+}
/* Determine of register must be saved/restored in call. */
static int
@@ -1994,9 +2013,14 @@ compute_frame_size (HOST_WIDE_INT size)
interrupt_handler =
microblaze_interrupt_function_p (current_function_decl);
+ break_handler =
+ microblaze_break_function_p (current_function_decl);
+
fast_interrupt =
microblaze_fast_interrupt_function_p (current_function_decl);
save_volatiles = microblaze_save_volatiles (current_function_decl);
+ if (break_handler)
+ interrupt_handler = break_handler;
gp_reg_size = 0;
mask = 0;
@@ -2641,9 +2665,11 @@ microblaze_function_prologue (FILE * file, HOST_WIDE_INT size ATTRIBUTE_UNUSED)
{
fputs ("\t.ent\t", file);
if (interrupt_handler && strcmp (INTERRUPT_HANDLER_NAME, fnname))
- fputs ("_interrupt_handler", file);
+ fputs ("_interrupt_handler", file);
+ else if (break_handler && strcmp (BREAK_HANDLER_NAME, fnname))
+ fputs ("_break_handler", file);
else if (fast_interrupt && strcmp (FAST_INTERRUPT_NAME, fnname))
- fputs ("_fast_interrupt", file);
+ fputs ("_fast_interrupt", file);
else
assemble_name (file, fnname);
fputs ("\n", file);
@@ -2656,7 +2682,8 @@ microblaze_function_prologue (FILE * file, HOST_WIDE_INT size ATTRIBUTE_UNUSED)
if (interrupt_handler && strcmp (INTERRUPT_HANDLER_NAME, fnname))
fputs ("_interrupt_handler:\n", file);
-
+ if (break_handler && strcmp (BREAK_HANDLER_NAME, fnname))
+ fputs ("_break_handler:\n", file);
if (!flag_inhibit_size_directive)
{
/* .frame FRAMEREG, FRAMESIZE, RETREG. */
@@ -2791,6 +2818,7 @@ microblaze_expand_prologue (void)
if (flag_stack_usage_info)
current_function_static_stack_size = fsiz;
+
/* If this function is a varargs function, store any registers that
would normally hold arguments ($5 - $10) on the stack. */
if (((TYPE_ARG_TYPES (fntype) != 0
@@ -2892,8 +2920,10 @@ microblaze_function_epilogue (FILE * file ATTRIBUTE_UNUSED,
if (!flag_inhibit_size_directive)
{
fputs ("\t.end\t", file);
- if (interrupt_handler)
+ if (interrupt_handler && !break_handler)
fputs ("_interrupt_handler", file);
+ else if (break_handler)
+ fputs ("_break_handler", file);
else
assemble_name (file, fnname);
fputs ("\n", file);
@@ -3007,6 +3037,8 @@ microblaze_globalize_label (FILE * stream, const char *name)
{
if (interrupt_handler && strcmp (name, INTERRUPT_HANDLER_NAME))
fputs (INTERRUPT_HANDLER_NAME, stream);
+ else if (break_handler && strcmp (name, BREAK_HANDLER_NAME))
+ fputs (BREAK_HANDLER_NAME, stream);
else if (fast_interrupt && strcmp (name, FAST_INTERRUPT_NAME))
fputs (FAST_INTERRUPT_NAME, stream);
fputs ("\n\t.globl\t", stream);
diff --git a/gcc/config/microblaze/microblaze.h b/gcc/config/microblaze/microblaze.h
index 58d8895a319..edb7d8aaab8 100644
--- a/gcc/config/microblaze/microblaze.h
+++ b/gcc/config/microblaze/microblaze.h
@@ -263,7 +263,6 @@ extern enum pipeline_type microblaze_pipe;
1, 1, 1, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \
1, 1, 1, 1 \
}
-
#define GP_REG_FIRST 0
#define GP_REG_LAST 31
#define GP_REG_NUM (GP_REG_LAST - GP_REG_FIRST + 1)
@@ -763,6 +762,10 @@ extern int fast_interrupt;
extern int save_volatiles;
#define INTERRUPT_HANDLER_NAME "_interrupt_handler"
+/* The function name for the function tagged with attribute break_handler
+ has been set in the RTL as _break_handler. This function name is used
+ in the generation of directives .ent .end and .global. */
+#define BREAK_HANDLER_NAME "_break_handler"
#define FAST_INTERRUPT_NAME "_fast_interrupt"
/* The following #defines are used in the headers files. Always retain these. */
diff --git a/gcc/config/microblaze/microblaze.md b/gcc/config/microblaze/microblaze.md
index 815d6b5d706..7945d96b794 100644
--- a/gcc/config/microblaze/microblaze.md
+++ b/gcc/config/microblaze/microblaze.md
@@ -1945,8 +1945,10 @@
(define_insn "*<optab>"
[(any_return)]
""
- {
- if (microblaze_is_interrupt_variant ())
+ {
+ if (microblaze_is_break_handler ())
+ return "rtbd\tr16, 8\;%#";
+ else if (microblaze_is_interrupt_variant ())
return "rtid\tr14, 0\;%#";
else
return "rtsd\tr15, 8\;%#";
@@ -1962,8 +1964,10 @@
[(any_return)
(use (match_operand:SI 0 "register_operand" ""))]
""
- {
- if (microblaze_is_interrupt_variant ())
+ {
+ if (microblaze_is_break_handler ())
+ return "rtbd\tr16,8\;%#";
+ else if (microblaze_is_interrupt_variant ())
return "rtid\tr14,0 \;%#";
else
return "rtsd\tr15,8 \;%#";
@@ -2068,8 +2072,14 @@
register rtx target2 = gen_rtx_REG (Pmode,
GP_REG_FIRST + MB_ABI_SUB_RETURN_ADDR_REGNUM);
if (GET_CODE (target) == SYMBOL_REF) {
- gen_rtx_CLOBBER (VOIDmode, target2);
- return "brlid\tr15,%0\;%#";
+ if (microblaze_break_function_p (SYMBOL_REF_DECL (target))) {
+ gen_rtx_CLOBBER (VOIDmode, target2);
+ return "brki\tr16,%0\;%#";
+ }
+ else {
+ gen_rtx_CLOBBER (VOIDmode, target2);
+ return "brlid\tr15,%0\;%#";
+ }
} else if (GET_CODE (target) == CONST_INT)
return "la\t%@,r0,%0\;brald\tr15,%@\;%#";
else if (GET_CODE (target) == REG)
@@ -2173,13 +2183,15 @@
if (GET_CODE (target) == SYMBOL_REF)
{
gen_rtx_CLOBBER (VOIDmode,target2);
- if (SYMBOL_REF_FLAGS (target) & SYMBOL_FLAG_FUNCTION)
+ if (microblaze_break_function_p (SYMBOL_REF_DECL (target)))
+ return "brki\tr16,%1\;%#";
+ else if (SYMBOL_REF_FLAGS (target) & SYMBOL_FLAG_FUNCTION)
{
return "brlid\tr15,%1\;%#";
}
else
{
- return "bralid\tr15,%1\;%#";
+ return "bralid\tr15,%1\;%#";
}
}
else if (GET_CODE (target) == CONST_INT)