2004-01-30 H.J. Lu <hongjiu.lu@intel.com>
authorH.J. Lu <hjl.tools@gmail.com>
Fri, 30 Jan 2004 23:13:28 +0000 (23:13 +0000)
committerH.J. Lu <hjl.tools@gmail.com>
Fri, 30 Jan 2004 23:13:28 +0000 (23:13 +0000)
* elfxx-ia64.c (elfNN_ia64_relax_brl): New function.
(elfNN_ia64_relax_section): Optimize brl to br during the relax
finalize pass.

bfd/ChangeLog
bfd/elfxx-ia64.c

index 6ff4553a856ac188210c07af547c06fdff7db575..72a2e2ffa49c229861e5fc0761350576c33d43f0 100644 (file)
@@ -1,3 +1,9 @@
+2004-01-30  H.J. Lu  <hongjiu.lu@intel.com>
+
+       * elfxx-ia64.c (elfNN_ia64_relax_brl): New function.
+       (elfNN_ia64_relax_section): Optimize brl to br during the relax
+       finalize pass.
+
 2004-01-30  Alexandre Oliva  <aoliva@redhat.com>
 
        * elf32-frv.c (elf32_frv_always_size_sections): Initialize pointer
index c33aec14462304a27349f828bfbe2a676bdc4a85..e223a10e09bc4ef47b7943de9272e12e802b4b97 100644 (file)
@@ -672,6 +672,36 @@ bfd_elfNN_ia64_after_parse (int itanium)
   oor_branch_size = itanium ? sizeof (oor_ip) : sizeof (oor_brl);
 }
 
+static void
+elfNN_ia64_relax_brl (bfd *abfd, bfd_byte *contents, bfd_vma off)
+{
+  int template;
+  bfd_byte *hit_addr;
+  bfd_vma t0, t1, i0, i1, i2;
+
+  hit_addr = (bfd_byte *) (contents + off);
+  hit_addr -= (long) hit_addr & 0x3;
+  t0 = bfd_get_64 (abfd, hit_addr);
+  t1 = bfd_get_64 (abfd, hit_addr + 8);
+
+  /* Keep the instruction in slot 0. */
+  i0 = (t0 >> 5) & 0x1ffffffffffLL;
+  /* Use nop.b for slot 1. */
+  i1 = 0x4000000000LL;
+  /* For slot 2, turn brl into br by masking out bit 40.  */
+  i2 = (t1 >> 23) & 0x0ffffffffffLL;
+
+  /* Turn a MLX bundle into a MBB bundle with the same stop-bit
+     variety.  */
+  template = 0x12;
+  if ((t0 & 0x1fLL) == 5)
+    template += 1;
+  t0 = (i1 << 46) | (i0 << 5) | template;
+  t1 = (i2 << 23) | (i1 >> 18);
+
+  bfd_put_64 (abfd, t0, hit_addr);
+  bfd_put_64 (abfd, t1, hit_addr + 8);
+}
 \f
 /* These functions do relaxation for IA-64 ELF.  */
 
@@ -765,13 +795,30 @@ elfNN_ia64_relax_section (abfd, sec, link_info, again)
        case R_IA64_PCREL21BI:
        case R_IA64_PCREL21M:
        case R_IA64_PCREL21F:
+         /* In the finalize pass, all br relaxations are done. We can
+            skip it. */
          if (!link_info->need_relax_finalize)
            continue;
          is_branch = TRUE;
          break;
 
+       case R_IA64_PCREL60B:
+         /* We can't optimize brl to br before the finalize pass since
+            br relaxations will increase the code size. Defer it to
+            the finalize pass.  */
+         if (link_info->need_relax_finalize)
+           {
+             sec->need_finalize_relax = 1;
+             continue;
+           }
+         is_branch = TRUE;
+         break;
+
        case R_IA64_LTOFF22X:
        case R_IA64_LDXMOV:
+         /* We can't relax ldx/mov before the finalize pass since
+            br relaxations will increase the code size. Defer it to
+            the finalize pass.  */
          if (link_info->need_relax_finalize)
            {
              sec->need_finalize_relax = 1;
@@ -885,6 +932,25 @@ elfNN_ia64_relax_section (abfd, sec, link_info, again)
          /* If the branch is in range, no need to do anything.  */
          if ((bfd_signed_vma) (symaddr - reladdr) >= -0x1000000
              && (bfd_signed_vma) (symaddr - reladdr) <= 0x0FFFFF0)
+           {
+             /* If the 60-bit branch is in 21-bit range, optimize it. */
+             if (r_type == R_IA64_PCREL60B)
+               {
+                 elfNN_ia64_relax_brl (abfd, contents, roff);
+
+                 irel->r_info
+                   = ELF64_R_INFO (ELF64_R_SYM (irel->r_info),
+                                   R_IA64_PCREL21B);
+
+                 /* If the original relocation offset points to slot
+                    1, change it to slot 2.  */
+                 if ((irel->r_offset & 3) == 1)
+                   irel->r_offset += 1;
+               }
+
+             continue;
+           }
+         else if (r_type == R_IA64_PCREL60B)
            continue;
 
          /* If the branch and target are in the same section, you've
This page took 0.031137 seconds and 4 git commands to generate.