Based on the Feedback, Resubmitting the Updated Patch. [Patch, MicroBlaze] Add break Handler Support
Added Break Handler support to incorporate the hardware and software break. The Break Handler routine will be generating the rtbd instruction. At the call point where the software breaks are generated with the instruction brki with register operand as r16. ChangeLog: 2014-05-14 Ajit Agarwal <ajit...@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. Signed-off-by:Ajit Agarwal <ajit...@xilinx.com> --- gcc/config/microblaze/microblaze-protos.h | 4 +- gcc/config/microblaze/microblaze.c | 45 +++++++++++++++++--- gcc/config/microblaze/microblaze.h | 5 ++- gcc/config/microblaze/microblaze.md | 34 ++++++++++---- gcc/doc/extend.texi | 12 +++++ .../gcc.target/microblaze/others/break_handler.c | 15 +++++++ 6 files changed, 97 insertions(+), 18 deletions(-) create mode 100644 gcc/testsuite/gcc.target/microblaze/others/break_handler.c 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..b7e9675 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,13 @@ 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 +2015,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 +2667,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 +2684,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 +2820,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 +2922,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); @@ -2934,7 +2966,7 @@ microblaze_expand_epilogue (void) sequence of load-followed by a use (in rtsd) in every prologue. Saves a load-use stall cycle :) This is also important to handle alloca. (See comments for if (frame_pointer_needed) below. */ - + if (!crtl->is_leaf || interrupt_handler) { mem_rtx = @@ -3007,6 +3039,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); @@ -3247,7 +3281,6 @@ microblaze_expand_shift (rtx operands[]) return 0; } - /* Return an RTX indicating where the return address to the calling function can be found. */ rtx 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..c368c70 100644 --- a/gcc/config/microblaze/microblaze.md +++ b/gcc/config/microblaze/microblaze.md @@ -1945,9 +1945,12 @@ (define_insn "*<optab>" [(any_return)] "" - { - if (microblaze_is_interrupt_variant ()) - return "rtid\tr14, 0\;%#"; + { + if (microblaze_is_break_handler ()) + return "rtbd\tr16, 8\;%#"; + else if (microblaze_is_interrupt_variant () + && (!microblaze_is_break_handler())) + return "rtid\tr14, 0\;%#"; else return "rtsd\tr15, 8\;%#"; } @@ -1962,9 +1965,12 @@ [(any_return) (use (match_operand:SI 0 "register_operand" ""))] "" - { - if (microblaze_is_interrupt_variant ()) - return "rtid\tr14,0 \;%#"; + { + if (microblaze_is_break_handler ()) + return "rtbd\tr16,8\;%#"; + else if (microblaze_is_interrupt_variant () + && (!microblaze_is_break_handler())) + return "rtid\tr14,0 \;%#"; else return "rtsd\tr15,8 \;%#"; } @@ -2068,8 +2074,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 +2185,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 9780d92..adb6410 100644 --- a/gcc/doc/extend.texi +++ b/gcc/doc/extend.texi @@ -3776,6 +3776,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; +} -- 1.7.1 -----Original Message----- From: gcc-patches-ow...@gcc.gnu.org [mailto:gcc-patches-ow...@gcc.gnu.org] On Behalf Of Michael Eager Sent: Wednesday, May 14, 2014 3:33 AM To: Ajit Kumar Agarwal; gcc-patches@gcc.gnu.org Cc: Vinod Kathail; Vidhumouli Hunsigida; Nagaraju Mekala Subject: Re: [Patch,Microblaze]: Added Break Handler Support On 05/13/14 14:42, Ajit Kumar Agarwal wrote: > Hello Michael: > > Resubmitting the Patch with documentation for _break_handler in the > config/microblaze/microblaze.h. Please put everything together in one place. When you resubmit a patch, include the ChangeLog. I'm not sure what you changed, but there are no changes to gcc/doc/extend.texi in your patch. -- Michael Eager ea...@eagercon.com 1960 Park Blvd., Palo Alto, CA 94306 650-325-8077
0001-Patch-MicroBlaze-Add-break-Handler-Support.patch
Description: 0001-Patch-MicroBlaze-Add-break-Handler-Support.patch