aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--bfd/ChangeLog14
-rw-r--r--bfd/elfxx-mips.c48
-rw-r--r--bfd/elfxx-mips.h4
-rw-r--r--gas/ChangeLog28
-rw-r--r--gas/config/tc-mips.c22
-rw-r--r--gas/doc/as.texinfo12
-rw-r--r--gas/doc/c-mips.texi31
-rw-r--r--gas/testsuite/gas/mips/branch-local-ignore-2.d29
-rw-r--r--gas/testsuite/gas/mips/branch-local-ignore-3.d23
-rw-r--r--gas/testsuite/gas/mips/branch-local-ignore-n32-2.d29
-rw-r--r--gas/testsuite/gas/mips/branch-local-ignore-n32-3.d23
-rw-r--r--gas/testsuite/gas/mips/branch-local-ignore-n64-2.d37
-rw-r--r--gas/testsuite/gas/mips/branch-local-ignore-n64-3.d27
-rw-r--r--gas/testsuite/gas/mips/mips.exp6
-rw-r--r--ld/ChangeLog30
-rw-r--r--ld/emultempl/mipself.em25
-rw-r--r--ld/ld.texinfo30
-rw-r--r--ld/testsuite/ld-mips-elf/bal-jalx-pic-ignore-n32.d6
-rw-r--r--ld/testsuite/ld-mips-elf/bal-jalx-pic-ignore-n64.d6
-rw-r--r--ld/testsuite/ld-mips-elf/bal-jalx-pic-ignore.d22
-rw-r--r--ld/testsuite/ld-mips-elf/mips-elf.exp11
-rw-r--r--ld/testsuite/ld-mips-elf/unaligned-branch-ignore-2.d64
-rw-r--r--ld/testsuite/ld-mips-elf/unaligned-branch-ignore-micromips.d84
-rw-r--r--ld/testsuite/ld-mips-elf/unaligned-branch-ignore-mips16.d36
-rw-r--r--ld/testsuite/ld-mips-elf/unaligned-branch-ignore-r6-1.d72
25 files changed, 694 insertions, 25 deletions
diff --git a/bfd/ChangeLog b/bfd/ChangeLog
index bbc7e0e..8ff43e1 100644
--- a/bfd/ChangeLog
+++ b/bfd/ChangeLog
@@ -1,3 +1,17 @@
+2017-01-30 Maciej W. Rozycki <macro@imgtec.com>
+
+ * elfxx-mips.h (_bfd_mips_elf_insn32): Rename prototype to...
+ (_bfd_mips_elf_linker_flags): ... this. Add another parameter.
+ * elfxx-mips.c (mips_elf_link_hash_table): Add
+ `ignore_branch_isa' member.
+ (mips_elf_perform_relocation): Do not treat an ISA mode mismatch
+ in branch relocation calculation as an error if
+ `ignore_branch_isa' has been set.
+ (_bfd_mips_elf_insn32): Rename to...
+ (_bfd_mips_elf_linker_flags): ... this. Rename the `on'
+ parameter to `insn32' and add an `ignore_branch_isa' parameter.
+ Handle the new parameter.
+
2017-01-18 Maciej W. Rozycki <macro@imgtec.com>
PR ld/20828
diff --git a/bfd/elfxx-mips.c b/bfd/elfxx-mips.c
index ce58c43..bda02b1 100644
--- a/bfd/elfxx-mips.c
+++ b/bfd/elfxx-mips.c
@@ -443,6 +443,9 @@ struct mips_elf_link_hash_table
/* True if we can only use 32-bit microMIPS instructions. */
bfd_boolean insn32;
+ /* True if we suppress checks for invalid branches between ISA modes. */
+ bfd_boolean ignore_branch_isa;
+
/* True if we're generating code for VxWorks. */
bfd_boolean is_vxworks;
@@ -6416,31 +6419,33 @@ mips_elf_perform_relocation (struct bfd_link_info *info,
value <<= 2;
}
- if (bfd_link_pic (info) || !ok)
+ if (ok && !bfd_link_pic (info))
{
- info->callbacks->einfo
- (_("%X%H: Unsupported branch between ISA modes\n"),
- input_bfd, input_section, relocation->r_offset);
- return TRUE;
- }
+ addr = (input_section->output_section->vma
+ + input_section->output_offset
+ + relocation->r_offset
+ + 4);
+ dest = addr + (((value & 0x3ffff) ^ 0x20000) - 0x20000);
- addr = (input_section->output_section->vma
- + input_section->output_offset
- + relocation->r_offset
- + 4);
- dest = addr + (((value & 0x3ffff) ^ 0x20000) - 0x20000);
+ if ((addr >> 28) << 28 != (dest >> 28) << 28)
+ {
+ info->callbacks->einfo
+ (_("%X%H: Cannot convert branch between ISA modes "
+ "to JALX: relocation out of range\n"),
+ input_bfd, input_section, relocation->r_offset);
+ return TRUE;
+ }
- if ((addr >> 28) << 28 != (dest >> 28) << 28)
+ /* Make this the JALX opcode. */
+ x = ((dest >> 2) & 0x3ffffff) | jalx_opcode << 26;
+ }
+ else if (!mips_elf_hash_table (info)->ignore_branch_isa)
{
info->callbacks->einfo
- (_("%X%H: Cannot convert branch between ISA modes "
- "to JALX: relocation out of range\n"),
+ (_("%X%H: Unsupported branch between ISA modes\n"),
input_bfd, input_section, relocation->r_offset);
return TRUE;
}
-
- /* Make this the JALX opcode. */
- x = ((dest >> 2) & 0x3ffffff) | jalx_opcode << 26;
}
/* Try converting JAL to BAL and J(AL)R to B(AL), if the target is in
@@ -14095,12 +14100,15 @@ _bfd_mips_elf_use_plts_and_copy_relocs (struct bfd_link_info *info)
}
/* A function that the linker calls to select between all or only
- 32-bit microMIPS instructions. */
+ 32-bit microMIPS instructions, and between making or ignoring
+ branch relocation checks for invalid transitions between ISA modes. */
void
-_bfd_mips_elf_insn32 (struct bfd_link_info *info, bfd_boolean on)
+_bfd_mips_elf_linker_flags (struct bfd_link_info *info, bfd_boolean insn32,
+ bfd_boolean ignore_branch_isa)
{
- mips_elf_hash_table (info)->insn32 = on;
+ mips_elf_hash_table (info)->insn32 = insn32;
+ mips_elf_hash_table (info)->ignore_branch_isa = ignore_branch_isa;
}
/* Structure for saying that BFD machine EXTENSION extends BASE. */
diff --git a/bfd/elfxx-mips.h b/bfd/elfxx-mips.h
index 8f16cc9..fa5b5d2 100644
--- a/bfd/elfxx-mips.h
+++ b/bfd/elfxx-mips.h
@@ -150,8 +150,8 @@ extern bfd_boolean _bfd_mips_elf_ignore_undef_symbol
(struct elf_link_hash_entry *);
extern void _bfd_mips_elf_use_plts_and_copy_relocs
(struct bfd_link_info *);
-extern void _bfd_mips_elf_insn32
- (struct bfd_link_info *, bfd_boolean);
+extern void _bfd_mips_elf_linker_flags
+ (struct bfd_link_info *, bfd_boolean, bfd_boolean);
extern bfd_boolean _bfd_mips_elf_init_stubs
(struct bfd_link_info *,
asection *(*) (const char *, asection *, asection *));
diff --git a/gas/ChangeLog b/gas/ChangeLog
index c693e2f..d6f9aef 100644
--- a/gas/ChangeLog
+++ b/gas/ChangeLog
@@ -1,5 +1,33 @@
2017-01-30 Maciej W. Rozycki <macro@imgtec.com>
+ * config/tc-mips.c (mips_ignore_branch_isa): New variable.
+ (options): Add OPTION_IGNORE_BRANCH_ISA and
+ OPTION_NO_IGNORE_BRANCH_ISA enum values.
+ (md_longopts): Add "mignore-branch-isa" and
+ "mno-ignore-branch-isa" options.
+ (md_parse_option): Handle OPTION_IGNORE_BRANCH_ISA and
+ OPTION_NO_IGNORE_BRANCH_ISA.
+ (fix_bad_cross_mode_branch_p): Return FALSE if
+ `mips_ignore_branch_isa' has been set.
+ (md_show_usage): Add `-mignore-branch-isa' and
+ `-mno-ignore-branch-isa'.
+
+ * doc/as.texinfo (Target MIPS options): Add
+ `-mignore-branch-isa' and `-mno-ignore-branch-isa' options.
+ (-mignore-branch-isa, -mno-ignore-branch-isa): New options.
+ * doc/c-mips.texi (MIPS Options): Add `-mignore-branch-isa' and
+ `-mno-ignore-branch-isa' options.
+
+ * testsuite/gas/mips/branch-local-ignore-2.d: New test.
+ * testsuite/gas/mips/branch-local-ignore-3.d: New test.
+ * testsuite/gas/mips/branch-local-ignore-n32-2.d: New test.
+ * testsuite/gas/mips/branch-local-ignore-n32-3.d: New test.
+ * testsuite/gas/mips/branch-local-ignore-n64-2.d: New test.
+ * testsuite/gas/mips/branch-local-ignore-n64-3.d: New test.
+ * testsuite/gas/mips/mips.exp: Run the new tests.
+
+2017-01-30 Maciej W. Rozycki <macro@imgtec.com>
+
* testsuite/gas/mips/branch-local-2.d: New test.
* testsuite/gas/mips/branch-local-3.d: New test.
* testsuite/gas/mips/branch-local-n32-2.d: New test.
diff --git a/gas/config/tc-mips.c b/gas/config/tc-mips.c
index 1487e73..e24e84d 100644
--- a/gas/config/tc-mips.c
+++ b/gas/config/tc-mips.c
@@ -943,6 +943,11 @@ static bfd_boolean mips_fix_cn63xxp1;
efficient expansion. */
static int mips_relax_branch;
+
+/* TRUE if checks are suppressed for invalid branches between ISA modes.
+ Needed for broken assembly produced by some GCC versions and some
+ sloppy code out there, where branches to data labels are present. */
+static bfd_boolean mips_ignore_branch_isa;
/* The expansion of many macros depends on the type of symbol that
they refer to. For example, when generating position-dependent code,
@@ -1465,6 +1470,8 @@ enum options
OPTION_GP64,
OPTION_RELAX_BRANCH,
OPTION_NO_RELAX_BRANCH,
+ OPTION_IGNORE_BRANCH_ISA,
+ OPTION_NO_IGNORE_BRANCH_ISA,
OPTION_INSN32,
OPTION_NO_INSN32,
OPTION_MSHARED,
@@ -1591,6 +1598,8 @@ struct option md_longopts[] =
{"mgp64", no_argument, NULL, OPTION_GP64},
{"relax-branch", no_argument, NULL, OPTION_RELAX_BRANCH},
{"no-relax-branch", no_argument, NULL, OPTION_NO_RELAX_BRANCH},
+ {"mignore-branch-isa", no_argument, NULL, OPTION_IGNORE_BRANCH_ISA},
+ {"mno-ignore-branch-isa", no_argument, NULL, OPTION_NO_IGNORE_BRANCH_ISA},
{"minsn32", no_argument, NULL, OPTION_INSN32},
{"mno-insn32", no_argument, NULL, OPTION_NO_INSN32},
{"mshared", no_argument, NULL, OPTION_MSHARED},
@@ -14499,6 +14508,14 @@ md_parse_option (int c, const char *arg)
mips_relax_branch = 0;
break;
+ case OPTION_IGNORE_BRANCH_ISA:
+ mips_ignore_branch_isa = TRUE;
+ break;
+
+ case OPTION_NO_IGNORE_BRANCH_ISA:
+ mips_ignore_branch_isa = FALSE;
+ break;
+
case OPTION_INSN32:
file_mips_opts.insn32 = TRUE;
break;
@@ -15133,6 +15150,9 @@ fix_bad_cross_mode_branch_p (fixS *fixP)
int other;
char *buf;
+ if (mips_ignore_branch_isa)
+ return FALSE;
+
if (!fixP->fx_addsy || S_FORCE_RELOC (fixP->fx_addsy, TRUE))
return FALSE;
@@ -19662,6 +19682,8 @@ MIPS options:\n\
-mdouble-float allow 32-bit and 64-bit floating-point operations\n\
--[no-]construct-floats [dis]allow floating point values to be constructed\n\
--[no-]relax-branch [dis]allow out-of-range branches to be relaxed\n\
+-mignore-branch-isa accept invalid branches requiring an ISA mode switch\n\
+-mno-ignore-branch-isa reject invalid branches requiring an ISA mode switch\n\
-mnan=ENCODING select an IEEE 754 NaN encoding convention, either of:\n"));
first = 1;
diff --git a/gas/doc/as.texinfo b/gas/doc/as.texinfo
index 83b85f3..e068419 100644
--- a/gas/doc/as.texinfo
+++ b/gas/doc/as.texinfo
@@ -416,6 +416,7 @@ gcc(1), ld(1), and the Info entries for @file{binutils} and @file{ld}.
[@b{-mips32r3}] [@b{-mips32r5}] [@b{-mips32r6}] [@b{-mips64}] [@b{-mips64r2}]
[@b{-mips64r3}] [@b{-mips64r5}] [@b{-mips64r6}]
[@b{-construct-floats}] [@b{-no-construct-floats}]
+ [@b{-mignore-branch-isa}] [@b{-mno-ignore-branch-isa}]
[@b{-mnan=@var{encoding}}]
[@b{-trap}] [@b{-no-break}] [@b{-break}] [@b{-no-trap}]
[@b{-mips16}] [@b{-no-mips16}]
@@ -1521,6 +1522,17 @@ The @samp{--relax-branch} option enables the relaxation of out-of-range
branches. By default @samp{--no-relax-branch} is selected, causing any
out-of-range branches to produce an error.
+@item -mignore-branch-isa
+@itemx -mno-ignore-branch-isa
+Ignore branch checks for invalid transitions between ISA modes. The
+semantics of branches does not provide for an ISA mode switch, so in
+most cases the ISA mode a branch has been encoded for has to be the
+same as the ISA mode of the branch's target label. Therefore GAS has
+checks implemented that verify in branch assembly that the two ISA
+modes match. @samp{-mignore-branch-isa} disables these checks. By
+default @samp{-mno-ignore-branch-isa} is selected, causing any invalid
+branch requiring a transition between ISA modes to produce an error.
+
@item -mnan=@var{encoding}
Select between the IEEE 754-2008 (@option{-mnan=2008}) or the legacy
(@option{-mnan=legacy}) NaN encoding format. The latter is the default.
diff --git a/gas/doc/c-mips.texi b/gas/doc/c-mips.texi
index 04666f4..d9a09f1 100644
--- a/gas/doc/c-mips.texi
+++ b/gas/doc/c-mips.texi
@@ -472,6 +472,37 @@ Also no MIPS16 branches are ever relaxed.
By default @samp{--no-relax-branch} is selected, causing any out-of-range
branches to produce an error.
+@item -mignore-branch-isa
+@itemx -mno-ignore-branch-isa
+Ignore branch checks for invalid transitions between ISA modes.
+
+The semantics of branches does not provide for an ISA mode switch, so in
+most cases the ISA mode a branch has been encoded for has to be the same
+as the ISA mode of the branch's target label. If the ISA modes do not
+match, then such a branch, if taken, will cause the ISA mode to remain
+unchanged and instructions that follow will be executed in the wrong ISA
+mode causing the program to misbehave or crash.
+
+In the case of the @code{BAL} instruction it may be possible to relax
+it to an equivalent @code{JALX} instruction so that the ISA mode is
+switched at the run time as required. For other branches no relaxation
+is possible and therefore GAS has checks implemented that verify in
+branch assembly that the two ISA modes match, and report an error
+otherwise so that the problem with code can be diagnosed at the assembly
+time rather than at the run time.
+
+However some assembly code, including generated code produced by some
+versions of GCC, may incorrectly include branches to data labels, which
+appear to require a mode switch but are either dead or immediately
+followed by valid instructions encoded for the same ISA the branch has
+been encoded for. While not strictly correct at the source level such
+code will execute as intended, so to help with these cases
+@samp{-mignore-branch-isa} is supported which disables ISA mode checks
+for branches.
+
+By default @samp{-mno-ignore-branch-isa} is selected, causing any invalid
+branch requiring a transition between ISA modes to produce an error.
+
@cindex @option{-mnan=} command line option, MIPS
@item -mnan=@var{encoding}
This option indicates whether the source code uses the IEEE 2008
diff --git a/gas/testsuite/gas/mips/branch-local-ignore-2.d b/gas/testsuite/gas/mips/branch-local-ignore-2.d
new file mode 100644
index 0000000..ddac741
--- /dev/null
+++ b/gas/testsuite/gas/mips/branch-local-ignore-2.d
@@ -0,0 +1,29 @@
+#objdump: -dr --prefix-addresses --show-raw-insn
+#name: MIPS branch local symbol relocation 2 (ignore branch ISA)
+#as: -32 -mignore-branch-isa
+#source: branch-local-2.s
+
+.*: +file format .*mips.*
+
+Disassembly of section \.text:
+ \.\.\.
+[0-9a-f]+ <[^>]*> 0000 02d0 not zero,zero
+[0-9a-f]+ <[^>]*> 001f 0f3c jr ra
+[0-9a-f]+ <[^>]*> 0000 02d0 not zero,zero
+[0-9a-f]+ <[^>]*> 0000 0000 nop
+[0-9a-f]+ <[^>]*> 00000027 nor zero,zero,zero
+[0-9a-f]+ <[^>]*> 1000ffff b 00001014 <bar\+0x4>
+[ ]*[0-9a-f]+: R_MIPS_PC16 foo
+[0-9a-f]+ <[^>]*> 00000027 nor zero,zero,zero
+[0-9a-f]+ <[^>]*> 1443ffff bne v0,v1,0000101c <bar\+0xc>
+[ ]*[0-9a-f]+: R_MIPS_PC16 foo
+[0-9a-f]+ <[^>]*> 00000027 nor zero,zero,zero
+[0-9a-f]+ <[^>]*> 0451ffff bgezal v0,00001024 <bar\+0x14>
+[ ]*[0-9a-f]+: R_MIPS_PC16 foo
+[0-9a-f]+ <[^>]*> 00000027 nor zero,zero,zero
+[0-9a-f]+ <[^>]*> 0450ffff bltzal v0,0000102c <bar\+0x1c>
+[ ]*[0-9a-f]+: R_MIPS_PC16 foo
+[0-9a-f]+ <[^>]*> 00000027 nor zero,zero,zero
+[0-9a-f]+ <[^>]*> 03e00009 jalr zero,ra
+[0-9a-f]+ <[^>]*> 00000027 nor zero,zero,zero
+ \.\.\.
diff --git a/gas/testsuite/gas/mips/branch-local-ignore-3.d b/gas/testsuite/gas/mips/branch-local-ignore-3.d
new file mode 100644
index 0000000..918a2ce
--- /dev/null
+++ b/gas/testsuite/gas/mips/branch-local-ignore-3.d
@@ -0,0 +1,23 @@
+#objdump: -dr --prefix-addresses --show-raw-insn -mmips:isa32r6
+#name: MIPS branch local symbol relocation 3 (ignore branch ISA)
+#as: -32 -mignore-branch-isa
+#source: branch-local-3.s
+
+.*: +file format .*mips.*
+
+Disassembly of section \.text:
+ \.\.\.
+[0-9a-f]+ <[^>]*> 0000 02d0 not zero,zero
+[0-9a-f]+ <[^>]*> 001f 0f3c jr ra
+[0-9a-f]+ <[^>]*> 0000 02d0 not zero,zero
+[0-9a-f]+ <[^>]*> 0000 0000 nop
+[0-9a-f]+ <[^>]*> 00000027 nor zero,zero,zero
+[0-9a-f]+ <[^>]*> cbffffff bc 00001014 <bar\+0x4>
+[ ]*[0-9a-f]+: R_MIPS_PC26_S2 foo
+[0-9a-f]+ <[^>]*> 00000027 nor zero,zero,zero
+[0-9a-f]+ <[^>]*> d85fffff beqzc v0,0000101c <bar\+0xc>
+[ ]*[0-9a-f]+: R_MIPS_PC21_S2 foo
+[0-9a-f]+ <[^>]*> 00000027 nor zero,zero,zero
+[0-9a-f]+ <[^>]*> 03e00009 jr ra
+[0-9a-f]+ <[^>]*> 00000027 nor zero,zero,zero
+ \.\.\.
diff --git a/gas/testsuite/gas/mips/branch-local-ignore-n32-2.d b/gas/testsuite/gas/mips/branch-local-ignore-n32-2.d
new file mode 100644
index 0000000..080402c
--- /dev/null
+++ b/gas/testsuite/gas/mips/branch-local-ignore-n32-2.d
@@ -0,0 +1,29 @@
+#objdump: -dr --prefix-addresses --show-raw-insn
+#name: MIPS branch local symbol relocation 2 (ignore branch ISA, n32)
+#as: -n32 -march=from-abi -mignore-branch-isa
+#source: branch-local-2.s
+
+.*: +file format .*mips.*
+
+Disassembly of section \.text:
+ \.\.\.
+[0-9a-f]+ <[^>]*> 0000 02d0 not zero,zero
+[0-9a-f]+ <[^>]*> 001f 0f3c jr ra
+[0-9a-f]+ <[^>]*> 0000 02d0 not zero,zero
+[0-9a-f]+ <[^>]*> 0000 0000 nop
+[0-9a-f]+ <[^>]*> 00000027 nor zero,zero,zero
+[0-9a-f]+ <[^>]*> 10000000 b 00001018 <bar\+0x8>
+[ ]*[0-9a-f]+: R_MIPS_PC16 foo-0x4
+[0-9a-f]+ <[^>]*> 00000027 nor zero,zero,zero
+[0-9a-f]+ <[^>]*> 14430000 bne v0,v1,00001020 <bar\+0x10>
+[ ]*[0-9a-f]+: R_MIPS_PC16 foo-0x4
+[0-9a-f]+ <[^>]*> 00000027 nor zero,zero,zero
+[0-9a-f]+ <[^>]*> 04510000 bgezal v0,00001028 <bar\+0x18>
+[ ]*[0-9a-f]+: R_MIPS_PC16 foo-0x4
+[0-9a-f]+ <[^>]*> 00000027 nor zero,zero,zero
+[0-9a-f]+ <[^>]*> 04500000 bltzal v0,00001030 <bar\+0x20>
+[ ]*[0-9a-f]+: R_MIPS_PC16 foo-0x4
+[0-9a-f]+ <[^>]*> 00000027 nor zero,zero,zero
+[0-9a-f]+ <[^>]*> 03e00009 jalr zero,ra
+[0-9a-f]+ <[^>]*> 00000027 nor zero,zero,zero
+ \.\.\.
diff --git a/gas/testsuite/gas/mips/branch-local-ignore-n32-3.d b/gas/testsuite/gas/mips/branch-local-ignore-n32-3.d
new file mode 100644
index 0000000..a4dbc7f
--- /dev/null
+++ b/gas/testsuite/gas/mips/branch-local-ignore-n32-3.d
@@ -0,0 +1,23 @@
+#objdump: -dr --prefix-addresses --show-raw-insn -mmips:isa32r6
+#name: MIPS branch local symbol relocation 3 (ignore branch ISA, n32)
+#as: -n32 -march=from-abi -mignore-branch-isa
+#source: branch-local-3.s
+
+.*: +file format .*mips.*
+
+Disassembly of section \.text:
+ \.\.\.
+[0-9a-f]+ <[^>]*> 0000 02d0 not zero,zero
+[0-9a-f]+ <[^>]*> 001f 0f3c jr ra
+[0-9a-f]+ <[^>]*> 0000 02d0 not zero,zero
+[0-9a-f]+ <[^>]*> 0000 0000 nop
+[0-9a-f]+ <[^>]*> 00000027 nor zero,zero,zero
+[0-9a-f]+ <[^>]*> c8000000 bc 00001018 <bar\+0x8>
+[ ]*[0-9a-f]+: R_MIPS_PC26_S2 foo-0x4
+[0-9a-f]+ <[^>]*> 00000027 nor zero,zero,zero
+[0-9a-f]+ <[^>]*> d8400000 beqzc v0,00001020 <bar\+0x10>
+[ ]*[0-9a-f]+: R_MIPS_PC21_S2 foo-0x4
+[0-9a-f]+ <[^>]*> 00000027 nor zero,zero,zero
+[0-9a-f]+ <[^>]*> 03e00009 jr ra
+[0-9a-f]+ <[^>]*> 00000027 nor zero,zero,zero
+ \.\.\.
diff --git a/gas/testsuite/gas/mips/branch-local-ignore-n64-2.d b/gas/testsuite/gas/mips/branch-local-ignore-n64-2.d
new file mode 100644
index 0000000..12cd510
--- /dev/null
+++ b/gas/testsuite/gas/mips/branch-local-ignore-n64-2.d
@@ -0,0 +1,37 @@
+#objdump: -dr --prefix-addresses --show-raw-insn
+#name: MIPS branch local symbol relocation 2 (ignore branch ISA, n64)
+#as: -64 -march=from-abi -mignore-branch-isa
+#source: branch-local-2.s
+
+.*: +file format .*mips.*
+
+Disassembly of section \.text:
+ \.\.\.
+[0-9a-f]+ <[^>]*> 0000 02d0 not zero,zero
+[0-9a-f]+ <[^>]*> 001f 0f3c jr ra
+[0-9a-f]+ <[^>]*> 0000 02d0 not zero,zero
+[0-9a-f]+ <[^>]*> 0000 0000 nop
+[0-9a-f]+ <[^>]*> 00000027 nor zero,zero,zero
+[0-9a-f]+ <[^>]*> 10000000 b 0000000000001018 <bar\+0x8>
+[ ]*[0-9a-f]+: R_MIPS_PC16 foo-0x4
+[ ]*[0-9a-f]+: R_MIPS_NONE \*ABS\*-0x4
+[ ]*[0-9a-f]+: R_MIPS_NONE \*ABS\*-0x4
+[0-9a-f]+ <[^>]*> 00000027 nor zero,zero,zero
+[0-9a-f]+ <[^>]*> 14430000 bne v0,v1,0000000000001020 <bar\+0x10>
+[ ]*[0-9a-f]+: R_MIPS_PC16 foo-0x4
+[ ]*[0-9a-f]+: R_MIPS_NONE \*ABS\*-0x4
+[ ]*[0-9a-f]+: R_MIPS_NONE \*ABS\*-0x4
+[0-9a-f]+ <[^>]*> 00000027 nor zero,zero,zero
+[0-9a-f]+ <[^>]*> 04510000 bgezal v0,0000000000001028 <bar\+0x18>
+[ ]*[0-9a-f]+: R_MIPS_PC16 foo-0x4
+[ ]*[0-9a-f]+: R_MIPS_NONE \*ABS\*-0x4
+[ ]*[0-9a-f]+: R_MIPS_NONE \*ABS\*-0x4
+[0-9a-f]+ <[^>]*> 00000027 nor zero,zero,zero
+[0-9a-f]+ <[^>]*> 04500000 bltzal v0,0000000000001030 <bar\+0x20>
+[ ]*[0-9a-f]+: R_MIPS_PC16 foo-0x4
+[ ]*[0-9a-f]+: R_MIPS_NONE \*ABS\*-0x4
+[ ]*[0-9a-f]+: R_MIPS_NONE \*ABS\*-0x4
+[0-9a-f]+ <[^>]*> 00000027 nor zero,zero,zero
+[0-9a-f]+ <[^>]*> 03e00009 jalr zero,ra
+[0-9a-f]+ <[^>]*> 00000027 nor zero,zero,zero
+ \.\.\.
diff --git a/gas/testsuite/gas/mips/branch-local-ignore-n64-3.d b/gas/testsuite/gas/mips/branch-local-ignore-n64-3.d
new file mode 100644
index 0000000..9d6dca9
--- /dev/null
+++ b/gas/testsuite/gas/mips/branch-local-ignore-n64-3.d
@@ -0,0 +1,27 @@
+#objdump: -dr --prefix-addresses --show-raw-insn -mmips:isa32r6
+#name: MIPS branch local symbol relocation 3 (ignore branch ISA, n64)
+#as: -64 -march=from-abi -mignore-branch-isa
+#source: branch-local-3.s
+
+.*: +file format .*mips.*
+
+Disassembly of section \.text:
+ \.\.\.
+[0-9a-f]+ <[^>]*> 0000 02d0 not zero,zero
+[0-9a-f]+ <[^>]*> 001f 0f3c jr ra
+[0-9a-f]+ <[^>]*> 0000 02d0 not zero,zero
+[0-9a-f]+ <[^>]*> 0000 0000 nop
+[0-9a-f]+ <[^>]*> 00000027 nor zero,zero,zero
+[0-9a-f]+ <[^>]*> c8000000 bc 0000000000001018 <bar\+0x8>
+[ ]*[0-9a-f]+: R_MIPS_PC26_S2 foo-0x4
+[ ]*[0-9a-f]+: R_MIPS_NONE \*ABS\*-0x4
+[ ]*[0-9a-f]+: R_MIPS_NONE \*ABS\*-0x4
+[0-9a-f]+ <[^>]*> 00000027 nor zero,zero,zero
+[0-9a-f]+ <[^>]*> d8400000 beqzc v0,0000000000001020 <bar\+0x10>
+[ ]*[0-9a-f]+: R_MIPS_PC21_S2 foo-0x4
+[ ]*[0-9a-f]+: R_MIPS_NONE \*ABS\*-0x4
+[ ]*[0-9a-f]+: R_MIPS_NONE \*ABS\*-0x4
+[0-9a-f]+ <[^>]*> 00000027 nor zero,zero,zero
+[0-9a-f]+ <[^>]*> 03e00009 jr ra
+[0-9a-f]+ <[^>]*> 00000027 nor zero,zero,zero
+ \.\.\.
diff --git a/gas/testsuite/gas/mips/mips.exp b/gas/testsuite/gas/mips/mips.exp
index 4580fbf..5a69542 100644
--- a/gas/testsuite/gas/mips/mips.exp
+++ b/gas/testsuite/gas/mips/mips.exp
@@ -626,16 +626,22 @@ if { [istarget mips*-*-vxworks*] } {
run_dump_test "branch-weak-7"
run_dump_test "branch-local-1"
run_dump_test "branch-local-2"
+ run_dump_test "branch-local-ignore-2"
run_dump_test "branch-local-3"
+ run_dump_test "branch-local-ignore-3"
run_dump_test "branch-local-4"
if $has_newabi {
run_dump_test "branch-local-n32-1"
run_dump_test "branch-local-n32-2"
+ run_dump_test "branch-local-ignore-n32-2"
run_dump_test "branch-local-n32-3"
+ run_dump_test "branch-local-ignore-n32-3"
run_dump_test "branch-local-n32-4"
run_dump_test "branch-local-n64-1"
run_dump_test "branch-local-n64-2"
+ run_dump_test "branch-local-ignore-n64-2"
run_dump_test "branch-local-n64-3"
+ run_dump_test "branch-local-ignore-n64-3"
run_dump_test "branch-local-n64-4"
}
run_dump_test "branch-addend"
diff --git a/ld/ChangeLog b/ld/ChangeLog
index 6323524..39b8757 100644
--- a/ld/ChangeLog
+++ b/ld/ChangeLog
@@ -1,3 +1,33 @@
+2017-01-30 Maciej W. Rozycki <macro@imgtec.com>
+
+ * emultempl/mipself.em (ignore_branch_isa): New variable.
+ (mips_create_output_section_statements): Rename
+ `_bfd_mips_elf_insn32' called to `_bfd_mips_elf_linker_flags',
+ add `ignore_branch_isa' argument.
+ (PARSE_AND_LIST_PROLOGUE): Add OPTION_IGNORE_BRANCH_ISA and
+ OPTION_NO_IGNORE_BRANCH_ISA enum values.
+ (PARSE_AND_LIST_LONGOPTS): Add "ignore-branch-isa" and
+ "no-ignore-branch-isa" options.
+ (PARSE_AND_LIST_OPTIONS): Add `--ignore-branch-isa' and
+ `--no-ignore-branch-isa'.
+ (PARSE_AND_LIST_ARGS_CASES): Handle OPTION_IGNORE_BRANCH_ISA and
+ OPTION_NO_IGNORE_BRANCH_ISA.
+
+ * ld.texinfo (Options specific to MIPS targets): Add
+ `--ignore-branch-isa' and `--no-ignore-branch-isa' options.
+ (ld and the MIPS family): Likewise.
+
+ * testsuite/ld-mips-elf/bal-jalx-pic-ignore.d: New test.
+ * testsuite/ld-mips-elf/bal-jalx-pic-ignore-n32.d: New test.
+ * testsuite/ld-mips-elf/bal-jalx-pic-ignore-n64.d: New test.
+ * testsuite/ld-mips-elf/unaligned-branch-ignore-2.d: New test.
+ * testsuite/ld-mips-elf/unaligned-branch-ignore-r6-1: New test.
+ * testsuite/ld-mips-elf/unaligned-branch-ignore-mips16: New
+ test.
+ * testsuite/ld-mips-elf/unaligned-branch-ignore-micromips: New
+ test.
+ * testsuite/ld-mips-elf/mips-elf.exp: Run the new tests.
+
2017-01-24 Maciej W. Rozycki <macro@imgtec.com>
* emultempl/solaris2.em (elf_solaris2_before_allocation): Do not
diff --git a/ld/emultempl/mipself.em b/ld/emultempl/mipself.em
index 74ede87..cd68707 100644
--- a/ld/emultempl/mipself.em
+++ b/ld/emultempl/mipself.em
@@ -34,6 +34,7 @@ static lang_input_statement_type *stub_file;
static bfd *stub_bfd;
static bfd_boolean insn32;
+static bfd_boolean ignore_branch_isa;
static void
mips_after_parse (void)
@@ -202,7 +203,7 @@ mips_create_output_section_statements (void)
htab = elf_hash_table (&link_info);
if (is_elf_hash_table (htab) && is_mips_elf (link_info.output_bfd))
- _bfd_mips_elf_insn32 (&link_info, insn32);
+ _bfd_mips_elf_linker_flags (&link_info, insn32, ignore_branch_isa);
if (is_mips_elf (link_info.output_bfd))
_bfd_mips_elf_init_stubs (&link_info, mips_add_stub_section);
@@ -253,13 +254,17 @@ PARSE_AND_LIST_PROLOGUE='
enum
{
OPTION_INSN32 = 301,
- OPTION_NO_INSN32
+ OPTION_NO_INSN32,
+ OPTION_IGNORE_BRANCH_ISA,
+ OPTION_NO_IGNORE_BRANCH_ISA
};
'
PARSE_AND_LIST_LONGOPTS='
{ "insn32", no_argument, NULL, OPTION_INSN32 },
{ "no-insn32", no_argument, NULL, OPTION_NO_INSN32 },
+ { "ignore-branch-isa", no_argument, NULL, OPTION_IGNORE_BRANCH_ISA },
+ { "no-ignore-branch-isa", no_argument, NULL, OPTION_NO_IGNORE_BRANCH_ISA },
'
PARSE_AND_LIST_OPTIONS='
@@ -269,6 +274,14 @@ PARSE_AND_LIST_OPTIONS='
fprintf (file, _("\
--no-insn32 Generate all microMIPS instructions\n"
));
+ fprintf (file, _("\
+ --ignore-branch-isa Accept invalid branch relocations requiring\n\
+ an ISA mode switch\n"
+ ));
+ fprintf (file, _("\
+ --no-ignore-branch-isa Reject invalid branch relocations requiring\n\
+ an ISA mode switch\n"
+ ));
'
PARSE_AND_LIST_ARGS_CASES='
@@ -279,6 +292,14 @@ PARSE_AND_LIST_ARGS_CASES='
case OPTION_NO_INSN32:
insn32 = FALSE;
break;
+
+ case OPTION_IGNORE_BRANCH_ISA:
+ ignore_branch_isa = TRUE;
+ break;
+
+ case OPTION_NO_IGNORE_BRANCH_ISA:
+ ignore_branch_isa = FALSE;
+ break;
'
LDEMUL_AFTER_PARSE=mips_after_parse
diff --git a/ld/ld.texinfo b/ld/ld.texinfo
index 29c2131..d393acdd 100644
--- a/ld/ld.texinfo
+++ b/ld/ld.texinfo
@@ -2985,7 +2985,8 @@ Info entry for @file{ld}.
@c man begin OPTIONS
The following options are supported to control microMIPS instruction
-generation when linking for MIPS targets.
+generation and branch relocation checks for ISA mode transitions when
+linking for MIPS targets.
@table @gcctabopt
@@ -3000,6 +3001,20 @@ or in relaxation. If @samp{--insn32} is used, then the linker only uses
used, all instruction encodings are used, including 16-bit ones where
possible.
+@kindex --ignore-branch-isa
+@item --ignore-branch-isa
+@kindex --no-ignore-branch-isa
+@itemx --no-ignore-branch-isa
+These options control branch relocation checks for invalid ISA mode
+transitions. If @samp{--ignore-branch-isa} is used, then the linker
+accepts any branch relocations and any ISA mode transition required
+is lost in relocation calculation, except for some cases of @code{BAL}
+instructions which meet relaxation conditions and are converted to
+equivalent @code{JALX} instructions as the associated relocation is
+calculated. By default or if @samp{--no-ignore-branch-isa} is used
+a check is made causing the loss of an ISA mode transition to produce
+an error.
+
@end table
@c man end
@@ -7046,6 +7061,19 @@ used, then the linker only uses 32-bit instruction encodings. By default
or if @samp{--no-insn32} is used, all instruction encodings are used,
including 16-bit ones where possible.
+@cindex MIPS branch relocation check control
+@kindex --ignore-branch-isa
+@kindex --no-ignore-branch-isa
+The @samp{--ignore-branch-isa} and @samp{--no-ignore-branch-isa} options
+control branch relocation checks for invalid ISA mode transitions. If
+@samp{--ignore-branch-isa} is used, then the linker accepts any branch
+relocations and any ISA mode transition required is lost in relocation
+calculation, except for some cases of @code{BAL} instructions which meet
+relaxation conditions and are converted to equivalent @code{JALX}
+instructions as the associated relocation is calculated. By default
+or if @samp{--no-ignore-branch-isa} is used a check is made causing
+the loss of an ISA mode transition to produce an error.
+
@ifclear GENERIC
@lowersections
@end ifclear
diff --git a/ld/testsuite/ld-mips-elf/bal-jalx-pic-ignore-n32.d b/ld/testsuite/ld-mips-elf/bal-jalx-pic-ignore-n32.d
new file mode 100644
index 0000000..c402ba8
--- /dev/null
+++ b/ld/testsuite/ld-mips-elf/bal-jalx-pic-ignore-n32.d
@@ -0,0 +1,6 @@
+#name: MIPS BAL/JALX in PIC mode (ignore branch ISA, n32)
+#source: ../../../gas/testsuite/gas/mips/branch-addend.s
+#as: -EB -n32 -march=from-abi
+#ld: -EB -Ttext 0x1c000000 -e 0x1c000000 -shared --ignore-branch-isa
+#objdump: -dr --prefix-addresses --show-raw-insn
+#dump: bal-jalx-pic-ignore.d
diff --git a/ld/testsuite/ld-mips-elf/bal-jalx-pic-ignore-n64.d b/ld/testsuite/ld-mips-elf/bal-jalx-pic-ignore-n64.d
new file mode 100644
index 0000000..e1bbb92
--- /dev/null
+++ b/ld/testsuite/ld-mips-elf/bal-jalx-pic-ignore-n64.d
@@ -0,0 +1,6 @@
+#name: MIPS BAL/JALX in PIC mode (ignore branch ISA, n64)
+#source: ../../../gas/testsuite/gas/mips/branch-addend.s
+#as: -EB -64 -march=from-abi
+#ld: -EB -Ttext 0x1c000000 -e 0x1c000000 -shared --ignore-branch-isa
+#objdump: -dr --prefix-addresses --show-raw-insn
+#dump: bal-jalx-pic-ignore.d
diff --git a/ld/testsuite/ld-mips-elf/bal-jalx-pic-ignore.d b/ld/testsuite/ld-mips-elf/bal-jalx-pic-ignore.d
new file mode 100644
index 0000000..279b87a
--- /dev/null
+++ b/ld/testsuite/ld-mips-elf/bal-jalx-pic-ignore.d
@@ -0,0 +1,22 @@
+#name: MIPS BAL/JALX in PIC mode (ignore branch ISA)
+#source: ../../../gas/testsuite/gas/mips/branch-addend.s
+#as: -EB -32
+#ld: -EB -Ttext 0x1c000000 -e 0x1c000000 -shared --ignore-branch-isa
+#objdump: -dr --prefix-addresses --show-raw-insn
+
+.*: +file format .*mips.*
+
+Disassembly of section \.text:
+ \.\.\.
+[0-9a-f]+ <[^>]*> 0000 02d0 not zero,zero
+[0-9a-f]+ <[^>]*> 001f 0f3c jr ra
+[0-9a-f]+ <[^>]*> 0000 02d0 not zero,zero
+[0-9a-f]+ <[^>]*> 0000 0000 nop
+[0-9a-f]+ <[^>]*> 00000027 nor zero,zero,zero
+[0-9a-f]+ <[^>]*> 04117ffa bal 0*1c021000 <.*>
+[0-9a-f]+ <[^>]*> 00000027 nor zero,zero,zero
+[0-9a-f]+ <[^>]*> 04117ffc bal 0*1c021010 <.*>
+[0-9a-f]+ <[^>]*> 00000027 nor zero,zero,zero
+[0-9a-f]+ <[^>]*> 03e00009 jalr zero,ra
+[0-9a-f]+ <[^>]*> 00000027 nor zero,zero,zero
+ \.\.\.
diff --git a/ld/testsuite/ld-mips-elf/mips-elf.exp b/ld/testsuite/ld-mips-elf/mips-elf.exp
index 5639c84..7fa11c5 100644
--- a/ld/testsuite/ld-mips-elf/mips-elf.exp
+++ b/ld/testsuite/ld-mips-elf/mips-elf.exp
@@ -216,17 +216,20 @@ run_dump_test "jalx-local" [list [list ld $abi_ldflags(o32)]]
run_dump_test "bal-jalx-addend" [list [list ld $abi_ldflags(o32)]]
run_dump_test "bal-jalx-local" [list [list ld $abi_ldflags(o32)]]
run_dump_test "bal-jalx-pic" [list [list ld $abi_ldflags(o32)]]
+run_dump_test "bal-jalx-pic-ignore" [list [list ld $abi_ldflags(o32)]]
if $has_newabi {
run_dump_test "jalx-addend-n32" [list [list ld $abi_ldflags(n32)]]
run_dump_test "jalx-local-n32" [list [list ld $abi_ldflags(n32)]]
run_dump_test "bal-jalx-addend-n32" [list [list ld $abi_ldflags(n32)]]
run_dump_test "bal-jalx-local-n32" [list [list ld $abi_ldflags(n32)]]
run_dump_test "bal-jalx-pic-n32" [list [list ld $abi_ldflags(n32)]]
+ run_dump_test "bal-jalx-pic-ignore-n32" [list [list ld $abi_ldflags(n32)]]
run_dump_test "jalx-addend-n64" [list [list ld $abi_ldflags(n64)]]
run_dump_test "jalx-local-n64" [list [list ld $abi_ldflags(n64)]]
run_dump_test "bal-jalx-addend-n64" [list [list ld $abi_ldflags(n64)]]
run_dump_test "bal-jalx-local-n64" [list [list ld $abi_ldflags(n64)]]
run_dump_test "bal-jalx-pic-n64" [list [list ld $abi_ldflags(n64)]]
+ run_dump_test "bal-jalx-pic-ignore-n64" [list [list ld $abi_ldflags(n64)]]
}
run_dump_test "unaligned-jalx-0" [list [list ld $abi_ldflags(o32)]]
@@ -262,14 +265,22 @@ run_dump_test "unaligned-branch" [list [list ld $abi_ldflags(o32)]]
if $has_newabi {
run_dump_test "unaligned-branch-2" \
[list [list ld $abi_ldflags(n32)]]
+ run_dump_test "unaligned-branch-ignore-2" \
+ [list [list ld $abi_ldflags(n32)]]
run_dump_test "unaligned-branch-r6-1" \
[list [list ld $abi_ldflags(n32)]]
+ run_dump_test "unaligned-branch-ignore-r6-1" \
+ [list [list ld $abi_ldflags(n32)]]
run_dump_test "unaligned-branch-r6-2" \
[list [list ld $abi_ldflags(n32)]]
run_dump_test "unaligned-branch-mips16" \
[list [list ld $abi_ldflags(n32)]]
+ run_dump_test "unaligned-branch-ignore-mips16" \
+ [list [list ld $abi_ldflags(n32)]]
run_dump_test "unaligned-branch-micromips" \
[list [list ld $abi_ldflags(n32)]]
+ run_dump_test "unaligned-branch-ignore-micromips" \
+ [list [list ld $abi_ldflags(n32)]]
run_dump_test "unaligned-jump" \
[list [list ld $abi_ldflags(n32)]]
run_dump_test "unaligned-jump-mips16" \
diff --git a/ld/testsuite/ld-mips-elf/unaligned-branch-ignore-2.d b/ld/testsuite/ld-mips-elf/unaligned-branch-ignore-2.d
new file mode 100644
index 0000000..323c43a
--- /dev/null
+++ b/ld/testsuite/ld-mips-elf/unaligned-branch-ignore-2.d
@@ -0,0 +1,64 @@
+#name: MIPS link branch to unaligned symbol 2 (ignore branch ISA)
+#as: -EB -n32 -march=from-abi
+#ld: -EB -Ttext 0x1c000000 -e 0x1c000000 --ignore-branch-isa
+#source: ../../../gas/testsuite/gas/mips/unaligned-branch-2.s
+#error: \A[^\n]*: In function `foo':\n
+#error: \(\.text\+0x101c\): Branch to a non-instruction-aligned address\n
+#error: [^\n]*: In function `foo':\n
+#error: \(\.text\+0x1024\): Branch to a non-instruction-aligned address\n
+#error: [^\n]*: In function `foo':\n
+#error: \(\.text\+0x102c\): Branch to a non-instruction-aligned address\n
+#error: [^\n]*: In function `foo':\n
+#error: \(\.text\+0x1034\): Branch to a non-instruction-aligned address\n
+#error: [^\n]*: In function `foo':\n
+#error: \(\.text\+0x103c\): Branch to a non-instruction-aligned address\n
+#error: [^\n]*: In function `foo':\n
+#error: \(\.text\+0x1044\): Branch to a non-instruction-aligned address\n
+#error: [^\n]*: In function `foo':\n
+#error: \(\.text\+0x104c\): Branch to a non-instruction-aligned address\n
+#error: [^\n]*: In function `foo':\n
+#error: \(\.text\+0x1054\): Branch to a non-instruction-aligned address\n
+#error: [^\n]*: In function `foo':\n
+#error: \(\.text\+0x105c\): Branch to a non-instruction-aligned address\n
+#error: [^\n]*: In function `foo':\n
+#error: \(\.text\+0x107c\): Branch to a non-instruction-aligned address\n
+#error: [^\n]*: In function `foo':\n
+#error: \(\.text\+0x1084\): Branch to a non-instruction-aligned address\n
+#error: [^\n]*: In function `foo':\n
+#error: \(\.text\+0x108c\): Branch to a non-instruction-aligned address\n
+#error: [^\n]*: In function `foo':\n
+#error: \(\.text\+0x1094\): Branch to a non-instruction-aligned address\n
+#error: [^\n]*: In function `foo':\n
+#error: \(\.text\+0x109c\): Branch to a non-instruction-aligned address\n
+#error: [^\n]*: In function `foo':\n
+#error: \(\.text\+0x10a4\): Branch to a non-instruction-aligned address\n
+#error: [^\n]*: In function `foo':\n
+#error: \(\.text\+0x10ac\): Branch to a non-instruction-aligned address\n
+#error: [^\n]*: In function `foo':\n
+#error: \(\.text\+0x10b4\): Branch to a non-instruction-aligned address\n
+#error: [^\n]*: In function `foo':\n
+#error: \(\.text\+0x10bc\): Branch to a non-instruction-aligned address\n
+#error: [^\n]*: In function `foo':\n
+#error: \(\.text\+0x10f4\): Cannot convert a branch to JALX for a non-word-aligned address\n
+#error: [^\n]*: In function `foo':\n
+#error: \(\.text\+0x10fc\): Cannot convert a branch to JALX for a non-word-aligned address\n
+#error: [^\n]*: In function `foo':\n
+#error: \(\.text\+0x1104\): Cannot convert a branch to JALX for a non-word-aligned address\n
+#error: [^\n]*: In function `foo':\n
+#error: \(\.text\+0x1124\): Cannot convert a branch to JALX for a non-word-aligned address\n
+#error: [^\n]*: In function `foo':\n
+#error: \(\.text\+0x112c\): Cannot convert a branch to JALX for a non-word-aligned address\n
+#error: [^\n]*: In function `foo':\n
+#error: \(\.text\+0x1134\): Cannot convert a branch to JALX for a non-word-aligned address\n
+#error: [^\n]*: In function `foo':\n
+#error: \(\.text\+0x113c\): Cannot convert a branch to JALX for a non-word-aligned address\n
+#error: [^\n]*: In function `foo':\n
+#error: \(\.text\+0x1144\): Cannot convert a branch to JALX for a non-word-aligned address\n
+#error: [^\n]*: In function `foo':\n
+#error: \(\.text\+0x114c\): Cannot convert a branch to JALX for a non-word-aligned address\n
+#error: [^\n]*: In function `foo':\n
+#error: \(\.text\+0x1154\): Cannot convert a branch to JALX for a non-word-aligned address\n
+#error: [^\n]*: In function `foo':\n
+#error: \(\.text\+0x115c\): Cannot convert a branch to JALX for a non-word-aligned address\n
+#error: [^\n]*: In function `foo':\n
+#error: \(\.text\+0x1164\): Cannot convert a branch to JALX for a non-word-aligned address\Z
diff --git a/ld/testsuite/ld-mips-elf/unaligned-branch-ignore-micromips.d b/ld/testsuite/ld-mips-elf/unaligned-branch-ignore-micromips.d
new file mode 100644
index 0000000..6a62fe5
--- /dev/null
+++ b/ld/testsuite/ld-mips-elf/unaligned-branch-ignore-micromips.d
@@ -0,0 +1,84 @@
+#name: microMIPS link branch to unaligned symbol (ignore branch ISA)
+#as: -EB -n32 -march=from-abi
+#ld: -EB -Ttext 0x1c000000 -e 0x1c000000 --ignore-branch-isa
+#source: ../../../gas/testsuite/gas/mips/unaligned-branch-micromips-2.s
+#error: \A[^\n]*: In function `foo':\n
+#error: \(\.text\+0x100a\): Cannot convert a branch to JALX for a non-word-aligned address\n
+#error: [^\n]*: In function `foo':\n
+#error: \(\.text\+0x1012\): Cannot convert a branch to JALX for a non-word-aligned address\n
+#error: [^\n]*: In function `foo':\n
+#error: \(\.text\+0x101a\): Cannot convert a branch to JALX for a non-word-aligned address\n
+#error: [^\n]*: In function `foo':\n
+#error: \(\.text\+0x102a\): Cannot convert a branch to JALX for a non-word-aligned address\n
+#error: [^\n]*: In function `foo':\n
+#error: \(\.text\+0x1032\): Cannot convert a branch to JALX for a non-word-aligned address\n
+#error: [^\n]*: In function `foo':\n
+#error: \(\.text\+0x103a\): Cannot convert a branch to JALX for a non-word-aligned address\n
+#error: [^\n]*: In function `foo':\n
+#error: \(\.text\+0x1062\): Branch to a non-instruction-aligned address\n
+#error: [^\n]*: In function `foo':\n
+#error: \(\.text\+0x1072\): Branch to a non-instruction-aligned address\n
+#error: [^\n]*: In function `foo':\n
+#error: \(\.text\+0x1088\): Cannot convert a branch to JALX for a non-word-aligned address\n
+#error: [^\n]*: In function `foo':\n
+#error: \(\.text\+0x108e\): Cannot convert a branch to JALX for a non-word-aligned address\n
+#error: [^\n]*: In function `foo':\n
+#error: \(\.text\+0x1094\): Cannot convert a branch to JALX for a non-word-aligned address\n
+#error: [^\n]*: In function `foo':\n
+#error: \(\.text\+0x10a0\): Cannot convert a branch to JALX for a non-word-aligned address\n
+#error: [^\n]*: In function `foo':\n
+#error: \(\.text\+0x10a6\): Cannot convert a branch to JALX for a non-word-aligned address\n
+#error: [^\n]*: In function `foo':\n
+#error: \(\.text\+0x10ac\): Cannot convert a branch to JALX for a non-word-aligned address\n
+#error: [^\n]*: In function `foo':\n
+#error: \(\.text\+0x10ca\): Branch to a non-instruction-aligned address\n
+#error: [^\n]*: In function `foo':\n
+#error: \(\.text\+0x10d6\): Branch to a non-instruction-aligned address\n
+#error: [^\n]*: In function `foo':\n
+#error: \(\.text\+0x10e8\): Cannot convert a branch to JALX for a non-word-aligned address\n
+#error: [^\n]*: In function `foo':\n
+#error: \(\.text\+0x10ee\): Cannot convert a branch to JALX for a non-word-aligned address\n
+#error: [^\n]*: In function `foo':\n
+#error: \(\.text\+0x10f4\): Cannot convert a branch to JALX for a non-word-aligned address\n
+#error: [^\n]*: In function `foo':\n
+#error: \(\.text\+0x1100\): Cannot convert a branch to JALX for a non-word-aligned address\n
+#error: [^\n]*: In function `foo':\n
+#error: \(\.text\+0x1106\): Cannot convert a branch to JALX for a non-word-aligned address\n
+#error: [^\n]*: In function `foo':\n
+#error: \(\.text\+0x110c\): Cannot convert a branch to JALX for a non-word-aligned address\n
+#error: [^\n]*: In function `foo':\n
+#error: \(\.text\+0x112a\): Branch to a non-instruction-aligned address\n
+#error: [^\n]*: In function `foo':\n
+#error: \(\.text\+0x1136\): Branch to a non-instruction-aligned address\n
+#error: [^\n]*: In function `foo':\n
+#error: \(\.text\+0x1146\): Cannot convert a branch to JALX for a non-word-aligned address\n
+#error: [^\n]*: In function `foo':\n
+#error: \(\.text\+0x114a\): Cannot convert a branch to JALX for a non-word-aligned address\n
+#error: [^\n]*: In function `foo':\n
+#error: \(\.text\+0x114e\): Cannot convert a branch to JALX for a non-word-aligned address\n
+#error: [^\n]*: In function `foo':\n
+#error: \(\.text\+0x1156\): Cannot convert a branch to JALX for a non-word-aligned address\n
+#error: [^\n]*: In function `foo':\n
+#error: \(\.text\+0x115a\): Cannot convert a branch to JALX for a non-word-aligned address\n
+#error: [^\n]*: In function `foo':\n
+#error: \(\.text\+0x115e\): Cannot convert a branch to JALX for a non-word-aligned address\n
+#error: [^\n]*: In function `foo':\n
+#error: \(\.text\+0x1172\): Branch to a non-instruction-aligned address\n
+#error: [^\n]*: In function `foo':\n
+#error: \(\.text\+0x117a\): Branch to a non-instruction-aligned address\n
+#error: [^\n]*: In function `foo':\n
+#error: \(\.text\+0x1186\): Cannot convert a branch to JALX for a non-word-aligned address\n
+#error: [^\n]*: In function `foo':\n
+#error: \(\.text\+0x118a\): Cannot convert a branch to JALX for a non-word-aligned address\n
+#error: [^\n]*: In function `foo':\n
+#error: \(\.text\+0x118e\): Cannot convert a branch to JALX for a non-word-aligned address\n
+#error: [^\n]*: In function `foo':\n
+#error: \(\.text\+0x1196\): Cannot convert a branch to JALX for a non-word-aligned address\n
+#error: [^\n]*: In function `foo':\n
+#error: \(\.text\+0x119a\): Cannot convert a branch to JALX for a non-word-aligned address\n
+#error: [^\n]*: In function `foo':\n
+#error: \(\.text\+0x119e\): Cannot convert a branch to JALX for a non-word-aligned address\n
+#error: [^\n]*: In function `foo':\n
+#error: \(\.text\+0x11b2\): Branch to a non-instruction-aligned address\n
+#error: [^\n]*: In function `foo':\n
+#error: \(\.text\+0x11ba\): Branch to a non-instruction-aligned address\Z
diff --git a/ld/testsuite/ld-mips-elf/unaligned-branch-ignore-mips16.d b/ld/testsuite/ld-mips-elf/unaligned-branch-ignore-mips16.d
new file mode 100644
index 0000000..f6ace4a
--- /dev/null
+++ b/ld/testsuite/ld-mips-elf/unaligned-branch-ignore-mips16.d
@@ -0,0 +1,36 @@
+#name: MIPS16 link branch to unaligned symbol (ignore branch ISA)
+#as: -EB -n32 -march=from-abi
+#ld: -EB -Ttext 0x1c000000 -e 0x1c000000 --ignore-branch-isa
+#source: ../../../gas/testsuite/gas/mips/unaligned-branch-mips16-2.s
+#error: [^\n]*: In function `foo':\n
+#error: \(\.text\+0x1008\): Cannot convert a branch to JALX for a non-word-aligned address\n
+#error: [^\n]*: In function `foo':\n
+#error: \(\.text\+0x100e\): Cannot convert a branch to JALX for a non-word-aligned address\n
+#error: [^\n]*: In function `foo':\n
+#error: \(\.text\+0x1014\): Cannot convert a branch to JALX for a non-word-aligned address\n
+#error: [^\n]*: In function `foo':\n
+#error: \(\.text\+0x1020\): Cannot convert a branch to JALX for a non-word-aligned address\n
+#error: [^\n]*: In function `foo':\n
+#error: \(\.text\+0x1026\): Cannot convert a branch to JALX for a non-word-aligned address\n
+#error: [^\n]*: In function `foo':\n
+#error: \(\.text\+0x102c\): Cannot convert a branch to JALX for a non-word-aligned address\n
+#error: [^\n]*: In function `foo':\n
+#error: \(\.text\+0x104a\): Branch to a non-instruction-aligned address\n
+#error: [^\n]*: In function `foo':\n
+#error: \(\.text\+0x1056\): Branch to a non-instruction-aligned address\n
+#error: [^\n]*: In function `foo':\n
+#error: \(\.text\+0x1068\): Cannot convert a branch to JALX for a non-word-aligned address\n
+#error: [^\n]*: In function `foo':\n
+#error: \(\.text\+0x106e\): Cannot convert a branch to JALX for a non-word-aligned address\n
+#error: [^\n]*: In function `foo':\n
+#error: \(\.text\+0x1074\): Cannot convert a branch to JALX for a non-word-aligned address\n
+#error: [^\n]*: In function `foo':\n
+#error: \(\.text\+0x1080\): Cannot convert a branch to JALX for a non-word-aligned address\n
+#error: [^\n]*: In function `foo':\n
+#error: \(\.text\+0x1086\): Cannot convert a branch to JALX for a non-word-aligned address\n
+#error: [^\n]*: In function `foo':\n
+#error: \(\.text\+0x108c\): Cannot convert a branch to JALX for a non-word-aligned address\n
+#error: [^\n]*: In function `foo':\n
+#error: \(\.text\+0x10aa\): Branch to a non-instruction-aligned address\n
+#error: [^\n]*: In function `foo':\n
+#error: \(\.text\+0x10b6\): Branch to a non-instruction-aligned address\Z
diff --git a/ld/testsuite/ld-mips-elf/unaligned-branch-ignore-r6-1.d b/ld/testsuite/ld-mips-elf/unaligned-branch-ignore-r6-1.d
new file mode 100644
index 0000000..b7a11bd
--- /dev/null
+++ b/ld/testsuite/ld-mips-elf/unaligned-branch-ignore-r6-1.d
@@ -0,0 +1,72 @@
+#name: MIPSr6 link branch to unaligned symbol 1 (ignore branch ISA)
+#as: -EB -n32 -march=from-abi
+#ld: -EB -Ttext 0x1c000000 -e 0x1c000000 --ignore-branch-isa
+#source: ../../../gas/testsuite/gas/mips/unaligned-branch-r6-3.s
+#error: \A[^\n]*: In function `foo':\n
+#error: \(\.text\+0x101c\): Branch to a non-instruction-aligned address\n
+#error: [^\n]*: In function `foo':\n
+#error: \(\.text\+0x1024\): Branch to a non-instruction-aligned address\n
+#error: [^\n]*: In function `foo':\n
+#error: \(\.text\+0x102c\): Branch to a non-instruction-aligned address\n
+#error: [^\n]*: In function `foo':\n
+#error: \(\.text\+0x1034\): Branch to a non-instruction-aligned address\n
+#error: [^\n]*: In function `foo':\n
+#error: \(\.text\+0x103c\): Branch to a non-instruction-aligned address\n
+#error: [^\n]*: In function `foo':\n
+#error: \(\.text\+0x1044\): Branch to a non-instruction-aligned address\n
+#error: [^\n]*: In function `foo':\n
+#error: \(\.text\+0x104c\): Branch to a non-instruction-aligned address\n
+#error: [^\n]*: In function `foo':\n
+#error: \(\.text\+0x1054\): Branch to a non-instruction-aligned address\n
+#error: [^\n]*: In function `foo':\n
+#error: \(\.text\+0x105c\): Branch to a non-instruction-aligned address\n
+#error: [^\n]*: In function `foo':\n
+#error: \(\.text\+0x107c\): Branch to a non-instruction-aligned address\n
+#error: [^\n]*: In function `foo':\n
+#error: \(\.text\+0x1084\): Branch to a non-instruction-aligned address\n
+#error: [^\n]*: In function `foo':\n
+#error: \(\.text\+0x108c\): Branch to a non-instruction-aligned address\n
+#error: [^\n]*: In function `foo':\n
+#error: \(\.text\+0x1094\): Branch to a non-instruction-aligned address\n
+#error: [^\n]*: In function `foo':\n
+#error: \(\.text\+0x109c\): Branch to a non-instruction-aligned address\n
+#error: [^\n]*: In function `foo':\n
+#error: \(\.text\+0x10a4\): Branch to a non-instruction-aligned address\n
+#error: [^\n]*: In function `foo':\n
+#error: \(\.text\+0x10ac\): Branch to a non-instruction-aligned address\n
+#error: [^\n]*: In function `foo':\n
+#error: \(\.text\+0x10b4\): Branch to a non-instruction-aligned address\n
+#error: [^\n]*: In function `foo':\n
+#error: \(\.text\+0x10bc\): Branch to a non-instruction-aligned address\n
+#error: [^\n]*: In function `foo':\n
+#error: \(\.text\+0x10dc\): Cannot convert a branch to JALX for a non-word-aligned address\n
+#error: [^\n]*: In function `foo':\n
+#error: \(\.text\+0x10e4\): Cannot convert a branch to JALX for a non-word-aligned address\n
+#error: [^\n]*: In function `foo':\n
+#error: \(\.text\+0x10f4\): Cannot convert a branch to JALX for a non-word-aligned address\n
+#error: [^\n]*: In function `foo':\n
+#error: \(\.text\+0x10fc\): Cannot convert a branch to JALX for a non-word-aligned address\n
+#error: [^\n]*: In function `foo':\n
+#error: \(\.text\+0x1104\): Cannot convert a branch to JALX for a non-word-aligned address\n
+#error: [^\n]*: In function `foo':\n
+#error: \(\.text\+0x110c\): Cannot convert a branch to JALX for a non-word-aligned address\n
+#error: [^\n]*: In function `foo':\n
+#error: \(\.text\+0x1114\): Cannot convert a branch to JALX for a non-word-aligned address\n
+#error: [^\n]*: In function `foo':\n
+#error: \(\.text\+0x1124\): Cannot convert a branch to JALX for a non-word-aligned address\n
+#error: [^\n]*: In function `foo':\n
+#error: \(\.text\+0x112c\): Cannot convert a branch to JALX for a non-word-aligned address\n
+#error: [^\n]*: In function `foo':\n
+#error: \(\.text\+0x1134\): Cannot convert a branch to JALX for a non-word-aligned address\n
+#error: [^\n]*: In function `foo':\n
+#error: \(\.text\+0x113c\): Cannot convert a branch to JALX for a non-word-aligned address\n
+#error: [^\n]*: In function `foo':\n
+#error: \(\.text\+0x1144\): Cannot convert a branch to JALX for a non-word-aligned address\n
+#error: [^\n]*: In function `foo':\n
+#error: \(\.text\+0x114c\): Cannot convert a branch to JALX for a non-word-aligned address\n
+#error: [^\n]*: In function `foo':\n
+#error: \(\.text\+0x1164\): Cannot convert a branch to JALX for a non-word-aligned address\n
+#error: [^\n]*: In function `foo':\n
+#error: \(\.text\+0x116c\): Cannot convert a branch to JALX for a non-word-aligned address\n
+#error: [^\n]*: In function `foo':\n
+#error: \(\.text\+0x1174\): Cannot convert a branch to JALX for a non-word-aligned address\Z