diff options
-rw-r--r-- | binutils/ChangeLog | 4 | ||||
-rw-r--r-- | binutils/doc/binutils.texi | 8 | ||||
-rw-r--r-- | opcodes/ChangeLog | 9 | ||||
-rw-r--r-- | opcodes/arc-dis.c | 131 |
4 files changed, 126 insertions, 26 deletions
diff --git a/binutils/ChangeLog b/binutils/ChangeLog index 163211f..1ecb042 100644 --- a/binutils/ChangeLog +++ b/binutils/ChangeLog @@ -1,3 +1,7 @@ +2017-05-30 Anton Kolesov <anton.kolesov@synopsys.com> + + * doc/binutils.texi: Document new cpu=... disassembler options for ARC. + 2017-05-30 H.J. Lu <hongjiu.lu@intel.com> PR binutils/21519 diff --git a/binutils/doc/binutils.texi b/binutils/doc/binutils.texi index 23d8685..a2a670a 100644 --- a/binutils/doc/binutils.texi +++ b/binutils/doc/binutils.texi @@ -2314,6 +2314,14 @@ of double precision assist instructions, @option{fpus} selects the printing of FPU single precision FP instructions, while @option{fpud} selects the printing of FPU souble precision FP instructions. +@option{cpu=...} allows to enforce a particular ISA when disassembling +instructions, overriding the @option{-m} value or whatever is in the ELF file. +This might be useful to select ARC EM or HS ISA, because architecture is same +for those and disassembler relies on private ELF header data to decide if code +is for EM or HS. This option might be specified multiple times - only the +latest value will be used. Valid values are same as for the assembler +@option{-mcpu=...} option. + If the target is an ARM architecture then this switch can be used to select which register name set is used during disassembler. Specifying @option{-M reg-names-std} (the default) will select the register names as diff --git a/opcodes/ChangeLog b/opcodes/ChangeLog index 8e7d4db..888126e 100644 --- a/opcodes/ChangeLog +++ b/opcodes/ChangeLog @@ -1,3 +1,12 @@ +2017-05-30 Anton Kolesov <anton.kolesov@synopsys.com> + + * arc-dis.c (enforced_isa_mask): Declare. + (cpu_types): Likewise. + (parse_cpu_option): New function. + (parse_disassembler_options): Use it. + (print_insn_arc): Use enforced_isa_mask. + (print_arc_disassembler_options): Document new options. + 2017-05-24 Yao Qi <yao.qi@linaro.org> * alpha-dis.c: Include disassemble.h, don't include diff --git a/opcodes/arc-dis.c b/opcodes/arc-dis.c index 0cf4bff..edd0c07 100644 --- a/opcodes/arc-dis.c +++ b/opcodes/arc-dis.c @@ -117,6 +117,11 @@ typedef struct skipclass disassembling. */ static linkclass decodelist = NULL; +/* ISA mask value enforced via disassembler info options. ARC_OPCODE_NONE + value means that no CPU is enforced. */ + +static unsigned enforced_isa_mask = ARC_OPCODE_NONE; + /* Macros section. */ #ifdef DEBUG @@ -770,6 +775,49 @@ parse_option (const char *option) fprintf (stderr, _("Unrecognised disassembler option: %s\n"), option); } +#define ARC_CPU_TYPE_A6xx(NAME,EXTRA) \ + { #NAME, ARC_OPCODE_ARC600, "ARC600" } +#define ARC_CPU_TYPE_A7xx(NAME,EXTRA) \ + { #NAME, ARC_OPCODE_ARC700, "ARC700" } +#define ARC_CPU_TYPE_AV2EM(NAME,EXTRA) \ + { #NAME, ARC_OPCODE_ARCv2EM, "ARC EM" } +#define ARC_CPU_TYPE_AV2HS(NAME,EXTRA) \ + { #NAME, ARC_OPCODE_ARCv2HS, "ARC HS" } +#define ARC_CPU_TYPE_NONE \ + { 0, 0, 0 } + +/* A table of CPU names and opcode sets. */ +static const struct cpu_type +{ + const char *name; + unsigned flags; + const char *isa; +} + cpu_types[] = +{ + #include "elf/arc-cpu.def" +}; + +/* Helper for parsing the CPU options. Accept any of the ARC architectures + values. OPTION should be a value passed to cpu=. */ + +static unsigned +parse_cpu_option (const char *option) +{ + int i; + + for (i = 0; cpu_types[i].name; ++i) + { + if (!strcasecmp (cpu_types[i].name, option)) + { + return cpu_types[i].flags; + } + } + + fprintf (stderr, _("Unrecognised disassembler CPU option: %s\n"), option); + return ARC_OPCODE_NONE; +} + /* Go over the options list and parse it. */ static void @@ -778,6 +826,12 @@ parse_disassembler_options (const char *options) if (options == NULL) return; + /* Disassembler might be reused for difference CPU's, and cpu option set for + the first one shouldn't be applied to second (which might not have + explicit cpu in its options. Therefore it is required to reset enforced + CPU when new options are being parsed. */ + enforced_isa_mask = ARC_OPCODE_NONE; + while (*options) { /* Skip empty options. */ @@ -787,7 +841,13 @@ parse_disassembler_options (const char *options) continue; } - parse_option (options); + /* A CPU option? Cannot use STRING_COMMA_LEN because strncmp is also a + preprocessor macro. */ + if (strncmp (options, "cpu=", 4) == 0) + /* Strip leading `cpu=`. */ + enforced_isa_mask = parse_cpu_option (options + 4); + else + parse_option (options); while (*options != ',' && *options != '\0') ++ options; @@ -859,7 +919,7 @@ print_insn_arc (bfd_vma memaddr, int status; unsigned int insn_len; unsigned long long insn = 0; - unsigned isa_mask; + unsigned isa_mask = ARC_OPCODE_NONE; const struct arc_opcode *opcode; bfd_boolean need_comma; bfd_boolean open_braket; @@ -867,7 +927,6 @@ print_insn_arc (bfd_vma memaddr, const struct arc_operand *operand; int value; struct arc_operand_iterator iter; - Elf_Internal_Ehdr *header = NULL; struct arc_disassemble_info *arc_infop; if (info->disassembler_options) @@ -885,34 +944,44 @@ print_insn_arc (bfd_vma memaddr, highbyte = ((info->endian == BFD_ENDIAN_LITTLE) ? 1 : 0); lowbyte = ((info->endian == BFD_ENDIAN_LITTLE) ? 0 : 1); - if (info->section && info->section->owner) - header = elf_elfheader (info->section->owner); - - switch (info->mach) + /* Figure out CPU type, unless it was enforced via disassembler options. */ + if (enforced_isa_mask == ARC_OPCODE_NONE) { - case bfd_mach_arc_arc700: - isa_mask = ARC_OPCODE_ARC700; - break; + Elf_Internal_Ehdr *header = NULL; - case bfd_mach_arc_arc600: - isa_mask = ARC_OPCODE_ARC600; - break; + if (info->section && info->section->owner) + header = elf_elfheader (info->section->owner); - case bfd_mach_arc_arcv2: - default: - isa_mask = ARC_OPCODE_ARCv2EM; - /* TODO: Perhaps remove defitinion of header since it is only used at - this location. */ - if (header != NULL - && (header->e_flags & EF_ARC_MACH_MSK) == EF_ARC_CPU_ARCV2HS) + switch (info->mach) { - isa_mask = ARC_OPCODE_ARCv2HS; - /* FPU instructions are not extensions for HS. */ - add_to_decodelist (FLOAT, SP); - add_to_decodelist (FLOAT, DP); - add_to_decodelist (FLOAT, CVT); + case bfd_mach_arc_arc700: + isa_mask = ARC_OPCODE_ARC700; + break; + + case bfd_mach_arc_arc600: + isa_mask = ARC_OPCODE_ARC600; + break; + + case bfd_mach_arc_arcv2: + default: + isa_mask = ARC_OPCODE_ARCv2EM; + /* TODO: Perhaps remove definition of header since it is only used at + this location. */ + if (header != NULL + && (header->e_flags & EF_ARC_MACH_MSK) == EF_ARC_CPU_ARCV2HS) + isa_mask = ARC_OPCODE_ARCv2HS; + break; } - break; + } + else + isa_mask = enforced_isa_mask; + + if (isa_mask == ARC_OPCODE_ARCv2HS) + { + /* FPU instructions are not extensions for HS. */ + add_to_decodelist (FLOAT, SP); + add_to_decodelist (FLOAT, DP); + add_to_decodelist (FLOAT, CVT); } /* This variable may be set by the instruction decoder. It suggests @@ -1278,10 +1347,20 @@ arc_get_disassembler (bfd *abfd) void print_arc_disassembler_options (FILE *stream) { + int i; + fprintf (stream, _("\n\ The following ARC specific disassembler options are supported for use \n\ with -M switch (multiple options should be separated by commas):\n")); + /* cpu=... options. */ + for (i = 0; cpu_types[i].name; ++i) + { + /* As of now all value CPU values are less than 16 characters. */ + fprintf (stream, " cpu=%-16s\tEnforce %s ISA.\n", + cpu_types[i].name, cpu_types[i].isa); + } + fprintf (stream, _("\ dsp Recognize DSP instructions.\n")); fprintf (stream, _("\ |