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/BFD: Convert jalr/jr to jal/j, if possible


From: Heiher <r@hev.cc>

2017-06-13  Heiher <r@hev.cc>

	* elfxx-mips.c (JALR_TO_JAL_P): New define to transform JALR to JAL.
	(JR_TO_J_P): New define to transform JR to J.
	It is true for all CPUs.
	Convert "jalr t9" to "jal", if possible.
	Convert "jr t9" to "j", if possible.
	Convert "jalr zero, t9" to "j", if possible.
---
 bfd/ChangeLog    |  9 ++++++
 bfd/elfxx-mips.c | 93 ++++++++++++++++++++++++++++++++++++++++----------------
 2 files changed, 76 insertions(+), 26 deletions(-)

diff --git a/bfd/ChangeLog b/bfd/ChangeLog
index daea1732bc..10edcb8d6f 100644
--- a/bfd/ChangeLog
+++ b/bfd/ChangeLog
@@ -1,3 +1,12 @@
+2017-06-13  Heiher <r@hev.cc>
+
+	* elfxx-mips.c (JALR_TO_JAL_P): New define to transform JALR to JAL.
+	(JR_TO_J_P): New define to transform JR to J.
+	It is true for all CPUs.
+	Convert "jalr t9" to "jal", if possible.
+	Convert "jr t9" to "j", if possible.
+	Convert "jalr zero, t9" to "j", if possible.
+
 2017-06-12  H.J. Lu  <hongjiu.lu@intel.com>
 
 	* elf-bfd.h (elf_backend_data): Add struct bfd_link_info *
diff --git a/bfd/elfxx-mips.c b/bfd/elfxx-mips.c
index 830207ad6a..308b8d76ad 100644
--- a/bfd/elfxx-mips.c
+++ b/bfd/elfxx-mips.c
@@ -777,6 +777,16 @@ static bfd *reldyn_sorting_bfd;
    all CPUs.  */
 #define JR_TO_B_P(abfd) 1
 
+/* True if ABFD is for CPUs that are faster if JALR is converted to JAL.
+   This should be safe for all architectures.  We enable this predicate for
+   all CPUs.  */
+#define JALR_TO_JAL_P(abfd) 1
+
+/* True if ABFD is for CPUs that are faster if JR is converted to J.
+   This should be safe for all architectures.  We enable this predicate for
+   all CPUs.  */
+#define JR_TO_J_P(abfd) 1
+
 /* True if ABFD is a PIC object.  */
 #define PIC_OBJECT_P(abfd) \
   ((elf_elfheader (abfd)->e_flags & EF_MIPS_PIC) != 0)
@@ -6459,11 +6469,14 @@ mips_elf_perform_relocation (struct bfd_link_info *info,
 	}
     }
 
-  /* Try converting JAL to BAL and J(AL)R to B(AL), if the target is in
-     range.  */
   if (!bfd_link_relocatable (info)
-      && !cross_mode_jump_p
-      && ((JAL_TO_BAL_P (input_bfd)
+      && !cross_mode_jump_p)
+    {
+      bfd_boolean skip_to_j_p = FALSE;
+
+      /* Try converting JAL to BAL and J(AL)R to B(AL), if the target is in
+         range.  */
+      if ((JAL_TO_BAL_P (input_bfd)
 	   && r_type == R_MIPS_26
 	   && (x >> 26) == 0x3)			/* jal addr */
 	  || (JALR_TO_BAL_P (input_bfd)
@@ -6471,28 +6484,56 @@ mips_elf_perform_relocation (struct bfd_link_info *info,
 	      && x == 0x0320f809)		/* jalr t9 */
 	  || (JR_TO_B_P (input_bfd)
 	      && r_type == R_MIPS_JALR
-	      && (x & ~1) == 0x03200008)))	/* jr t9 / jalr zero, t9 */
-    {
-      bfd_vma addr;
-      bfd_vma dest;
-      bfd_signed_vma off;
-
-      addr = (input_section->output_section->vma
-	      + input_section->output_offset
-	      + relocation->r_offset
-	      + 4);
-      if (r_type == R_MIPS_26)
-	dest = (value << 2) | ((addr >> 28) << 28);
-      else
-	dest = value;
-      off = dest - addr;
-      if (off <= 0x1ffff && off >= -0x20000)
-	{
-	  if ((x & ~1) == 0x03200008)		/* jr t9 / jalr zero, t9 */
-	    x = 0x10000000 | (((bfd_vma) off >> 2) & 0xffff);   /* b addr */
-	  else
-	    x = 0x04110000 | (((bfd_vma) off >> 2) & 0xffff);   /* bal addr */
-	}
+	      && (x & ~1) == 0x03200008))	/* jr t9 / jalr zero, t9 */
+        {
+          bfd_vma addr;
+          bfd_vma dest;
+          bfd_signed_vma off;
+
+          addr = (input_section->output_section->vma
+	          + input_section->output_offset
+	          + relocation->r_offset
+	          + 4);
+          if (r_type == R_MIPS_26)
+	    dest = (value << 2) | ((addr >> 28) << 28);
+          else
+	    dest = value;
+          off = dest - addr;
+          if (off <= 0x1ffff && off >= -0x20000)
+	    {
+	      if ((x & ~1) == 0x03200008)		/* jr t9 / jalr zero, t9 */
+	        x = 0x10000000 | (((bfd_vma) off >> 2) & 0xffff);   /* b addr */
+	      else
+	        x = 0x04110000 | (((bfd_vma) off >> 2) & 0xffff);   /* bal addr */
+	      skip_to_j_p = TRUE;
+	    }
+        }
+
+      /* Try converting J(AL)R to J(AL), if the target is in range. */
+      if (!bfd_link_pic (info)
+	  && !skip_to_j_p
+	  && ((JALR_TO_JAL_P (input_bfd)
+	         && r_type == R_MIPS_JALR
+	         && x == 0x0320f809)		/* jalr t9 */
+	     || (JR_TO_J_P (input_bfd)
+	         && r_type == R_MIPS_JALR
+	         && (x & ~1) == 0x03200008)))	/* jr t9 / jalr zero, t9 */
+        {
+          bfd_vma addr;
+          bfd_vma dest = value;
+
+          addr = (input_section->output_section->vma
+	          + input_section->output_offset
+	          + relocation->r_offset
+	          + 4);
+          if (((addr >> 28) << 28) == ((dest >> 28) << 28))
+	    {
+	      if ((x & ~1) == 0x03200008)		/* jr t9 / jalr zero, t9 */
+	        x = 0x08000000 | ((dest >> 2) & 0x3ffffff);   /* j addr */
+	      else
+	        x = 0x0c000000 | ((dest >> 2) & 0x3ffffff);   /* jal addr */
+	    }
+        }
     }
 
   /* Put the value into the output.  */
-- 
2.13.1


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