diff options
-rw-r--r-- | binutils/ChangeLog | 12 | ||||
-rw-r--r-- | binutils/testsuite/binutils-all/arm/vdup-cond.d | 27 | ||||
-rw-r--r-- | binutils/testsuite/binutils-all/arm/vdup-cond.s | 18 | ||||
-rw-r--r-- | binutils/testsuite/binutils-all/arm/vdup-thumb.d | 13 | ||||
-rw-r--r-- | binutils/testsuite/binutils-all/arm/vdup-thumb.s | 4 | ||||
-rw-r--r-- | opcodes/ChangeLog | 6 | ||||
-rw-r--r-- | opcodes/arm-dis.c | 57 |
7 files changed, 127 insertions, 10 deletions
diff --git a/binutils/ChangeLog b/binutils/ChangeLog index 5c9c18b..1b6a2f9 100644 --- a/binutils/ChangeLog +++ b/binutils/ChangeLog @@ -1,3 +1,15 @@ +2020-04-17 Fredrik Strupe <fredrik@strupe.net> + + * testsuite/binutils-all/arm/vdup-cond.d: New test for testing that + conditional VDUP instructions are disassembled correctly. + * testsuite/binutils-all/arm/vdup-cond.s: New file used by + vdup-cond.d. + * testsuite/binutils-all/arm/vdup-thumb.d: New test for testing + that VDUP instructions (which are conditional in A32) can be + disassembled in thumb mode. + * testsuite/binutils-all/arm/vdup-cond.s: New file used by + vdup-thumb.d. + 2020-04-17 Alan Modra <amodra@gmail.com> PR 25840 diff --git a/binutils/testsuite/binutils-all/arm/vdup-cond.d b/binutils/testsuite/binutils-all/arm/vdup-cond.d new file mode 100644 index 0000000..f75931b --- /dev/null +++ b/binutils/testsuite/binutils-all/arm/vdup-cond.d @@ -0,0 +1,27 @@ +#PROG: objcopy +#source vdup-cond.s +#as: -mfpu=neon +#objdump: -d +#skip: *-*-pe *-wince-* *-*-coff +#name: Check if disassembler can handle conditional neon (vdup) instructions + +.*: +file format .*arm.* + +Disassembly of section \.vdups: + +.+ <\.vdups>: +[^:]+: 0e800b10 vdupeq.32 d0, r0 +[^:]+: 1e800b10 vdupne.32 d0, r0 +[^:]+: 2e800b10 vdupcs.32 d0, r0 +[^:]+: 3e800b10 vdupcc.32 d0, r0 +[^:]+: 4e800b10 vdupmi.32 d0, r0 +[^:]+: 5e800b10 vduppl.32 d0, r0 +[^:]+: 6e800b10 vdupvs.32 d0, r0 +[^:]+: 7e800b10 vdupvc.32 d0, r0 +[^:]+: 8e800b10 vduphi.32 d0, r0 +[^:]+: 9e800b10 vdupls.32 d0, r0 +[^:]+: ae800b10 vdupge.32 d0, r0 +[^:]+: be800b10 vduplt.32 d0, r0 +[^:]+: ce800b10 vdupgt.32 d0, r0 +[^:]+: de800b10 vduple.32 d0, r0 +[^:]+: ee800b10 vdup.32 d0, r0 diff --git a/binutils/testsuite/binutils-all/arm/vdup-cond.s b/binutils/testsuite/binutils-all/arm/vdup-cond.s new file mode 100644 index 0000000..cc544ef --- /dev/null +++ b/binutils/testsuite/binutils-all/arm/vdup-cond.s @@ -0,0 +1,18 @@ +.text +.arm +.section .vdups, "ax" +vdupeq.32 d0, r0 +vdupne.32 d0, r0 +vdupcs.32 d0, r0 +vdupcc.32 d0, r0 +vdupmi.32 d0, r0 +vduppl.32 d0, r0 +vdupvs.32 d0, r0 +vdupvc.32 d0, r0 +vduphi.32 d0, r0 +vdupls.32 d0, r0 +vdupge.32 d0, r0 +vduplt.32 d0, r0 +vdupgt.32 d0, r0 +vduple.32 d0, r0 +vdup.32 d0, r0 diff --git a/binutils/testsuite/binutils-all/arm/vdup-thumb.d b/binutils/testsuite/binutils-all/arm/vdup-thumb.d new file mode 100644 index 0000000..30e8034 --- /dev/null +++ b/binutils/testsuite/binutils-all/arm/vdup-thumb.d @@ -0,0 +1,13 @@ +#PROG: objcopy +#source vdup-cond.s +#as: -mfpu=neon +#objdump: -d +#skip: *-*-pe *-wince-* *-*-coff +#name: Check if disassembler can handle vdup instructions in thumb + +.*: +file format .*arm.* + +Disassembly of section \.vdups: + +.+ <\.vdups>: +[^:]+: ee80 0b10 vdup.32 d0, r0 diff --git a/binutils/testsuite/binutils-all/arm/vdup-thumb.s b/binutils/testsuite/binutils-all/arm/vdup-thumb.s new file mode 100644 index 0000000..d98b6a4 --- /dev/null +++ b/binutils/testsuite/binutils-all/arm/vdup-thumb.s @@ -0,0 +1,4 @@ +.text +.thumb +.section .vdups, "ax" +vdup.32 d0, r0 diff --git a/opcodes/ChangeLog b/opcodes/ChangeLog index 1877338..e3233f0 100644 --- a/opcodes/ChangeLog +++ b/opcodes/ChangeLog @@ -1,3 +1,9 @@ +2020-04-17 Fredrik Strupe <fredrik@strupe.net> + + * arm-dis.c (neon_opcodes): Fix VDUP instruction masks. + (print_insn_neon): Support disassembly of conditional + instructions. + 2020-02-16 David Faust <david.faust@oracle.com> * bpf-desc.c: Regenerate. diff --git a/opcodes/arm-dis.c b/opcodes/arm-dis.c index b926b65..79a3dc6 100644 --- a/opcodes/arm-dis.c +++ b/opcodes/arm-dis.c @@ -1494,17 +1494,17 @@ static const struct opcode32 neon_opcodes[] = /* Data transfer between ARM and NEON registers. */ {ARM_FEATURE_COPROC (FPU_NEON_EXT_V1), - 0x0e800b10, 0x1ff00f70, "vdup%c.32\t%16-19,7D, %12-15r"}, + 0x0e800b10, 0x0ff00f70, "vdup%c.32\t%16-19,7D, %12-15r"}, {ARM_FEATURE_COPROC (FPU_NEON_EXT_V1), - 0x0e800b30, 0x1ff00f70, "vdup%c.16\t%16-19,7D, %12-15r"}, + 0x0e800b30, 0x0ff00f70, "vdup%c.16\t%16-19,7D, %12-15r"}, {ARM_FEATURE_COPROC (FPU_NEON_EXT_V1), - 0x0ea00b10, 0x1ff00f70, "vdup%c.32\t%16-19,7Q, %12-15r"}, + 0x0ea00b10, 0x0ff00f70, "vdup%c.32\t%16-19,7Q, %12-15r"}, {ARM_FEATURE_COPROC (FPU_NEON_EXT_V1), - 0x0ea00b30, 0x1ff00f70, "vdup%c.16\t%16-19,7Q, %12-15r"}, + 0x0ea00b30, 0x0ff00f70, "vdup%c.16\t%16-19,7Q, %12-15r"}, {ARM_FEATURE_COPROC (FPU_NEON_EXT_V1), - 0x0ec00b10, 0x1ff00f70, "vdup%c.8\t%16-19,7D, %12-15r"}, + 0x0ec00b10, 0x0ff00f70, "vdup%c.8\t%16-19,7D, %12-15r"}, {ARM_FEATURE_COPROC (FPU_NEON_EXT_V1), - 0x0ee00b10, 0x1ff00f70, "vdup%c.8\t%16-19,7Q, %12-15r"}, + 0x0ee00b10, 0x0ff00f70, "vdup%c.8\t%16-19,7Q, %12-15r"}, /* Move data element to all lanes. */ {ARM_FEATURE_COPROC (FPU_NEON_EXT_V1), @@ -9032,13 +9032,51 @@ print_insn_neon (struct disassemble_info *info, long given, bfd_boolean thumb) || (given & 0xff000000) == 0xfc000000) ; /* vdup is also a valid neon instruction. */ - else if ((given & 0xff910f5f) != 0xee800b10) + else if ((given & 0xff900f5f) != 0xee800b10) return FALSE; } for (insn = neon_opcodes; insn->assembler; insn++) { - if ((given & insn->mask) == insn->value) + unsigned long cond_mask = insn->mask; + unsigned long cond_value = insn->value; + int cond; + + if (thumb) + { + if ((cond_mask & 0xf0000000) == 0) { + /* For the entries in neon_opcodes, an opcode mask/value with + the high 4 bits equal to 0 indicates a conditional + instruction. For thumb however, we need to include those + bits in the instruction matching. */ + cond_mask |= 0xf0000000; + /* Furthermore, the thumb encoding of a conditional instruction + will have the high 4 bits equal to 0xe. */ + cond_value |= 0xe0000000; + } + if (ifthen_state) + cond = IFTHEN_COND; + else + cond = COND_UNCOND; + } + else + { + if ((given & 0xf0000000) == 0xf0000000) + { + /* If the instruction is unconditional, update the mask to only + match against unconditional opcode values. */ + cond_mask |= 0xf0000000; + cond = COND_UNCOND; + } + else + { + cond = (given >> 28) & 0xf; + if (cond == 0xe) + cond = COND_UNCOND; + } + } + + if ((given & cond_mask) == cond_value) { signed long value_in_comment = 0; bfd_boolean is_unpredictable = FALSE; @@ -9060,8 +9098,7 @@ print_insn_neon (struct disassemble_info *info, long given, bfd_boolean thumb) /* Fall through. */ case 'c': - if (thumb && ifthen_state) - func (stream, "%s", arm_conditional[IFTHEN_COND]); + func (stream, "%s", arm_conditional[cond]); break; case 'A': |