This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

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)
  	{


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]