aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNick Clifton <nickc@redhat.com>2009-06-18 10:31:21 +0000
committerNick Clifton <nickc@redhat.com>2009-06-18 10:31:21 +0000
commit0313a2b8d2bc3ac3a15912d7fa9fe02722eaa14c (patch)
treedc124b744e50e56ff817cd08c6ef38edeb61e28f
parent470c710ef03d4c05314c605b26f47fb5a61beb34 (diff)
downloadgdb-0313a2b8d2bc3ac3a15912d7fa9fe02722eaa14c.zip
gdb-0313a2b8d2bc3ac3a15912d7fa9fe02722eaa14c.tar.gz
gdb-0313a2b8d2bc3ac3a15912d7fa9fe02722eaa14c.tar.bz2
PR 10288
* arm-dis.c (print_insn_coprocessor): Check that a user specified ARM architecture supports the matched instruction. (print_insn_arm): Likewise. (select_arm_features): New function. Fills in the fields of an arm_feature_set structure based on a given arm machine number. (print_insn): Initialise an arm_feature_set structure. * objdump.c (disassemble_bytes): Set the USER_SPECIFIED_MACHINE_TYPE flag in the disassemble_info structure if the user has invoked the -m switch. * doc/binutils.texi: Document the additional behaviour of objdump's -m switch for ARM targets. * dis-asm.h (USER_SPECIFIED_MACHINE_TYPE): New value for the flags field of struct disassemble_info. * gas/arm/align.s: Add labels so that COFF based targets can correctly locate THUMB code. * gas/arm/copro.d: Do not pass --architecture switch to objdump.
-rw-r--r--binutils/ChangeLog14
-rw-r--r--binutils/doc/binutils.texi11
-rw-r--r--binutils/objdump.c2
-rw-r--r--gas/testsuite/ChangeLog7
-rw-r--r--gas/testsuite/gas/arm/align.s4
-rw-r--r--gas/testsuite/gas/arm/copro.d2
-rw-r--r--include/ChangeLog9
-rw-r--r--include/dis-asm.h3
-rw-r--r--opcodes/ChangeLog10
-rw-r--r--opcodes/arm-dis.c848
10 files changed, 522 insertions, 388 deletions
diff --git a/binutils/ChangeLog b/binutils/ChangeLog
index f7974f7..ddacde1 100644
--- a/binutils/ChangeLog
+++ b/binutils/ChangeLog
@@ -1,8 +1,18 @@
+2009-06-18 Nick Clifton <nickc@redhat.com>
+
+ PR 10288
+ * objdump.c (disassemble_bytes): Set the
+ USER_SPECIFIED_MACHINE_TYPE flag in the disassemble_info structure
+ if the user has invoked the -m switch.
+ * doc/binutils.texi: Document the additional behaviour of
+ objdump's -m switch for ARM targets.
+
2009-06-18 Dave Korn <dave.korn.cygwin@gmail.com>
- Merge cegcc and mingw32ce target name changes from CeGCC project.
+ * configure.in: Merge cegcc and mingw32ce target name changes from
+ CeGCC project.
- 2007-12-25 Pedro Alves <pedro_alves@portugalmail.pt>
+2007-12-25 Pedro Alves <pedro_alves@portugalmail.pt>
* configure.in: Add arm*-*-cegcc* and arm*-*-mingw32ce* targets.
* configure: Regenerate.
diff --git a/binutils/doc/binutils.texi b/binutils/doc/binutils.texi
index 7680c6f..d74b12b 100644
--- a/binutils/doc/binutils.texi
+++ b/binutils/doc/binutils.texi
@@ -1801,6 +1801,10 @@ expected to contain instructions.
Like @option{-d}, but disassemble the contents of all sections, not just
those expected to contain instructions.
+If the target is an ARM architecture this switch also has the effect
+of forcing the disassembler to decode pieces of data found in code
+sections as if they were instructions.
+
@item --prefix-addresses
When disassembling, print the complete address on each line. This is
the older disassembly format.
@@ -1884,6 +1888,13 @@ can be useful when disassembling object files which do not describe
architecture information, such as S-records. You can list the available
architectures with the @option{-i} option.
+If the target is an ARM architecture then this switch has an
+additional effect. It restricts the disassembly to only those
+instructions supported by the architecture specified by @var{machine}.
+If it is necessary to use this switch because the input file does not
+contain any architecture information, but it is also desired to
+disassemble all the instructions use @option{-marm}.
+
@item -M @var{options}
@itemx --disassembler-options=@var{options}
Pass target specific information to the disassembler. Only supported on
diff --git a/binutils/objdump.c b/binutils/objdump.c
index 3cf03f7..dfe6a57 100644
--- a/binutils/objdump.c
+++ b/binutils/objdump.c
@@ -1526,6 +1526,8 @@ disassemble_bytes (struct disassemble_info * info,
info->bytes_per_line = 0;
info->bytes_per_chunk = 0;
info->flags = disassemble_all ? DISASSEMBLE_DATA : 0;
+ if (machine)
+ info->flags |= USER_SPECIFIED_MACHINE_TYPE;
if (info->disassembler_needs_relocs
&& (bfd_get_file_flags (aux->abfd) & EXEC_P) == 0
diff --git a/gas/testsuite/ChangeLog b/gas/testsuite/ChangeLog
index b2fba43..5bac61e 100644
--- a/gas/testsuite/ChangeLog
+++ b/gas/testsuite/ChangeLog
@@ -1,3 +1,10 @@
+2009-06-18 Nick Clifton <nickc@redhat.com>
+
+ PR 10288
+ * gas/arm/align.s: Add labels so that COFF based targets can
+ correctly locate THUMB code.
+ * gas/arm/copro.d: Do not pass --architecture switch to objdump.
+
2009-06-15 Nick Clifton <nickc@redhat.com>
PR gas/10186
diff --git a/gas/testsuite/gas/arm/align.s b/gas/testsuite/gas/arm/align.s
index 43c73ca..7ed8fbb 100644
--- a/gas/testsuite/gas/arm/align.s
+++ b/gas/testsuite/gas/arm/align.s
@@ -1,5 +1,7 @@
.syntax unified
.thumb
+ .global foo
+foo:
nop
mov r1,r2
.p2align 4
@@ -7,6 +9,8 @@
.p2align 3
.arm
+ .global bar
+bar:
nop
mov r1,r2
.p2align 4
diff --git a/gas/testsuite/gas/arm/copro.d b/gas/testsuite/gas/arm/copro.d
index ce79031..e97d6c4 100644
--- a/gas/testsuite/gas/arm/copro.d
+++ b/gas/testsuite/gas/arm/copro.d
@@ -1,4 +1,4 @@
-#objdump: -dr --prefix-addresses --show-raw-insn --architecture=armv5te
+#objdump: -dr --prefix-addresses --show-raw-insn
#name: ARM CoProcessor Instructions
#as: -march=armv5te -EL
diff --git a/include/ChangeLog b/include/ChangeLog
index 6742d24..8f85774 100644
--- a/include/ChangeLog
+++ b/include/ChangeLog
@@ -1,11 +1,16 @@
+2009-06-18 Nick Clifton <nickc@redhat.com>
+
+ * dis-asm.h (USER_SPECIFIED_MACHINE_TYPE): New value for the flags
+ field of struct disassemble_info.
+
2009-06-09 Ian Lance Taylor <ian@airs.com>
* ansidecl.h (ATTRIBUTE_UNUSED_LABEL): Define for C++.
2009-06-15 Nick Clifton <nickc@redhat.com>
- * dis-asm.h (struct disassemble_info): New value for the flags
- field.
+ * dis-asm.h (DISASSEMBLE_DATA): New value for the flags field of
+ struct disassemble_info.
2009-06-02 Ian Lance Taylor <iant@google.com>
diff --git a/include/dis-asm.h b/include/dis-asm.h
index 3872f8b..b7949c1 100644
--- a/include/dis-asm.h
+++ b/include/dis-asm.h
@@ -113,6 +113,9 @@ typedef struct disassemble_info
#define INSN_HAS_RELOC (1 << 31)
/* Set if the user has requested the disassembly of data as well as code. */
#define DISASSEMBLE_DATA (1 << 30)
+ /* Set if the user has specifically set the machine type encoded in the
+ mach field of this structure. */
+#define USER_SPECIFIED_MACHINE_TYPE (1 << 29)
/* Use internally by the target specific disassembly code. */
void *private_data;
diff --git a/opcodes/ChangeLog b/opcodes/ChangeLog
index 156a82a..a3a2263 100644
--- a/opcodes/ChangeLog
+++ b/opcodes/ChangeLog
@@ -1,3 +1,13 @@
+2009-06-18 Nick Clifton <nickc@redhat.com>
+
+ PR 10288
+ * arm-dis.c (print_insn_coprocessor): Check that a user specified
+ ARM architecture supports the matched instruction.
+ (print_insn_arm): Likewise.
+ (select_arm_features): New function. Fills in the fields of an
+ arm_feature_set structure based on a given arm machine number.
+ (print_insn): Initialise an arm_feature_set structure.
+
2009-06-16 Maciej W. Rozycki <macro@linux-mips.org>
* vax-dis.c (is_function_entry): Return success for synthetic
diff --git a/opcodes/arm-dis.c b/opcodes/arm-dis.c
index ce724a5..fb21f06 100644
--- a/opcodes/arm-dis.c
+++ b/opcodes/arm-dis.c
@@ -1635,6 +1635,8 @@ print_insn_coprocessor (bfd_vma pc, struct disassemble_info *info, long given,
for (insn = coprocessor_opcodes; insn->assembler; insn++)
{
+ const char *c;
+
if (insn->value == FIRST_IWMMXT_INSN
&& info->mach != bfd_mach_arm_XScale
&& info->mach != bfd_mach_arm_iWMMXt
@@ -1671,447 +1673,447 @@ print_insn_coprocessor (bfd_vma pc, struct disassemble_info *info, long given,
cond = 16;
}
}
- if ((given & mask) == value)
- {
- const char *c;
+
+ if ((given & mask) != value)
+ continue;
- for (c = insn->assembler; *c; c++)
+ if ((insn->arch & ((arm_feature_set *) info->private_data)->coproc) == 0)
+ continue;
+
+ for (c = insn->assembler; *c; c++)
+ {
+ if (*c == '%')
{
- if (*c == '%')
+ switch (*++c)
{
- switch (*++c)
+ case '%':
+ func (stream, "%%");
+ break;
+
+ case 'A':
+ func (stream, "[%s", arm_regnames [(given >> 16) & 0xf]);
+
+ if ((given & (1 << 24)) != 0)
{
- case '%':
- func (stream, "%%");
- break;
+ int offset = given & 0xff;
- case 'A':
- func (stream, "[%s", arm_regnames [(given >> 16) & 0xf]);
+ if (offset)
+ func (stream, ", #%s%d]%s",
+ ((given & 0x00800000) == 0 ? "-" : ""),
+ offset * 4,
+ ((given & 0x00200000) != 0 ? "!" : ""));
+ else
+ func (stream, "]");
+ }
+ else
+ {
+ int offset = given & 0xff;
- if ((given & (1 << 24)) != 0)
- {
- int offset = given & 0xff;
+ func (stream, "]");
+ if (given & (1 << 21))
+ {
if (offset)
- func (stream, ", #%s%d]%s",
+ func (stream, ", #%s%d",
((given & 0x00800000) == 0 ? "-" : ""),
- offset * 4,
- ((given & 0x00200000) != 0 ? "!" : ""));
- else
- func (stream, "]");
+ offset * 4);
}
else
- {
- int offset = given & 0xff;
+ func (stream, ", {%d}", offset);
+ }
+ break;
- func (stream, "]");
+ case 'B':
+ {
+ int regno = ((given >> 12) & 0xf) | ((given >> (22 - 4)) & 0x10);
+ int offset = (given >> 1) & 0x3f;
+
+ if (offset == 1)
+ func (stream, "{d%d}", regno);
+ else if (regno + offset > 32)
+ func (stream, "{d%d-<overflow reg d%d>}", regno, regno + offset - 1);
+ else
+ func (stream, "{d%d-d%d}", regno, regno + offset - 1);
+ }
+ break;
- if (given & (1 << 21))
- {
- if (offset)
- func (stream, ", #%s%d",
- ((given & 0x00800000) == 0 ? "-" : ""),
- offset * 4);
- }
- else
- func (stream, ", {%d}", offset);
- }
- break;
+ case 'C':
+ {
+ int rn = (given >> 16) & 0xf;
+ int offset = (given & 0xff) * 4;
+ int add = (given >> 23) & 1;
- case 'B':
+ func (stream, "[%s", arm_regnames[rn]);
+
+ if (offset)
{
- int regno = ((given >> 12) & 0xf) | ((given >> (22 - 4)) & 0x10);
- int offset = (given >> 1) & 0x3f;
-
- if (offset == 1)
- func (stream, "{d%d}", regno);
- else if (regno + offset > 32)
- func (stream, "{d%d-<overflow reg d%d>}", regno, regno + offset - 1);
- else
- func (stream, "{d%d-d%d}", regno, regno + offset - 1);
+ if (!add)
+ offset = -offset;
+ func (stream, ", #%d", offset);
}
- break;
-
- case 'C':
+ func (stream, "]");
+ if (rn == 15)
{
- int rn = (given >> 16) & 0xf;
- int offset = (given & 0xff) * 4;
- int add = (given >> 23) & 1;
-
- func (stream, "[%s", arm_regnames[rn]);
-
- if (offset)
- {
- if (!add)
- offset = -offset;
- func (stream, ", #%d", offset);
- }
- func (stream, "]");
- if (rn == 15)
- {
- func (stream, "\t; ");
- /* FIXME: Unsure if info->bytes_per_chunk is the
- right thing to use here. */
- info->print_address_func (offset + pc
- + info->bytes_per_chunk * 2, info);
- }
+ func (stream, "\t; ");
+ /* FIXME: Unsure if info->bytes_per_chunk is the
+ right thing to use here. */
+ info->print_address_func (offset + pc
+ + info->bytes_per_chunk * 2, info);
}
- break;
+ }
+ break;
- case 'c':
- func (stream, "%s", arm_conditional[cond]);
- break;
+ case 'c':
+ func (stream, "%s", arm_conditional[cond]);
+ break;
- case 'I':
- /* Print a Cirrus/DSP shift immediate. */
- /* Immediates are 7bit signed ints with bits 0..3 in
- bits 0..3 of opcode and bits 4..6 in bits 5..7
- of opcode. */
- {
- int imm;
+ case 'I':
+ /* Print a Cirrus/DSP shift immediate. */
+ /* Immediates are 7bit signed ints with bits 0..3 in
+ bits 0..3 of opcode and bits 4..6 in bits 5..7
+ of opcode. */
+ {
+ int imm;
- imm = (given & 0xf) | ((given & 0xe0) >> 1);
+ imm = (given & 0xf) | ((given & 0xe0) >> 1);
- /* Is ``imm'' a negative number? */
- if (imm & 0x40)
- imm |= (-1 << 7);
+ /* Is ``imm'' a negative number? */
+ if (imm & 0x40)
+ imm |= (-1 << 7);
- func (stream, "%d", imm);
- }
+ func (stream, "%d", imm);
+ }
+
+ break;
+ case 'F':
+ switch (given & 0x00408000)
+ {
+ case 0:
+ func (stream, "4");
+ break;
+ case 0x8000:
+ func (stream, "1");
+ break;
+ case 0x00400000:
+ func (stream, "2");
break;
+ default:
+ func (stream, "3");
+ }
+ break;
- case 'F':
- switch (given & 0x00408000)
- {
- case 0:
- func (stream, "4");
- break;
- case 0x8000:
- func (stream, "1");
- break;
- case 0x00400000:
- func (stream, "2");
- break;
- default:
- func (stream, "3");
- }
+ case 'P':
+ switch (given & 0x00080080)
+ {
+ case 0:
+ func (stream, "s");
+ break;
+ case 0x80:
+ func (stream, "d");
+ break;
+ case 0x00080000:
+ func (stream, "e");
+ break;
+ default:
+ func (stream, _("<illegal precision>"));
break;
+ }
+ break;
- case 'P':
- switch (given & 0x00080080)
- {
- case 0:
- func (stream, "s");
- break;
- case 0x80:
- func (stream, "d");
- break;
- case 0x00080000:
- func (stream, "e");
- break;
- default:
- func (stream, _("<illegal precision>"));
- break;
- }
+ case 'Q':
+ switch (given & 0x00408000)
+ {
+ case 0:
+ func (stream, "s");
break;
- case 'Q':
- switch (given & 0x00408000)
- {
- case 0:
- func (stream, "s");
- break;
- case 0x8000:
- func (stream, "d");
- break;
- case 0x00400000:
- func (stream, "e");
- break;
- default:
- func (stream, "p");
- break;
- }
+ case 0x8000:
+ func (stream, "d");
break;
- case 'R':
- switch (given & 0x60)
- {
- case 0:
- break;
- case 0x20:
- func (stream, "p");
- break;
- case 0x40:
- func (stream, "m");
- break;
- default:
- func (stream, "z");
- break;
- }
+ case 0x00400000:
+ func (stream, "e");
+ break;
+ default:
+ func (stream, "p");
break;
+ }
+ break;
- case '0': case '1': case '2': case '3': case '4':
- case '5': case '6': case '7': case '8': case '9':
- {
- int width;
- unsigned long value;
+ case 'R':
+ switch (given & 0x60)
+ {
+ case 0:
+ break;
+ case 0x20:
+ func (stream, "p");
+ break;
+ case 0x40:
+ func (stream, "m");
+ break;
+ default:
+ func (stream, "z");
+ break;
+ }
+ break;
- c = arm_decode_bitfield (c, given, &value, &width);
+ case '0': case '1': case '2': case '3': case '4':
+ case '5': case '6': case '7': case '8': case '9':
+ {
+ int width;
+ unsigned long value;
- switch (*c)
- {
- case 'r':
- func (stream, "%s", arm_regnames[value]);
- break;
- case 'D':
- func (stream, "d%ld", value);
- break;
- case 'Q':
- if (value & 1)
- func (stream, "<illegal reg q%ld.5>", value >> 1);
- else
- func (stream, "q%ld", value >> 1);
- break;
- case 'd':
- func (stream, "%ld", value);
- break;
- case 'k':
- {
- int from = (given & (1 << 7)) ? 32 : 16;
- func (stream, "%ld", from - value);
- }
- break;
-
- case 'f':
- if (value > 7)
- func (stream, "#%s", arm_fp_const[value & 7]);
- else
- func (stream, "f%ld", value);
- break;
+ c = arm_decode_bitfield (c, given, &value, &width);
- case 'w':
- if (width == 2)
- func (stream, "%s", iwmmxt_wwnames[value]);
- else
- func (stream, "%s", iwmmxt_wwssnames[value]);
- break;
+ switch (*c)
+ {
+ case 'r':
+ func (stream, "%s", arm_regnames[value]);
+ break;
+ case 'D':
+ func (stream, "d%ld", value);
+ break;
+ case 'Q':
+ if (value & 1)
+ func (stream, "<illegal reg q%ld.5>", value >> 1);
+ else
+ func (stream, "q%ld", value >> 1);
+ break;
+ case 'd':
+ func (stream, "%ld", value);
+ break;
+ case 'k':
+ {
+ int from = (given & (1 << 7)) ? 32 : 16;
+ func (stream, "%ld", from - value);
+ }
+ break;
- case 'g':
- func (stream, "%s", iwmmxt_regnames[value]);
- break;
- case 'G':
- func (stream, "%s", iwmmxt_cregnames[value]);
- break;
+ case 'f':
+ if (value > 7)
+ func (stream, "#%s", arm_fp_const[value & 7]);
+ else
+ func (stream, "f%ld", value);
+ break;
- case 'x':
- func (stream, "0x%lx", value);
- break;
+ case 'w':
+ if (width == 2)
+ func (stream, "%s", iwmmxt_wwnames[value]);
+ else
+ func (stream, "%s", iwmmxt_wwssnames[value]);
+ break;
- case '`':
- c++;
- if (value == 0)
- func (stream, "%c", *c);
- break;
- case '\'':
- c++;
- if (value == ((1ul << width) - 1))
- func (stream, "%c", *c);
- break;
- case '?':
- func (stream, "%c", c[(1 << width) - (int)value]);
- c += 1 << width;
- break;
- default:
- abort ();
- }
+ case 'g':
+ func (stream, "%s", iwmmxt_regnames[value]);
+ break;
+ case 'G':
+ func (stream, "%s", iwmmxt_cregnames[value]);
break;
- case 'y':
- case 'z':
- {
- int single = *c++ == 'y';
- int regno;
-
- switch (*c)
- {
- case '4': /* Sm pair */
- case '0': /* Sm, Dm */
- regno = given & 0x0000000f;
- if (single)
- {
- regno <<= 1;
- regno += (given >> 5) & 1;
- }
- else
- regno += ((given >> 5) & 1) << 4;
- break;
+ case 'x':
+ func (stream, "0x%lx", value);
+ break;
- case '1': /* Sd, Dd */
- regno = (given >> 12) & 0x0000000f;
- if (single)
- {
- regno <<= 1;
- regno += (given >> 22) & 1;
- }
- else
- regno += ((given >> 22) & 1) << 4;
- break;
+ case '`':
+ c++;
+ if (value == 0)
+ func (stream, "%c", *c);
+ break;
+ case '\'':
+ c++;
+ if (value == ((1ul << width) - 1))
+ func (stream, "%c", *c);
+ break;
+ case '?':
+ func (stream, "%c", c[(1 << width) - (int)value]);
+ c += 1 << width;
+ break;
+ default:
+ abort ();
+ }
+ break;
- case '2': /* Sn, Dn */
- regno = (given >> 16) & 0x0000000f;
- if (single)
- {
- regno <<= 1;
- regno += (given >> 7) & 1;
- }
- else
- regno += ((given >> 7) & 1) << 4;
- break;
-
- case '3': /* List */
- func (stream, "{");
- regno = (given >> 12) & 0x0000000f;
- if (single)
- {
- regno <<= 1;
- regno += (given >> 22) & 1;
- }
- else
- regno += ((given >> 22) & 1) << 4;
- break;
-
- default:
- abort ();
+ case 'y':
+ case 'z':
+ {
+ int single = *c++ == 'y';
+ int regno;
+
+ switch (*c)
+ {
+ case '4': /* Sm pair */
+ case '0': /* Sm, Dm */
+ regno = given & 0x0000000f;
+ if (single)
+ {
+ regno <<= 1;
+ regno += (given >> 5) & 1;
}
+ else
+ regno += ((given >> 5) & 1) << 4;
+ break;
- func (stream, "%c%d", single ? 's' : 'd', regno);
+ case '1': /* Sd, Dd */
+ regno = (given >> 12) & 0x0000000f;
+ if (single)
+ {
+ regno <<= 1;
+ regno += (given >> 22) & 1;
+ }
+ else
+ regno += ((given >> 22) & 1) << 4;
+ break;
- if (*c == '3')
+ case '2': /* Sn, Dn */
+ regno = (given >> 16) & 0x0000000f;
+ if (single)
{
- int count = given & 0xff;
-
- if (single == 0)
- count >>= 1;
-
- if (--count)
- {
- func (stream, "-%c%d",
- single ? 's' : 'd',
- regno + count);
- }
-
- func (stream, "}");
+ regno <<= 1;
+ regno += (given >> 7) & 1;
}
- else if (*c == '4')
- func (stream, ", %c%d", single ? 's' : 'd',
- regno + 1);
- }
- break;
+ else
+ regno += ((given >> 7) & 1) << 4;
+ break;
- case 'L':
- switch (given & 0x00400100)
- {
- case 0x00000000: func (stream, "b"); break;
- case 0x00400000: func (stream, "h"); break;
- case 0x00000100: func (stream, "w"); break;
- case 0x00400100: func (stream, "d"); break;
- default:
- break;
- }
- break;
+ case '3': /* List */
+ func (stream, "{");
+ regno = (given >> 12) & 0x0000000f;
+ if (single)
+ {
+ regno <<= 1;
+ regno += (given >> 22) & 1;
+ }
+ else
+ regno += ((given >> 22) & 1) << 4;
+ break;
- case 'Z':
- {
- int value;
- /* given (20, 23) | given (0, 3) */
- value = ((given >> 16) & 0xf0) | (given & 0xf);
- func (stream, "%d", value);
+ default:
+ abort ();
}
- break;
- case 'l':
- /* This is like the 'A' operator, except that if
- the width field "M" is zero, then the offset is
- *not* multiplied by four. */
+ func (stream, "%c%d", single ? 's' : 'd', regno);
+
+ if (*c == '3')
{
- int offset = given & 0xff;
- int multiplier = (given & 0x00000100) ? 4 : 1;
+ int count = given & 0xff;
- func (stream, "[%s", arm_regnames [(given >> 16) & 0xf]);
+ if (single == 0)
+ count >>= 1;
- if (offset)
+ if (--count)
{
- if ((given & 0x01000000) != 0)
- func (stream, ", #%s%d]%s",
- ((given & 0x00800000) == 0 ? "-" : ""),
- offset * multiplier,
- ((given & 0x00200000) != 0 ? "!" : ""));
- else
- func (stream, "], #%s%d",
- ((given & 0x00800000) == 0 ? "-" : ""),
- offset * multiplier);
+ func (stream, "-%c%d",
+ single ? 's' : 'd',
+ regno + count);
}
- else
- func (stream, "]");
+
+ func (stream, "}");
}
+ else if (*c == '4')
+ func (stream, ", %c%d", single ? 's' : 'd',
+ regno + 1);
+ }
+ break;
+
+ case 'L':
+ switch (given & 0x00400100)
+ {
+ case 0x00000000: func (stream, "b"); break;
+ case 0x00400000: func (stream, "h"); break;
+ case 0x00000100: func (stream, "w"); break;
+ case 0x00400100: func (stream, "d"); break;
+ default:
break;
+ }
+ break;
- case 'r':
- {
- int imm4 = (given >> 4) & 0xf;
- int puw_bits = ((given >> 22) & 6) | ((given >> 21) & 1);
- int ubit = (given >> 23) & 1;
- const char *rm = arm_regnames [given & 0xf];
- const char *rn = arm_regnames [(given >> 16) & 0xf];
+ case 'Z':
+ {
+ int value;
+ /* given (20, 23) | given (0, 3) */
+ value = ((given >> 16) & 0xf0) | (given & 0xf);
+ func (stream, "%d", value);
+ }
+ break;
- switch (puw_bits)
- {
- case 1:
- /* fall through */
- case 3:
- func (stream, "[%s], %c%s", rn, ubit ? '+' : '-', rm);
- if (imm4)
- func (stream, ", lsl #%d", imm4);
- break;
-
- case 4:
- /* fall through */
- case 5:
- /* fall through */
- case 6:
- /* fall through */
- case 7:
- func (stream, "[%s, %c%s", rn, ubit ? '+' : '-', rm);
- if (imm4 > 0)
- func (stream, ", lsl #%d", imm4);
- func (stream, "]");
- if (puw_bits == 5 || puw_bits == 7)
- func (stream, "!");
- break;
-
- default:
- func (stream, "INVALID");
- }
+ case 'l':
+ /* This is like the 'A' operator, except that if
+ the width field "M" is zero, then the offset is
+ *not* multiplied by four. */
+ {
+ int offset = given & 0xff;
+ int multiplier = (given & 0x00000100) ? 4 : 1;
+
+ func (stream, "[%s", arm_regnames [(given >> 16) & 0xf]);
+
+ if (offset)
+ {
+ if ((given & 0x01000000) != 0)
+ func (stream, ", #%s%d]%s",
+ ((given & 0x00800000) == 0 ? "-" : ""),
+ offset * multiplier,
+ ((given & 0x00200000) != 0 ? "!" : ""));
+ else
+ func (stream, "], #%s%d",
+ ((given & 0x00800000) == 0 ? "-" : ""),
+ offset * multiplier);
}
- break;
+ else
+ func (stream, "]");
+ }
+ break;
+
+ case 'r':
+ {
+ int imm4 = (given >> 4) & 0xf;
+ int puw_bits = ((given >> 22) & 6) | ((given >> 21) & 1);
+ int ubit = (given >> 23) & 1;
+ const char *rm = arm_regnames [given & 0xf];
+ const char *rn = arm_regnames [(given >> 16) & 0xf];
- case 'i':
+ switch (puw_bits)
{
- long imm5;
- imm5 = ((given & 0x100) >> 4) | (given & 0xf);
- func (stream, "%ld", (imm5 == 0) ? 32 : imm5);
+ case 1:
+ case 3:
+ func (stream, "[%s], %c%s", rn, ubit ? '+' : '-', rm);
+ if (imm4)
+ func (stream, ", lsl #%d", imm4);
+ break;
+
+ case 4:
+ case 5:
+ case 6:
+ case 7:
+ func (stream, "[%s, %c%s", rn, ubit ? '+' : '-', rm);
+ if (imm4 > 0)
+ func (stream, ", lsl #%d", imm4);
+ func (stream, "]");
+ if (puw_bits == 5 || puw_bits == 7)
+ func (stream, "!");
+ break;
+
+ default:
+ func (stream, "INVALID");
}
- break;
+ }
+ break;
- default:
- abort ();
- }
+ case 'i':
+ {
+ long imm5;
+ imm5 = ((given & 0x100) >> 4) | (given & 0xf);
+ func (stream, "%ld", (imm5 == 0) ? 32 : imm5);
}
+ break;
+
+ default:
+ abort ();
+ }
}
- else
- func (stream, "%c", *c);
}
- return TRUE;
+ else
+ func (stream, "%c", *c);
}
+ return TRUE;
}
return FALSE;
}
@@ -2221,7 +2223,7 @@ print_insn_neon (struct disassemble_info *info, long given, bfd_boolean thumb)
{
if ((given & 0xef000000) == 0xef000000)
{
- /* move bit 28 to bit 24 to translate Thumb2 to ARM encoding. */
+ /* Move bit 28 to bit 24 to translate Thumb2 to ARM encoding. */
unsigned long bit28 = given & (1 << 28);
given &= 0x00ffffff;
@@ -2687,13 +2689,18 @@ print_insn_arm (bfd_vma pc, struct disassemble_info *info, long given)
&& info->mach != bfd_mach_arm_iWMMXt)
insn = insn + IWMMXT_INSN_COUNT;
- if ((given & insn->mask) == insn->value
- /* Special case: an instruction with all bits set in the condition field
- (0xFnnn_nnnn) is only matched if all those bits are set in insn->mask,
- or by the catchall at the end of the table. */
- && ((given & 0xF0000000) != 0xF0000000
- || (insn->mask & 0xF0000000) == 0xF0000000
- || (insn->mask == 0 && insn->value == 0)))
+ if ((given & insn->mask) != insn->value)
+ continue;
+
+ if ((insn->arch & ((arm_feature_set *) info->private_data)->core) == 0)
+ continue;
+
+ /* Special case: an instruction with all bits set in the condition field
+ (0xFnnn_nnnn) is only matched if all those bits are set in insn->mask,
+ or by the catchall at the end of the table. */
+ if ((given & 0xF0000000) != 0xF0000000
+ || (insn->mask & 0xF0000000) == 0xF0000000
+ || (insn->mask == 0 && insn->value == 0))
{
const char *c;
@@ -3967,6 +3974,47 @@ get_sym_code_type (struct disassemble_info *info, int n,
return FALSE;
}
+/* Given a bfd_mach_arm_XXX value, this function fills in the fields
+ of the supplied arm_feature_set structure with bitmasks indicating
+ the support base architectures and coprocessor extensions.
+
+ FIXME: This could more efficiently implemented as a constant array,
+ although it would also be less robust. */
+
+static void
+select_arm_features (unsigned long mach,
+ arm_feature_set * features)
+{
+#undef ARM_FEATURE
+#define ARM_FEATURE(ARCH,CEXT) \
+ features->core = (ARCH); \
+ features->coproc = (CEXT) | FPU_FPA; \
+ return
+
+ switch (mach)
+ {
+ case bfd_mach_arm_2: ARM_ARCH_V2;
+ case bfd_mach_arm_2a: ARM_ARCH_V2S;
+ case bfd_mach_arm_3: ARM_ARCH_V3;
+ case bfd_mach_arm_3M: ARM_ARCH_V3M;
+ case bfd_mach_arm_4: ARM_ARCH_V4;
+ case bfd_mach_arm_4T: ARM_ARCH_V4T;
+ case bfd_mach_arm_5: ARM_ARCH_V5;
+ case bfd_mach_arm_5T: ARM_ARCH_V5T;
+ case bfd_mach_arm_5TE: ARM_ARCH_V5TE;
+ case bfd_mach_arm_XScale: ARM_ARCH_XSCALE;
+ case bfd_mach_arm_ep9312: ARM_FEATURE (ARM_AEXT_V4T, ARM_CEXT_MAVERICK | FPU_MAVERICK);
+ case bfd_mach_arm_iWMMXt: ARM_ARCH_IWMMXT;
+ case bfd_mach_arm_iWMMXt2: ARM_ARCH_IWMMXT2;
+ /* If the machine type is unknown allow all
+ architecture types and all extensions. */
+ case bfd_mach_arm_unknown: ARM_FEATURE (-1UL, -1UL);
+ default:
+ abort ();
+ }
+}
+
+
/* NOTE: There are no checks in these routines that
the relevant number of data bytes exist. */
@@ -3991,6 +4039,40 @@ print_insn (bfd_vma pc, struct disassemble_info *info, bfd_boolean little)
info->disassembler_options = NULL;
}
+ /* PR 10288: Control which instructions will be disassembled. */
+ if (info->private_data == NULL)
+ {
+ static arm_feature_set features;
+
+ if ((info->flags & USER_SPECIFIED_MACHINE_TYPE) == 0)
+ /* If the user did not use the -m command line switch then default to
+ disassembling all types of ARM instruction.
+
+ The info->mach value has to be ignored as this will be based on
+ the default archictecture for the target and/or hints in the notes
+ section, but it will never be greater than the current largest arm
+ machine value (iWMMXt2), which is only equivalent to the V5TE
+ architecture. ARM architectures have advanced beyond the machine
+ value encoding, and these newer architectures would be ignored if
+ the machine value was used.
+
+ Ie the -m switch is used to restrict which instructions will be
+ disassembled. If it is necessary to use the -m switch to tell
+ objdump that an ARM binary is being disassembled, eg because the
+ input is a raw binary file, but it is also desired to disassemble
+ all ARM instructions then use "-marm". This will select the
+ "unknown" arm architecture which is compatible with any ARM
+ instruction. */
+ info->mach = bfd_mach_arm_unknown;
+
+ /* Compute the architecture bitmask from the machine number.
+ Note: This assumes that the machine number will not change
+ during disassembly.... */
+ select_arm_features (info->mach, & features);
+
+ info->private_data = & features;
+ }
+
/* Decide if our code is going to be little-endian, despite what the
function argument might say. */
little_code = ((info->endian_code == BFD_ENDIAN_LITTLE) || little);
@@ -4146,7 +4228,7 @@ print_insn (bfd_vma pc, struct disassemble_info *info, bfd_boolean little)
info->bytes_per_chunk = 4;
size = 4;
- status = info->read_memory_func (pc, (bfd_byte *)b, 4, info);
+ status = info->read_memory_func (pc, (bfd_byte *) b, 4, info);
if (little_code)
given = (b[0]) | (b[1] << 8) | (b[2] << 16) | (b[3] << 24);
else
@@ -4176,7 +4258,7 @@ print_insn (bfd_vma pc, struct disassemble_info *info, bfd_boolean little)
|| (given & 0xF800) == 0xF000
|| (given & 0xF800) == 0xE800)
{
- status = info->read_memory_func (pc + 2, (bfd_byte *)b, 2, info);
+ status = info->read_memory_func (pc + 2, (bfd_byte *) b, 2, info);
if (little_code)
given = (b[0]) | (b[1] << 8) | (given << 16);
else
@@ -4188,7 +4270,7 @@ print_insn (bfd_vma pc, struct disassemble_info *info, bfd_boolean little)
}
if (ifthen_address != pc)
- find_ifthen_state(pc, info, little_code);
+ find_ifthen_state (pc, info, little_code);
if (ifthen_state)
{