bfd/
authorNathan Sidwell <nathan@codesourcery.com>
Wed, 5 Aug 2009 12:36:14 +0000 (12:36 +0000)
committerNathan Sidwell <nathan@codesourcery.com>
Wed, 5 Aug 2009 12:36:14 +0000 (12:36 +0000)
* elf32-arm.c (elf32_arm_stub_type): Add arm_stub_a8_veneer_lwm.
(arm_build_one_stub): Build a8 veneers as a separate pass.
(cortex_a8_erratum_scan): Add prev_num_a8_fixes and stub_changed_p
parameters.  Use them to check if we create a different a8 fixup
than the previous pass.
(elf32_arm_size_stubs): Move scope of stub_changed and
prev_num_a8_fixes into main loop.
(elf32_arm_build_stubs): Build a8 veneers in a second pass.

ld/testsuite/
* ld-arm/cortex-a8-far-1.s: New.
* ld-arm/cortex-a8-far-2.s: New.
* ld-arm/cortex-a8-far.d: New.
* ld-arm/arm-elf.exp: Add new test.

bfd/ChangeLog
bfd/elf32-arm.c
ld/testsuite/ChangeLog
ld/testsuite/ld-arm/arm-elf.exp
ld/testsuite/ld-arm/cortex-a8-far-1.s [new file with mode: 0644]
ld/testsuite/ld-arm/cortex-a8-far-2.s [new file with mode: 0644]
ld/testsuite/ld-arm/cortex-a8-far.d [new file with mode: 0644]

index 50866fc313095c96ef3c2973afcd566c1d059155..577918ca0ee5883934bab0e07f224b7eb0069908 100644 (file)
@@ -1,3 +1,14 @@
+2009-08-05  Nathan Sidwell  <nathan@codesourcery.com>
+
+       * elf32-arm.c (elf32_arm_stub_type): Add arm_stub_a8_veneer_lwm.
+       (arm_build_one_stub): Build a8 veneers as a separate pass.
+       (cortex_a8_erratum_scan): Add prev_num_a8_fixes and stub_changed_p
+       parameters.  Use them to check if we create a different a8 fixup
+       than the previous pass.
+       (elf32_arm_size_stubs): Move scope of stub_changed and
+       prev_num_a8_fixes into main loop.
+       (elf32_arm_build_stubs): Build a8 veneers in a second pass.
+
 2009-08-04  Alan Modra  <amodra@bigpond.net.au>
 
        * elf32-ppc.c (ppc_elf_relax_section): Correct conditions under
index 1e23626518fb25b2459e7f834ef73eaf63a03a89..5aba3f360a78e50f16510bbff5c089f89c4a2be3 100644 (file)
@@ -2228,6 +2228,8 @@ static const insn_sequence elf32_arm_stub_a8_veneer_blx[] =
 enum elf32_arm_stub_type {
   arm_stub_none,
   DEF_STUBS
+  /* Note the first a8_veneer type */
+  arm_stub_a8_veneer_lwm = arm_stub_a8_veneer_b_cond
 };
 #undef DEF_STUB
 
@@ -3437,6 +3439,12 @@ arm_build_one_stub (struct bfd_hash_entry *gen_entry,
   htab = elf32_arm_hash_table (info);
   stub_sec = stub_entry->stub_sec;
 
+  if ((htab->fix_cortex_a8 < 0)
+      != (stub_entry->stub_type >= arm_stub_a8_veneer_lwm))
+    /* We have to do the a8 fixes last, as they are less aligned than
+       the other veneers.  */
+    return TRUE;
+  
   /* Make a note of the offset within the stubs for this entry.  */
   stub_entry->stub_offset = stub_sec->size;
   loc = stub_sec->contents + stub_entry->stub_offset;
@@ -3893,7 +3901,9 @@ cortex_a8_erratum_scan (bfd *input_bfd,
                        unsigned int *num_a8_fixes_p,
                        unsigned int *a8_fix_table_size_p,
                        struct a8_erratum_reloc *a8_relocs,
-                       unsigned int num_a8_relocs)
+                       unsigned int num_a8_relocs,
+                       unsigned prev_num_a8_fixes,
+                       bfd_boolean *stub_changed_p)
 {
   asection *section;
   struct elf32_arm_link_hash_table *htab = elf32_arm_hash_table (info);
@@ -4105,7 +4115,7 @@ cortex_a8_erratum_scan (bfd *input_bfd,
 
                       if (((base_vma + i) & ~0xfff) == (target & ~0xfff))
                         {
-                          char *stub_name;
+                          char *stub_name = NULL;
 
                           if (num_a8_fixes == a8_fix_table_size)
                             {
@@ -4115,9 +4125,28 @@ cortex_a8_erratum_scan (bfd *input_bfd,
                                 * a8_fix_table_size);
                             }
 
-                          stub_name = bfd_malloc (8 + 1 + 8 + 1);
-                          if (stub_name != NULL)
-                            sprintf (stub_name, "%x:%x", section->id, i);
+                         if (num_a8_fixes < prev_num_a8_fixes)
+                           {
+                             /* If we're doing a subsequent scan,
+                                check if we've found the same fix as
+                                before, and try and reuse the stub
+                                name.  */
+                             stub_name = a8_fixes[num_a8_fixes].stub_name;
+                             if ((a8_fixes[num_a8_fixes].section != section)
+                                 || (a8_fixes[num_a8_fixes].offset != i))
+                               {
+                                 free (stub_name);
+                                 stub_name = NULL;
+                                 *stub_changed_p = TRUE;
+                               }
+                           }
+
+                         if (!stub_name)
+                           {
+                             stub_name = bfd_malloc (8 + 1 + 8 + 1);
+                             if (stub_name != NULL)
+                               sprintf (stub_name, "%x:%x", section->id, i);
+                           }
 
                           a8_fixes[num_a8_fixes].input_bfd = input_bfd;
                           a8_fixes[num_a8_fixes].section = section;
@@ -4165,10 +4194,9 @@ elf32_arm_size_stubs (bfd *output_bfd,
 {
   bfd_size_type stub_group_size;
   bfd_boolean stubs_always_after_branch;
-  bfd_boolean stub_changed = 0;
   struct elf32_arm_link_hash_table *htab = elf32_arm_hash_table (info);
   struct a8_erratum_fix *a8_fixes = NULL;
-  unsigned int num_a8_fixes = 0, prev_num_a8_fixes = 0, a8_fix_table_size = 10;
+  unsigned int num_a8_fixes = 0, a8_fix_table_size = 10;
   struct a8_erratum_reloc *a8_relocs = NULL;
   unsigned int num_a8_relocs = 0, a8_reloc_table_size = 10, i;
 
@@ -4223,9 +4251,10 @@ elf32_arm_size_stubs (bfd *output_bfd,
       bfd *input_bfd;
       unsigned int bfd_indx;
       asection *stub_sec;
+      bfd_boolean stub_changed = FALSE;
+      unsigned prev_num_a8_fixes = num_a8_fixes;
 
       num_a8_fixes = 0;
-
       for (input_bfd = info->input_bfds, bfd_indx = 0;
           input_bfd != NULL;
           input_bfd = input_bfd->link_next, bfd_indx++)
@@ -4452,6 +4481,7 @@ elf32_arm_size_stubs (bfd *output_bfd,
                        {
                          /* The proper stub has already been created.  */
                          free (stub_name);
+                         stub_entry->target_value = sym_value;
                          break;
                        }
 
@@ -4548,18 +4578,21 @@ elf32_arm_size_stubs (bfd *output_bfd,
           if (htab->fix_cortex_a8)
            {
               /* Sort relocs which might apply to Cortex-A8 erratum.  */
-              qsort (a8_relocs, num_a8_relocs, sizeof (struct a8_erratum_reloc),
+              qsort (a8_relocs, num_a8_relocs,
+                    sizeof (struct a8_erratum_reloc),
                      &a8_reloc_compare);
 
               /* Scan for branches which might trigger Cortex-A8 erratum.  */
               if (cortex_a8_erratum_scan (input_bfd, info, &a8_fixes,
                                          &num_a8_fixes, &a8_fix_table_size,
-                                         a8_relocs, num_a8_relocs) != 0)
+                                         a8_relocs, num_a8_relocs,
+                                         prev_num_a8_fixes, &stub_changed)
+                 != 0)
                goto error_ret_free_local;
            }
        }
 
-      if (htab->fix_cortex_a8 && num_a8_fixes != prev_num_a8_fixes)
+      if (prev_num_a8_fixes != num_a8_fixes)
         stub_changed = TRUE;
 
       if (!stub_changed)
@@ -4598,8 +4631,6 @@ elf32_arm_size_stubs (bfd *output_bfd,
 
       /* Ask the linker to do its stuff.  */
       (*htab->layout_sections_again) ();
-      stub_changed = FALSE;
-      prev_num_a8_fixes = num_a8_fixes;
     }
 
   /* Add stubs for Cortex-A8 erratum fixes now.  */
@@ -4696,6 +4727,12 @@ elf32_arm_build_stubs (struct bfd_link_info *info)
   /* Build the stubs as directed by the stub hash table.  */
   table = &htab->stub_hash_table;
   bfd_hash_traverse (table, arm_build_one_stub, info);
+  if (htab->fix_cortex_a8)
+    {
+      /* Place the cortex a8 stubs last.  */
+      htab->fix_cortex_a8 = -1;
+      bfd_hash_traverse (table, arm_build_one_stub, info);
+    }
 
   return TRUE;
 }
index 60ee1ec8dccb962c0a4c42c62c114e5cedb0d35c..d63c14b47fa824973607ae875e624ad515fa1fc1 100644 (file)
@@ -1,3 +1,10 @@
+2009-08-05  Nathan Sidwell  <nathan@codesourcery.com>
+
+       * ld-arm/cortex-a8-far-1.s: New.
+       * ld-arm/cortex-a8-far-2.s: New.
+       * ld-arm/cortex-a8-far.d: New.
+       * ld-arm/arm-elf.exp: Add new test.
+
 2009-08-02  H.J. Lu  <hongjiu.lu@intel.com>
 
        PR ld/6443
index de3628eb121bfb8e3aca2c3e614bbd09e5b45907..941ef50c6976043089bea556d45e49501d36efc9 100644 (file)
@@ -205,6 +205,10 @@ set armelftests {
      "-EL -Ttext=0x8f00 --fix-cortex-a8" "-EL" {cortex-a8-thumb-target.s cortex-a8-fix-blx-rel.s}
      {{objdump -dr cortex-a8-fix-blx-rel-thumb.d}}
      "cortex-a8-fix-blx-rel-thumb"}
+    {"Cortex-A8 erratum fix, relocate bl.w and far call"
+     "-EL -Ttext=0x00 --fix-cortex-a8 --defsym far_fn1=0x80000000 --defsym far_fn2=0x80000004  --defsym far_fn=0x7fff0000 --defsym _start=0" "-EL" {cortex-a8-far-1.s cortex-a8-far-2.s}
+     {{objdump -dr cortex-a8-far.d}}
+     "cortex-a8-far"}
     {"Unwinding and -gc-sections" "-gc-sections" "" {gc-unwind.s}
      {{objdump -sj.data gc-unwind.d}}
      "gc-unwind"}
diff --git a/ld/testsuite/ld-arm/cortex-a8-far-1.s b/ld/testsuite/ld-arm/cortex-a8-far-1.s
new file mode 100644 (file)
index 0000000..09d3583
--- /dev/null
@@ -0,0 +1,8 @@
+       .syntax unified
+       .thumb
+       .globl two
+two:   
+       bl far_fn
+       .rept 0x200000
+       .long 0
+       .endr
diff --git a/ld/testsuite/ld-arm/cortex-a8-far-2.s b/ld/testsuite/ld-arm/cortex-a8-far-2.s
new file mode 100644 (file)
index 0000000..22fd40f
--- /dev/null
@@ -0,0 +1,20 @@
+       .syntax unified
+       .thumb
+three:
+       bl far_fn1
+       bl far_fn2
+       .rept 1016
+       .long 0
+       .endr
+       nop
+label1:        
+       eor.w   r0, r1, r2
+       beq.w     label1
+
+       eor.w   r0, r1, r2
+       eor.w   r0, r1, r2
+       b.w     label1
+
+       eor.w   r0, r1, r2
+       eor.w   r0, r1, r2
diff --git a/ld/testsuite/ld-arm/cortex-a8-far.d b/ld/testsuite/ld-arm/cortex-a8-far.d
new file mode 100644 (file)
index 0000000..3d9059d
--- /dev/null
@@ -0,0 +1,40 @@
+
+.*:     file format .*
+
+
+Disassembly of section \.text:
+
+00000000 <two>:
+       0:      f000 c802       blx     800008 <__far_fn_from_thumb>
+       ...
+#...
+00800008 <__far_fn_from_thumb>:
+  800008:      e51ff004        ldr     pc, \[pc, #-4\] ; 80000c <__far_fn_from_thumb\+0x4>
+  80000c:      7fff0000        .word   0x7fff0000
+
+00800010 <three>:
+  800010:      f001 e806       blx     801020 <__far_fn1_from_thumb>
+  800014:      f001 e800       blx     801018 <__far_fn2_from_thumb>
+       ...
+  800ff8:      bf00            nop
+
+00800ffa <label1>:
+  800ffa:      ea81 0002       eor.w   r0, r1, r2
+  800ffe:      f000 b813       b.w     801028 <__far_fn1_from_thumb\+0x8>
+  801002:      ea81 0002       eor.w   r0, r1, r2
+  801006:      ea81 0002       eor.w   r0, r1, r2
+  80100a:      f7ff bff6       b.w     800ffa <label1>
+  80100e:      ea81 0002       eor.w   r0, r1, r2
+  801012:      ea81 0002       eor.w   r0, r1, r2
+       ...
+
+00801018 <__far_fn2_from_thumb>:
+  801018:      e51ff004        ldr     pc, \[pc, #-4\] ; 80101c <__far_fn2_from_thumb\+0x4>
+  80101c:      80000004        .word   0x80000004
+
+00801020 <__far_fn1_from_thumb>:
+  801020:      e51ff004        ldr     pc, \[pc, #-4\] ; 801024 <__far_fn1_from_thumb\+0x4>
+  801024:      80000000        .word   0x80000000
+  801028:      d001            beq.n   80102e <__far_fn1_from_thumb\+0xe>
+  80102a:      f7ff bfea       b.w     801002 <label1\+0x8>
+  80102e:      f7ff bfe4       b.w     800ffa <label1>
This page took 0.03954 seconds and 4 git commands to generate.