diff options
author | David Holsgrove <david.holsgrove@xilinx.com> | 2013-03-05 19:34:25 +0000 |
---|---|---|
committer | Michael Eager <eager@eagercon.com> | 2013-03-05 19:34:25 +0000 |
commit | 384b00831f70e049aa99a42b147f06f2cced5525 (patch) | |
tree | c4a63e2bb0be3c0472bbea65f4a0a3f85051f9be /gcc/config/microblaze | |
parent | 7e52ca7afbf21341336354f3e55624bcec5806c8 (diff) |
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: https://gcc.gnu.org/svn/gcc/trunk@196474 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/config/microblaze')
-rw-r--r-- | gcc/config/microblaze/microblaze-protos.h | 2 | ||||
-rw-r--r-- | gcc/config/microblaze/microblaze.c | 56 | ||||
-rw-r--r-- | gcc/config/microblaze/microblaze.h | 2 | ||||
-rw-r--r-- | gcc/config/microblaze/microblaze.md | 6 |
4 files changed, 46 insertions, 20 deletions
diff --git a/gcc/config/microblaze/microblaze-protos.h b/gcc/config/microblaze/microblaze-protos.h index fe2ac09f86a..e19939f0930 100644 --- a/gcc/config/microblaze/microblaze-protos.h +++ b/gcc/config/microblaze/microblaze-protos.h @@ -39,7 +39,7 @@ extern void print_operand (FILE *, rtx, int); 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_handler (void); +extern int microblaze_is_interrupt_variant (void); 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); 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); diff --git a/gcc/config/microblaze/microblaze.h b/gcc/config/microblaze/microblaze.h index c726978800d..8fbe5bf8085 100644 --- a/gcc/config/microblaze/microblaze.h +++ b/gcc/config/microblaze/microblaze.h @@ -756,9 +756,11 @@ do { \ /* Handle interrupt attribute. */ extern int interrupt_handler; +extern int fast_interrupt; extern int save_volatiles; #define INTERRUPT_HANDLER_NAME "_interrupt_handler" +#define FAST_INTERRUPT_NAME "_fast_interrupt" /* The following #defines are used in the headers files. Always retain these. */ diff --git a/gcc/config/microblaze/microblaze.md b/gcc/config/microblaze/microblaze.md index 78c033ee2f6..02857875022 100644 --- a/gcc/config/microblaze/microblaze.md +++ b/gcc/config/microblaze/microblaze.md @@ -961,7 +961,7 @@ (define_insn "movsi_status" [(set (match_operand:SI 0 "register_operand" "=d,d,z") (match_operand:SI 1 "register_operand" "z,d,d"))] - "interrupt_handler" + "microblaze_is_interrupt_variant ()" "@ mfs\t%0,%1 #mfs addk\t%0,%1,r0 #add movsi @@ -1918,7 +1918,7 @@ [(any_return)] "" { - if (microblaze_is_interrupt_handler ()) + if (microblaze_is_interrupt_variant ()) return "rtid\tr14, 0\;%#"; else return "rtsd\tr15, 8\;%#"; @@ -1935,7 +1935,7 @@ (use (match_operand:SI 0 "register_operand" ""))] "" { - if (microblaze_is_interrupt_handler ()) + if (microblaze_is_interrupt_variant ()) return "rtid\tr14,0 \;%#"; else return "rtsd\tr15,8 \;%#"; |