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