From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 22066 invoked by alias); 13 May 2005 01:19:52 -0000 Mailing-List: contact binutils-help@sources.redhat.com; run by ezmlm Precedence: bulk List-Subscribe: List-Archive: List-Post: List-Help: , Sender: binutils-owner@sources.redhat.com Received: (qmail 22034 invoked from network); 13 May 2005 01:19:46 -0000 Received: from unknown (HELO rwcrmhc11.comcast.net) (204.127.198.35) by sourceware.org with SMTP; 13 May 2005 01:19:46 -0000 Received: from lucon.org ([24.6.212.230]) by comcast.net (rwcrmhc11) with ESMTP id <2005051301194501300n2tfce>; Fri, 13 May 2005 01:19:45 +0000 Received: by lucon.org (Postfix, from userid 1000) id AD8DA649BC; Thu, 12 May 2005 18:19:45 -0700 (PDT) Date: Fri, 13 May 2005 07:40:00 -0000 From: "H. J. Lu" To: Richard Henderson Cc: binutils@sources.redhat.com Subject: Re: PATCH: PR 834: IA64: Change br to brl for "far" branches when possible Message-ID: <20050513011945.GA13797@lucon.org> References: <20050512161141.GA5705@lucon.org> <20050512163732.GA6106@lucon.org> <20050512195602.GA6540@redhat.com> <20050512200522.GA9089@lucon.org> <20050512213633.GA6755@redhat.com> <20050513005818.GA13457@lucon.org> Mime-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: <20050513005818.GA13457@lucon.org> User-Agent: Mutt/1.4.1i X-SW-Source: 2005-05/txt/msg00447.txt.bz2 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 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. */