yann@1: --- gcc-3.4.0/gcc/config/arm/arm.c.arm-ldm 2004-02-27 09:51:05.000000000 -0500 yann@1: +++ gcc-3.4.0/gcc/config/arm/arm.c 2004-04-24 18:16:25.000000000 -0400 yann@1: @@ -8520,6 +8520,26 @@ yann@1: return_used_this_function = 0; yann@1: } yann@1: yann@1: +/* Return the number (counting from 0) of yann@1: + the least significant set bit in MASK. */ yann@1: + yann@1: +#ifdef __GNUC__ yann@1: +inline yann@1: +#endif yann@1: +static int yann@1: +number_of_first_bit_set (mask) yann@1: + int mask; yann@1: +{ yann@1: + int bit; yann@1: + yann@1: + for (bit = 0; yann@1: + (mask & (1 << bit)) == 0; yann@1: + ++bit) yann@1: + continue; yann@1: + yann@1: + return bit; yann@1: +} yann@1: + yann@1: const char * yann@1: arm_output_epilogue (rtx sibling) yann@1: { yann@1: @@ -8753,27 +8773,47 @@ yann@1: saved_regs_mask |= (1 << PC_REGNUM); yann@1: } yann@1: yann@1: - /* Load the registers off the stack. If we only have one register yann@1: - to load use the LDR instruction - it is faster. */ yann@1: - if (saved_regs_mask == (1 << LR_REGNUM)) yann@1: - { yann@1: - /* The exception handler ignores the LR, so we do yann@1: - not really need to load it off the stack. */ yann@1: - if (eh_ofs) yann@1: - asm_fprintf (f, "\tadd\t%r, %r, #4\n", SP_REGNUM, SP_REGNUM); yann@1: - else yann@1: - asm_fprintf (f, "\tldr\t%r, [%r], #4\n", LR_REGNUM, SP_REGNUM); yann@1: - } yann@1: - else if (saved_regs_mask) yann@1: + if (saved_regs_mask) yann@1: { yann@1: - if (saved_regs_mask & (1 << SP_REGNUM)) yann@1: - /* Note - write back to the stack register is not enabled yann@1: - (ie "ldmfd sp!..."). We know that the stack pointer is yann@1: - in the list of registers and if we add writeback the yann@1: - instruction becomes UNPREDICTABLE. */ yann@1: - print_multi_reg (f, "ldmfd\t%r", SP_REGNUM, saved_regs_mask); yann@1: + /* Load the registers off the stack. If we only have one register yann@1: + to load use the LDR instruction - it is faster. */ yann@1: + if (bit_count (saved_regs_mask) == 1) yann@1: + { yann@1: + int reg = number_of_first_bit_set (saved_regs_mask); yann@1: + yann@1: + switch (reg) yann@1: + { yann@1: + case SP_REGNUM: yann@1: + /* Mustn't use base writeback when loading SP. */ yann@1: + asm_fprintf (f, "\tldr\t%r, [%r]\n", SP_REGNUM, SP_REGNUM); yann@1: + break; yann@1: + yann@1: + case LR_REGNUM: yann@1: + if (eh_ofs) yann@1: + { yann@1: + /* The exception handler ignores the LR, so we do yann@1: + not really need to load it off the stack. */ yann@1: + asm_fprintf (f, "\tadd\t%r, %r, #4\n", SP_REGNUM, SP_REGNUM); yann@1: + break; yann@1: + } yann@1: + /* else fall through */ yann@1: + yann@1: + default: yann@1: + asm_fprintf (f, "\tldr\t%r, [%r], #4\n", reg, SP_REGNUM); yann@1: + break; yann@1: + } yann@1: + } yann@1: else yann@1: - print_multi_reg (f, "ldmfd\t%r!", SP_REGNUM, saved_regs_mask); yann@1: + { yann@1: + if (saved_regs_mask & (1 << SP_REGNUM)) yann@1: + /* Note - write back to the stack register is not enabled yann@1: + (ie "ldmfd sp!..."). We know that the stack pointer is yann@1: + in the list of registers and if we add writeback the yann@1: + instruction becomes UNPREDICTABLE. */ yann@1: + print_multi_reg (f, "ldmfd\t%r", SP_REGNUM, saved_regs_mask); yann@1: + else yann@1: + print_multi_reg (f, "ldmfd\t%r!", SP_REGNUM, saved_regs_mask); yann@1: + } yann@1: } yann@1: yann@1: if (current_function_pretend_args_size) yann@1: @@ -11401,22 +11441,6 @@ yann@1: } yann@1: } yann@1: yann@1: -/* Return the number (counting from 0) of yann@1: - the least significant set bit in MASK. */ yann@1: - yann@1: -inline static int yann@1: -number_of_first_bit_set (int mask) yann@1: -{ yann@1: - int bit; yann@1: - yann@1: - for (bit = 0; yann@1: - (mask & (1 << bit)) == 0; yann@1: - ++bit) yann@1: - continue; yann@1: - yann@1: - return bit; yann@1: -} yann@1: - yann@1: /* Generate code to return from a thumb function. yann@1: If 'reg_containing_return_addr' is -1, then the return address is yann@1: actually on the stack, at the stack pointer. */