Commit ee61ea38 by David Holsgrove Committed by Michael Eager

Add fast interrupt.

	*  config/microblaze/microblaze-protos.h: Rename
	microblaze_is_interrupt_handler to microblaze_is_interrupt_variant.
	*  config/microblaze/microblaze.c (microblaze_attribute_table): Add
	fast_interrupt.
	(microblaze_fast_interrupt_function_p): New function.
	(microblaze_is_interrupt_handler): Rename to
	microblaze_is_interrupt_variant and add fast_interrupt check.
	(microblaze_must_save_register): Use microblaze_is_interrupt_variant.
	(save_restore_insns): Likewise.
	(compute_frame_size): Likewise.
	(microblaze_function_prologue): Add FAST_INTERRUPT_NAME.
	(microblaze_globalize_label): Likewise.
	*  config/microblaze/microblaze.h: Define FAST_INTERRUPT_NAME.
	*  config/microblaze/microblaze.md: Use wrapper
	microblaze_is_interrupt_variant.

From-SVN: r196474
parent 887a780f
2013-03-05 David Holsgrove <david.holsgrove@xilinx.com>
* config/microblaze/microblaze-protos.h: Rename
microblaze_is_interrupt_handler to microblaze_is_interrupt_variant.
* config/microblaze/microblaze.c (microblaze_attribute_table): Add
fast_interrupt.
(microblaze_fast_interrupt_function_p): New function.
(microblaze_is_interrupt_handler): Rename to
microblaze_is_interrupt_variant and add fast_interrupt check.
(microblaze_must_save_register): Use microblaze_is_interrupt_variant.
(save_restore_insns): Likewise.
(compute_frame_size): Likewise.
(microblaze_function_prologue): Add FAST_INTERRUPT_NAME.
(microblaze_globalize_label): Likewise.
* config/microblaze/microblaze.h: Define FAST_INTERRUPT_NAME.
* config/microblaze/microblaze.md: Use wrapper
microblaze_is_interrupt_variant.
2013-03-05 Kai Tietz <ktietz@redhat.com> 2013-03-05 Kai Tietz <ktietz@redhat.com>
* sdbout.c (sdbout_one_type): Switch to current function's section * sdbout.c (sdbout_one_type): Switch to current function's section
......
...@@ -39,7 +39,7 @@ extern void print_operand (FILE *, rtx, int); ...@@ -39,7 +39,7 @@ extern void print_operand (FILE *, rtx, int);
extern void print_operand_address (FILE *, rtx); extern void print_operand_address (FILE *, rtx);
extern void init_cumulative_args (CUMULATIVE_ARGS *,tree, rtx); extern void init_cumulative_args (CUMULATIVE_ARGS *,tree, rtx);
extern bool microblaze_legitimate_address_p (enum machine_mode, rtx, bool); extern bool microblaze_legitimate_address_p (enum machine_mode, rtx, bool);
extern int microblaze_is_interrupt_handler (void); extern int microblaze_is_interrupt_variant (void);
extern rtx microblaze_return_addr (int, rtx); extern rtx microblaze_return_addr (int, rtx);
extern int simple_memory_operand (rtx, enum machine_mode); extern int simple_memory_operand (rtx, enum machine_mode);
extern int double_memory_operand (rtx, enum machine_mode); extern int double_memory_operand (rtx, enum machine_mode);
......
...@@ -195,6 +195,7 @@ enum reg_class microblaze_regno_to_class[] = ...@@ -195,6 +195,7 @@ enum reg_class microblaze_regno_to_class[] =
and epilogue and use appropriate interrupt return. and epilogue and use appropriate interrupt return.
save_volatiles - Similar to interrupt handler, but use normal return. */ save_volatiles - Similar to interrupt handler, but use normal return. */
int interrupt_handler; int interrupt_handler;
int fast_interrupt;
int save_volatiles; int save_volatiles;
const struct attribute_spec microblaze_attribute_table[] = { const struct attribute_spec microblaze_attribute_table[] = {
...@@ -202,6 +203,8 @@ const struct attribute_spec microblaze_attribute_table[] = { ...@@ -202,6 +203,8 @@ const struct attribute_spec microblaze_attribute_table[] = {
affects_type_identity */ affects_type_identity */
{"interrupt_handler", 0, 0, true, false, false, NULL, {"interrupt_handler", 0, 0, true, false, false, NULL,
false }, false },
{"fast_interrupt", 0, 0, true, false, false, NULL,
false },
{"save_volatiles" , 0, 0, true, false, false, NULL, {"save_volatiles" , 0, 0, true, false, false, NULL,
false }, false },
{ NULL, 0, 0, false, false, false, NULL, { NULL, 0, 0, false, false, false, NULL,
...@@ -1506,6 +1509,18 @@ microblaze_interrupt_function_p (tree func) ...@@ -1506,6 +1509,18 @@ microblaze_interrupt_function_p (tree func)
return a != NULL_TREE; return a != NULL_TREE;
} }
static int
microblaze_fast_interrupt_function_p (tree func)
{
tree a;
if (TREE_CODE (func) != FUNCTION_DECL)
return 0;
a = lookup_attribute ("fast_interrupt", DECL_ATTRIBUTES (func));
return a != NULL_TREE;
}
/* Return true if FUNC is an interrupt function which uses /* Return true if FUNC is an interrupt function which uses
normal return, indicated by the "save_volatiles" attribute. */ normal return, indicated by the "save_volatiles" attribute. */
...@@ -1522,12 +1537,13 @@ microblaze_save_volatiles (tree func) ...@@ -1522,12 +1537,13 @@ microblaze_save_volatiles (tree func)
} }
/* Return whether function is tagged with 'interrupt_handler' /* Return whether function is tagged with 'interrupt_handler'
attribute. Return true if function should use return from or 'fast_interrupt' attribute. Return true if function
interrupt rather than normal function return. */ should use return from interrupt rather than normal
function return. */
int int
microblaze_is_interrupt_handler (void) microblaze_is_interrupt_variant (void)
{ {
return interrupt_handler; return (interrupt_handler || fast_interrupt);
} }
/* Determine of register must be saved/restored in call. */ /* Determine of register must be saved/restored in call. */
...@@ -1548,17 +1564,18 @@ microblaze_must_save_register (int regno) ...@@ -1548,17 +1564,18 @@ microblaze_must_save_register (int regno)
{ {
if (regno == MB_ABI_SUB_RETURN_ADDR_REGNUM) if (regno == MB_ABI_SUB_RETURN_ADDR_REGNUM)
return 1; return 1;
if ((interrupt_handler || save_volatiles) && if ((microblaze_is_interrupt_variant () || save_volatiles) &&
(regno >= 3 && regno <= 12)) (regno >= 3 && regno <= 12))
return 1; return 1;
} }
if (interrupt_handler) if (microblaze_is_interrupt_variant ())
{ {
if (df_regs_ever_live_p (regno) if (df_regs_ever_live_p (regno)
|| regno == MB_ABI_MSR_SAVE_REG || regno == MB_ABI_MSR_SAVE_REG
|| regno == MB_ABI_ASM_TEMP_REGNUM || (interrupt_handler
|| regno == MB_ABI_EXCEPTION_RETURN_ADDR_REGNUM) && (regno == MB_ABI_ASM_TEMP_REGNUM
|| regno == MB_ABI_EXCEPTION_RETURN_ADDR_REGNUM)))
return 1; return 1;
} }
...@@ -1631,6 +1648,8 @@ compute_frame_size (HOST_WIDE_INT size) ...@@ -1631,6 +1648,8 @@ compute_frame_size (HOST_WIDE_INT size)
interrupt_handler = interrupt_handler =
microblaze_interrupt_function_p (current_function_decl); microblaze_interrupt_function_p (current_function_decl);
fast_interrupt =
microblaze_fast_interrupt_function_p (current_function_decl);
save_volatiles = microblaze_save_volatiles (current_function_decl); save_volatiles = microblaze_save_volatiles (current_function_decl);
gp_reg_size = 0; gp_reg_size = 0;
...@@ -1664,7 +1683,7 @@ compute_frame_size (HOST_WIDE_INT size) ...@@ -1664,7 +1683,7 @@ compute_frame_size (HOST_WIDE_INT size)
total_size += gp_reg_size; total_size += gp_reg_size;
/* Add 4 bytes for MSR. */ /* Add 4 bytes for MSR. */
if (interrupt_handler) if (microblaze_is_interrupt_variant ())
total_size += 4; total_size += 4;
/* No space to be allocated for link register in leaf functions with no other /* No space to be allocated for link register in leaf functions with no other
...@@ -2156,7 +2175,7 @@ save_restore_insns (int prologue) ...@@ -2156,7 +2175,7 @@ save_restore_insns (int prologue)
base_reg_rtx = stack_pointer_rtx; base_reg_rtx = stack_pointer_rtx;
/* For interrupt_handlers, need to save/restore the MSR. */ /* For interrupt_handlers, need to save/restore the MSR. */
if (interrupt_handler) if (microblaze_is_interrupt_variant ())
{ {
isr_mem_rtx = gen_rtx_MEM (SImode, isr_mem_rtx = gen_rtx_MEM (SImode,
gen_rtx_PLUS (Pmode, base_reg_rtx, gen_rtx_PLUS (Pmode, base_reg_rtx,
...@@ -2170,7 +2189,7 @@ save_restore_insns (int prologue) ...@@ -2170,7 +2189,7 @@ save_restore_insns (int prologue)
isr_msr_rtx = gen_rtx_REG (SImode, ST_REG); isr_msr_rtx = gen_rtx_REG (SImode, ST_REG);
} }
if (interrupt_handler && !prologue) if (microblaze_is_interrupt_variant () && !prologue)
{ {
emit_move_insn (isr_reg_rtx, isr_mem_rtx); emit_move_insn (isr_reg_rtx, isr_mem_rtx);
emit_move_insn (isr_msr_rtx, isr_reg_rtx); emit_move_insn (isr_msr_rtx, isr_reg_rtx);
...@@ -2190,7 +2209,7 @@ save_restore_insns (int prologue) ...@@ -2190,7 +2209,7 @@ save_restore_insns (int prologue)
reg_rtx = gen_rtx_REG (SImode, regno); reg_rtx = gen_rtx_REG (SImode, regno);
insn = gen_rtx_PLUS (Pmode, base_reg_rtx, GEN_INT (gp_offset)); insn = gen_rtx_PLUS (Pmode, base_reg_rtx, GEN_INT (gp_offset));
mem_rtx = gen_rtx_MEM (SImode, insn); mem_rtx = gen_rtx_MEM (SImode, insn);
if (interrupt_handler || save_volatiles) if (microblaze_is_interrupt_variant () || save_volatiles)
/* Do not optimize in flow analysis. */ /* Do not optimize in flow analysis. */
MEM_VOLATILE_P (mem_rtx) = 1; MEM_VOLATILE_P (mem_rtx) = 1;
...@@ -2208,7 +2227,7 @@ save_restore_insns (int prologue) ...@@ -2208,7 +2227,7 @@ save_restore_insns (int prologue)
} }
} }
if (interrupt_handler && prologue) if (microblaze_is_interrupt_variant () && prologue)
{ {
emit_move_insn (isr_reg_rtx, isr_msr_rtx); emit_move_insn (isr_reg_rtx, isr_msr_rtx);
emit_move_insn (isr_mem_rtx, isr_reg_rtx); emit_move_insn (isr_mem_rtx, isr_reg_rtx);
...@@ -2238,10 +2257,12 @@ microblaze_function_prologue (FILE * file, HOST_WIDE_INT size ATTRIBUTE_UNUSED) ...@@ -2238,10 +2257,12 @@ microblaze_function_prologue (FILE * file, HOST_WIDE_INT size ATTRIBUTE_UNUSED)
fputs ("\t.ent\t", file); fputs ("\t.ent\t", file);
if (interrupt_handler && strcmp (INTERRUPT_HANDLER_NAME, fnname)) if (interrupt_handler && strcmp (INTERRUPT_HANDLER_NAME, fnname))
fputs ("_interrupt_handler", file); fputs ("_interrupt_handler", file);
else if (fast_interrupt && strcmp (FAST_INTERRUPT_NAME, fnname))
fputs ("_fast_interrupt", file);
else else
assemble_name (file, fnname); assemble_name (file, fnname);
fputs ("\n", file); fputs ("\n", file);
if (!interrupt_handler) if (!microblaze_is_interrupt_variant ())
ASM_OUTPUT_TYPE_DIRECTIVE (file, fnname, "function"); ASM_OUTPUT_TYPE_DIRECTIVE (file, fnname, "function");
} }
...@@ -2593,9 +2614,12 @@ static void ...@@ -2593,9 +2614,12 @@ static void
microblaze_globalize_label (FILE * stream, const char *name) microblaze_globalize_label (FILE * stream, const char *name)
{ {
fputs ("\t.globl\t", stream); fputs ("\t.globl\t", stream);
if (interrupt_handler && strcmp (name, INTERRUPT_HANDLER_NAME)) if (microblaze_is_interrupt_variant ())
{ {
if (interrupt_handler && strcmp (name, INTERRUPT_HANDLER_NAME))
fputs (INTERRUPT_HANDLER_NAME, stream); fputs (INTERRUPT_HANDLER_NAME, stream);
else if (fast_interrupt && strcmp (name, FAST_INTERRUPT_NAME))
fputs (FAST_INTERRUPT_NAME, stream);
fputs ("\n\t.globl\t", stream); fputs ("\n\t.globl\t", stream);
} }
assemble_name (stream, name); assemble_name (stream, name);
......
...@@ -756,9 +756,11 @@ do { \ ...@@ -756,9 +756,11 @@ do { \
/* Handle interrupt attribute. */ /* Handle interrupt attribute. */
extern int interrupt_handler; extern int interrupt_handler;
extern int fast_interrupt;
extern int save_volatiles; extern int save_volatiles;
#define INTERRUPT_HANDLER_NAME "_interrupt_handler" #define INTERRUPT_HANDLER_NAME "_interrupt_handler"
#define FAST_INTERRUPT_NAME "_fast_interrupt"
/* The following #defines are used in the headers files. Always retain these. */ /* The following #defines are used in the headers files. Always retain these. */
......
...@@ -961,7 +961,7 @@ ...@@ -961,7 +961,7 @@
(define_insn "movsi_status" (define_insn "movsi_status"
[(set (match_operand:SI 0 "register_operand" "=d,d,z") [(set (match_operand:SI 0 "register_operand" "=d,d,z")
(match_operand:SI 1 "register_operand" "z,d,d"))] (match_operand:SI 1 "register_operand" "z,d,d"))]
"interrupt_handler" "microblaze_is_interrupt_variant ()"
"@ "@
mfs\t%0,%1 #mfs mfs\t%0,%1 #mfs
addk\t%0,%1,r0 #add movsi addk\t%0,%1,r0 #add movsi
...@@ -1918,7 +1918,7 @@ ...@@ -1918,7 +1918,7 @@
[(any_return)] [(any_return)]
"" ""
{ {
if (microblaze_is_interrupt_handler ()) if (microblaze_is_interrupt_variant ())
return "rtid\tr14, 0\;%#"; return "rtid\tr14, 0\;%#";
else else
return "rtsd\tr15, 8\;%#"; return "rtsd\tr15, 8\;%#";
...@@ -1935,7 +1935,7 @@ ...@@ -1935,7 +1935,7 @@
(use (match_operand:SI 0 "register_operand" ""))] (use (match_operand:SI 0 "register_operand" ""))]
"" ""
{ {
if (microblaze_is_interrupt_handler ()) if (microblaze_is_interrupt_variant ())
return "rtid\tr14,0 \;%#"; return "rtid\tr14,0 \;%#";
else else
return "rtsd\tr15,8 \;%#"; return "rtsd\tr15,8 \;%#";
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment