From: Maciej W. Rozycki Date: Thu, 8 Dec 2016 23:29:01 +0000 (+0000) Subject: MIPS16/opcodes: Fix PC-relative operation delay-slot adjustment X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=860b03a8f357d1565bd9d79ae25121059b2d28ae;p=binutils-gdb.git MIPS16/opcodes: Fix PC-relative operation delay-slot adjustment Complement commit dd8b7c222e0e ("MIPS: mips16e jalrc/jrc opcodes"), , 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. --- diff --git a/binutils/ChangeLog b/binutils/ChangeLog index ae19b532946..f41e4fff428 100644 --- a/binutils/ChangeLog +++ b/binutils/ChangeLog @@ -1,3 +1,9 @@ +2016-12-08 Maciej W. Rozycki + + * 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. + 2016-12-08 Étienne Buira * readelf.c (process_program_headers): Always use hex prefix when diff --git a/binutils/testsuite/binutils-all/mips/mips.exp b/binutils/testsuite/binutils-all/mips/mips.exp index 4dab9a60459..5dc872d7ef4 100644 --- a/binutils/testsuite/binutils-all/mips/mips.exp +++ b/binutils/testsuite/binutils-all/mips/mips.exp @@ -24,4 +24,5 @@ if [is_elf_format] { run_dump_test "mixed-micromips" run_dump_test "mixed-mips16-micromips" run_dump_test "mips16-undecoded" + run_dump_test "mips16-pcrel" } diff --git a/binutils/testsuite/binutils-all/mips/mips16-pcrel.d b/binutils/testsuite/binutils-all/mips/mips16-pcrel.d new file mode 100644 index 00000000000..6b8e96b4219 --- /dev/null +++ b/binutils/testsuite/binutils-all/mips/mips16-pcrel.d @@ -0,0 +1,200 @@ +#PROG: objcopy +#objdump: -d --prefix-addresses --show-raw-insn +#name: MIPS16 PC-relative instruction disassembly +#as: -32 + +# Verify delay-slot adjustment for PC-relative operations. + +.*: +file format .*mips.* + +Disassembly of section \.text: +00000000 <[^>]*> 6500 nop +00000002 <[^>]*> 6500 nop +00000004 <[^>]*> 0aff la v0,00000400 +00000006 <[^>]*> 6500 nop +00000008 <[^>]*> 6500 nop +0000000a <[^>]*> 6500 nop +0000000c <[^>]*> b3ff lw v1,00000408 +0000000e <[^>]*> 6500 nop +00000010 <[^>]*> 6500 nop +00000012 <[^>]*> 6500 nop +00000014 <[^>]*> fe9f dla a0,00000090 +00000016 <[^>]*> 6500 nop +00000018 <[^>]*> 6500 nop +0000001a <[^>]*> 6500 nop +0000001c <[^>]*> 6500 nop +0000001e <[^>]*> 6500 nop +00000020 <[^>]*> fcbf ld a1,00000118 + \.\.\. +00001000 <[^>]*> 1800 0000 jal 00000000 +00001004 <[^>]*> 0aff la v0,000013fc +00001006 <[^>]*> 6500 nop +00001008 <[^>]*> 1800 0000 jal 00000000 +0000100c <[^>]*> b3ff lw v1,00001404 +0000100e <[^>]*> 6500 nop +00001010 <[^>]*> 1800 0000 jal 00000000 +00001014 <[^>]*> fe9f dla a0,0000108c +00001016 <[^>]*> 6500 nop +00001018 <[^>]*> 6500 nop +0000101a <[^>]*> 6500 nop +0000101c <[^>]*> 1800 0000 jal 00000000 +00001020 <[^>]*> fcbf ld a1,00001110 + \.\.\. +00002000 <[^>]*> 1c00 0000 jalx 00000000 +00002004 <[^>]*> 0aff la v0,000023fc +00002006 <[^>]*> 6500 nop +00002008 <[^>]*> 1c00 0000 jalx 00000000 +0000200c <[^>]*> b3ff lw v1,00002404 +0000200e <[^>]*> 6500 nop +00002010 <[^>]*> 1c00 0000 jalx 00000000 +00002014 <[^>]*> fe9f dla a0,0000208c +00002016 <[^>]*> 6500 nop +00002018 <[^>]*> 6500 nop +0000201a <[^>]*> 6500 nop +0000201c <[^>]*> 1c00 0000 jalx 00000000 +00002020 <[^>]*> fcbf ld a1,00002110 + \.\.\. +00003000 <[^>]*> 6500 nop +00003002 <[^>]*> e800 jr s0 +00003004 <[^>]*> 0aff la v0,000033fc +00003006 <[^>]*> 6500 nop +00003008 <[^>]*> 6500 nop +0000300a <[^>]*> e800 jr s0 +0000300c <[^>]*> b3ff lw v1,00003404 +0000300e <[^>]*> 6500 nop +00003010 <[^>]*> 6500 nop +00003012 <[^>]*> e800 jr s0 +00003014 <[^>]*> fe9f dla a0,0000308c +00003016 <[^>]*> 6500 nop +00003018 <[^>]*> 6500 nop +0000301a <[^>]*> 6500 nop +0000301c <[^>]*> 6500 nop +0000301e <[^>]*> e800 jr s0 +00003020 <[^>]*> fcbf ld a1,00003110 + \.\.\. +00004000 <[^>]*> 6500 nop +00004002 <[^>]*> e820 jr ra +00004004 <[^>]*> 0aff la v0,000043fc +00004006 <[^>]*> 6500 nop +00004008 <[^>]*> 6500 nop +0000400a <[^>]*> e820 jr ra +0000400c <[^>]*> b3ff lw v1,00004404 +0000400e <[^>]*> 6500 nop +00004010 <[^>]*> 6500 nop +00004012 <[^>]*> e820 jr ra +00004014 <[^>]*> fe9f dla a0,0000408c +00004016 <[^>]*> 6500 nop +00004018 <[^>]*> 6500 nop +0000401a <[^>]*> 6500 nop +0000401c <[^>]*> 6500 nop +0000401e <[^>]*> e820 jr ra +00004020 <[^>]*> fcbf ld a1,00004110 + \.\.\. +00005000 <[^>]*> 6500 nop +00005002 <[^>]*> e840 jalr s0 +00005004 <[^>]*> 0aff la v0,000053fc +00005006 <[^>]*> 6500 nop +00005008 <[^>]*> 6500 nop +0000500a <[^>]*> e840 jalr s0 +0000500c <[^>]*> b3ff lw v1,00005404 +0000500e <[^>]*> 6500 nop +00005010 <[^>]*> 6500 nop +00005012 <[^>]*> e840 jalr s0 +00005014 <[^>]*> fe9f dla a0,0000508c +00005016 <[^>]*> 6500 nop +00005018 <[^>]*> 6500 nop +0000501a <[^>]*> 6500 nop +0000501c <[^>]*> 6500 nop +0000501e <[^>]*> e840 jalr s0 +00005020 <[^>]*> fcbf ld a1,00005110 + \.\.\. +00006000 <[^>]*> 6500 nop +00006002 <[^>]*> e860 0xe860 +00006004 <[^>]*> 0aff la v0,00006400 +00006006 <[^>]*> 6500 nop +00006008 <[^>]*> 6500 nop +0000600a <[^>]*> e860 0xe860 +0000600c <[^>]*> b3ff lw v1,00006408 +0000600e <[^>]*> 6500 nop +00006010 <[^>]*> 6500 nop +00006012 <[^>]*> e860 0xe860 +00006014 <[^>]*> fe9f dla a0,00006090 +00006016 <[^>]*> 6500 nop +00006018 <[^>]*> 6500 nop +0000601a <[^>]*> 6500 nop +0000601c <[^>]*> 6500 nop +0000601e <[^>]*> e860 0xe860 +00006020 <[^>]*> fcbf ld a1,00006118 + \.\.\. +00007000 <[^>]*> 6500 nop +00007002 <[^>]*> e880 jrc s0 +00007004 <[^>]*> 0aff la v0,00007400 +00007006 <[^>]*> 6500 nop +00007008 <[^>]*> 6500 nop +0000700a <[^>]*> e880 jrc s0 +0000700c <[^>]*> b3ff lw v1,00007408 +0000700e <[^>]*> 6500 nop +00007010 <[^>]*> 6500 nop +00007012 <[^>]*> e880 jrc s0 +00007014 <[^>]*> fe9f dla a0,00007090 +00007016 <[^>]*> 6500 nop +00007018 <[^>]*> 6500 nop +0000701a <[^>]*> 6500 nop +0000701c <[^>]*> 6500 nop +0000701e <[^>]*> e880 jrc s0 +00007020 <[^>]*> fcbf ld a1,00007118 + \.\.\. +00008000 <[^>]*> 6500 nop +00008002 <[^>]*> e8a0 jrc ra +00008004 <[^>]*> 0aff la v0,00008400 +00008006 <[^>]*> 6500 nop +00008008 <[^>]*> 6500 nop +0000800a <[^>]*> e8a0 jrc ra +0000800c <[^>]*> b3ff lw v1,00008408 +0000800e <[^>]*> 6500 nop +00008010 <[^>]*> 6500 nop +00008012 <[^>]*> e8a0 jrc ra +00008014 <[^>]*> fe9f dla a0,00008090 +00008016 <[^>]*> 6500 nop +00008018 <[^>]*> 6500 nop +0000801a <[^>]*> 6500 nop +0000801c <[^>]*> 6500 nop +0000801e <[^>]*> e8a0 jrc ra +00008020 <[^>]*> fcbf ld a1,00008118 + \.\.\. +00009000 <[^>]*> 6500 nop +00009002 <[^>]*> e8c0 jalrc s0 +00009004 <[^>]*> 0aff la v0,00009400 +00009006 <[^>]*> 6500 nop +00009008 <[^>]*> 6500 nop +0000900a <[^>]*> e8c0 jalrc s0 +0000900c <[^>]*> b3ff lw v1,00009408 +0000900e <[^>]*> 6500 nop +00009010 <[^>]*> 6500 nop +00009012 <[^>]*> e8c0 jalrc s0 +00009014 <[^>]*> fe9f dla a0,00009090 +00009016 <[^>]*> 6500 nop +00009018 <[^>]*> 6500 nop +0000901a <[^>]*> 6500 nop +0000901c <[^>]*> 6500 nop +0000901e <[^>]*> e8c0 jalrc s0 +00009020 <[^>]*> fcbf ld a1,00009118 + \.\.\. +0000a000 <[^>]*> 6500 nop +0000a002 <[^>]*> e960 0xe960 +0000a004 <[^>]*> 0aff la v0,0000a400 +0000a006 <[^>]*> 6500 nop +0000a008 <[^>]*> 6500 nop +0000a00a <[^>]*> e960 0xe960 +0000a00c <[^>]*> b3ff lw v1,0000a408 +0000a00e <[^>]*> 6500 nop +0000a010 <[^>]*> 6500 nop +0000a012 <[^>]*> e960 0xe960 +0000a014 <[^>]*> fe9f dla a0,0000a090 +0000a016 <[^>]*> 6500 nop +0000a018 <[^>]*> 6500 nop +0000a01a <[^>]*> 6500 nop +0000a01c <[^>]*> 6500 nop +0000a01e <[^>]*> e960 0xe960 +0000a020 <[^>]*> fcbf ld a1,0000a118 + \.\.\. diff --git a/binutils/testsuite/binutils-all/mips/mips16-pcrel.s b/binutils/testsuite/binutils-all/mips/mips16-pcrel.s new file mode 100644 index 00000000000..f73aeaefc31 --- /dev/null +++ b/binutils/testsuite/binutils-all/mips/mips16-pcrel.s @@ -0,0 +1,219 @@ + .module mips64 + .set mips16 + .set noreorder + .set noautoextend + + .align 12, 0 +foo0: + nop + nop + addiu $2, $pc, 0x3fc + nop + nop + nop + lw $3, 0x3fc($pc) + nop + nop + nop + daddiu $4, $pc, 0x7c + nop + nop + nop + nop + nop + ld $5, 0xf8($pc) + + .align 12, 0 +foo1: + jal bar0 + addiu $2, $pc, 0x3fc + nop + jal bar0 + lw $3, 0x3fc($pc) + nop + jal bar0 + daddiu $4, $pc, 0x7c + nop + nop + nop + jal bar0 + ld $5, 0xf8($pc) + + .align 12, 0 +foo2: + jalx bar1 + addiu $2, $pc, 0x3fc + nop + jalx bar1 + lw $3, 0x3fc($pc) + nop + jalx bar1 + daddiu $4, $pc, 0x7c + nop + nop + nop + jalx bar1 + ld $5, 0xf8($pc) + + .align 12, 0 +foo3: + nop + jr $16 + addiu $2, $pc, 0x3fc + nop + nop + jr $16 + lw $3, 0x3fc($pc) + nop + nop + jr $16 + daddiu $4, $pc, 0x7c + nop + nop + nop + nop + jr $16 + ld $5, 0xf8($pc) + + .align 12, 0 +foo4: + nop + jr $31 + addiu $2, $pc, 0x3fc + nop + nop + jr $31 + lw $3, 0x3fc($pc) + nop + nop + jr $31 + daddiu $4, $pc, 0x7c + nop + nop + nop + nop + jr $31 + ld $5, 0xf8($pc) + + .align 12, 0 +foo5: + nop + jalr $16 + addiu $2, $pc, 0x3fc + nop + nop + jalr $16 + lw $3, 0x3fc($pc) + nop + nop + jalr $16 + daddiu $4, $pc, 0x7c + nop + nop + nop + nop + jalr $16 + ld $5, 0xf8($pc) + + .align 12, 0 +foo6: + nop + .half 0xe860 + addiu $2, $pc, 0x3fc + nop + nop + .half 0xe860 + lw $3, 0x3fc($pc) + nop + nop + .half 0xe860 + daddiu $4, $pc, 0x7c + nop + nop + nop + nop + .half 0xe860 + ld $5, 0xf8($pc) + + .align 12, 0 +foo7: + nop + jrc $16 + addiu $2, $pc, 0x3fc + nop + nop + jrc $16 + lw $3, 0x3fc($pc) + nop + nop + jrc $16 + daddiu $4, $pc, 0x7c + nop + nop + nop + nop + jrc $16 + ld $5, 0xf8($pc) + + .align 12, 0 +foo8: + nop + jrc $31 + addiu $2, $pc, 0x3fc + nop + nop + jrc $31 + lw $3, 0x3fc($pc) + nop + nop + jrc $31 + daddiu $4, $pc, 0x7c + nop + nop + nop + nop + jrc $31 + ld $5, 0xf8($pc) + + .align 12, 0 +foo9: + nop + jalrc $16 + addiu $2, $pc, 0x3fc + nop + nop + jalrc $16 + lw $3, 0x3fc($pc) + nop + nop + jalrc $16 + daddiu $4, $pc, 0x7c + nop + nop + nop + nop + jalrc $16 + ld $5, 0xf8($pc) + + .align 12, 0 +fooa: + nop + .half 0xe960 + addiu $2, $pc, 0x3fc + nop + nop + .half 0xe960 + lw $3, 0x3fc($pc) + nop + nop + .half 0xe960 + daddiu $4, $pc, 0x7c + nop + nop + nop + nop + .half 0xe960 + ld $5, 0xf8($pc) + +# Force some (non-delay-slot) zero bytes, to make 'objdump' print ... + .align 12, 0 diff --git a/opcodes/ChangeLog b/opcodes/ChangeLog index 110739a2c8a..70f91502c9c 100644 --- a/opcodes/ChangeLog +++ b/opcodes/ChangeLog @@ -1,3 +1,9 @@ +2016-12-08 Maciej W. Rozycki + + * 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 * aarch64-asm.c (aarch64_ins_reglane): Rename `index' local diff --git a/opcodes/mips-dis.c b/opcodes/mips-dis.c index 7192c846813..19d0366e8f3 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;