and epilogue and use appropriate interrupt return.
save_volatiles - Similar to interrupt handler, but use normal return. */
int interrupt_handler;
+int fast_interrupt;
int save_volatiles;
const struct attribute_spec microblaze_attribute_table[] = {
affects_type_identity */
{"interrupt_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,
false },
{ NULL, 0, 0, false, false, false, NULL,
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
normal return, indicated by the "save_volatiles" attribute. */
}
/* Return whether function is tagged with 'interrupt_handler'
- attribute. Return true if function should use return from
- interrupt rather than normal function return. */
+ or 'fast_interrupt' attribute. Return true if function
+ should use return from interrupt rather than normal
+ function return. */
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. */
{
if (regno == MB_ABI_SUB_RETURN_ADDR_REGNUM)
return 1;
- if ((interrupt_handler || save_volatiles) &&
+ if ((microblaze_is_interrupt_variant () || save_volatiles) &&
(regno >= 3 && regno <= 12))
return 1;
}
- if (interrupt_handler)
+ if (microblaze_is_interrupt_variant ())
{
if (df_regs_ever_live_p (regno)
|| regno == MB_ABI_MSR_SAVE_REG
- || regno == MB_ABI_ASM_TEMP_REGNUM
- || regno == MB_ABI_EXCEPTION_RETURN_ADDR_REGNUM)
+ || (interrupt_handler
+ && (regno == MB_ABI_ASM_TEMP_REGNUM
+ || regno == MB_ABI_EXCEPTION_RETURN_ADDR_REGNUM)))
return 1;
}
interrupt_handler =
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);
gp_reg_size = 0;
total_size += gp_reg_size;
/* Add 4 bytes for MSR. */
- if (interrupt_handler)
+ if (microblaze_is_interrupt_variant ())
total_size += 4;
/* No space to be allocated for link register in leaf functions with no other
base_reg_rtx = stack_pointer_rtx;
/* For interrupt_handlers, need to save/restore the MSR. */
- if (interrupt_handler)
+ if (microblaze_is_interrupt_variant ())
{
isr_mem_rtx = gen_rtx_MEM (SImode,
gen_rtx_PLUS (Pmode, base_reg_rtx,
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_msr_rtx, isr_reg_rtx);
reg_rtx = gen_rtx_REG (SImode, regno);
insn = gen_rtx_PLUS (Pmode, base_reg_rtx, GEN_INT (gp_offset));
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. */
MEM_VOLATILE_P (mem_rtx) = 1;
}
}
- if (interrupt_handler && prologue)
+ if (microblaze_is_interrupt_variant () && prologue)
{
emit_move_insn (isr_reg_rtx, isr_msr_rtx);
emit_move_insn (isr_mem_rtx, isr_reg_rtx);
fputs ("\t.ent\t", file);
if (interrupt_handler && strcmp (INTERRUPT_HANDLER_NAME, fnname))
fputs ("_interrupt_handler", file);
+ else if (fast_interrupt && strcmp (FAST_INTERRUPT_NAME, fnname))
+ fputs ("_fast_interrupt", file);
else
assemble_name (file, fnname);
fputs ("\n", file);
- if (!interrupt_handler)
+ if (!microblaze_is_interrupt_variant ())
ASM_OUTPUT_TYPE_DIRECTIVE (file, fnname, "function");
}
microblaze_globalize_label (FILE * stream, const char *name)
{
fputs ("\t.globl\t", stream);
- if (interrupt_handler && strcmp (name, INTERRUPT_HANDLER_NAME))
+ if (microblaze_is_interrupt_variant ())
{
- fputs (INTERRUPT_HANDLER_NAME, stream);
+ if (interrupt_handler && strcmp (name, INTERRUPT_HANDLER_NAME))
+ 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);
}
assemble_name (stream, name);