mirror of
https://github.com/crosstool-ng/crosstool-ng.git
synced 2024-12-25 15:31:05 +00:00
121 lines
3.4 KiB
Diff
121 lines
3.4 KiB
Diff
diff -durN gcc-3.4.6.orig/gcc/config/arm/arm.c gcc-3.4.6/gcc/config/arm/arm.c
|
|
--- gcc-3.4.6.orig/gcc/config/arm/arm.c 2007-08-15 22:56:20.000000000 +0200
|
|
+++ gcc-3.4.6/gcc/config/arm/arm.c 2007-08-15 22:56:20.000000000 +0200
|
|
@@ -8524,6 +8524,26 @@
|
|
return_used_this_function = 0;
|
|
}
|
|
|
|
+/* Return the number (counting from 0) of
|
|
+ the least significant set bit in MASK. */
|
|
+
|
|
+#ifdef __GNUC__
|
|
+inline
|
|
+#endif
|
|
+static int
|
|
+number_of_first_bit_set (mask)
|
|
+ int mask;
|
|
+{
|
|
+ int bit;
|
|
+
|
|
+ for (bit = 0;
|
|
+ (mask & (1 << bit)) == 0;
|
|
+ ++bit)
|
|
+ continue;
|
|
+
|
|
+ return bit;
|
|
+}
|
|
+
|
|
const char *
|
|
arm_output_epilogue (rtx sibling)
|
|
{
|
|
@@ -8757,27 +8777,47 @@
|
|
saved_regs_mask |= (1 << PC_REGNUM);
|
|
}
|
|
|
|
- /* Load the registers off the stack. If we only have one register
|
|
- to load use the LDR instruction - it is faster. */
|
|
- if (saved_regs_mask == (1 << LR_REGNUM))
|
|
- {
|
|
- /* The exception handler ignores the LR, so we do
|
|
- not really need to load it off the stack. */
|
|
- if (eh_ofs)
|
|
- asm_fprintf (f, "\tadd\t%r, %r, #4\n", SP_REGNUM, SP_REGNUM);
|
|
- else
|
|
- asm_fprintf (f, "\tldr\t%r, [%r], #4\n", LR_REGNUM, SP_REGNUM);
|
|
- }
|
|
- else if (saved_regs_mask)
|
|
+ if (saved_regs_mask)
|
|
{
|
|
- if (saved_regs_mask & (1 << SP_REGNUM))
|
|
- /* Note - write back to the stack register is not enabled
|
|
- (ie "ldmfd sp!..."). We know that the stack pointer is
|
|
- in the list of registers and if we add writeback the
|
|
- instruction becomes UNPREDICTABLE. */
|
|
- print_multi_reg (f, "ldmfd\t%r", SP_REGNUM, saved_regs_mask);
|
|
+ /* Load the registers off the stack. If we only have one register
|
|
+ to load use the LDR instruction - it is faster. */
|
|
+ if (bit_count (saved_regs_mask) == 1)
|
|
+ {
|
|
+ int reg = number_of_first_bit_set (saved_regs_mask);
|
|
+
|
|
+ switch (reg)
|
|
+ {
|
|
+ case SP_REGNUM:
|
|
+ /* Mustn't use base writeback when loading SP. */
|
|
+ asm_fprintf (f, "\tldr\t%r, [%r]\n", SP_REGNUM, SP_REGNUM);
|
|
+ break;
|
|
+
|
|
+ case LR_REGNUM:
|
|
+ if (eh_ofs)
|
|
+ {
|
|
+ /* The exception handler ignores the LR, so we do
|
|
+ not really need to load it off the stack. */
|
|
+ asm_fprintf (f, "\tadd\t%r, %r, #4\n", SP_REGNUM, SP_REGNUM);
|
|
+ break;
|
|
+ }
|
|
+ /* else fall through */
|
|
+
|
|
+ default:
|
|
+ asm_fprintf (f, "\tldr\t%r, [%r], #4\n", reg, SP_REGNUM);
|
|
+ break;
|
|
+ }
|
|
+ }
|
|
else
|
|
- print_multi_reg (f, "ldmfd\t%r!", SP_REGNUM, saved_regs_mask);
|
|
+ {
|
|
+ if (saved_regs_mask & (1 << SP_REGNUM))
|
|
+ /* Note - write back to the stack register is not enabled
|
|
+ (ie "ldmfd sp!..."). We know that the stack pointer is
|
|
+ in the list of registers and if we add writeback the
|
|
+ instruction becomes UNPREDICTABLE. */
|
|
+ print_multi_reg (f, "ldmfd\t%r", SP_REGNUM, saved_regs_mask);
|
|
+ else
|
|
+ print_multi_reg (f, "ldmfd\t%r!", SP_REGNUM, saved_regs_mask);
|
|
+ }
|
|
}
|
|
|
|
if (current_function_pretend_args_size)
|
|
@@ -11405,22 +11445,6 @@
|
|
}
|
|
}
|
|
|
|
-/* Return the number (counting from 0) of
|
|
- the least significant set bit in MASK. */
|
|
-
|
|
-inline static int
|
|
-number_of_first_bit_set (int mask)
|
|
-{
|
|
- int bit;
|
|
-
|
|
- for (bit = 0;
|
|
- (mask & (1 << bit)) == 0;
|
|
- ++bit)
|
|
- continue;
|
|
-
|
|
- return bit;
|
|
-}
|
|
-
|
|
/* Generate code to return from a thumb function.
|
|
If 'reg_containing_return_addr' is -1, then the return address is
|
|
actually on the stack, at the stack pointer. */
|