diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 8355d02452b..e68309da96a 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,8 @@ +2012-06-18 Greta Yorsh + + * config/arm/arm.c (ldm_stm_operation_p): Require SP + as base register for loads if SP is in the register list. + 2012-06-18 Richard Guenther PR tree-optimization/53693 diff --git a/gcc/config/arm/arm.c b/gcc/config/arm/arm.c index bb04392cec3..d00849cb0ad 100644 --- a/gcc/config/arm/arm.c +++ b/gcc/config/arm/arm.c @@ -10080,6 +10080,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); @@ -10103,6 +10109,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