X-Git-Url: http://git.efficios.com/?a=blobdiff_plain;f=opcodes%2Farm-dis.c;h=25000046d9fa5b2e4d20133c51eb22c998e0d60a;hb=25aa13e522c595cbdbb3868f1daa434a17ba2ab2;hp=372c11e1c5f6c884cb40b46ac89499d35f492988;hpb=db7b55faa1a11e632ddf57505c9bb64bc783471a;p=deliverable%2Fbinutils-gdb.git diff --git a/opcodes/arm-dis.c b/opcodes/arm-dis.c index 372c11e1c5..25000046d9 100644 --- a/opcodes/arm-dis.c +++ b/opcodes/arm-dis.c @@ -1,5 +1,5 @@ /* Instruction printing code for the ARM - Copyright (C) 1994-2016 Free Software Foundation, Inc. + Copyright (C) 1994-2017 Free Software Foundation, Inc. Contributed by Richard Earnshaw (rwe@pegasus.esprit.ec.org) Modification by James G. Smith (jsmith@cygnus.co.uk) @@ -22,10 +22,11 @@ #include "sysdep.h" -#include "dis-asm.h" +#include "disassemble.h" #include "opcode/arm.h" #include "opintl.h" #include "safe-ctype.h" +#include "libiberty.h" #include "floatformat.h" /* FIXME: This shouldn't be done here. */ @@ -41,10 +42,6 @@ #define strneq(a,b,n) (strncmp ((a), (b), (n)) == 0) #endif -#ifndef NUM_ELEM -#define NUM_ELEM(a) (sizeof (a) / sizeof (a)[0]) -#endif - /* Cached mapping symbol state. */ enum map_type { @@ -506,6 +503,8 @@ static const struct opcode32 coprocessor_opcodes[] = 0x0ee60a10, 0x0fff0fff, "vmsr%c\tmvfr1, %12-15r"}, {ARM_FEATURE_COPROC (FPU_VFP_EXT_V1xD), 0x0ee70a10, 0x0fff0fff, "vmsr%c\tmvfr0, %12-15r"}, + {ARM_FEATURE_COPROC (FPU_VFP_EXT_ARMV8), + 0x0ee50a10, 0x0fff0fff, "vmsr%c\tmvfr2, %12-15r"}, {ARM_FEATURE_COPROC (FPU_VFP_EXT_V1xD), 0x0ee80a10, 0x0fff0fff, "vmsr%c\tfpexc, %12-15r"}, {ARM_FEATURE_COPROC (FPU_VFP_EXT_V1xD), @@ -518,6 +517,8 @@ static const struct opcode32 coprocessor_opcodes[] = 0x0ef1fa10, 0x0fffffff, "vmrs%c\tAPSR_nzcv, fpscr"}, {ARM_FEATURE_COPROC (FPU_VFP_EXT_V1xD), 0x0ef10a10, 0x0fff0fff, "vmrs%c\t%12-15r, fpscr"}, + {ARM_FEATURE_COPROC (FPU_VFP_EXT_ARMV8), + 0x0ef50a10, 0x0fff0fff, "vmrs%c\t%12-15r, mvfr2"}, {ARM_FEATURE_COPROC (FPU_VFP_EXT_V1xD), 0x0ef60a10, 0x0fff0fff, "vmrs%c\t%12-15r, mvfr1"}, {ARM_FEATURE_COPROC (FPU_VFP_EXT_V1xD), @@ -897,13 +898,19 @@ static const struct opcode32 coprocessor_opcodes[] = {ARM_FEATURE_CORE_HIGH (ARM_EXT2_V8_3A), 0xfd300800, 0xff300f10, "vcmla%c.f32\t%12-15,22V, %16-19,7V, %0-3,5V, #%23?21%23?780"}, {ARM_FEATURE_CORE_HIGH (ARM_EXT2_V8_3A), - 0xfe000800, 0xfea00f10, "vcmla%c.f16\t%12-15,22V, %16-19,7V, %0-3D[%5?10], #%20'90"}, + 0xfe000800, 0xffa00f10, "vcmla%c.f16\t%12-15,22V, %16-19,7V, %0-3D[%5?10], #%20'90"}, {ARM_FEATURE_CORE_HIGH (ARM_EXT2_V8_3A), - 0xfe200800, 0xfea00f10, "vcmla%c.f16\t%12-15,22V, %16-19,7V, %0-3D[%5?10], #%20?21%23?780"}, + 0xfe200800, 0xffa00f10, "vcmla%c.f16\t%12-15,22V, %16-19,7V, %0-3D[%5?10], #%20?21%20?780"}, {ARM_FEATURE_CORE_HIGH (ARM_EXT2_V8_3A), - 0xfe800800, 0xfea00f10, "vcmla%c.f32\t%12-15,22V, %16-19,7V, %0-3,5D[0], #%20'90"}, + 0xfe800800, 0xffa00f10, "vcmla%c.f32\t%12-15,22V, %16-19,7V, %0-3,5D[0], #%20'90"}, {ARM_FEATURE_CORE_HIGH (ARM_EXT2_V8_3A), - 0xfea00800, 0xfea00f10, "vcmla%c.f32\t%12-15,22V, %16-19,7V, %0-3,5D[0], #%20?21%23?780"}, + 0xfea00800, 0xffa00f10, "vcmla%c.f32\t%12-15,22V, %16-19,7V, %0-3,5D[0], #%20?21%20?780"}, + + /* Dot Product instructions in the space of coprocessor 13. */ + {ARM_FEATURE_COPROC (FPU_NEON_EXT_DOTPROD), + 0xfc200d00, 0xffb00f00, "v%4?usdot.%4?us8\t%12-15,22V, %16-19,7V, %0-3,5V"}, + {ARM_FEATURE_COPROC (FPU_NEON_EXT_DOTPROD), + 0xfe000d00, 0xff000f00, "v%4?usdot.%4?us8\t%12-15,22V, %16-19,7V, %0-3D[%5?10]"}, /* V5 coprocessor instructions. */ {ARM_FEATURE_CORE_LOW (ARM_EXT_V5), @@ -2313,8 +2320,6 @@ static const struct opcode32 arm_opcodes[] = 0x01300000, 0x0ff00010, "teq%p%c\t%16-19r, %o"}, {ARM_FEATURE_CORE_LOW (ARM_EXT_V1), 0x01300010, 0x0ff00010, "teq%p%c\t%16-19R, %o"}, - {ARM_FEATURE_CORE_LOW (ARM_EXT_V5), - 0x0130f000, 0x0ff0f010, "bx%c\t%0-3r"}, {ARM_FEATURE_CORE_LOW (ARM_EXT_V1), 0x03400000, 0x0fe00000, "cmp%p%c\t%16-19r, %o"}, @@ -3198,18 +3203,20 @@ arm_regname; static const arm_regname regnames[] = { - { "raw" , "Select raw register names", + { "reg-names-raw", N_("Select raw register names"), { "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15"}}, - { "gcc", "Select register names used by GCC", + { "reg-names-gcc", N_("Select register names used by GCC"), { "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "sl", "fp", "ip", "sp", "lr", "pc" }}, - { "std", "Select register names used in ARM's ISA documentation", + { "reg-names-std", N_("Select register names used in ARM's ISA documentation"), { "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11", "r12", "sp", "lr", "pc" }}, - { "apcs", "Select register names used in the APCS", + { "force-thumb", N_("Assume all insns are Thumb insns"), {NULL} }, + { "no-force-thumb", N_("Examine preceding label to determine an insn's type"), {NULL} }, + { "reg-names-apcs", N_("Select register names used in the APCS"), { "a1", "a2", "a3", "a4", "v1", "v2", "v3", "v4", "v5", "v6", "sl", "fp", "ip", "sp", "lr", "pc" }}, - { "atpcs", "Select register names used in the ATPCS", + { "reg-names-atpcs", N_("Select register names used in the ATPCS"), { "a1", "a2", "a3", "a4", "v1", "v2", "v3", "v4", "v5", "v6", "v7", "v8", "IP", "SP", "LR", "PC" }}, - { "special-atpcs", "Select special register names used in the ATPCS", - { "a1", "a2", "a3", "a4", "v1", "v2", "v3", "WR", "v5", "SB", "SL", "FP", "IP", "SP", "LR", "PC" }}, + { "reg-names-special-atpcs", N_("Select special register names used in the ATPCS"), + { "a1", "a2", "a3", "a4", "v1", "v2", "v3", "WR", "v5", "SB", "SL", "FP", "IP", "SP", "LR", "PC" }} }; static const char *const iwmmxt_wwnames[] = @@ -3235,7 +3242,7 @@ static const char *const iwmmxt_cregnames[] = /* Default to GCC register name set. */ static unsigned int regname_selected = 1; -#define NUM_ARM_REGNAMES NUM_ELEM (regnames) +#define NUM_ARM_OPTIONS ARRAY_SIZE (regnames) #define arm_regnames regnames[regname_selected].reg_names static bfd_boolean force_thumb = FALSE; @@ -3254,31 +3261,6 @@ static bfd_vma ifthen_address; /* Functions. */ -int -get_arm_regname_num_options (void) -{ - return NUM_ARM_REGNAMES; -} - -int -set_arm_regname_option (int option) -{ - int old = regname_selected; - regname_selected = option; - return old; -} - -int -get_arm_regnames (int option, - const char **setname, - const char **setdescription, - const char *const **register_names) -{ - *setname = regnames[option].name; - *setdescription = regnames[option].description; - *register_names = regnames[option].reg_names; - return 16; -} /* Decode a bitfield of the form matching regexp (N(-N)?,)*N(-N)?. Returns pointer to following character of the format string and @@ -5759,7 +5741,7 @@ print_insn_thumb32 (bfd_vma pc, struct disassemble_info *info, long given) if (off || !U) { func (stream, ", #%c%u", U ? '+' : '-', off * 4); - value_in_comment = (off && U) ? 1 : -1; + value_in_comment = off * 4 * (U ? 1 : -1); } func (stream, "]"); if (W) @@ -5771,7 +5753,7 @@ print_insn_thumb32 (bfd_vma pc, struct disassemble_info *info, long given) if (W) { func (stream, "#%c%u", U ? '+' : '-', off * 4); - value_in_comment = (off && U) ? 1 : -1; + value_in_comment = off * 4 * (U ? 1 : -1); } else { @@ -6124,64 +6106,39 @@ arm_symbol_is_valid (asymbol * sym, return (name && *name != '$' && strncmp (name, "__tagsym$$", 10)); } -/* Parse an individual disassembler option. */ +/* Parse the string of disassembler options. */ -void -parse_arm_disassembler_option (char *option) +static void +parse_arm_disassembler_options (const char *options) { - if (option == NULL) - return; + const char *opt; - if (CONST_STRNEQ (option, "reg-names-")) + FOR_EACH_DISASSEMBLER_OPTION (opt, options) { - int i; - - option += 10; - - for (i = NUM_ARM_REGNAMES; i--;) - if (strneq (option, regnames[i].name, strlen (regnames[i].name))) - { - regname_selected = i; - break; - } + if (CONST_STRNEQ (opt, "reg-names-")) + { + unsigned int i; + for (i = 0; i < NUM_ARM_OPTIONS; i++) + if (disassembler_options_cmp (opt, regnames[i].name) == 0) + { + regname_selected = i; + break; + } - if (i < 0) - /* XXX - should break 'option' at following delimiter. */ - fprintf (stderr, _("Unrecognised register name set: %s\n"), option); + if (i >= NUM_ARM_OPTIONS) + fprintf (stderr, _("Unrecognised register name set: %s\n"), opt); + } + else if (CONST_STRNEQ (opt, "force-thumb")) + force_thumb = 1; + else if (CONST_STRNEQ (opt, "no-force-thumb")) + force_thumb = 0; + else + fprintf (stderr, _("Unrecognised disassembler option: %s\n"), opt); } - else if (CONST_STRNEQ (option, "force-thumb")) - force_thumb = 1; - else if (CONST_STRNEQ (option, "no-force-thumb")) - force_thumb = 0; - else - /* XXX - should break 'option' at following delimiter. */ - fprintf (stderr, _("Unrecognised disassembler option: %s\n"), option); return; } -/* Parse the string of disassembler options, spliting it at whitespaces - or commas. (Whitespace separators supported for backwards compatibility). */ - -static void -parse_disassembler_options (char *options) -{ - if (options == NULL) - return; - - while (*options) - { - parse_arm_disassembler_option (options); - - /* Skip forward to next seperator. */ - while ((*options) && (! ISSPACE (*options)) && (*options != ',')) - ++ options; - /* Skip forward past seperators. */ - while (ISSPACE (*options) || (*options == ',')) - ++ options; - } -} - static bfd_boolean mapping_symbol_for_insn (bfd_vma pc, struct disassemble_info *info, enum map_type *map_symbol); @@ -6473,7 +6430,7 @@ print_insn (bfd_vma pc, struct disassemble_info *info, bfd_boolean little) if (info->disassembler_options) { - parse_disassembler_options (info->disassembler_options); + parse_arm_disassembler_options (info->disassembler_options); /* To avoid repeated parsing of these options, we remove them here. */ info->disassembler_options = NULL; @@ -6842,21 +6799,51 @@ print_insn_little_arm (bfd_vma pc, struct disassemble_info *info) return print_insn (pc, info, TRUE); } +const disasm_options_t * +disassembler_options_arm (void) +{ + static disasm_options_t *opts = NULL; + + if (opts == NULL) + { + unsigned int i; + opts = XNEW (disasm_options_t); + opts->name = XNEWVEC (const char *, NUM_ARM_OPTIONS + 1); + opts->description = XNEWVEC (const char *, NUM_ARM_OPTIONS + 1); + for (i = 0; i < NUM_ARM_OPTIONS; i++) + { + opts->name[i] = regnames[i].name; + if (regnames[i].description != NULL) + opts->description[i] = _(regnames[i].description); + else + opts->description[i] = NULL; + } + /* The array we return must be NULL terminated. */ + opts->name[i] = NULL; + opts->description[i] = NULL; + } + + return opts; +} + void print_arm_disassembler_options (FILE *stream) { - int i; - + unsigned int i, max_len = 0; fprintf (stream, _("\n\ The following ARM specific disassembler options are supported for use with\n\ the -M switch:\n")); - for (i = NUM_ARM_REGNAMES; i--;) - fprintf (stream, " reg-names-%s %*c%s\n", - regnames[i].name, - (int)(14 - strlen (regnames[i].name)), ' ', - regnames[i].description); + for (i = 0; i < NUM_ARM_OPTIONS; i++) + { + unsigned int len = strlen (regnames[i].name); + if (max_len < len) + max_len = len; + } - fprintf (stream, " force-thumb Assume all insns are Thumb insns\n"); - fprintf (stream, " no-force-thumb Examine preceding label to determine an insn's type\n\n"); + for (i = 0, max_len++; i < NUM_ARM_OPTIONS; i++) + fprintf (stream, " %s%*c %s\n", + regnames[i].name, + (int)(max_len - strlen (regnames[i].name)), ' ', + _(regnames[i].description)); }