This is the mail archive of the binutils@sources.redhat.com mailing list for the binutils project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]

powerpc64 branch hints


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;
 


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]