aboutsummaryrefslogtreecommitdiff
path: root/opcodes
diff options
context:
space:
mode:
authorMaciej W. Rozycki <macro@imgtec.com>2016-12-08 23:29:01 +0000
committerMaciej W. Rozycki <macro@imgtec.com>2016-12-08 23:30:57 +0000
commit860b03a8f357d1565bd9d79ae25121059b2d28ae (patch)
treec76f74a44626b05d308861754e7561fe8f73bcb3 /opcodes
parent731f7c4ea30cc409c45412eec15e3d66afe051f5 (diff)
downloadfsf-binutils-gdb-860b03a8f357d1565bd9d79ae25121059b2d28ae.zip
fsf-binutils-gdb-860b03a8f357d1565bd9d79ae25121059b2d28ae.tar.gz
fsf-binutils-gdb-860b03a8f357d1565bd9d79ae25121059b2d28ae.tar.bz2
MIPS16/opcodes: Fix PC-relative operation delay-slot adjustment
Complement commit dd8b7c222e0e ("MIPS: mips16e jalrc/jrc opcodes"), <https://sourceware.org/ml/binutils/2005-07/msg00349.html>, and stop the disassembler making a delay-slot adjustment for PC-relative operations following either MIPS16e compact jumps, or undefined RR/J(AL)R(C) encodings that have the `l' (link) and `ra' (source register is `ra') bits set both at a time. Adjust code description for accuracy. Add a suitable test case. opcodes/ * mips-dis.c (print_mips16_insn_arg): Avoid delay-slot adjustment for PC-relative operations following MIPS16e compact jumps or undefined RR/J(AL)R(C) encodings. binutils/ * testsuite/binutils-all/mips/mips16-pcrel.d: New test. * testsuite/binutils-all/mips/mips16-pcrel.s: New test source. * testsuite/binutils-all/mips/mips.exp: Run the new test.
Diffstat (limited to 'opcodes')
-rw-r--r--opcodes/ChangeLog6
-rw-r--r--opcodes/mips-dis.c16
2 files changed, 16 insertions, 6 deletions
diff --git a/opcodes/ChangeLog b/opcodes/ChangeLog
index 110739a..70f9150 100644
--- a/opcodes/ChangeLog
+++ b/opcodes/ChangeLog
@@ -1,5 +1,11 @@
2016-12-08 Maciej W. Rozycki <macro@imgtec.com>
+ * mips-dis.c (print_mips16_insn_arg): Avoid delay-slot
+ adjustment for PC-relative operations following MIPS16e compact
+ jumps or undefined RR/J(AL)R(C) encodings.
+
+2016-12-08 Maciej W. Rozycki <macro@imgtec.com>
+
* aarch64-asm.c (aarch64_ins_reglane): Rename `index' local
variable to `reglane_index'.
diff --git a/opcodes/mips-dis.c b/opcodes/mips-dis.c
index 7192c84..19d0366 100644
--- a/opcodes/mips-dis.c
+++ b/opcodes/mips-dis.c
@@ -1917,12 +1917,12 @@ print_mips16_insn_arg (struct disassemble_info *info,
{
bfd_byte buffer[2];
- /* If this instruction is in the delay slot of a JR
+ /* If this instruction is in the delay slot of a JAL/JALX
instruction, the base address is the address of the
- JR instruction. If it is in the delay slot of a JALR
- instruction, the base address is the address of the
- JALR instruction. This test is unreliable: we have
- no way of knowing whether the previous word is
+ JAL/JALX instruction. If it is in the delay slot of
+ a JR/JALR instruction, the base address is the address
+ of the JR/JALR instruction. This test is unreliable:
+ we have no way of knowing whether the previous word is
instruction or data. */
if (info->read_memory_func (memaddr - 4, buffer, 2, info) == 0
&& (((info->endian == BFD_ENDIAN_BIG
@@ -1935,7 +1935,11 @@ print_mips16_insn_arg (struct disassemble_info *info,
&& (((info->endian == BFD_ENDIAN_BIG
? bfd_getb16 (buffer)
: bfd_getl16 (buffer))
- & 0xf81f) == 0xe800))
+ & 0xf89f) == 0xe800)
+ && (((info->endian == BFD_ENDIAN_BIG
+ ? bfd_getb16 (buffer)
+ : bfd_getl16 (buffer))
+ & 0x0060) != 0x0060))
baseaddr = memaddr - 2;
else
baseaddr = memaddr;