aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--binutils/ChangeLog12
-rw-r--r--binutils/testsuite/binutils-all/arm/vdup-cond.d27
-rw-r--r--binutils/testsuite/binutils-all/arm/vdup-cond.s18
-rw-r--r--binutils/testsuite/binutils-all/arm/vdup-thumb.d13
-rw-r--r--binutils/testsuite/binutils-all/arm/vdup-thumb.s4
-rw-r--r--opcodes/ChangeLog6
-rw-r--r--opcodes/arm-dis.c57
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':