aboutsummaryrefslogtreecommitdiff
path: root/gas/config/tc-mips.c
diff options
context:
space:
mode:
authorMaciej W. Rozycki <macro@imgtec.com>2016-05-20 13:32:19 +0100
committerMaciej W. Rozycki <macro@imgtec.com>2016-05-20 13:38:48 +0100
commit17c6c9d9f3e71459edb4b6af5ec75125f0d06f87 (patch)
tree8ea38eb69685fd05cbeb181263dbd87556da3919 /gas/config/tc-mips.c
parent134c0c8bf4a258ba10e72b724eadf40f731bb7ec (diff)
downloadgdb-17c6c9d9f3e71459edb4b6af5ec75125f0d06f87.zip
gdb-17c6c9d9f3e71459edb4b6af5ec75125f0d06f87.tar.gz
gdb-17c6c9d9f3e71459edb4b6af5ec75125f0d06f87.tar.bz2
MIPS: Fix the encoding of immediates with microMIPS JALX
The microMIPS JALX instruction shares the R_MICROMIPS_26_S1 relocation with microMIPS J/JAL/JALS instructions, however unlike the latters its encoded immediate argument is unusually shifted left by 2 rather than 1 in calculating the value used for the operation requested. We already handle this exception in `mips_elf_calculate_relocation' in LD, in a scenario where JALX is produced as a result of relaxing JAL for the purpose of making a cross-mode jump. We also get it right in the disassembler in `decode_micromips_operand'. What we don't correctly do however is processing microMIPS JALX produced by GAS from an assembly source, where a non-zero constant argument or a symbol reference with a non-zero in-place addend has been used. In this case the same calculation is made as for microMIPS J/JAL/JALS, causing the wrong encoding to be produced by GAS on making an object file, and then again by LD in the final link. The latter in particular causes the calculation, where the addend fits in the relocatable field, to produce different final addresses for the same source code depending on whether REL or RELA relocations are used. Correct these issues by special-casing microMIPS JALX in the places that have been previously missed. bfd/ * elfxx-mips.c (mips_elf_read_rel_addend): Adjust the addend for microMIPS JALX. gas/ * config/tc-mips.c (append_insn): Correct the encoding of a constant argument for microMIPS JALX. (tc_gen_reloc): Correct the encoding of an in-place addend for microMIPS JALX. * testsuite/gas/mips/jalx-addend.d: New test. * testsuite/gas/mips/jalx-addend-n32.d: New test. * testsuite/gas/mips/jalx-addend-n64.d: New test. * testsuite/gas/mips/jalx-imm.d: New test. * testsuite/gas/mips/jalx-imm-n32.d: New test. * testsuite/gas/mips/jalx-imm-n64.d: New test. * testsuite/gas/mips/jalx-addend.s: New test source. * testsuite/gas/mips/jalx-imm.s: New test source. * testsuite/gas/mips/mips.exp: Run the new tests. ld/ * testsuite/ld-mips-elf/jalx-addend.d: New test. * testsuite/ld-mips-elf/jalx-addend-n32.d: New test. * testsuite/ld-mips-elf/jalx-addend-n64.d: New test. * testsuite/ld-mips-elf/mips-elf.exp: Run the new tests.
Diffstat (limited to 'gas/config/tc-mips.c')
-rw-r--r--gas/config/tc-mips.c13
1 files changed, 12 insertions, 1 deletions
diff --git a/gas/config/tc-mips.c b/gas/config/tc-mips.c
index ccdda0c..233c641 100644
--- a/gas/config/tc-mips.c
+++ b/gas/config/tc-mips.c
@@ -7044,7 +7044,9 @@ append_insn (struct mips_cl_insn *ip, expressionS *address_expr,
{
int shift;
- shift = mips_opts.micromips ? 1 : 2;
+ /* Shift is 2, unusually, for microMIPS JALX. */
+ shift = (mips_opts.micromips
+ && strcmp (ip->insn_mo->name, "jalx") != 0) ? 1 : 2;
if ((address_expr->X_add_number & ((1 << shift) - 1)) != 0)
as_bad (_("jump to misaligned address (0x%lx)"),
(unsigned long) address_expr->X_add_number);
@@ -17225,6 +17227,15 @@ tc_gen_reloc (asection *section ATTRIBUTE_UNUSED, fixS *fixp)
Relocations want only the symbol offset. */
reloc->addend = fixp->fx_addnumber + reloc->address;
}
+ else if (HAVE_IN_PLACE_ADDENDS
+ && fixp->fx_r_type == BFD_RELOC_MICROMIPS_JMP
+ && (read_compressed_insn (fixp->fx_frag->fr_literal
+ + fixp->fx_where, 4) >> 26) == 0x3c)
+ {
+ /* Shift is 2, unusually, for microMIPS JALX. Adjust the in-place
+ addend accordingly. */
+ reloc->addend = fixp->fx_addnumber >> 1;
+ }
else
reloc->addend = fixp->fx_addnumber;