diff options
author | DJ Delorie <dj@redhat.com> | 2009-08-17 18:25:06 -0400 |
---|---|---|
committer | DJ Delorie <dj@gcc.gnu.org> | 2009-08-17 18:25:06 -0400 |
commit | 65655f79213b9bbc5a5d6962a7f6a637883f780b (patch) | |
tree | c06c38535dd2071c8584011e69f62f150c8e33df /gcc | |
parent | df15255add5471998a5cd84063dc4db98a6b774b (diff) | |
download | gcc-65655f79213b9bbc5a5d6962a7f6a637883f780b.zip gcc-65655f79213b9bbc5a5d6962a7f6a637883f780b.tar.gz gcc-65655f79213b9bbc5a5d6962a7f6a637883f780b.tar.bz2 |
m32c.md (UNS_FSETB, UNS_FREIT): New.
* config/m32c/m32c.md (UNS_FSETB, UNS_FREIT): New.
* config/m32c/prologue.md (epilogue_freit): New.
(fset_b): New.
* config/m32c/m32c.c (m32c_function_needs_enter): Add prototype.
(bank_switch_p): Likewise.
(fast_interrupt_p): Likewise.
(interrupt_p): Likewise.
(m32c_conditional_register_usage): Round memregs size up.
(need_to_save): We only need to save $a0 when we use ENTER.
(interrupt_p): Check for fast_interrupt too.
(bank_switch_p): New.
(fast_interrupt_p): New.
(m32c_attribute_table): Add bank_switch and fast_interrupt.
(m32c_emit_prolog): Support bank switching and fast interrupts.
* doc/extend.texi (Function Attributes): Add bank_switch and
fast_interrupt.
From-SVN: r150862
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/ChangeLog | 19 | ||||
-rw-r--r-- | gcc/config/m32c/m32c.c | 85 | ||||
-rw-r--r-- | gcc/config/m32c/m32c.md | 2 | ||||
-rw-r--r-- | gcc/config/m32c/prologue.md | 17 | ||||
-rw-r--r-- | gcc/doc/extend.texi | 13 |
5 files changed, 122 insertions, 14 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 953397e..94e20b3 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,22 @@ +2009-08-17 DJ Delorie <dj@redhat.com> + + * config/m32c/m32c.md (UNS_FSETB, UNS_FREIT): New. + * config/m32c/prologue.md (epilogue_freit): New. + (fset_b): New. + * config/m32c/m32c.c (m32c_function_needs_enter): Add prototype. + (bank_switch_p): Likewise. + (fast_interrupt_p): Likewise. + (interrupt_p): Likewise. + (m32c_conditional_register_usage): Round memregs size up. + (need_to_save): We only need to save $a0 when we use ENTER. + (interrupt_p): Check for fast_interrupt too. + (bank_switch_p): New. + (fast_interrupt_p): New. + (m32c_attribute_table): Add bank_switch and fast_interrupt. + (m32c_emit_prolog): Support bank switching and fast interrupts. + * doc/extend.texi (Function Attributes): Add bank_switch and + fast_interrupt. + 2009-08-17 Douglas B Rupp <rupp@gnat.com> * config/alpha/alpha.c (vms_valid_pointer_mode): New function. diff --git a/gcc/config/m32c/m32c.c b/gcc/config/m32c/m32c.c index 46dc4dc..ae4c897 100644 --- a/gcc/config/m32c/m32c.c +++ b/gcc/config/m32c/m32c.c @@ -60,9 +60,13 @@ typedef enum PP_justcount } Push_Pop_Type; +static bool m32c_function_needs_enter (void); static tree interrupt_handler (tree *, tree, tree, int, bool *); static tree function_vector_handler (tree *, tree, tree, int, bool *); static int interrupt_p (tree node); +static int bank_switch_p (tree node); +static int fast_interrupt_p (tree node); +static int interrupt_p (tree node); static bool m32c_asm_integer (rtx, unsigned int, int); static int m32c_comp_type_attributes (const_tree, const_tree); static bool m32c_fixed_condition_code_regs (unsigned int *, unsigned int *); @@ -493,7 +497,7 @@ m32c_conditional_register_usage (void) { /* The command line option is bytes, but our "registers" are 16-bit words. */ - for (i = target_memregs/2; i < 8; i++) + for (i = (target_memregs+1)/2; i < 8; i++) { fixed_regs[MEM0_REGNO + i] = 1; CLEAR_HARD_REG_BIT (reg_class_contents[MEM_REGS], MEM0_REGNO + i); @@ -1255,7 +1259,10 @@ need_to_save (int regno) if (regno == FP_REGNO) return 0; if (cfun->machine->is_interrupt - && (!cfun->machine->is_leaf || regno == A0_REGNO)) + && (!cfun->machine->is_leaf + || (regno == A0_REGNO + && m32c_function_needs_enter ()) + )) return 1; if (df_regs_ever_live_p (regno) && (!call_used_regs[regno] || cfun->machine->is_interrupt)) @@ -2733,6 +2740,34 @@ interrupt_p (tree node ATTRIBUTE_UNUSED) return 1; list = TREE_CHAIN (list); } + return fast_interrupt_p (node); +} + +/* Returns TRUE if the given tree has the "bank_switch" attribute. */ +static int +bank_switch_p (tree node ATTRIBUTE_UNUSED) +{ + tree list = M32C_ATTRIBUTES (node); + while (list) + { + if (is_attribute_p ("bank_switch", TREE_PURPOSE (list))) + return 1; + list = TREE_CHAIN (list); + } + return 0; +} + +/* Returns TRUE if the given tree has the "fast_interrupt" attribute. */ +static int +fast_interrupt_p (tree node ATTRIBUTE_UNUSED) +{ + tree list = M32C_ATTRIBUTES (node); + while (list) + { + if (is_attribute_p ("fast_interrupt", TREE_PURPOSE (list))) + return 1; + list = TREE_CHAIN (list); + } return 0; } @@ -2846,6 +2881,8 @@ current_function_special_page_vector (rtx x) #define TARGET_ATTRIBUTE_TABLE m32c_attribute_table static const struct attribute_spec m32c_attribute_table[] = { {"interrupt", 0, 0, false, false, false, interrupt_handler}, + {"bank_switch", 0, 0, false, false, false, interrupt_handler}, + {"fast_interrupt", 0, 0, false, false, false, interrupt_handler}, {"function_vector", 1, 1, true, false, false, function_vector_handler}, {0, 0, 0, 0, 0, 0, 0} }; @@ -3928,16 +3965,23 @@ m32c_emit_prologue (void) cfun->machine->is_interrupt = 1; complex_prologue = 1; } + else if (bank_switch_p (cfun->decl)) + warning (OPT_Wattributes, + "%<bank_switch%> has no effect on non-interrupt functions"); reg_save_size = m32c_pushm_popm (PP_justcount); if (interrupt_p (cfun->decl)) - emit_insn (gen_pushm (GEN_INT (cfun->machine->intr_pushm))); + { + if (bank_switch_p (cfun->decl)) + emit_insn (gen_fset_b ()); + else if (cfun->machine->intr_pushm) + emit_insn (gen_pushm (GEN_INT (cfun->machine->intr_pushm))); + } frame_size = m32c_initial_elimination_offset (FB_REGNO, SP_REGNO) - reg_save_size; if (frame_size == 0 - && !cfun->machine->is_interrupt && !m32c_function_needs_enter ()) cfun->machine->use_rts = 1; @@ -3988,16 +4032,29 @@ m32c_emit_epilogue (void) { enum machine_mode spmode = TARGET_A16 ? HImode : PSImode; - emit_move_insn (gen_rtx_REG (spmode, A0_REGNO), - gen_rtx_REG (spmode, FP_REGNO)); - emit_move_insn (gen_rtx_REG (spmode, SP_REGNO), - gen_rtx_REG (spmode, A0_REGNO)); - if (TARGET_A16) - emit_insn (gen_pophi_16 (gen_rtx_REG (HImode, FP_REGNO))); - else - emit_insn (gen_poppsi (gen_rtx_REG (PSImode, FP_REGNO))); - emit_insn (gen_popm (GEN_INT (cfun->machine->intr_pushm))); - if (TARGET_A16) + /* REIT clears B flag and restores $fp for us, but we still + have to fix up the stack. USE_RTS just means we didn't + emit ENTER. */ + if (!cfun->machine->use_rts) + { + emit_move_insn (gen_rtx_REG (spmode, A0_REGNO), + gen_rtx_REG (spmode, FP_REGNO)); + emit_move_insn (gen_rtx_REG (spmode, SP_REGNO), + gen_rtx_REG (spmode, A0_REGNO)); + /* We can't just add this to the POPM because it would be in + the wrong order, and wouldn't fix the stack if we're bank + switching. */ + if (TARGET_A16) + emit_insn (gen_pophi_16 (gen_rtx_REG (HImode, FP_REGNO))); + else + emit_insn (gen_poppsi (gen_rtx_REG (PSImode, FP_REGNO))); + } + if (!bank_switch_p (cfun->decl) && cfun->machine->intr_pushm) + emit_insn (gen_popm (GEN_INT (cfun->machine->intr_pushm))); + + if (fast_interrupt_p (cfun->decl)) + emit_jump_insn (gen_epilogue_freit ()); + else if (TARGET_A16) emit_jump_insn (gen_epilogue_reit_16 ()); else emit_jump_insn (gen_epilogue_reit_24 ()); diff --git a/gcc/config/m32c/m32c.md b/gcc/config/m32c/m32c.md index da0f8dd..739f24c 100644 --- a/gcc/config/m32c/m32c.md +++ b/gcc/config/m32c/m32c.md @@ -47,6 +47,8 @@ (UNS_SSTR 7) (UNS_SCMPU 8) (UNS_SMOVU 9) + (UNS_FSETB 10) + (UNS_FREIT 11) ]) ;; n = no change, x = clobbered. The first 16 values are chosen such diff --git a/gcc/config/m32c/prologue.md b/gcc/config/m32c/prologue.md index 9db4920..175b2b0 100644 --- a/gcc/config/m32c/prologue.md +++ b/gcc/config/m32c/prologue.md @@ -149,6 +149,15 @@ [(set_attr "flags" "x")] ) +(define_insn "epilogue_freit" + [(unspec [(const_int 0)] UNS_FREIT) + (return) + ] + "" + "freit" + [(set_attr "flags" "x")] + ) + (define_insn "epilogue_rts" [(return) ] @@ -180,3 +189,11 @@ "popm\t%p0" [(set_attr "flags" "n")] ) + +(define_insn "fset_b" + [(unspec [(const_int 0)] UNS_FSETB)] + "" + "fset\tB" + [(set_attr "flags" "n")] + ) + diff --git a/gcc/doc/extend.texi b/gcc/doc/extend.texi index 827198e..4e9f189 100644 --- a/gcc/doc/extend.texi +++ b/gcc/doc/extend.texi @@ -2019,6 +2019,12 @@ info format it will either mean marking the function as artificial or using the caller location for all instructions within the inlined body. +@item bank_switch +@cindex interrupt handler functions +When added to an interrupt handler with the M32C port, causes the +prologue and epilogue to use bank switching to preserve the registers +rather than saving them on the stack. + @item flatten @cindex @code{flatten} function attribute Generally, inlining into a function is limited. For a function marked with @@ -2272,6 +2278,13 @@ On MeP targets this causes the compiler to use a calling convention which assumes the called function is too far away for the built-in addressing modes. +@item fast_interrupt +@cindex interrupt handler functions +Use this attribute on the M32C port to indicate that the specified +function is a fast interrupt handler. This is just like the +@code{interrupt} attribute, except that @code{freit} is used to return +instead of @code{reit}. + @item fastcall @cindex functions that pop the argument stack on the 386 On the Intel 386, the @code{fastcall} attribute causes the compiler to |