aboutsummaryrefslogtreecommitdiff
path: root/gcc/config/arm/arm.c
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/config/arm/arm.c')
-rw-r--r--gcc/config/arm/arm.c28
1 files changed, 19 insertions, 9 deletions
diff --git a/gcc/config/arm/arm.c b/gcc/config/arm/arm.c
index 768678d..b70e68b 100644
--- a/gcc/config/arm/arm.c
+++ b/gcc/config/arm/arm.c
@@ -8260,15 +8260,25 @@ output_return_instruction (rtx operand, int really_return, int reverse)
return_reg = reg_names[LR_REGNUM];
if ((live_regs_mask & (1 << IP_REGNUM)) == (1 << IP_REGNUM))
- /* There are two possible reasons for the IP register being saved.
- Either a stack frame was created, in which case IP contains the
- old stack pointer, or an ISR routine corrupted it. If this in an
- ISR routine then just restore IP, otherwise restore IP into SP. */
- if (! IS_INTERRUPT (func_type))
- {
- live_regs_mask &= ~ (1 << IP_REGNUM);
- live_regs_mask |= (1 << SP_REGNUM);
- }
+ {
+ /* There are three possible reasons for the IP register
+ being saved. 1) a stack frame was created, in which case
+ IP contains the old stack pointer, or 2) an ISR routine
+ corrupted it, or 3) it was saved to align the stack on
+ iWMMXt. In case 1, restore IP into SP, otherwise just
+ restore IP. */
+ if (frame_pointer_needed)
+ {
+ live_regs_mask &= ~ (1 << IP_REGNUM);
+ live_regs_mask |= (1 << SP_REGNUM);
+ }
+ else
+ {
+ if (! IS_INTERRUPT (func_type)
+ && ! TARGET_REALLY_IWMMXT)
+ abort ();
+ }
+ }
/* On some ARM architectures it is faster to use LDR rather than
LDM to load a single register. On other architectures, the