]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
invoke.texi: Document --fix-cortex-m3.
authorPaul Brook <paul@codesourcery.com>
Thu, 13 Nov 2008 15:19:02 +0000 (15:19 +0000)
committerPaul Brook <pbrook@gcc.gnu.org>
Thu, 13 Nov 2008 15:19:02 +0000 (15:19 +0000)
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

gcc/ChangeLog
gcc/config/arm/arm.c
gcc/config/arm/arm.opt
gcc/doc/invoke.texi

index 0ec0db6060337bc75f59f3a3519fa9fef741d702..2ae685a51e83c31d87cb7678428da9627b15bba2 100644 (file)
@@ -1,3 +1,12 @@
+2008-11-13  Paul Brook  <paul@codesourcery.com>
+
+       * 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.
+
 2008-11-13  Jakub Jelinek  <jakub@redhat.com>
 
        PR bootstrap/38100
index aeb0e53ea729007999530073b0e54100490d38ca..a1cef0bd103b4f671ad267e2abd231202a0e9b88 100644 (file)
@@ -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
            {
index c8bdcf80f4812d775dbcc00a3084806d729e6ba0..1d07cedf0de9288e822b4f1d1aea47dd3705e0ae 100644 (file)
@@ -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.
index 3f6f400f6dcc593fc966bd4a751550b5bef18b69..ce621520fce423822d5dbc4f7179f1ff7f2b6103 100644 (file)
@@ -452,8 +452,9 @@ Objective-C and Objective-C++ Dialects}.
 -mthumb  -marm @gol
 -mtpcs-frame  -mtpcs-leaf-frame @gol
 -mcaller-super-interworking  -mcallee-super-interworking @gol
--mtp=@var{name}
--mword-relocations}
+-mtp=@var{name} @gol
+-mword-relocations @gol
+-mfix-cortex-m3-ldrd}
 
 @emph{AVR Options}
 @gccoptlist{-mmcu=@var{mcu}  -msize  -minit-stack=@var{n}  -mno-interrupts @gol
@@ -8708,6 +8709,13 @@ Put functions, data, and readonly data in @var{text-section},
 by default.  This can be overridden with the @code{section} attribute.
 @xref{Variable Attributes}.
 
+@item -mfix-cortex-m3-ldrd
+@opindex mfix-cortex-m3-ldrd
+Some Cortex-M3 cores can cause data corruption when @code{ldrd} instructions
+with overlapping destination and base registers are used.  This option avoids
+generating these instructions.  This option is enabled by default when
+@option{-mcpu=cortex-m3} is specified.
+
 @end table
 
 @node ARM Options