This is the mail archive of the
binutils@sourceware.org
mailing list for the binutils project.
[PATCH] MIPS: microMIPS compact branch linker relaxation check
- From: "Maciej W. Rozycki" <macro at codesourcery dot com>
- To: Richard Sandiford <rdsandiford at googlemail dot com>
- Cc: binutils at sourceware dot org, Chao-ying Fu <fu at mips dot com>, Rich Fuhler <rich at mips dot com>, David Lau <davidlau at mips dot com>, Kevin Mills <kevinm at mips dot com>, Ilie Garbacea <ilie at mips dot com>, Catherine Moore <clm at codesourcery dot com>, Nathan Sidwell <nathan at codesourcery dot com>, Joseph Myers <joseph at codesourcery dot com>
- Date: Sat, 30 Jul 2011 00:28:39 +0100 (BST)
- Subject: [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;