rx.c (rx_conditional_register_usage): Do not warn if no fixed registers are available for interrupt handlers.

* 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.

From-SVN: r154903
This commit is contained in:
Nick Clifton 2009-12-02 10:59:04 +00:00 committed by Nick Clifton
parent 57cdf653e3
commit dafcb54e42
2 changed files with 57 additions and 44 deletions

View File

@ -1,3 +1,17 @@
2009-12-02 Nick Clifton <nickc@redhat.com>
* 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 <sebastian.pop@amd.com>
* config/i386/abmintrin.h (__lzcnt16): New.

View File

@ -887,46 +887,25 @@ rx_conditional_register_usage (void)
if (use_fixed_regs)
{
unsigned int switched = 0;
unsigned int r;
memcpy (saved_fixed_regs, fixed_regs, sizeof fixed_regs);
memcpy (saved_call_used_regs, call_used_regs, sizeof call_used_regs);
/* 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;
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. */