diff options
-rw-r--r-- | gcc/ChangeLog | 9 | ||||
-rw-r--r-- | gcc/config/rl78/rl78.c | 51 |
2 files changed, 40 insertions, 20 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 2b0d211..fc511f0 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,12 @@ +2013-09-17 Nick Clifton <nickc@redhat.com> + + * config/rl78/rl78.c (need_to_save): Change return type to bool. + For interrupt functions: save all call clobbered registers if the + interrupt handler is not a leaf function. + (rl78_expand_prologue): Always recompute the frame information. + For interrupt functions: only select bank 0 if one of the bank 0 + registers is going to be psuhed. + 2013-09-17 DJ Delorie <dj@redhat.com> * config/rl78/constraints.md: For each W* constraint, rename to C* diff --git a/gcc/config/rl78/rl78.c b/gcc/config/rl78/rl78.c index e7bd3de..70e1dee 100644 --- a/gcc/config/rl78/rl78.c +++ b/gcc/config/rl78/rl78.c @@ -540,34 +540,39 @@ rl78_can_eliminate (const int from ATTRIBUTE_UNUSED, const int to ATTRIBUTE_UNUS return true; } -/* Returns nonzero if the given register needs to be saved by the +/* Returns true if the given register needs to be saved by the current function. */ -static int -need_to_save (int regno) +static bool +need_to_save (unsigned int regno) { if (is_interrupt_func (cfun->decl)) { - if (regno < 8) - return 1; /* don't know what devirt will need */ + /* We don't need to save registers that have + been reserved for interrupt handlers. */ if (regno > 23) - return 0; /* don't need to save interrupt registers */ - if (crtl->is_leaf) - { - return df_regs_ever_live_p (regno); - } - else - return 1; + return false; + + /* If the handler is a non-leaf function then it may call + non-interrupt aware routines which will happily clobber + any call_used registers, so we have to preserve them. */ + if (!crtl->is_leaf && call_used_regs[regno]) + return true; + + /* Otherwise we only have to save a register, call_used + or not, if it is used by this handler. */ + return df_regs_ever_live_p (regno); } + if (regno == FRAME_POINTER_REGNUM && frame_pointer_needed) - return 1; + return true; if (fixed_regs[regno]) - return 0; + return false; if (crtl->calls_eh_return) - return 1; + return true; if (df_regs_ever_live_p (regno) && !call_used_regs[regno]) - return 1; - return 0; + return true; + return false; } /* We use this to wrap all emitted insns in the prologue. */ @@ -1026,14 +1031,20 @@ rl78_expand_prologue (void) if (rl78_is_naked_func ()) return; - if (!cfun->machine->computed) - rl78_compute_frame_info (); + /* Always re-compute the frame info - the register usage may have changed. */ + rl78_compute_frame_info (); if (flag_stack_usage_info) current_function_static_stack_size = cfun->machine->framesize; if (is_interrupt_func (cfun->decl) && !TARGET_G10) - emit_insn (gen_sel_rb (GEN_INT (0))); + for (i = 0; i < 4; i++) + if (cfun->machine->need_to_push [i]) + { + /* Select Bank 0 if we are using any registers from Bank 0. */ + emit_insn (gen_sel_rb (GEN_INT (0))); + break; + } for (i = 0; i < 16; i++) if (cfun->machine->need_to_push [i]) |