This is the mail archive of the
binutils@sources.redhat.com
mailing list for the binutils project.
powerpc64 branch hints
- To: binutils at sources dot redhat dot com
- Subject: powerpc64 branch hints
- From: Alan Modra <amodra at bigpond dot net dot au>
- Date: Thu, 1 Nov 2001 16:05:46 +1030
64 bit powerpc branch prediction hints differ from 32 bit hints.
bfd/ChangeLog
* elf64-ppc.c (ppc64_elf_relocate_section): Correct branch
prediction bits.
Committed.
--
Alan Modra
Index: bfd/elf64-ppc.c
===================================================================
RCS file: /cvs/src/src/bfd/elf64-ppc.c,v
retrieving revision 1.9
diff -u -p -r1.9 elf64-ppc.c
--- elf64-ppc.c 2001/10/15 09:45:48 1.9
+++ elf64-ppc.c 2001/11/01 05:13:55
@@ -92,9 +92,6 @@ static boolean ppc64_elf_finish_dynamic_
PARAMS ((bfd *, struct bfd_link_info *));
-/* Branch prediction bit for branch taken relocs. */
-#define BRANCH_PREDICT_BIT 0x200000
-
/* Mask to set RA in memory instructions. */
#define RA_REGISTER_MASK 0x001f0000
@@ -3161,6 +3158,7 @@ ppc64_elf_relocate_section (output_bfd,
}
/* First handle relocations that tweak non-addend part of insn. */
+ insn = 0;
switch (r_type)
{
default:
@@ -3169,22 +3167,23 @@ ppc64_elf_relocate_section (output_bfd,
/* Branch taken prediction relocations. */
case R_PPC64_ADDR14_BRTAKEN:
case R_PPC64_REL14_BRTAKEN:
- insn = bfd_get_32 (output_bfd, contents + offset);
- if ((relocation - offset) & 0x8000)
- insn &= ~BRANCH_PREDICT_BIT;
- else
- insn |= BRANCH_PREDICT_BIT;
- bfd_put_32 (output_bfd, (bfd_vma) insn, contents + offset);
- break;
+ insn = 0x01 << 21; /* Set 't' bit, lowest bit of BO field. */
+ /* Fall thru. */
- /* Branch not taken predicition relocations. */
+ /* Branch not taken prediction relocations. */
case R_PPC64_ADDR14_BRNTAKEN:
case R_PPC64_REL14_BRNTAKEN:
- insn = bfd_get_32 (output_bfd, contents + offset);
- if ((relocation - offset) & 0x8000)
- insn |= BRANCH_PREDICT_BIT;
+ insn |= bfd_get_32 (output_bfd, contents + offset) & ~(0x01 << 21);
+ /* Set 'a' bit. This is 0b00010 in BO field for branch on CR(BI)
+ insns (BO == 001at or 011at), and 0b01000 for branch on CTR
+ insns (BO == 1a00t or 1a01t). */
+ if ((insn & (0x14 << 21)) == (0x04 << 21))
+ insn |= 0x02 << 21;
+ else if ((insn & (0x14 << 21)) == (0x10 << 21))
+ insn |= 0x08 << 21;
else
- insn &= ~BRANCH_PREDICT_BIT;
+ break;
+
bfd_put_32 (output_bfd, (bfd_vma) insn, contents + offset);
break;