ChangeLog:

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
This commit is contained in:
Ajit Agarwal 2014-05-17 15:12:38 +00:00 committed by Michael Eager
parent a0eaa08ceb
commit 86498dbaae
7 changed files with 118 additions and 14 deletions

View 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

View 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 *,

View 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);

View 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. */

View file

@ -1945,8 +1945,10 @@
(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\;%#";
@ -1962,8 +1964,10 @@
[(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 \;%#";
@ -2068,8 +2072,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 +2183,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)

View 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.

View file

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