diff mbox

[Microblaze] : Added Break Handler Support

Message ID 26155c61-aa14-409f-be18-45415112f309@BN1BFFO11FD015.protection.gbl
State New
Headers show

Commit Message

Ajit Kumar Agarwal May 14, 2014, 9:24 a.m. UTC
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 <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.

Signed-off-by:Ajit Agarwal <ajitkum@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

-- 
1.7.1

-----Original Message-----
From: gcc-patches-owner@gcc.gnu.org [mailto:gcc-patches-owner@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	 eager@eagercon.com
1960 Park Blvd., Palo Alto, CA 94306  650-325-8077

Comments

Michael Eager May 17, 2014, 3:13 p.m. UTC | #1
On 05/14/14 02:24, Ajit Kumar Agarwal wrote:
> 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.

I made the following changes:

Your patch:
> 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()))

Replaced with:
-  {
-    if (microblaze_is_interrupt_variant ())
-        return "rtid\tr14, 0\;%#";
+  {
+    if (microblaze_is_break_handler ())
+        return "rtbd\tr16, 8\;%#";
+    else if (microblaze_is_interrupt_variant ())
+        return "rtid\tr14, 0\;%#";

Your patch:
> @@ -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 \;%#";

Replaced with
-  {	
-    if (microblaze_is_interrupt_variant ())
-        return "rtid\tr14,0 \;%#";
+  {
+    if (microblaze_is_break_handler ())
+        return "rtbd\tr16,8\;%#";
+    else if (microblaze_is_interrupt_variant ())
+        return "rtid\tr14,0 \;%#";

Please remove trailing white space in future patches.

The code in the "call_internal" pattern does not follow GNU indent
conventions.  If you are modifying code which does not follow these
conventions, please bring it up to date, rather than repeating the
indent violations.

Committed revision 210559.
diff mbox

Patch

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;
+}