summaryrefslogtreecommitdiffstats
path: root/binutils-2.25/bfd/elfxx-mips.c
diff options
context:
space:
mode:
Diffstat (limited to 'binutils-2.25/bfd/elfxx-mips.c')
-rw-r--r--binutils-2.25/bfd/elfxx-mips.c65
1 files changed, 48 insertions, 17 deletions
diff --git a/binutils-2.25/bfd/elfxx-mips.c b/binutils-2.25/bfd/elfxx-mips.c
index 27176100..2bd45d20 100644
--- a/binutils-2.25/bfd/elfxx-mips.c
+++ b/binutils-2.25/bfd/elfxx-mips.c
@@ -442,6 +442,9 @@ struct mips_elf_link_hash_table
/* True if we can only use 32-bit microMIPS instructions. */
bfd_boolean insn32;
+ /* True if we are targetting R6 compact branches. */
+ bfd_boolean compact_branches;
+
/* True if we're generating code for VxWorks. */
bfd_boolean is_vxworks;
@@ -1105,15 +1108,20 @@ static const bfd_vma mips_exec_plt_entry[] =
0x03200008 /* jr $25 */
};
-/* In the following PLT entry the JR and ADDIU instructions will
- be swapped in _bfd_mips_elf_finish_dynamic_symbol because
- LOAD_INTERLOCKS_P will be true for MIPS R6. */
static const bfd_vma mipsr6_exec_plt_entry[] =
{
0x3c0f0000, /* lui $15, %hi(.got.plt entry) */
0x01f90000, /* l[wd] $25, %lo(.got.plt entry)($15) */
+ 0x03200009, /* jr $25 */
+ 0x25f80000 /* addiu $24, $15, %lo(.got.plt entry) */
+};
+
+static const bfd_vma mipsr6_exec_plt_entry_compact[] =
+{
+ 0x3c0f0000, /* lui $15, %hi(.got.plt entry) */
+ 0x01f90000, /* l[wd] $25, %lo(.got.plt entry)($15) */
0x25f80000, /* addiu $24, $15, %lo(.got.plt entry) */
- 0x03200009 /* jr $25 */
+ 0xd8190000 /* jic $25, 0 */
};
/* The format of subsequent MIPS16 o32 PLT entries. We use v0 ($2)
@@ -5928,7 +5936,8 @@ mips_elf_calculate_relocation (bfd *abfd, bfd *input_bfd,
to them before. */
if (was_local_p)
value += gp0;
- overflowed_p = mips_elf_overflow_p (value, 16);
+ if (was_local_p || h->root.root.type != bfd_link_hash_undefweak)
+ overflowed_p = mips_elf_overflow_p (value, 16);
break;
case R_MIPS16_GOT16:
@@ -5983,7 +5992,8 @@ mips_elf_calculate_relocation (bfd *abfd, bfd *input_bfd,
return bfd_reloc_outofrange;
value = symbol + addend - p;
- overflowed_p = mips_elf_overflow_p (value, 18);
+ if (was_local_p || h->root.root.type != bfd_link_hash_undefweak)
+ overflowed_p = mips_elf_overflow_p (value, 18);
value >>= howto->rightshift;
value &= howto->dst_mask;
break;
@@ -5996,7 +6006,8 @@ mips_elf_calculate_relocation (bfd *abfd, bfd *input_bfd,
return bfd_reloc_outofrange;
value = symbol + addend - p;
- overflowed_p = mips_elf_overflow_p (value, 23);
+ if (was_local_p || h->root.root.type != bfd_link_hash_undefweak)
+ overflowed_p = mips_elf_overflow_p (value, 23);
value >>= howto->rightshift;
value &= howto->dst_mask;
break;
@@ -6009,7 +6020,8 @@ mips_elf_calculate_relocation (bfd *abfd, bfd *input_bfd,
return bfd_reloc_outofrange;
value = symbol + addend - p;
- overflowed_p = mips_elf_overflow_p (value, 28);
+ if (was_local_p || h->root.root.type != bfd_link_hash_undefweak)
+ overflowed_p = mips_elf_overflow_p (value, 28);
value >>= howto->rightshift;
value &= howto->dst_mask;
break;
@@ -6022,7 +6034,8 @@ mips_elf_calculate_relocation (bfd *abfd, bfd *input_bfd,
return bfd_reloc_outofrange;
value = symbol + addend - ((p | 7) ^ 7);
- overflowed_p = mips_elf_overflow_p (value, 21);
+ if (was_local_p || h->root.root.type != bfd_link_hash_undefweak)
+ overflowed_p = mips_elf_overflow_p (value, 21);
value >>= howto->rightshift;
value &= howto->dst_mask;
break;
@@ -6035,14 +6048,16 @@ mips_elf_calculate_relocation (bfd *abfd, bfd *input_bfd,
return bfd_reloc_outofrange;
value = symbol + addend - p;
- overflowed_p = mips_elf_overflow_p (value, 21);
+ if (was_local_p || h->root.root.type != bfd_link_hash_undefweak)
+ overflowed_p = mips_elf_overflow_p (value, 21);
value >>= howto->rightshift;
value &= howto->dst_mask;
break;
case R_MIPS_PCHI16:
value = mips_elf_high (symbol + addend - p);
- overflowed_p = mips_elf_overflow_p (value, 16);
+ if (was_local_p || h->root.root.type != bfd_link_hash_undefweak)
+ overflowed_p = mips_elf_overflow_p (value, 16);
value &= howto->dst_mask;
break;
@@ -6057,7 +6072,8 @@ mips_elf_calculate_relocation (bfd *abfd, bfd *input_bfd,
if (howto->partial_inplace)
addend = _bfd_mips_elf_sign_extend (addend, 8);
value = symbol + addend - p;
- overflowed_p = mips_elf_overflow_p (value, 8);
+ if (was_local_p || h->root.root.type != bfd_link_hash_undefweak)
+ overflowed_p = mips_elf_overflow_p (value, 8);
value >>= howto->rightshift;
value &= howto->dst_mask;
break;
@@ -6066,7 +6082,8 @@ mips_elf_calculate_relocation (bfd *abfd, bfd *input_bfd,
if (howto->partial_inplace)
addend = _bfd_mips_elf_sign_extend (addend, 11);
value = symbol + addend - p;
- overflowed_p = mips_elf_overflow_p (value, 11);
+ if (was_local_p || h->root.root.type != bfd_link_hash_undefweak)
+ overflowed_p = mips_elf_overflow_p (value, 11);
value >>= howto->rightshift;
value &= howto->dst_mask;
break;
@@ -6075,7 +6092,8 @@ mips_elf_calculate_relocation (bfd *abfd, bfd *input_bfd,
if (howto->partial_inplace)
addend = _bfd_mips_elf_sign_extend (addend, 17);
value = symbol + addend - p;
- overflowed_p = mips_elf_overflow_p (value, 17);
+ if (was_local_p || h->root.root.type != bfd_link_hash_undefweak)
+ overflowed_p = mips_elf_overflow_p (value, 17);
value >>= howto->rightshift;
value &= howto->dst_mask;
break;
@@ -6084,7 +6102,8 @@ mips_elf_calculate_relocation (bfd *abfd, bfd *input_bfd,
if (howto->partial_inplace)
addend = _bfd_mips_elf_sign_extend (addend, 25);
value = symbol + addend - ((p | 3) ^ 3);
- overflowed_p = mips_elf_overflow_p (value, 25);
+ if (was_local_p || h->root.root.type != bfd_link_hash_undefweak)
+ overflowed_p = mips_elf_overflow_p (value, 25);
value >>= howto->rightshift;
value &= howto->dst_mask;
break;
@@ -10546,7 +10565,10 @@ _bfd_mips_elf_finish_dynamic_symbol (bfd *output_bfd,
/* Fill in the PLT entry itself. */
- if (MIPSR6_P (output_bfd))
+ if (MIPSR6_P (output_bfd)
+ && mips_elf_hash_table (info)->compact_branches)
+ plt_entry = mipsr6_exec_plt_entry_compact;
+ else if (MIPSR6_P (output_bfd))
plt_entry = mipsr6_exec_plt_entry;
else
plt_entry = mips_exec_plt_entry;
@@ -10554,7 +10576,7 @@ _bfd_mips_elf_finish_dynamic_symbol (bfd *output_bfd,
bfd_put_32 (output_bfd, plt_entry[1] | got_address_low | load,
loc + 4);
- if (! LOAD_INTERLOCKS_P (output_bfd))
+ if (! LOAD_INTERLOCKS_P (output_bfd) || MIPSR6_P (output_bfd))
{
bfd_put_32 (output_bfd, plt_entry[2] | got_address_low, loc + 8);
bfd_put_32 (output_bfd, plt_entry[3], loc + 12);
@@ -13865,6 +13887,13 @@ _bfd_mips_elf_insn32 (struct bfd_link_info *info, bfd_boolean on)
{
mips_elf_hash_table (info)->insn32 = on;
}
+
+void
+_bfd_mips_elf_compact_branches (struct bfd_link_info *info, bfd_boolean on)
+{
+ mips_elf_hash_table (info)->compact_branches = on;
+}
+
/* Return the .MIPS.abiflags value representing each ISA Extension. */
@@ -15491,6 +15520,8 @@ print_mips_ases (FILE *file, unsigned int mask)
fputs ("\n\tDSP ASE", file);
if (mask & AFL_ASE_DSPR2)
fputs ("\n\tDSP R2 ASE", file);
+ if (mask & AFL_ASE_DSPR6)
+ fputs ("\n\tDSP R6 ASE", file);
if (mask & AFL_ASE_EVA)
fputs ("\n\tEnhanced VA Scheme", file);
if (mask & AFL_ASE_MCU)