This patch updates ldm_stm_operation_p to check for loads that if SP is in
the register list, then the base register is SP. It guarantees that SP is
reset correctly when an LDM instruction is interrupted. Otherwise, we might
end up with a corrupt stack. 

ChangeLog:

gcc

2012-05-31  Greta Yorsh  <greta.yo...@arm.com>

        * config/arm/arm.c (ldm_stm_operation_p): Require SP
      as base register for loads if SP is in the register list.
diff --git a/gcc/config/arm/arm.c b/gcc/config/arm/arm.c
index e3290e2..4717725 100644
--- a/gcc/config/arm/arm.c
+++ b/gcc/config/arm/arm.c
@@ -10247,6 +10247,12 @@ ldm_stm_operation_p (rtx op, bool load, enum 
machine_mode mode,
   if (!REG_P (addr))
     return false;
 
+  /* Don't allow SP to be loaded unless it is also the base register. It
+     guarantees that SP is reset correctly when an LDM instruction
+     is interruptted. Otherwise, we might end up with a corrupt stack.  */
+  if (load && (REGNO (reg) == SP_REGNUM) && (REGNO (addr) != SP_REGNUM))
+    return false;
+
   for (; i < count; i++)
     {
       elt = XVECEXP (op, 0, i);
@@ -10270,6 +10276,10 @@ ldm_stm_operation_p (rtx op, bool load, enum 
machine_mode mode,
           || (consecutive
               && (REGNO (reg) !=
                   (unsigned int) (first_regno + regs_per_val * (i - base))))
+          /* Don't allow SP to be loaded unless it is also the base register. 
It
+             guarantees that SP is reset correctly when an LDM instruction
+             is interrupted. Otherwise, we might end up with a corrupt stack.  
*/
+          || (load && (REGNO (reg) == SP_REGNUM) && (REGNO (addr) != 
SP_REGNUM))
           || !MEM_P (mem)
           || GET_MODE (mem) != mode
           || ((GET_CODE (XEXP (mem, 0)) != PLUS

Reply via email to