diff options
author | Nick Clifton <nickc@redhat.com> | 2009-06-18 10:31:21 +0000 |
---|---|---|
committer | Nick Clifton <nickc@redhat.com> | 2009-06-18 10:31:21 +0000 |
commit | 0313a2b8d2bc3ac3a15912d7fa9fe02722eaa14c (patch) | |
tree | dc124b744e50e56ff817cd08c6ef38edeb61e28f | |
parent | 470c710ef03d4c05314c605b26f47fb5a61beb34 (diff) | |
download | gdb-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/ChangeLog | 14 | ||||
-rw-r--r-- | binutils/doc/binutils.texi | 11 | ||||
-rw-r--r-- | binutils/objdump.c | 2 | ||||
-rw-r--r-- | gas/testsuite/ChangeLog | 7 | ||||
-rw-r--r-- | gas/testsuite/gas/arm/align.s | 4 | ||||
-rw-r--r-- | gas/testsuite/gas/arm/copro.d | 2 | ||||
-rw-r--r-- | include/ChangeLog | 9 | ||||
-rw-r--r-- | include/dis-asm.h | 3 | ||||
-rw-r--r-- | opcodes/ChangeLog | 10 | ||||
-rw-r--r-- | opcodes/arm-dis.c | 848 |
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) { |