This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
arm-pe: Do not generate type 2 LDM instructions with writeback
- From: Nick Clifton <nickc at redhat dot com>
- To: gcc-patches at gcc dot gnu dot org
- Date: 13 Mar 2003 12:02:10 +0000
- Subject: arm-pe: Do not generate type 2 LDM instructions with writeback
Hi Guys,
Whilst looking over the arm-pe port I found that it was generating
LDM instructions using writeback "sp!" and CPSR update "^" which is
UNPREDICTABLE if the PC is not one of the registers being loaded.
The following patch takes care of this problem and fixes quite a few
unexpected failures in the gcc testsuite. (There are still lots
more that need to be looked at though - maybe one day).
Cheers
Nick
PS. Sorry Richard - this patch adds more code :-(
2003-03-13 Nick Clifton <nickc at redhat dot com>
* config/arm/arm.c (print_multi_reg): Do not generate a type 2
LDM instructions with writeback enabled.
(output_return_instruction): Likewise.
Index: gcc/config/arm/arm.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/arm/arm.c,v
retrieving revision 1.265
diff -c -3 -p -w -r1.265 arm.c
*** gcc/config/arm/arm.c 10 Mar 2003 17:53:18 -0000 1.265
--- gcc/config/arm/arm.c 13 Mar 2003 11:55:55 -0000
*************** print_multi_reg (stream, instr, reg, mas
*** 7204,7210 ****
not_first = TRUE;
}
! fprintf (stream, "}%s\n", TARGET_APCS_32 ? "" : "^");
}
/* Output a 'call' insn. */
--- 7204,7220 ----
not_first = TRUE;
}
! fprintf (stream, "}");
!
! /* Add a ^ character for the 26-bit ABI, but only if we were loading
! the PC or not updating the stack pointer. Otherwise we generate
! an UNPREDICTABLE instruction. */
! if (! TARGET_APCS_32
! && (((mask & (1 << PC_REGNUM)) != 0)
! || strchr (instr, '!') == NULL))
! fprintf (stream, "^");
!
! fprintf (stream, "\n");
}
/* Output a 'call' insn. */
*************** output_return_instruction (operand, real
*** 8210,8229 ****
if (live_regs_mask & (1 << LR_REGNUM))
{
! int l = strlen (return_reg);
!
! if (! first)
! {
! memcpy (p, ", ", 2);
! p += 2;
! }
!
! memcpy (p, "%|", 2);
! memcpy (p + 2, return_reg, l);
! strcpy (p + 2 + l, ((TARGET_APCS_32
! && !IS_INTERRUPT (func_type))
! || !really_return)
! ? "}" : "}^");
}
else
strcpy (p, "}");
--- 8220,8245 ----
if (live_regs_mask & (1 << LR_REGNUM))
{
! sprintf (p, "%s%%|%s}", first ? "" : ", ", return_reg);
! /* Decide if we need to add the ^ symbol to the end of the
! register list. This causes the saved condition codes
! register to be copied into the current condition codes
! register. We do the copy if we are conforming to the 32-bit
! ABI and this is an interrupt function, or if we are
! conforming to the 26-bit ABI. There is a special case for
! the 26-bit ABI however, which is if we are writing back the
! stack pointer but not loading the PC. In this case adding
! the ^ symbol would create a type 2 LDM instruction, where
! writeback is UNPREDICTABLE. We are safe in leaving the ^
! character off in this case however, since the actual return
! instruction will be a MOVS which will restore the CPSR. */
! if ((TARGET_APCS_32 && IS_INTERRUPT (func_type))
! || (really_return
! && ! frame_pointer_needed
! && ((live_regs_mask & (1 << SP_REGNUM)) == 0)
! && ((live_regs_mask & (1 << PC_REGNUM)) == 0))
! )
! strcat (p, "^");
}
else
strcpy (p, "}");