If a function is both a leaf function and an interrupt function, leaf register renumbering causes the wrong set of registers to be saved. This patch disables renumbering for interrupt functions.
* config/rx/rx.c (rx_leaf_registers): New. (rx_set_leaf_registers): New. (rx_expand_prologue): Call it. * config/rx/rx.h (LEAF_REGISTERS): Define. (LEAF_REG_REMAP): Define. Index: gcc/config/rx/rx.c =================================================================== --- gcc/config/rx/rx.c (revision 176766) +++ gcc/config/rx/rx.c (working copy) @@ -985,12 +985,24 @@ is_naked_func (const_tree decl) { return has_func_attr (decl, "naked"); } static bool use_fixed_regs = false; +char rx_leaf_registers [FIRST_PSEUDO_REGISTER]; + +static void +rx_set_leaf_registers (int enable) +{ + int i; + + if (rx_leaf_registers[0] != enable) + for (i = 0; i < FIRST_PSEUDO_REGISTER; i++) + rx_leaf_registers[i] = enable; +} + static void rx_conditional_register_usage (void) { static bool using_fixed_regs = false; if (rx_small_data_limit > 0) @@ -1380,12 +1392,17 @@ rx_expand_prologue (void) rtx insn; /* Naked functions use their own, programmer provided prologues. */ if (is_naked_func (NULL_TREE)) return; + /* We must not allow register renaming in interrupt functions, + because that invalidates the correctness of the set of call-used + registers we're going to save/restore. */ + rx_set_leaf_registers (is_interrupt_func (NULL_TREE) ? 0 : 1); + rx_get_stack_layout (& low, & high, & mask, & frame_size, & stack_size); /* If we use any of the callee-saved registers, save them now. */ if (mask) { /* Push registers in reverse order. */ Index: gcc/config/rx/rx.h =================================================================== --- gcc/config/rx/rx.h (revision 176766) +++ gcc/config/rx/rx.h (working copy) @@ -260,12 +260,17 @@ enum reg_class /* Order of allocation of registers. */ #define REG_ALLOC_ORDER \ { 7, 10, 11, 12, 13, 14, 4, 3, 2, 1, 9, 8, 6, 5, 15 \ } +/* We must somehow disable register remapping for interrupt functions. */ +extern char rx_leaf_registers[]; +#define LEAF_REGISTERS rx_leaf_registers +#define LEAF_REG_REMAP(REG) (REG) + #define REGNO_IN_RANGE(REGNO, MIN, MAX) \ (IN_RANGE ((REGNO), (MIN), (MAX)) \ || (reg_renumber != NULL \ && reg_renumber[(REGNO)] >= (MIN) \ && reg_renumber[(REGNO)] <= (MAX)))