diff options
author | Ajit Agarwal <ajitkum@xilinx.com> | 2014-05-17 15:12:38 +0000 |
---|---|---|
committer | Michael Eager <eager@gcc.gnu.org> | 2014-05-17 15:12:38 +0000 |
commit | 86498dbaae86f711a98ea020441562de84946879 (patch) | |
tree | b594c0ab7cce86755578cc61bfda61439424797a /gcc | |
parent | a0eaa08cebd801a6a1d340dfd71b0183c510f599 (diff) | |
download | gcc-86498dbaae86f711a98ea020441562de84946879.zip gcc-86498dbaae86f711a98ea020441562de84946879.tar.gz gcc-86498dbaae86f711a98ea020441562de84946879.tar.bz2 |
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.
From-SVN: r210559
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/ChangeLog | 28 | ||||
-rw-r--r-- | gcc/config/microblaze/microblaze-protos.h | 4 | ||||
-rw-r--r-- | gcc/config/microblaze/microblaze.c | 40 | ||||
-rw-r--r-- | gcc/config/microblaze/microblaze.h | 5 | ||||
-rw-r--r-- | gcc/config/microblaze/microblaze.md | 28 | ||||
-rw-r--r-- | gcc/doc/extend.texi | 12 | ||||
-rw-r--r-- | gcc/testsuite/gcc.target/microblaze/others/break_handler.c | 15 |
7 files changed, 118 insertions, 14 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 22c52a6..fa738a5 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,31 @@ +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. + (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. + 2014-05-17 Uros Bizjak <ubizjak@gmail.com> * doc/extend.texi (Size of an asm): Move node text according diff --git a/gcc/config/microblaze/microblaze-protos.h b/gcc/config/microblaze/microblaze-protos.h index b03e9e1..f3cc099 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 ba8109b..b12b7bf 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 58d8895..edb7d8a 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 815d6b5..7945d96 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) diff --git a/gcc/doc/extend.texi b/gcc/doc/extend.texi index bd2c829..31a48dd 100644 --- a/gcc/doc/extend.texi +++ b/gcc/doc/extend.texi @@ -3772,6 +3772,18 @@ registers) are saved in the function prologue. If the function is a leaf function, only volatiles used by the function are saved. A normal function return is generated instead of a return from interrupt. +@item break_handler +@cindex break handler functions +Use this attribute on the MicroBlaze ports to indicate that +the specified function is an break handler. The compiler generates function +entry and exit sequences suitable for use in an break handler when this +attribute is present. The return from @code{break_handler} is done through +the @code{rtbd} instead of @code{rtsd}. + +@smallexample +void f () __attribute__ ((break_handler)); +@end smallexample + @item section ("@var{section-name}") @cindex @code{section} function attribute Normally, the compiler places the code it generates in the @code{text} section. diff --git a/gcc/testsuite/gcc.target/microblaze/others/break_handler.c b/gcc/testsuite/gcc.target/microblaze/others/break_handler.c new file mode 100644 index 0000000..1ccafd0 --- /dev/null +++ b/gcc/testsuite/gcc.target/microblaze/others/break_handler.c @@ -0,0 +1,15 @@ +int func () __attribute__ ((break_handler)); +volatile int intr_occurred; + +int func () +{ + + /* { dg-final { scan-assembler "rtbd\tr(\[0-9]\|\[1-2]\[0-9]\|3\[0-1]),8" } } */ + intr_occurred += 1; +} +int main() +{ + /* { dg-final { scan-assembler "brki\tr16" } } */ + func(); + return 0; +} |