]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
ChangeLog:
authorAjit Agarwal <ajitkum@xilinx.com>
Sat, 17 May 2014 15:12:38 +0000 (15:12 +0000)
committerMichael Eager <eager@gcc.gnu.org>
Sat, 17 May 2014 15:12:38 +0000 (15:12 +0000)
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

gcc/ChangeLog
gcc/config/microblaze/microblaze-protos.h
gcc/config/microblaze/microblaze.c
gcc/config/microblaze/microblaze.h
gcc/config/microblaze/microblaze.md
gcc/doc/extend.texi
gcc/testsuite/gcc.target/microblaze/others/break_handler.c [new file with mode: 0644]

index 22c52a6dc5b2acc67a95391dc99779734d80fdf7..fa738a524ccb04b9bc76f9f63f558b68a792dfd2 100644 (file)
@@ -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
index b03e9e126c0dda854782866dde14abe00278fb9b..f3cc0991ae01c823b026389612350b70f8c1bc99 100644 (file)
@@ -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 *,
index ba8109bc123a7997b2bce5ea9d8a2d8367f680a5..b12b7bf047f633fa2bc9a279568509f428cc18a0 100644 (file)
@@ -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);
index 58d8895a319c7187aeb8360db0b51eee5a5926e3..edb7d8aaab88b510bc523c94a1250f62be24b9ac 100644 (file)
@@ -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.  */
index 815d6b5d7067c1cbee5e72c865eb8179a2d46ef3..7945d96b794e84aef6ac6b987e50485c894a2941 100644 (file)
 (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\;%#";
   [(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 \;%#";
     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)
     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)
index bd2c82915bcb3c9a15bf85b25ce95c1441a77ef7..31a48dd82cb2113ca715fa8e64836e6352d60a9d 100644 (file)
@@ -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 (file)
index 0000000..1ccafd0
--- /dev/null
@@ -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;
+}