diff options
author | Shahab Vahedi <shahab@synopsys.com> | 2021-06-02 15:30:16 +0300 |
---|---|---|
committer | Claudiu Zissulescu <claziss@synopsys.com> | 2021-06-02 15:32:58 +0300 |
commit | 8f467114435286e4f78b16fc1f5864acf6488fc0 (patch) | |
tree | f2478dacbe828a020cf9d94a39704363b57d85b3 /opcodes | |
parent | f2d4211150abba189c4fcd2f7cf0290161474631 (diff) | |
download | binutils-gdb-8f467114435286e4f78b16fc1f5864acf6488fc0.tar.gz |
arc: Construct disassembler options dynamically
The idea of this change is simple: Populate a data structure, namely
"disasm_option_and_arg_t" from "include/dis-asm.h", to encompass the
disassembly options and their possible arguments.
This will make it easier to manage or extend those options by adapting
entries in a data structure, "arc_options". There will be lesser need
to hard-code the options in the code itself. Moreover, ARC GDB will
use this population function, "disassembler_options_arc ()", to enable
the "set disassembler-option" for ARC targets. The gdb change will be
in a separate patch though.
The changes in this patch can be divided into:
1) Introduction of "disassembler_options_arc ()" that will return a
"disasm_option_and_arg_t" structure representing the disassembly
options and their likely arguments.
2) New data type "arc_options_arg_t" and new data "arc_options".
These are the internals for keeping track of options and arguments
entries that can easily be extended.
3) To print the options, the "print_arc_disassembler_options ()" has
been adjusted to use this dynamically built structure instead of having
them hard-coded inside.
To see this in effect, one can look into the output of:
$ ./binutils/objdump --help
...
The following ARC specific disassembler options are...
...
include/ChangeLog:
* dis-asm.h (disassembler_options_arc): New prototype.
opcodes/ChangeLog:
* arc-dis.c (arc_option_arg_t): New enumeration.
(arc_options): New variable.
(disassembler_options_arc): New function.
(print_arc_disassembler_options): Reimplement in terms of
"disassembler_options_arc".
Diffstat (limited to 'opcodes')
-rw-r--r-- | opcodes/ChangeLog | 8 | ||||
-rw-r--r-- | opcodes/arc-dis.c | 180 |
2 files changed, 161 insertions, 27 deletions
diff --git a/opcodes/ChangeLog b/opcodes/ChangeLog index e6b5f3e2167..fc3dd0818dc 100644 --- a/opcodes/ChangeLog +++ b/opcodes/ChangeLog @@ -1,3 +1,11 @@ +2021-06-02 Shahab Vahedi <shahab@synopsys.com> + + * arc-dis.c (arc_option_arg_t): New enumeration. + (arc_options): New variable. + (disassembler_options_arc): New function. + (print_arc_disassembler_options): Reimplement in terms of + "disassembler_options_arc". + 2021-05-29 Alan Modra <amodra@gmail.com> * ppc-dis.c (lookup_powerpc): Test deprecated field when -Many. diff --git a/opcodes/arc-dis.c b/opcodes/arc-dis.c index 78e8e80eed9..4abb866304d 100644 --- a/opcodes/arc-dis.c +++ b/opcodes/arc-dis.c @@ -1412,41 +1412,167 @@ arc_get_disassembler (bfd *abfd) return print_insn_arc; } +/* Indices into option argument vector for options that do require + an argument. Use ARC_OPTION_ARG_NONE for options that don't + expect an argument. */ +typedef enum +{ + ARC_OPTION_ARG_NONE = -1, + ARC_OPTION_ARG_ARCH, + ARC_OPTION_ARG_SIZE +} arc_option_arg_t; + +/* Valid ARC disassembler options. */ +static struct +{ + const char *name; + const char *description; + arc_option_arg_t arg; +} arc_options[] = +{ + { "cpu=", N_("Enforce the designated architecture while decoding."), + ARC_OPTION_ARG_ARCH }, + { "dsp", N_("Recognize DSP instructions."), + ARC_OPTION_ARG_NONE }, + { "spfp", N_("Recognize FPX SP instructions."), + ARC_OPTION_ARG_NONE }, + { "dpfp", N_("Recognize FPX DP instructions."), + ARC_OPTION_ARG_NONE }, + { "quarkse_em", N_("Recognize FPU QuarkSE-EM instructions."), + ARC_OPTION_ARG_NONE }, + { "fpuda", N_("Recognize double assist FPU instructions."), + ARC_OPTION_ARG_NONE }, + { "fpus", N_("Recognize single precision FPU instructions."), + ARC_OPTION_ARG_NONE }, + { "fpud", N_("Recognize double precision FPU instructions."), + ARC_OPTION_ARG_NONE }, + { "nps400", N_("Recognize NPS400 instructions."), + ARC_OPTION_ARG_NONE }, + { "hex", N_("Use only hexadecimal number to print immediates."), + ARC_OPTION_ARG_NONE } +}; + +/* Populate the structure for representing ARC's disassembly options. + Such a dynamic initialization is desired, because it makes the maintenance + easier and also gdb uses this to enable the "disassembler-option". */ + +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) { - int i; + 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; + } - 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")); + /* 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")); + } - /* cpu=... options. */ - for (i = 0; cpu_types[i].name; ++i) + /* Print the possible values of an argument. */ + for (i = 0; args[i].name != NULL; ++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); + 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, _("\ - dsp Recognize DSP instructions.\n")); - fprintf (stream, _("\ - spfp Recognize FPX SP instructions.\n")); - fprintf (stream, _("\ - dpfp Recognize FPX DP instructions.\n")); - fprintf (stream, _("\ - quarkse_em Recognize FPU QuarkSE-EM instructions.\n")); - fprintf (stream, _("\ - fpuda Recognize double assist FPU instructions.\n")); - fprintf (stream, _("\ - fpus Recognize single precision FPU instructions.\n")); - fprintf (stream, _("\ - fpud Recognize double precision FPU instructions.\n")); - fprintf (stream, _("\ - nps400 Recognize NPS400 instructions.\n")); - fprintf (stream, _("\ - hex Use only hexadecimal number to print immediates.\n")); + fprintf (stream, _("\n")); } void arc_insn_decode (bfd_vma addr, |