This is the mail archive of the
binutils@sourceware.org
mailing list for the binutils project.
[PATCH] MIPS/BFD: Convert jalr/jr to jal/j, if possible
- From: r at hev dot cc
- To: binutils at sourceware dot org
- Cc: Chao-ying dot Fu at imgtec dot com, Heiher <r at hev dot cc>
- Date: Tue, 13 Jun 2017 13:41:51 +0800
- Subject: [PATCH] MIPS/BFD: Convert jalr/jr to jal/j, if possible
- Authentication-results: sourceware.org; auth=none
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