From: nickc Date: Wed, 2 Dec 2009 10:59:04 +0000 (+0000) Subject: * config/rx/rx.c (rx_conditional_register_usage): Do not warn if X-Git-Tag: upstream/4.9.2~32102 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=e4d9e8e56c07a324f92dadc8f3c63cc2339a35bd;p=platform%2Fupstream%2Flinaro-gcc.git * config/rx/rx.c (rx_conditional_register_usage): Do not warn if no fixed registers are available for interrupt handlers. Do not fix normal registers. (MUST_SAVE_ACC_REGISTER): New macro. (rx_get_stack_layout): Create a stack frame for fast interrupt handlers, if necessary. Push extra registers if needed in order to save the accumulator. (rx_expand_prologue): Create a stack frame for fast interrupt handlers, if necessary. (rx_expand_builtin_mvfc): Handle the case where there is no target. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@154903 138bc75d-0d04-0410-961f-82ee72b054a4 --- diff --git a/gcc/ChangeLog b/gcc/ChangeLog index a28fc61..2459495 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,17 @@ +2009-12-02 Nick Clifton + + * config/rx/rx.c (rx_conditional_register_usage): Do not warn if + no fixed registers are available for interrupt handlers. Do not + fix normal registers. + (MUST_SAVE_ACC_REGISTER): New macro. + (rx_get_stack_layout): Create a stack frame for fast interrupt + handlers, if necessary. Push extra registers if needed in order + to save the accumulator. + (rx_expand_prologue): Create a stack frame for fast interrupt + handlers, if necessary. + (rx_expand_builtin_mvfc): Handle the case where there is no + target. + 2009-12-01 Sebastian Pop * config/i386/abmintrin.h (__lzcnt16): New. diff --git a/gcc/config/rx/rx.c b/gcc/config/rx/rx.c index 14cf09b..3fb8b32 100644 --- a/gcc/config/rx/rx.c +++ b/gcc/config/rx/rx.c @@ -887,46 +887,25 @@ rx_conditional_register_usage (void) if (use_fixed_regs) { - unsigned int switched = 0; unsigned int r; - /* This is for fast interrupt handlers. Any register in - the range r10 to r13 (inclusive) that is currently - marked as fixed is now a viable, call-saved register. - All other registers are fixed. */ memcpy (saved_fixed_regs, fixed_regs, sizeof fixed_regs); memcpy (saved_call_used_regs, call_used_regs, sizeof call_used_regs); - - for (r = 1; r < 10; r++) - fixed_regs[r] = call_used_regs[r] = 1; - + + /* This is for fast interrupt handlers. Any register in + the range r10 to r13 (inclusive) that is currently + marked as fixed is now a viable, call-used register. */ for (r = 10; r <= 13; r++) if (fixed_regs[r]) { fixed_regs[r] = 0; call_used_regs[r] = 1; - ++ switched; - } - else - { - fixed_regs[r] = 1; - call_used_regs[r] = 1; } - fixed_regs[14] = call_used_regs[14] = 1; - fixed_regs[15] = call_used_regs[15] = 1; - - if (switched == 0) - { - static bool warned = false; - - if (! warned) - { - warning (0, "no fixed registers available " - "for use by fast interrupt handler"); - warned = true; - } - } + /* Mark r7 as fixed. This is just a hack to avoid + altering the reg_alloc_order array so that the newly + freed r10-r13 registers are the preferred registers. */ + fixed_regs[7] = call_used_regs[7] = 1; } else { @@ -1017,6 +996,11 @@ bit_count (unsigned int x) return (x + (x >> 16)) & 0x3f; } +#define MUST_SAVE_ACC_REGISTER \ + (TARGET_SAVE_ACC_REGISTER \ + && (is_interrupt_func (NULL_TREE) \ + || is_fast_interrupt_func (NULL_TREE))) + /* Returns either the lowest numbered and highest numbered registers that occupy the call-saved area of the stack frame, if the registers are stored as a contiguous block, or else a bitmask of the individual @@ -1040,15 +1024,10 @@ rx_get_stack_layout (unsigned int * lowest, unsigned int pushed_mask; unsigned int unneeded_pushes; - if (is_naked_func (NULL_TREE) - || is_fast_interrupt_func (NULL_TREE)) + if (is_naked_func (NULL_TREE)) { /* Naked functions do not create their own stack frame. - Instead the programmer must do that for us. - - Fast interrupt handlers use fixed registers that have - been epsecially released to the function, so they do - not need or want a stack frame. */ + Instead the programmer must do that for us. */ * lowest = 0; * highest = 0; * register_mask = 0; @@ -1063,7 +1042,14 @@ rx_get_stack_layout (unsigned int * lowest, && (! call_used_regs[reg] /* Even call clobbered registered must be pushed inside interrupt handlers. */ - || is_interrupt_func (NULL_TREE))) + || is_interrupt_func (NULL_TREE) + /* Likewise for fast interrupt handlers, except registers r10 - + r13. These are normally call-saved, but may have been set + to call-used by rx_conditional_register_usage. If so then + they can be used in the fast interrupt handler without + saving them on the stack. */ + || (is_fast_interrupt_func (NULL_TREE) + && ! IN_RANGE (reg, 10, 13)))) { if (low == 0) low = reg; @@ -1078,6 +1064,18 @@ rx_get_stack_layout (unsigned int * lowest, fixed_reg = reg; } + /* If we have to save the accumulator register, make sure + that at least two registers are pushed into the frame. */ + if (MUST_SAVE_ACC_REGISTER + && bit_count (save_mask) < 2) + { + save_mask |= (1 << 13) | (1 << 14); + if (low == 0) + low = 13; + if (high == 0) + high = 14; + } + /* Decide if it would be faster fill in the call-saved area of the stack frame using multiple PUSH instructions instead of a single PUSHM instruction. @@ -1207,9 +1205,7 @@ rx_expand_prologue (void) rtx insn; /* Naked functions use their own, programmer provided prologues. */ - if (is_naked_func (NULL_TREE) - /* Fast interrupt functions never use the stack. */ - || is_fast_interrupt_func (NULL_TREE)) + if (is_naked_func (NULL_TREE)) return; rx_get_stack_layout (& low, & high, & mask, & frame_size, & stack_size); @@ -1236,13 +1232,13 @@ rx_expand_prologue (void) mark_frame_related (insn); } - if (is_interrupt_func (NULL_TREE) && TARGET_SAVE_ACC_REGISTER) + if (MUST_SAVE_ACC_REGISTER) { unsigned int acc_high, acc_low; /* Interrupt handlers have to preserve the accumulator register if so requested by the user. Use the first - two pushed register as intermediaries. */ + two pushed registers as intermediaries. */ if (mask) { acc_low = acc_high = 0; @@ -1510,7 +1506,7 @@ rx_expand_epilogue (bool is_sibcall) emit_insn (gen_addsi3 (stack_pointer_rtx, stack_pointer_rtx, GEN_INT (total_size))); - if (is_interrupt_func (NULL_TREE) && TARGET_SAVE_ACC_REGISTER) + if (MUST_SAVE_ACC_REGISTER) { unsigned int acc_low, acc_high; @@ -1901,6 +1897,9 @@ rx_expand_builtin_mvfc (tree t_arg, rtx target) if (! CONST_INT_P (arg)) return NULL_RTX; + if (target == NULL_RTX) + return NULL_RTX; + if (! REG_P (target)) target = force_reg (SImode, target); @@ -2135,7 +2134,7 @@ rx_func_attr_inlinable (const_tree decl) a function_decl or NULL if this is an indirect call, using EXP */ static bool -rx_function_ok_for_sibcall (tree decl, tree exp) +rx_function_ok_for_sibcall (tree decl, tree exp ATTRIBUTE_UNUSED) { /* Do not allow indirect tailcalls. The sibcall patterns do not support them. */