aboutsummaryrefslogtreecommitdiff
path: root/gcc/config/arm
diff options
context:
space:
mode:
authorPaul Brook <paul@codesourcery.com>2008-11-13 15:19:02 +0000
committerPaul Brook <pbrook@gcc.gnu.org>2008-11-13 15:19:02 +0000
commit5fd424238b25fd8ff6ac403ef923bdce2b2b2347 (patch)
treec0fb255f1910301b63c8be710bb26c06656095ad /gcc/config/arm
parent255e5b0481a06f5fb7cf41c8b1d511cf506b943f (diff)
downloadgcc-5fd424238b25fd8ff6ac403ef923bdce2b2b2347.zip
gcc-5fd424238b25fd8ff6ac403ef923bdce2b2b2347.tar.gz
gcc-5fd424238b25fd8ff6ac403ef923bdce2b2b2347.tar.bz2
invoke.texi: Document --fix-cortex-m3.
2008-11-13 Paul Brook <paul@codesourcery.com> gcc/ * doc/invoke.texi: Document --fix-cortex-m3. * config/arm/arm.c (arm_override_options): Set fix_cm3_ldrd if Cortex-M3 cpu is selected. (output_move_double): Avoid overlapping base register and first destination register when fix_cm3_ldrd. * config/arm/arm.opt: Add mfix-cortex-m3-ldrd. From-SVN: r141822
Diffstat (limited to 'gcc/config/arm')
-rw-r--r--gcc/config/arm/arm.c70
-rw-r--r--gcc/config/arm/arm.opt7
2 files changed, 55 insertions, 22 deletions
diff --git a/gcc/config/arm/arm.c b/gcc/config/arm/arm.c
index aeb0e53..a1cef0b 100644
--- a/gcc/config/arm/arm.c
+++ b/gcc/config/arm/arm.c
@@ -1037,6 +1037,7 @@ arm_override_options (void)
{
unsigned i;
enum processor_type target_arch_cpu = arm_none;
+ enum processor_type selected_cpu = arm_none;
/* Set up the flags based on the cpu/architecture selected by the user. */
for (i = ARRAY_SIZE (arm_select); i--;)
@@ -1069,6 +1070,9 @@ arm_override_options (void)
if (i == ARM_OPT_SET_ARCH)
target_arch_cpu = sel->core;
+ if (i == ARM_OPT_SET_CPU)
+ selected_cpu = (enum processor_type) (sel - ptr->processors);
+
if (i != ARM_OPT_SET_TUNE)
{
/* If we have been given an architecture and a processor
@@ -1099,21 +1103,20 @@ arm_override_options (void)
{
const struct processors * sel;
unsigned int sought;
- enum processor_type cpu;
- cpu = TARGET_CPU_DEFAULT;
- if (cpu == arm_none)
+ selected_cpu = TARGET_CPU_DEFAULT;
+ if (selected_cpu == arm_none)
{
#ifdef SUBTARGET_CPU_DEFAULT
/* Use the subtarget default CPU if none was specified by
configure. */
- cpu = SUBTARGET_CPU_DEFAULT;
+ selected_cpu = SUBTARGET_CPU_DEFAULT;
#endif
/* Default to ARM6. */
- if (cpu == arm_none)
- cpu = arm6;
+ if (selected_cpu == arm_none)
+ selected_cpu = arm6;
}
- sel = &all_cores[cpu];
+ sel = &all_cores[selected_cpu];
insn_flags = sel->flags;
@@ -1505,6 +1508,15 @@ arm_override_options (void)
arm_pic_register = pic_register;
}
+ /* Enable -mfix-cortex-m3-ldrd by default for Cortex-M3 cores. */
+ if (fix_cm3_ldrd == 2)
+ {
+ if (selected_cpu == cortexm3)
+ fix_cm3_ldrd = 1;
+ else
+ fix_cm3_ldrd = 0;
+ }
+
/* ??? We might want scheduling for thumb2. */
if (TARGET_THUMB && flag_schedule_insns)
{
@@ -9978,7 +9990,8 @@ output_move_double (rtx *operands)
switch (GET_CODE (XEXP (operands[1], 0)))
{
case REG:
- if (TARGET_LDRD)
+ if (TARGET_LDRD
+ && !(fix_cm3_ldrd && reg0 == REGNO(XEXP (operands[1], 0))))
output_asm_insn ("ldr%(d%)\t%0, [%m1]", operands);
else
output_asm_insn ("ldm%(ia%)\t%m1, %M0", operands);
@@ -10010,6 +10023,10 @@ output_move_double (rtx *operands)
case PRE_MODIFY:
case POST_MODIFY:
+ /* Autoicrement addressing modes should never have overlapping
+ base and destination registers, and overlapping index registers
+ are already prohibited, so this doesn't need to worry about
+ fix_cm3_ldrd. */
otherops[0] = operands[0];
otherops[1] = XEXP (XEXP (XEXP (operands[1], 0), 1), 0);
otherops[2] = XEXP (XEXP (XEXP (operands[1], 0), 1), 1);
@@ -10062,11 +10079,15 @@ output_move_double (rtx *operands)
/* We might be able to use ldrd %0, %1 here. However the range is
different to ldr/adr, and it is broken on some ARMv7-M
implementations. */
- output_asm_insn ("adr%?\t%0, %1", operands);
+ /* Use the second register of the pair to avoid problematic
+ overlap. */
+ otherops[1] = operands[1];
+ output_asm_insn ("adr%?\t%0, %1", otherops);
+ operands[1] = otherops[0];
if (TARGET_LDRD)
- output_asm_insn ("ldr%(d%)\t%0, [%0]", operands);
+ output_asm_insn ("ldr%(d%)\t%0, [%1]", operands);
else
- output_asm_insn ("ldm%(ia%)\t%0, %M0", operands);
+ output_asm_insn ("ldm%(ia%)\t%1, %M0", operands);
break;
/* ??? This needs checking for thumb2. */
@@ -10099,30 +10120,37 @@ output_move_double (rtx *operands)
return "";
}
}
+ otherops[0] = gen_rtx_REG(SImode, REGNO(operands[0]) + 1);
+ operands[1] = otherops[0];
if (TARGET_LDRD
&& (GET_CODE (otherops[2]) == REG
|| (GET_CODE (otherops[2]) == CONST_INT
&& INTVAL (otherops[2]) > -256
&& INTVAL (otherops[2]) < 256)))
{
- if (reg_overlap_mentioned_p (otherops[0],
+ if (reg_overlap_mentioned_p (operands[0],
otherops[2]))
{
+ rtx tmp;
/* Swap base and index registers over to
avoid a conflict. */
- otherops[1] = XEXP (XEXP (operands[1], 0), 1);
- otherops[2] = XEXP (XEXP (operands[1], 0), 0);
+ tmp = otherops[1];
+ otherops[1] = otherops[2];
+ otherops[2] = tmp;
}
/* If both registers conflict, it will usually
have been fixed by a splitter. */
- if (reg_overlap_mentioned_p (otherops[0], otherops[2]))
+ if (reg_overlap_mentioned_p (operands[0], otherops[2])
+ || (fix_cm3_ldrd && reg0 == REGNO (otherops[1])))
{
- output_asm_insn ("add%?\t%1, %1, %2", otherops);
- output_asm_insn ("ldr%(d%)\t%0, [%1]",
- otherops);
+ output_asm_insn ("add%?\t%0, %1, %2", otherops);
+ output_asm_insn ("ldr%(d%)\t%0, [%1]", operands);
}
else
- output_asm_insn ("ldr%(d%)\t%0, [%1, %2]", otherops);
+ {
+ otherops[0] = operands[0];
+ output_asm_insn ("ldr%(d%)\t%0, [%1, %2]", otherops);
+ }
return "";
}
@@ -10140,9 +10168,9 @@ output_move_double (rtx *operands)
output_asm_insn ("sub%?\t%0, %1, %2", otherops);
if (TARGET_LDRD)
- return "ldr%(d%)\t%0, [%0]";
+ return "ldr%(d%)\t%0, [%1]";
- return "ldm%(ia%)\t%0, %M0";
+ return "ldm%(ia%)\t%1, %M0";
}
else
{
diff --git a/gcc/config/arm/arm.opt b/gcc/config/arm/arm.opt
index c8bdcf8..1d07ced 100644
--- a/gcc/config/arm/arm.opt
+++ b/gcc/config/arm/arm.opt
@@ -159,4 +159,9 @@ Use Neon quad-word (rather than double-word) registers for vectorization
mword-relocations
Target Report Var(target_word_relocations) Init(TARGET_DEFAULT_WORD_RELOCATIONS)
-+Only generate absolute relocations on word sized values.
+Only generate absolute relocations on word sized values.
+
+mfix-cortex-m3-ldrd
+Target Report Var(fix_cm3_ldrd) Init(2)
+Avoid overlapping destination and address registers on LDRD instructions
+that may trigger Cortex-M3 errata.