From 15dfaee8feef37430745d3dbc58f74bed876aabb Mon Sep 17 00:00:00 2001 From: Ajit Kumar Agarwal Date: Tue, 13 May 2014 13:25:52 +0530 Subject: [PATCH] [Patch, microblaze] Added 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. 2014-05-13 Ajit Agarwal * config/microblaze/microblaze.c (microblaze_break_function_p,microblaze_is_break_handler) : New * config/microblaze/microblaze.h (BREAK_HANDLER_NAME) : New macro * config/microblaze/microblaze.md : Extended support for generation of brki instruction and rtbd instruction. * config/microblaze/microblaze-protos.h (microblaze_break_function_p,microblaze_is_break_handler) : New Declaration. * testsuite/gcc.target/microblaze/others/break_handler.c : New. Signed-off-by:Nagaraju --- gcc/config/microblaze/microblaze-protos.h | 4 +- gcc/config/microblaze/microblaze.c | 47 +++++++++++++++++--- gcc/config/microblaze/microblaze.h | 2 +- gcc/config/microblaze/microblaze.md | 34 ++++++++++---- .../gcc.target/microblaze/others/break_handler.c | 15 ++++++ 5 files changed, 83 insertions(+), 19 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..fc458a5 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); @@ -2654,9 +2682,10 @@ microblaze_function_prologue (FILE * file, HOST_WIDE_INT size ATTRIBUTE_UNUSED) assemble_name (file, fnname); fputs (":\n", file); - if (interrupt_handler && strcmp (INTERRUPT_HANDLER_NAME, fnname)) + if (interrupt_handler && strcmp (INTERRUPT_HANDLER_NAME, fnname) && !break_handler) 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..b979206 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,7 @@ extern int fast_interrupt; extern int save_volatiles; #define INTERRUPT_HANDLER_NAME "_interrupt_handler" +#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 "*" [(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/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