This is the mail archive of the
binutils@sources.redhat.com
mailing list for the binutils project.
Re: PATCH: PR 834: IA64: Change br to brl for "far" branches when possible
On Thu, May 12, 2005 at 05:58:18PM -0700, H. J. Lu wrote:
> On Thu, May 12, 2005 at 02:36:33PM -0700, Richard Henderson wrote:
> > On Thu, May 12, 2005 at 01:05:22PM -0700, H. J. Lu wrote:
> > > > I really wish you'd extract the three insns independently, rather
> > > > than extracting 3 words and using quite so many arbitrary masks.
> > > > It's not like we don't have a 64-bit type available.
> > > >
> > >
> > > I was thinking to use long long since long may be 32bit. But I am not
> > > sure if all compilers support it. I guess I can use
> > >
> > > #if BFD_HOST_LONG_LONG
> > > long long ..
> > > #else
> > > return FALSE;
> > > #endif
> >
> > We already assume a 64-bit type, for instance in elfNN_ia64_install_value.
> > I see that elf32-ia64.lo is in BFD32_BACKENDS; that's probably a mistake.
> >
> > I see no reason to complicate things by doing anything other than assuming
> > a 64-bit type is available when compiling for ia64. Every reasonable
> > compiler does support such a type.
> >
> >
>
> Here is the updated patch.
>
>
Added 40bit masks for instructions.
H.J.
---
2005-05-12 H.J. Lu <hongjiu.lu@intel.com>
PR 834
* elfxx-ia64.c (elfNN_ia64_relax_br): New.
(elfNN_ia64_relax_brl): Use it.
--- bfd/elfxx-ia64.c.brl 2005-05-07 06:58:12.000000000 -0700
+++ bfd/elfxx-ia64.c 2005-05-12 17:50:36.000000000 -0700
@@ -681,6 +681,108 @@ bfd_elfNN_ia64_after_parse (int itanium)
oor_branch_size = itanium ? sizeof (oor_ip) : sizeof (oor_brl);
}
+static bfd_boolean
+elfNN_ia64_relax_br (bfd_byte *contents, bfd_vma off)
+{
+ unsigned int template, mlx;
+ bfd_vma t0, t1, s0, s1, s2, br_code;
+ long br_slot;
+ bfd_byte *hit_addr;
+
+ hit_addr = (bfd_byte *) (contents + off);
+ br_slot = (long) hit_addr & 0x3;
+ hit_addr -= br_slot;
+ t0 = bfd_getl64 (hit_addr + 0);
+ t1 = bfd_getl64 (hit_addr + 8);
+
+ /* Check if we can turn br into brl. A label is always at the start
+ of the bundle. Even if there are predicates on NOPs, we still
+ perform this optimization. */
+ template = t0 & 0x1e;
+ s0 = (t0 >> 5) & 0x1ffffffffffLL;
+ s1 = ((t0 >> 46) | (t1 << 18)) & 0x1ffffffffffLL;
+ s2 = (t1 >> 23) & 0x1ffffffffffLL;
+ switch (br_slot)
+ {
+ case 0:
+ /* Check if slot 1 and slot 2 are NOPs. Possible template is
+ BBB. We only need to check nop.b. */
+ if (!((s1 & 0x1e1f8000000LL) == 0x4000000000LL
+ && (s2 & 0x1e1f8000000LL) == 0x4000000000LL))
+ return FALSE;
+ br_code = s0;
+ break;
+ case 1:
+ /* Check if slot 2 is NOP. Possible templates are MBB and BBB.
+ For BBB, slot 0 also has to be nop.b. */
+ if (!((template == 0x12 /* MBB */
+ && (s2 & 0x1e1f8000000LL) == 0x4000000000LL)
+ || (template == 0x16 /* BBB */
+ && (s0 & 0x1e1f8000000LL) == 0x4000000000LL
+ && (s2 & 0x1e1f8000000LL) == 0x4000000000LL)))
+ return FALSE;
+ br_code = s1;
+ break;
+ case 2:
+ /* Check if slot 1 is NOP. Possible templates are MIB, MBB, BBB,
+ MMB and MFB. For BBB, slot 0 also has to be nop.b. */
+ if (!((template == 0x10 /* MIB */
+ && (s1 & 0x1effc000000LL) == 0x8000000LL)
+ || (template == 0x12 /* MBB */
+ && (s1 & 0x1e1f8000000LL) == 0x4000000000LL)
+ || (template == 0x16 /* BBB */
+ && (s0 & 0x1e1f8000000LL) == 0x4000000000LL
+ && (s1 & 0x1e1f8000000LL) == 0x4000000000LL)
+ || (template == 0x18 /* MMB */
+ && (s1 & 0x1effc000000LL) == 0x8000000LL)
+ || (template == 0x1c /* MFB */
+ && (s1 & 0x1e3fc000000LL) == 0x8000000LL)))
+ return FALSE;
+ br_code = s2;
+ break;
+ default:
+ /* It should never happen. */
+ abort ();
+ }
+
+ /* We can turn br.cond/br.call into brl.cond/brl.call. */
+ if (!(((br_code & 0x1e0000001c0LL) == 0x8000000000LL)
+ || (br_code & 0x1e000000000LL) == 0xa000000000LL))
+ return FALSE;
+
+ /* Turn br into brl by setting bit 40. */
+ br_code |= 0x10000000000LL;
+
+ /* Turn the old bundle into a MLX bundle with the same stop-bit
+ variety. */
+ if (t0 & 0x1)
+ mlx = 0x5;
+ else
+ mlx = 0x4;
+
+ if (template == 0x16)
+ {
+ /* For BBB, we need to put nop.m in slot 0 and keep the original
+ predicate. */
+ t0 &= 0x7e0LL;
+ t0 |= 0x100000000LL;
+ }
+ else
+ {
+ /* Keep the original instruction in slot 0. */
+ t0 &= 0x3fffffffffe0LL;
+ }
+
+ t0 |= mlx;
+
+ /* Put brl in slot 1. */
+ t1 = br_code << 23;
+
+ bfd_putl64 (t0, hit_addr);
+ bfd_putl64 (t1, hit_addr + 8);
+ return TRUE;
+}
+
static void
elfNN_ia64_relax_brl (bfd_byte *contents, bfd_vma off)
{
@@ -985,6 +1087,16 @@ elfNN_ia64_relax_section (abfd, sec, lin
}
else if (r_type == R_IA64_PCREL60B)
continue;
+ else if (elfNN_ia64_relax_br (contents, roff))
+ {
+ irel->r_info
+ = ELFNN_R_INFO (ELFNN_R_SYM (irel->r_info),
+ R_IA64_PCREL60B);
+
+ /* Make the relocation offset point to slot 1. */
+ irel->r_offset = (irel->r_offset & ~((bfd_vma) 0x3)) + 1;
+ continue;
+ }
/* We can't put a trampoline in a .init/.fini section. Issue
an error. */