[RFC] Only NOP in delayed branches in .MIPS.stubs section
Maksim Kozlov
maksim.e.kozlov@gmail.com
Wed Apr 4 10:07:00 GMT 2018
Hi all,
I work with mips32 based SoC, which has some restrictions (errata). One of
them - only the NOP instruction in delay slot is allowed.
Mainly, this restriction is resolved easily by passing -fno-delayed-branch
flag to compiller and by patching .noreorder sections in assembler code.
But there is a problem with .MIPS.stubs section - ELF backend linker
generates code like this:
004007a0 <_MIPS_STUBS_>:
4007a0: 8f998010 lw t9,-32752(gp)
4007a4: 03e07825 move t7,ra
4007a8: 0320f809 jalr t9
4007ac: 2418000b li t8,11
4007b0: 8f998010 lw t9,-32752(gp)
4007b4: 03e07825 move t7,ra
4007b8: 0320f809 jalr t9
4007bc: 24180009 li t8,9
But it is expected like this:
004007a0 <_MIPS_STUBS_>:
4007a0: 8f998010 lw t9,-32752(gp)
4007a4: 03e07825 move t7,ra
4007a8: 2418000b li t8,11
4007ac: 0320f809 jalr t9
4007b0: 00000000 nop
4007b4: 8f998010 lw t9,-32752(gp)
4007b8: 03e07825 move t7,ra
4007bc: 24180009 li t8,9
4007c0: 0320f809 jalr t9
4007c4: 00000000 nop
For now, to resolve this, I use my own patch which is just a dirty hack
(bellow, at the end of the message). I'm not a GNU tools expert, but, in my
humble opinion, it would be great to get the same result just by passing
-fno-delayed-branch flag to compiler.
I would like to create more proper patch, but my main difficulty is that I
can not found a right way to detect if -fno-delayed-branch flag is used
(was used in as). So, I need advice to resolve this. I would be very
thankfull for that.
And more general question - does it make sense to develop correct patch for
that at all? Or this is minor specific problem that everyone should resolve
himself for his specific situation?
--
Best regards,
Maksim Kozlov
diff --git a/bfd/elfxx-mips.c b/bfd/elfxx-mips.c
index fc49f2f..b13e6a7 100644
--- a/bfd/elfxx-mips.c
+++ b/bfd/elfxx-mips.c
@@ -940,9 +940,10 @@ static bfd *reldyn_sorting_bfd;
(ABI_64_P (abfd) \
? 0x5f000000 + (VAL) /* daddiu t8,zero,VAL sign extended */ \
: 0x33000000 + (VAL)) /* addiu t8,zero,VAL sign extended */
+#define STUB_NOP 0x00000000
-#define MIPS_FUNCTION_STUB_NORMAL_SIZE 16
-#define MIPS_FUNCTION_STUB_BIG_SIZE 20
+#define MIPS_FUNCTION_STUB_NORMAL_SIZE 20
+#define MIPS_FUNCTION_STUB_BIG_SIZE 24
#define MICROMIPS_FUNCTION_STUB_NORMAL_SIZE 12
#define MICROMIPS_FUNCTION_STUB_BIG_SIZE 16
#define MICROMIPS_INSN32_FUNCTION_STUB_NORMAL_SIZE 16
@@ -10822,8 +10823,6 @@ _bfd_mips_elf_finish_dynamic_symbol (bfd
*output_bfd,
stub + idx);
idx += 4;
}
- bfd_put_32 (output_bfd, STUB_JALR, stub + idx);
- idx += 4;
/* If a large stub is not required and sign extension is not a
problem, then use legacy code in the stub. */
@@ -10836,6 +10835,12 @@ _bfd_mips_elf_finish_dynamic_symbol (bfd
*output_bfd,
else
bfd_put_32 (output_bfd, STUB_LI16S (output_bfd, h->dynindx),
stub + idx);
+
+ idx += 4;
+
+ bfd_put_32 (output_bfd, STUB_JALR, stub + idx);
+ idx += 4;
+ bfd_put_32 (output_bfd, STUB_NOP, stub + idx);
}
BFD_ASSERT (h->plt.plist->stub_offset <= htab->sstubs->size);
More information about the Binutils
mailing list