This is the mail archive of the binutils@sourceware.org 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]
Other format: [Raw text]

[PATCH] MIPS: microMIPS compact branch linker relaxation check


Hi Richard,

 Here's a regenerated version of the compact branch linker relaxation 
check.  With my previous note about bzc being an optimisation, do you 
agree this change can go in as it stands?

 Actually all this linker relaxation machinery begs for a code example.  
I believe I've got a test case somewhere though it needs adapting to our 
test framework.  If not, then I'll cook something up from scratch, though 
it may be possible that any test code won't make too much sense before 
I've got the ADDIUPC relaxation fixes in -- or otherwise I'd have to fix 
the output from the test case up with each follow-up commit.  It may be 
good for illustration purposes anyway, so I'll post it regardless.

2011-07-29  Maciej W. Rozycki  <macro@codesourcery.com>

	bfd/
	* elfxx-mips.c (check_4byte_branch): Remove function.
	(check_bzc): New function.
	(_bfd_mips_elf_relax_section): Permit the relaxation of LUI
	instructions that immediately follow a compact branch
	instruction.

  Maciej

binutils-umips-bzc.diff
Index: binutils-fsf-trunk-quilt/bfd/elfxx-mips.c
===================================================================
--- binutils-fsf-trunk-quilt.orig/bfd/elfxx-mips.c	2011-07-29 21:51:47.000000000 +0100
+++ binutils-fsf-trunk-quilt/bfd/elfxx-mips.c	2011-07-29 21:22:12.000000000 +0100
@@ -12264,32 +12264,37 @@ check_br32 (bfd *abfd, bfd_byte *ptr, un
   return FALSE;
 }
 
-/* Bitsize checking.  */
-#define IS_BITSIZE(val, N)						\
-  (((((val) & ((1ULL << (N)) - 1)) ^ (1ULL << ((N) - 1)))		\
-    - (1ULL << ((N) - 1))) == (val))
-
-/* See if relocations [INTERNAL_RELOCS, IRELEND) confirm that there
-   is a 4-byte branch at offset OFFSET.  */
+/* If the instruction encoding at PTR and relocations [INTERNAL_RELOCS,
+   IRELEND) at OFFSET indicate that it is a compact branch there, then
+   return TRUE, otherwise FALSE.  */
 
 static bfd_boolean
-check_4byte_branch (Elf_Internal_Rela *internal_relocs,
-		    Elf_Internal_Rela *irelend, bfd_vma offset)
+check_bzc (bfd *abfd, const bfd_byte *ptr, bfd_vma offset,
+	   const Elf_Internal_Rela *internal_relocs,
+	   const Elf_Internal_Rela *irelend)
 {
-  Elf_Internal_Rela *irel;
-  unsigned long r_type;
+  const Elf_Internal_Rela *irel;
+  unsigned long opcode;
+
+  opcode   = bfd_get_16 (abfd, ptr);
+  opcode <<= 16;
+  opcode  |= bfd_get_16 (abfd, ptr + 2);
+  if (find_match (opcode, bzc_insns_32) < 0)
+    return FALSE;
 
   for (irel = internal_relocs; irel < irelend; irel++)
-    if (irel->r_offset == offset)
-      {
-	r_type = ELF32_R_TYPE (irel->r_info);
-	if (r_type == R_MICROMIPS_26_S1
-	    || r_type == R_MICROMIPS_PC16_S1
-	    || r_type == R_MICROMIPS_JALR)
-	  return TRUE;
-      }
+    if (irel->r_offset == offset
+	&& ELF32_R_TYPE (irel->r_info) == R_MICROMIPS_PC16_S1)
+      return TRUE;
+
   return FALSE;
 }
+
+/* Bitsize checking.  */
+#define IS_BITSIZE(val, N)						\
+  (((((val) & ((1ULL << (N)) - 1)) ^ (1ULL << ((N) - 1)))		\
+    - (1ULL << ((N) - 1))) == (val))
+
 
 bfd_boolean
 _bfd_mips_elf_relax_section (bfd *abfd, asection *sec,
@@ -12451,6 +12456,7 @@ _bfd_mips_elf_relax_section (bfd *abfd, 
          out the offset).  */
       if (r_type == R_MICROMIPS_HI16 && MATCH (opcode, lui_insn))
 	{
+	  bfd_boolean bzc = FALSE;
 	  unsigned long nextopc;
 	  unsigned long reg;
 	  bfd_vma offset;
@@ -12474,18 +12480,18 @@ _bfd_mips_elf_relax_section (bfd *abfd, 
 	      && ELF32_R_SYM (irel[2].r_info) == r_symndx)
 	    continue;
 
-	  /* See if the LUI instruction *might* be in a branch delay slot.  */
+	  /* See if the LUI instruction *might* be in a branch delay slot.
+	     We check whether what looks like a 16-bit branch or jump is
+	     actually an immediate argument to a compact branch, and let
+	     it through if so.  */
 	  if (irel->r_offset >= 2
 	      && check_br16_dslot (abfd, ptr - 2)
 	      && !(irel->r_offset >= 4
-		   /* If the instruction is actually a 4-byte branch,
-		      the value of check_br16_dslot doesn't matter.
-		      We should use check_br32_dslot to check whether
-		      the branch has a delay slot.  */
-		   && check_4byte_branch (internal_relocs, irelend,
-					  irel->r_offset - 4)))
+		   && (bzc = check_bzc (abfd, ptr - 4, irel->r_offset - 4,
+					internal_relocs, irelend))))
 	    continue;
 	  if (irel->r_offset >= 4
+	      && !bzc
 	      && check_br32_dslot (abfd, ptr - 4))
 	    continue;
 


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