aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--binutils/ChangeLog4
-rw-r--r--binutils/doc/binutils.texi8
-rw-r--r--opcodes/ChangeLog9
-rw-r--r--opcodes/arc-dis.c131
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, _("\