1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1.2 +++ b/patches/gcc/3.4.6/150-arm-ldm.patch Wed May 19 18:22:32 2010 +0200
1.3 @@ -0,0 +1,120 @@
1.4 +diff -durN gcc-3.4.6.orig/gcc/config/arm/arm.c gcc-3.4.6/gcc/config/arm/arm.c
1.5 +--- gcc-3.4.6.orig/gcc/config/arm/arm.c 2007-08-15 22:56:20.000000000 +0200
1.6 ++++ gcc-3.4.6/gcc/config/arm/arm.c 2007-08-15 22:56:20.000000000 +0200
1.7 +@@ -8524,6 +8524,26 @@
1.8 + return_used_this_function = 0;
1.9 + }
1.10 +
1.11 ++/* Return the number (counting from 0) of
1.12 ++ the least significant set bit in MASK. */
1.13 ++
1.14 ++#ifdef __GNUC__
1.15 ++inline
1.16 ++#endif
1.17 ++static int
1.18 ++number_of_first_bit_set (mask)
1.19 ++ int mask;
1.20 ++{
1.21 ++ int bit;
1.22 ++
1.23 ++ for (bit = 0;
1.24 ++ (mask & (1 << bit)) == 0;
1.25 ++ ++bit)
1.26 ++ continue;
1.27 ++
1.28 ++ return bit;
1.29 ++}
1.30 ++
1.31 + const char *
1.32 + arm_output_epilogue (rtx sibling)
1.33 + {
1.34 +@@ -8757,27 +8777,47 @@
1.35 + saved_regs_mask |= (1 << PC_REGNUM);
1.36 + }
1.37 +
1.38 +- /* Load the registers off the stack. If we only have one register
1.39 +- to load use the LDR instruction - it is faster. */
1.40 +- if (saved_regs_mask == (1 << LR_REGNUM))
1.41 +- {
1.42 +- /* The exception handler ignores the LR, so we do
1.43 +- not really need to load it off the stack. */
1.44 +- if (eh_ofs)
1.45 +- asm_fprintf (f, "\tadd\t%r, %r, #4\n", SP_REGNUM, SP_REGNUM);
1.46 +- else
1.47 +- asm_fprintf (f, "\tldr\t%r, [%r], #4\n", LR_REGNUM, SP_REGNUM);
1.48 +- }
1.49 +- else if (saved_regs_mask)
1.50 ++ if (saved_regs_mask)
1.51 + {
1.52 +- if (saved_regs_mask & (1 << SP_REGNUM))
1.53 +- /* Note - write back to the stack register is not enabled
1.54 +- (ie "ldmfd sp!..."). We know that the stack pointer is
1.55 +- in the list of registers and if we add writeback the
1.56 +- instruction becomes UNPREDICTABLE. */
1.57 +- print_multi_reg (f, "ldmfd\t%r", SP_REGNUM, saved_regs_mask);
1.58 ++ /* Load the registers off the stack. If we only have one register
1.59 ++ to load use the LDR instruction - it is faster. */
1.60 ++ if (bit_count (saved_regs_mask) == 1)
1.61 ++ {
1.62 ++ int reg = number_of_first_bit_set (saved_regs_mask);
1.63 ++
1.64 ++ switch (reg)
1.65 ++ {
1.66 ++ case SP_REGNUM:
1.67 ++ /* Mustn't use base writeback when loading SP. */
1.68 ++ asm_fprintf (f, "\tldr\t%r, [%r]\n", SP_REGNUM, SP_REGNUM);
1.69 ++ break;
1.70 ++
1.71 ++ case LR_REGNUM:
1.72 ++ if (eh_ofs)
1.73 ++ {
1.74 ++ /* The exception handler ignores the LR, so we do
1.75 ++ not really need to load it off the stack. */
1.76 ++ asm_fprintf (f, "\tadd\t%r, %r, #4\n", SP_REGNUM, SP_REGNUM);
1.77 ++ break;
1.78 ++ }
1.79 ++ /* else fall through */
1.80 ++
1.81 ++ default:
1.82 ++ asm_fprintf (f, "\tldr\t%r, [%r], #4\n", reg, SP_REGNUM);
1.83 ++ break;
1.84 ++ }
1.85 ++ }
1.86 + else
1.87 +- print_multi_reg (f, "ldmfd\t%r!", SP_REGNUM, saved_regs_mask);
1.88 ++ {
1.89 ++ if (saved_regs_mask & (1 << SP_REGNUM))
1.90 ++ /* Note - write back to the stack register is not enabled
1.91 ++ (ie "ldmfd sp!..."). We know that the stack pointer is
1.92 ++ in the list of registers and if we add writeback the
1.93 ++ instruction becomes UNPREDICTABLE. */
1.94 ++ print_multi_reg (f, "ldmfd\t%r", SP_REGNUM, saved_regs_mask);
1.95 ++ else
1.96 ++ print_multi_reg (f, "ldmfd\t%r!", SP_REGNUM, saved_regs_mask);
1.97 ++ }
1.98 + }
1.99 +
1.100 + if (current_function_pretend_args_size)
1.101 +@@ -11405,22 +11445,6 @@
1.102 + }
1.103 + }
1.104 +
1.105 +-/* Return the number (counting from 0) of
1.106 +- the least significant set bit in MASK. */
1.107 +-
1.108 +-inline static int
1.109 +-number_of_first_bit_set (int mask)
1.110 +-{
1.111 +- int bit;
1.112 +-
1.113 +- for (bit = 0;
1.114 +- (mask & (1 << bit)) == 0;
1.115 +- ++bit)
1.116 +- continue;
1.117 +-
1.118 +- return bit;
1.119 +-}
1.120 +-
1.121 + /* Generate code to return from a thumb function.
1.122 + If 'reg_containing_return_addr' is -1, then the return address is
1.123 + actually on the stack, at the stack pointer. */