+const disasm_options_and_args_t *
+disassembler_options_arc (void)
+{
+ static disasm_options_and_args_t *opts_and_args;
+
+ if (opts_and_args == NULL)
+ {
+ disasm_option_arg_t *args;
+ disasm_options_t *opts;
+ size_t i;
+ const size_t nr_of_options = ARRAY_SIZE (arc_options);
+ /* There is a null element at the end of CPU_TYPES, therefore
+ NR_OF_CPUS is actually 1 more and that is desired here too. */
+ const size_t nr_of_cpus = ARRAY_SIZE (cpu_types);
+
+ opts_and_args = XNEW (disasm_options_and_args_t);
+ opts_and_args->args
+ = XNEWVEC (disasm_option_arg_t, ARC_OPTION_ARG_SIZE + 1);
+ opts_and_args->options.name
+ = XNEWVEC (const char *, nr_of_options + 1);
+ opts_and_args->options.description
+ = XNEWVEC (const char *, nr_of_options + 1);
+ opts_and_args->options.arg
+ = XNEWVEC (const disasm_option_arg_t *, nr_of_options + 1);
+
+ /* Populate the arguments for "cpu=" option. */
+ args = opts_and_args->args;
+ args[ARC_OPTION_ARG_ARCH].name = "ARCH";
+ args[ARC_OPTION_ARG_ARCH].values = XNEWVEC (const char *, nr_of_cpus);
+ for (i = 0; i < nr_of_cpus; ++i)
+ args[ARC_OPTION_ARG_ARCH].values[i] = cpu_types[i].name;
+ args[ARC_OPTION_ARG_SIZE].name = NULL;
+ args[ARC_OPTION_ARG_SIZE].values = NULL;
+
+ /* Populate the options. */
+ opts = &opts_and_args->options;
+ for (i = 0; i < nr_of_options; ++i)
+ {
+ opts->name[i] = arc_options[i].name;
+ opts->description[i] = arc_options[i].description;
+ if (arc_options[i].arg != ARC_OPTION_ARG_NONE)
+ opts->arg[i] = &args[arc_options[i].arg];
+ else
+ opts->arg[i] = NULL;
+ }
+ opts->name[nr_of_options] = NULL;
+ opts->description[nr_of_options] = NULL;
+ opts->arg[nr_of_options] = NULL;
+ }
+
+ return opts_and_args;
+}
+
+
+void
+print_arc_disassembler_options (FILE *stream)
+{
+ const disasm_options_and_args_t *opts_and_args;
+ const disasm_option_arg_t *args;
+ const disasm_options_t *opts;
+ size_t i, j;
+ size_t max_len = 0;
+
+ opts_and_args = disassembler_options_arc ();
+ opts = &opts_and_args->options;
+ args = opts_and_args->args;
+
+ fprintf (stream, _("\nThe following ARC specific disassembler options are"
+ " supported for use \nwith the -M switch (multiple"
+ " options should be separated by commas):\n"));
+
+ /* Find the maximum length for printing options (and their arg name). */
+ for (i = 0; opts->name[i] != NULL; ++i)
+ {
+ size_t len = strlen (opts->name[i]);
+ len += (opts->arg[i]) ? strlen (opts->arg[i]->name) : 0;
+ max_len = (len > max_len) ? len : max_len;
+ }
+
+ /* Print the options, their arg and description, if any. */
+ for (i = 0, ++max_len; opts->name[i] != NULL; ++i)
+ {
+ fprintf (stream, " %s", opts->name[i]);
+ if (opts->arg[i] != NULL)
+ fprintf (stream, "%s", opts->arg[i]->name);
+ if (opts->description[i] != NULL)
+ {
+ size_t len = strlen (opts->name[i]);
+ len += (opts->arg[i]) ? strlen (opts->arg[i]->name) : 0;
+ fprintf (stream,
+ "%*c %s", (int) (max_len - len), ' ', opts->description[i]);
+ }
+ fprintf (stream, _("\n"));
+ }
+
+ /* Print the possible values of an argument. */
+ for (i = 0; args[i].name != NULL; ++i)
+ {
+ size_t len = 3;
+ fprintf (stream, _("\n\
+ For the options above, the following values are supported for \"%s\":\n "),
+ args[i].name);
+ for (j = 0; args[i].values[j] != NULL; ++j)
+ {
+ fprintf (stream, " %s", args[i].values[j]);
+ len += strlen (args[i].values[j]) + 1;
+ /* reset line if printed too long. */
+ if (len >= 78)
+ {
+ fprintf (stream, _("\n "));
+ len = 3;
+ }
+ }
+ fprintf (stream, _("\n"));
+ }
+
+ fprintf (stream, _("\n"));
+}
+
+void arc_insn_decode (bfd_vma addr,
+ struct disassemble_info *info,
+ disassembler_ftype disasm_func,
+ struct arc_instruction *insn)
+{
+ const struct arc_opcode *opcode;
+ struct arc_disassemble_info *arc_infop;
+
+ /* Ensure that insn would be in the reset state. */
+ memset (insn, 0, sizeof (struct arc_instruction));
+
+ /* There was an error when disassembling, for example memory read error. */
+ if (disasm_func (addr, info) < 0)
+ {
+ insn->valid = false;
+ return;
+ }
+
+ assert (info->private_data != NULL);
+ arc_infop = info->private_data;
+
+ insn->length = arc_infop->insn_len;;
+ insn->address = addr;
+
+ /* Quick exit if memory at this address is not an instruction. */
+ if (info->insn_type == dis_noninsn)
+ {
+ insn->valid = false;
+ return;
+ }