diff options
author | eager <eager@138bc75d-0d04-0410-961f-82ee72b054a4> | 2013-03-05 19:34:25 +0000 |
---|---|---|
committer | eager <eager@138bc75d-0d04-0410-961f-82ee72b054a4> | 2013-03-05 19:34:25 +0000 |
commit | d9c1b6019c0221a1e8f22371a0390f0d0bae1f6b (patch) | |
tree | c4a63e2bb0be3c0472bbea65f4a0a3f85051f9be /gcc/config/microblaze/microblaze.c | |
parent | fd1c674e0695e11618a780e4f0bfe39f66f06aef (diff) | |
download | gcc-d9c1b6019c0221a1e8f22371a0390f0d0bae1f6b.tar.gz |
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.
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@196474 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/config/microblaze/microblaze.c')
-rw-r--r-- | gcc/config/microblaze/microblaze.c | 56 |
1 files changed, 40 insertions, 16 deletions
diff --git a/gcc/config/microblaze/microblaze.c b/gcc/config/microblaze/microblaze.c index 5286316e0ce..3a5299410b9 100644 --- a/gcc/config/microblaze/microblaze.c +++ b/gcc/config/microblaze/microblaze.c @@ -195,6 +195,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 fast_interrupt; int save_volatiles; const struct attribute_spec microblaze_attribute_table[] = { @@ -202,6 +203,8 @@ 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, @@ -1506,6 +1509,18 @@ microblaze_interrupt_function_p (tree func) 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. */ @@ -1522,12 +1537,13 @@ microblaze_save_volatiles (tree func) } /* 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. */ @@ -1548,17 +1564,18 @@ microblaze_must_save_register (int regno) { 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; } @@ -1631,6 +1648,8 @@ compute_frame_size (HOST_WIDE_INT size) 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; @@ -1664,7 +1683,7 @@ compute_frame_size (HOST_WIDE_INT size) 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 @@ -2156,7 +2175,7 @@ save_restore_insns (int prologue) 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, @@ -2170,7 +2189,7 @@ save_restore_insns (int prologue) 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); @@ -2190,7 +2209,7 @@ save_restore_insns (int prologue) 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; @@ -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_mem_rtx, isr_reg_rtx); @@ -2238,10 +2257,12 @@ 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); + 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"); } @@ -2593,9 +2614,12 @@ static void 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); |