149 lines
3.9 KiB
Plaintext
149 lines
3.9 KiB
Plaintext
#! /bin/sh -e
|
|
|
|
src=gcc
|
|
if [ $# -eq 3 -a "$2" = '-d' ]; then
|
|
pdir="-d $3"
|
|
src=$3/gcc
|
|
elif [ $# -ne 1 ]; then
|
|
echo >&2 "`basename $0`: script expects -patch|-unpatch as argument"
|
|
exit 1
|
|
fi
|
|
case "$1" in
|
|
-patch)
|
|
patch $pdir -f --no-backup-if-mismatch -p0 --fuzz 10 < $0
|
|
;;
|
|
-unpatch)
|
|
patch $pdir -f --no-backup-if-mismatch -R -p0 --fuzz 10 < $0
|
|
;;
|
|
*)
|
|
echo >&2 "`basename $0`: script expects -patch|-unpatch as argument"
|
|
exit 1
|
|
esac
|
|
exit 0
|
|
|
|
# DP: try harder to avoid ldm in function epilogues
|
|
|
|
--- gcc/config/arm/arm.c Fri Mar 5 18:49:42 2004
|
|
+++ gcc/config/arm/arm.c Fri Mar 5 16:00:21 2004
|
|
@@ -7598,6 +7629,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 (really_return)
|
|
int really_return;
|
|
@@ -7788,27 +7839,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)
|
|
@@ -9610,26 +9677,6 @@
|
|
}
|
|
}
|
|
|
|
-/* 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;
|
|
-}
|
|
-
|
|
/* 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. */
|