This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
ARM: Do not LDM instructions with writeback when loading the SP
- From: Nick Clifton <nickc at redhat dot com>
- To: gcc-patches at gcc dot gnu dot org
- Date: 17 Sep 2002 20:29:26 +0100
- Subject: ARM: Do not LDM instructions with writeback when loading the SP
Hi Guys,
I am applying the patch below to fix a small bug with ARM code
generation. Currently the compiler can generate an LDM instruction
in the function epilogue which loads the stack pointer and which
includes writeback to the stack pointer. The behavior of such an
instruction is UNPREDICTABLE, and although it works for some ARMs,
it definitely does not for the XScale.
Cheers
Nick
2002-09-17 Nick Clifton <nickc@redhat.com>
* config/arm/arm.c (output_return_instruction): Do not
writeback the stack pointer when it is being loaded.
(arm_output_epilogue): Likewise.
Index: config/arm/arm.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/arm/arm.c,v
retrieving revision 1.230
diff -c -3 -p -w -r1.230 arm.c
*** config/arm/arm.c 15 Sep 2002 18:24:03 -0000 1.230
--- config/arm/arm.c 17 Sep 2002 19:24:24 -0000
*************** output_return_instruction (operand, real
*** 7325,7330 ****
--- 7325,7332 ----
/* Generate the load multiple instruction to restore the registers. */
if (frame_pointer_needed)
sprintf (instr, "ldm%sea\t%%|fp, {", conditional);
+ else if (live_regs_mask & (1 << SP_REGNUM))
+ sprintf (instr, "ldm%sfd\t%%|sp, {", conditional);
else
sprintf (instr, "ldm%sfd\t%%|sp!, {", conditional);
*************** arm_output_epilogue (really_return)
*** 7736,7742 ****
--- 7738,7753 ----
asm_fprintf (f, "\tldr\t%r, [%r], #4\n", LR_REGNUM, SP_REGNUM);
}
else if (saved_regs_mask)
+ {
+ if (saved_regs_mask & (1 << SP_REGNUM))
+ /* Note - write back to the stack register is not enabled
+ (ie "ldmfd sp!..."). We know that the stack pointer is
+ in the list of registers and if we add writeback the
+ instruction becomes UNPREDICTABLE. */
+ print_multi_reg (f, "ldmfd\t%r", SP_REGNUM, saved_regs_mask);
+ else
print_multi_reg (f, "ldmfd\t%r!", SP_REGNUM, saved_regs_mask);
+ }
if (current_function_pretend_args_size)
{