[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