Hello Michael:

The following patch is to handle Software and Hardware breaks in Microblaze 
Architecture.
Deja GNU testcase does not have any regressions and the testcase attached 
passes through.
Review comments are incorporated.

Okay for trunk?

Thanks & Regards
Ajit

From 15dfaee8feef37430745d3dbc58f74bed876aabb Mon Sep 17 00:00:00 2001
From: Ajit Kumar Agarwal <ajit...@xilinx.com>
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 <ajit...@xilinx.com>

* 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 <nmek...@xilinx.com>
---
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 "*<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/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: Michael Eager [mailto:ea...@eagercon.com] 
Sent: Tuesday, May 06, 2014 8:04 PM
To: Ajit Kumar Agarwal; gcc-patches@gcc.gnu.org
Cc: Edgar Iglesias; John Williams; Vinod Kathail; Vidhumouli Hunsigida; 
Nagaraju Mekala
Subject: Re: [Patch,Microblaze]: Added Break Handler Support

On 05/06/14 06:10, Ajit Kumar Agarwal wrote:
> Hello All:
>
> Could you please review this patch.
>
> [PATCH] Break handler is used to support a normal hardware break.
> This is similar to interrupt_handler except that RTBD should be used instead 
> of RTID.
>
> Changelog
>
> 2014-05-06 Nagaraju <nmek...@xilinx.com>
>
> * gcc/config/microblaze/microblaze-protos.h : Declaration of 
> microblaze_is_break_handler.
> * gcc/config/microblaze/microblaze.c :  Add functions to support break 
> handler
> * gcc/config/microblaze/microblaze.h :  Add required defination declaration.
> * gcc/config/microblaze/microblaze.md : Add pattern for generating 
> instruction rtbd.

Please follow conventions for ChangeLog.  For example
   * config/microblaze/microblaze.c (microblaze_break_function_p): New.

See http://www.gnu.org/prep/standards/html_node/Change-Logs.html#Change-Logs

Add documentation for _break_handler.

Add test case(s).

Code formatting issues:
+  a = lookup_attribute("break_handler",DECL_ATTRIBUTES (func));
Space before left paren, after comma.
+      else if (break_handler && strcmp (BREAK_HANDLER_NAME, fnname))
+               fputs ("_break_handler", file);
Incorrect indent.
+    if (microblaze_is_break_handler ())
+        return "rtbd\tr16, 0\;%#";
Ditto.
+    if (microblaze_is_break_handler ())
+        return "rtbd\tr16, 0\;%#";
Ditto.


> This email and any attachments are intended for the sole use of the 
> named recipient(s) and
> contain(s) confidential information that may be proprietary, 
> privileged or copyrighted under applicable law. If you are not the 
> intended recipient, do not read, copy, or forward this email message or any 
> attachments. Delete this email message and any attachments immediately.

Mailing list conventions do not permit these kind of restrictive annotations.


-- 
Michael Eager    ea...@eagercon.com
1960 Park Blvd., Palo Alto, CA 94306  650-325-8077

Attachment: 0001-Patch-microblaze-Added-Break-Handler-support.patch
Description: 0001-Patch-microblaze-Added-Break-Handler-support.patch

Reply via email to