diff options
author | Paul Brook <paul@codesourcery.com> | 2008-11-13 15:19:02 +0000 |
---|---|---|
committer | Paul Brook <pbrook@gcc.gnu.org> | 2008-11-13 15:19:02 +0000 |
commit | 5fd424238b25fd8ff6ac403ef923bdce2b2b2347 (patch) | |
tree | c0fb255f1910301b63c8be710bb26c06656095ad /gcc/config/arm | |
parent | 255e5b0481a06f5fb7cf41c8b1d511cf506b943f (diff) | |
download | gcc-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.c | 70 | ||||
-rw-r--r-- | gcc/config/arm/arm.opt | 7 |
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. |