diff options
author | Richard Earnshaw <rearnsha@arm.com> | 2003-10-17 14:45:47 +0000 |
---|---|---|
committer | Nathan Sidwell <nathan@gcc.gnu.org> | 2003-10-17 14:45:47 +0000 |
commit | efc2515b4913b2b8870b041475542277520aa002 (patch) | |
tree | 431e646419600f7ff50a09192331f97028048699 | |
parent | 51a785a03619403e4dec65d83553edb5bdff0f75 (diff) | |
download | gcc-efc2515b4913b2b8870b041475542277520aa002.zip gcc-efc2515b4913b2b8870b041475542277520aa002.tar.gz gcc-efc2515b4913b2b8870b041475542277520aa002.tar.bz2 |
arm.c (use_return_insn): Not a single instruction, if there's a frame pointer.
* config/arm/arm.c (use_return_insn): Not a single instruction, if
there's a frame pointer.
(arm_output_epilogue): Protect stack pointer from being corrupted
on interrupt.
Co-Authored-By: Nathan Sidwell <nathan@codesourcery.com>
From-SVN: r72606
-rw-r--r-- | gcc/ChangeLog | 8 | ||||
-rw-r--r-- | gcc/config/arm/arm.c | 20 |
2 files changed, 25 insertions, 3 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 2b8fc81..912074a 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,11 @@ +2003-10-17 Richard Earnshaw <rearnsha@arm.com> + Nathan Sidwell <nathan@codesourcery.com> + + * config/arm/arm.c (use_return_insn): Not a single instruction, if + there's a frame pointer. + (arm_output_epilogue): Protect stack pointer from being corrupted + on interrupt. + 2003-10-17 Ulrich Weigand <uweigand@de.ibm.com> * ifcvt.c (noce_try_addcc): Handle ifs with 'else' case. diff --git a/gcc/config/arm/arm.c b/gcc/config/arm/arm.c index dc8c536..70ea4cd 100644 --- a/gcc/config/arm/arm.c +++ b/gcc/config/arm/arm.c @@ -986,7 +986,11 @@ use_return_insn (int iscond) /* Never use a return instruction before reload has run. */ if (!reload_completed) return 0; - + + /* We need two instructions when there's a frame pointer. */ + if (frame_pointer_needed) + return 0; + func_type = arm_current_func_type (); /* Naked functions and volatile functions need special @@ -8500,8 +8504,18 @@ arm_output_epilogue (int really_return) saved_regs_mask &= ~ (1 << LR_REGNUM); else saved_regs_mask &= ~ (1 << PC_REGNUM); - - print_multi_reg (f, "ldmea\t%r", FP_REGNUM, saved_regs_mask); + + /* We must use SP as the base register, because SP is one of the + registers being restored. If an interrupt or page fault + happens in the ldm instruction, the SP might or might not + have been restored. That would be bad, as then SP will no + longer indicate the safe area of stack, and we can get stack + corruption. Using SP as the base register means that it will + be reset correctly to the original value, should an interrupt + occur. */ + asm_fprintf (f, "\tsub\t%r,%r,#%d\n", SP_REGNUM, FP_REGNUM, + 4 * bit_count (saved_regs_mask)); + print_multi_reg (f, "ldmfd\t%r", SP_REGNUM, saved_regs_mask); if (IS_INTERRUPT (func_type)) /* Interrupt handlers will have pushed the |