yann@339
|
1 |
diff -durN gcc-3.4.6.orig/gcc/config/arm/arm.c gcc-3.4.6/gcc/config/arm/arm.c
|
yann@339
|
2 |
--- gcc-3.4.6.orig/gcc/config/arm/arm.c 2007-08-15 22:56:20.000000000 +0200
|
yann@339
|
3 |
+++ gcc-3.4.6/gcc/config/arm/arm.c 2007-08-15 22:56:20.000000000 +0200
|
yann@339
|
4 |
@@ -8524,6 +8524,26 @@
|
yann@339
|
5 |
return_used_this_function = 0;
|
yann@339
|
6 |
}
|
yann@339
|
7 |
|
yann@339
|
8 |
+/* Return the number (counting from 0) of
|
yann@339
|
9 |
+ the least significant set bit in MASK. */
|
yann@339
|
10 |
+
|
yann@339
|
11 |
+#ifdef __GNUC__
|
yann@339
|
12 |
+inline
|
yann@339
|
13 |
+#endif
|
yann@339
|
14 |
+static int
|
yann@339
|
15 |
+number_of_first_bit_set (mask)
|
yann@339
|
16 |
+ int mask;
|
yann@339
|
17 |
+{
|
yann@339
|
18 |
+ int bit;
|
yann@339
|
19 |
+
|
yann@339
|
20 |
+ for (bit = 0;
|
yann@339
|
21 |
+ (mask & (1 << bit)) == 0;
|
yann@339
|
22 |
+ ++bit)
|
yann@339
|
23 |
+ continue;
|
yann@339
|
24 |
+
|
yann@339
|
25 |
+ return bit;
|
yann@339
|
26 |
+}
|
yann@339
|
27 |
+
|
yann@339
|
28 |
const char *
|
yann@339
|
29 |
arm_output_epilogue (rtx sibling)
|
yann@339
|
30 |
{
|
yann@339
|
31 |
@@ -8757,27 +8777,47 @@
|
yann@339
|
32 |
saved_regs_mask |= (1 << PC_REGNUM);
|
yann@339
|
33 |
}
|
yann@339
|
34 |
|
yann@339
|
35 |
- /* Load the registers off the stack. If we only have one register
|
yann@339
|
36 |
- to load use the LDR instruction - it is faster. */
|
yann@339
|
37 |
- if (saved_regs_mask == (1 << LR_REGNUM))
|
yann@339
|
38 |
- {
|
yann@339
|
39 |
- /* The exception handler ignores the LR, so we do
|
yann@339
|
40 |
- not really need to load it off the stack. */
|
yann@339
|
41 |
- if (eh_ofs)
|
yann@339
|
42 |
- asm_fprintf (f, "\tadd\t%r, %r, #4\n", SP_REGNUM, SP_REGNUM);
|
yann@339
|
43 |
- else
|
yann@339
|
44 |
- asm_fprintf (f, "\tldr\t%r, [%r], #4\n", LR_REGNUM, SP_REGNUM);
|
yann@339
|
45 |
- }
|
yann@339
|
46 |
- else if (saved_regs_mask)
|
yann@339
|
47 |
+ if (saved_regs_mask)
|
yann@339
|
48 |
{
|
yann@339
|
49 |
- if (saved_regs_mask & (1 << SP_REGNUM))
|
yann@339
|
50 |
- /* Note - write back to the stack register is not enabled
|
yann@339
|
51 |
- (ie "ldmfd sp!..."). We know that the stack pointer is
|
yann@339
|
52 |
- in the list of registers and if we add writeback the
|
yann@339
|
53 |
- instruction becomes UNPREDICTABLE. */
|
yann@339
|
54 |
- print_multi_reg (f, "ldmfd\t%r", SP_REGNUM, saved_regs_mask);
|
yann@339
|
55 |
+ /* Load the registers off the stack. If we only have one register
|
yann@339
|
56 |
+ to load use the LDR instruction - it is faster. */
|
yann@339
|
57 |
+ if (bit_count (saved_regs_mask) == 1)
|
yann@339
|
58 |
+ {
|
yann@339
|
59 |
+ int reg = number_of_first_bit_set (saved_regs_mask);
|
yann@339
|
60 |
+
|
yann@339
|
61 |
+ switch (reg)
|
yann@339
|
62 |
+ {
|
yann@339
|
63 |
+ case SP_REGNUM:
|
yann@339
|
64 |
+ /* Mustn't use base writeback when loading SP. */
|
yann@339
|
65 |
+ asm_fprintf (f, "\tldr\t%r, [%r]\n", SP_REGNUM, SP_REGNUM);
|
yann@339
|
66 |
+ break;
|
yann@339
|
67 |
+
|
yann@339
|
68 |
+ case LR_REGNUM:
|
yann@339
|
69 |
+ if (eh_ofs)
|
yann@339
|
70 |
+ {
|
yann@339
|
71 |
+ /* The exception handler ignores the LR, so we do
|
yann@339
|
72 |
+ not really need to load it off the stack. */
|
yann@339
|
73 |
+ asm_fprintf (f, "\tadd\t%r, %r, #4\n", SP_REGNUM, SP_REGNUM);
|
yann@339
|
74 |
+ break;
|
yann@339
|
75 |
+ }
|
yann@339
|
76 |
+ /* else fall through */
|
yann@339
|
77 |
+
|
yann@339
|
78 |
+ default:
|
yann@339
|
79 |
+ asm_fprintf (f, "\tldr\t%r, [%r], #4\n", reg, SP_REGNUM);
|
yann@339
|
80 |
+ break;
|
yann@339
|
81 |
+ }
|
yann@339
|
82 |
+ }
|
yann@339
|
83 |
else
|
yann@339
|
84 |
- print_multi_reg (f, "ldmfd\t%r!", SP_REGNUM, saved_regs_mask);
|
yann@339
|
85 |
+ {
|
yann@339
|
86 |
+ if (saved_regs_mask & (1 << SP_REGNUM))
|
yann@339
|
87 |
+ /* Note - write back to the stack register is not enabled
|
yann@339
|
88 |
+ (ie "ldmfd sp!..."). We know that the stack pointer is
|
yann@339
|
89 |
+ in the list of registers and if we add writeback the
|
yann@339
|
90 |
+ instruction becomes UNPREDICTABLE. */
|
yann@339
|
91 |
+ print_multi_reg (f, "ldmfd\t%r", SP_REGNUM, saved_regs_mask);
|
yann@339
|
92 |
+ else
|
yann@339
|
93 |
+ print_multi_reg (f, "ldmfd\t%r!", SP_REGNUM, saved_regs_mask);
|
yann@339
|
94 |
+ }
|
yann@339
|
95 |
}
|
yann@339
|
96 |
|
yann@339
|
97 |
if (current_function_pretend_args_size)
|
yann@339
|
98 |
@@ -11405,22 +11445,6 @@
|
yann@339
|
99 |
}
|
yann@339
|
100 |
}
|
yann@339
|
101 |
|
yann@339
|
102 |
-/* Return the number (counting from 0) of
|
yann@339
|
103 |
- the least significant set bit in MASK. */
|
yann@339
|
104 |
-
|
yann@339
|
105 |
-inline static int
|
yann@339
|
106 |
-number_of_first_bit_set (int mask)
|
yann@339
|
107 |
-{
|
yann@339
|
108 |
- int bit;
|
yann@339
|
109 |
-
|
yann@339
|
110 |
- for (bit = 0;
|
yann@339
|
111 |
- (mask & (1 << bit)) == 0;
|
yann@339
|
112 |
- ++bit)
|
yann@339
|
113 |
- continue;
|
yann@339
|
114 |
-
|
yann@339
|
115 |
- return bit;
|
yann@339
|
116 |
-}
|
yann@339
|
117 |
-
|
yann@339
|
118 |
/* Generate code to return from a thumb function.
|
yann@339
|
119 |
If 'reg_containing_return_addr' is -1, then the return address is
|
yann@339
|
120 |
actually on the stack, at the stack pointer. */
|