diff options
Diffstat (limited to 'opcodes/aarch64-gen.c')
-rw-r--r-- | opcodes/aarch64-gen.c | 259 |
1 files changed, 176 insertions, 83 deletions
diff --git a/opcodes/aarch64-gen.c b/opcodes/aarch64-gen.c index ba48f06..4d0b4d5 100644 --- a/opcodes/aarch64-gen.c +++ b/opcodes/aarch64-gen.c @@ -23,6 +23,7 @@ #include <stdio.h> #include <stdlib.h> #include <stdarg.h> +#include <ctype.h> #include "libiberty.h" #include "getopt.h" @@ -33,6 +34,10 @@ static int debug = 0; +/* Table of labels for opcode nodes. We use this to stabilize the indices of + the data structures as the list of opcodes expands. */ +const char **opcode_node_labels; + /* Structure used in the decoding tree to group a list of aarch64_opcode entries. */ @@ -170,7 +175,8 @@ read_table (const struct aarch64_opcode* table) { fprintf (stderr, "%s (%08x,%08x): operands 1 and %u match, but tied=%u\n", - ent->name, ent->opcode, ent->mask, i + 1, ent->tied_operand); + ent->name, ent->opcode, ent->mask, i + 1, + ent->tied_operand); ++errors; } } @@ -199,7 +205,8 @@ read_table (const struct aarch64_opcode* table) /* If a subclass is set for one insn of an iclass, every insn of that iclass must have non-zero subclass field. */ if ((iclass_has_subclasses_p[ent->iclass] && !(ent->flags & F_SUBCLASS)) - || (!iclass_has_subclasses_p[ent->iclass] && (ent->flags & F_SUBCLASS))) + || (!iclass_has_subclasses_p[ent->iclass] + && (ent->flags & F_SUBCLASS))) { fprintf (stderr, "%s: unexpected subclass\n", ent->name); ++errors; @@ -460,11 +467,9 @@ print_decision_tree_1 (unsigned int indent, struct bittree* bittree) assert (bittree->list != NULL); indented_print (indent, "/* 33222222222211111111110000000000\n"); indented_print (indent, " 10987654321098765432109876543210\n"); - indented_print (indent, " %s\n", pattern); - indented_print (indent, " %s. */\n", - get_aarch64_opcode (bittree->list)->name); - indented_print (indent, "return %u;\n", - real_index (bittree->list->index)); + indented_print (indent, " %s. */\n", pattern); + indented_print (indent, "return %s;\n", + opcode_node_labels[real_index (bittree->list->index)]); return; } @@ -492,7 +497,7 @@ print_decision_tree (struct bittree* bittree) printf ("/* Called by aarch64_opcode_lookup. */\n\n"); - printf ("static int\n"); + printf ("static enum aarch64_opcode_idx\n"); printf ("aarch64_opcode_lookup_1 (uint32_t word)\n"); printf ("{\n"); @@ -529,18 +534,13 @@ print_find_next_opcode_1 (struct bittree* bittree) const aarch64_opcode *curr = get_aarch64_opcode (list); const aarch64_opcode *next = get_aarch64_opcode (list->next); - printf (" case %u: ", - (unsigned int)(curr - aarch64_opcode_table)); + printf (" case %s:\n", + opcode_node_labels[curr - aarch64_opcode_table]); if (list->next != NULL) - { - printf ("value = %u; break;\t", real_index (list->next->index)); - printf ("/* %s --> %s. */\n", curr->name, next->name); - } + printf (" value = %s;\n break;\n", + opcode_node_labels[real_index (list->next->index)]); else - { - printf ("return NULL;\t\t"); - printf ("/* %s --> NULL. */\n", curr->name); - } + printf (" return NULL;\n"); list = list->next; } @@ -566,8 +566,8 @@ print_find_next_opcode (struct bittree* bittree) printf ("aarch64_find_next_opcode (const aarch64_opcode *opcode)\n"); printf ("{\n"); printf (" /* Use the index as the key to locate the next opcode. */\n"); - printf (" int key = opcode - aarch64_opcode_table;\n"); - printf (" int value;\n"); + printf (" enum aarch64_opcode_idx key = opcode - aarch64_opcode_table;\n"); + printf (" enum aarch64_opcode_idx value;\n"); printf (" switch (key)\n"); printf (" {\n"); @@ -630,8 +630,8 @@ print_find_real_opcode (const opcode_node *table, int num) printf ("aarch64_find_real_opcode (const aarch64_opcode *opcode)\n"); printf ("{\n"); printf (" /* Use the index as the key to locate the real opcode. */\n"); - printf (" int key = opcode - aarch64_opcode_table;\n"); - printf (" int value;\n"); + printf (" enum aarch64_opcode_idx key = opcode - aarch64_opcode_table;\n"); + printf (" enum aarch64_opcode_idx value;\n"); printf (" switch (key)\n"); printf (" {\n"); @@ -640,10 +640,10 @@ print_find_real_opcode (const opcode_node *table, int num) const opcode_node *real = table + i; const opcode_node *alias = real->next; for (; alias; alias = alias->next) - printf (" case %u:\t/* %s */\n", real_index (alias->index), - get_aarch64_opcode (alias)->name); - printf (" value = %u;\t/* --> %s. */\n", real_index (real->index), - get_aarch64_opcode (real)->name); + printf (" case %s:\n", + opcode_node_labels[real_index (alias->index)]); + printf (" value = %s;\n", + opcode_node_labels[real_index (real->index)]); printf (" break;\n"); } @@ -671,8 +671,8 @@ print_find_alias_opcode (const opcode_node *table, int num) printf ("aarch64_find_alias_opcode (const aarch64_opcode *opcode)\n"); printf ("{\n"); printf (" /* Use the index as the key to locate the alias opcode. */\n"); - printf (" int key = opcode - aarch64_opcode_table;\n"); - printf (" int value;\n"); + printf (" enum aarch64_opcode_idx key = opcode - aarch64_opcode_table;\n"); + printf (" enum aarch64_opcode_idx value;\n"); printf (" switch (key)\n"); printf (" {\n"); @@ -680,10 +680,9 @@ print_find_alias_opcode (const opcode_node *table, int num) { const opcode_node *node = table + i; assert (node->next); - printf (" case %u: value = %u; break;", real_index (node->index), - real_index (node->next->index)); - printf ("\t/* %s --> %s. */\n", get_aarch64_opcode (node)->name, - get_aarch64_opcode (node->next)->name); + printf (" case %s:\n value = %s;\n break;\n", + opcode_node_labels[real_index (node->index)], + opcode_node_labels[real_index (node->next->index)]); } printf (" default: return NULL;\n"); @@ -710,8 +709,8 @@ print_find_next_alias_opcode (const opcode_node *table, int num) printf ("aarch64_find_next_alias_opcode (const aarch64_opcode *opcode)\n"); printf ("{\n"); printf (" /* Use the index as the key to locate the next opcode. */\n"); - printf (" int key = opcode - aarch64_opcode_table;\n"); - printf (" int value;\n"); + printf (" enum aarch64_opcode_idx key = opcode - aarch64_opcode_table;\n"); + printf (" enum aarch64_opcode_idx value;\n"); printf (" switch (key)\n"); printf (" {\n"); @@ -723,11 +722,9 @@ print_find_next_alias_opcode (const opcode_node *table, int num) continue; while (node->next->next) { - printf (" case %u: value = %u; break;", real_index (node->next->index), - real_index (node->next->next->index)); - printf ("\t/* %s --> %s. */\n", - get_aarch64_opcode (node->next)->name, - get_aarch64_opcode (node->next->next)->name); + printf (" case %s:\n value = %s;\n break;\n", + opcode_node_labels[real_index (node->next->index)], + opcode_node_labels[real_index (node->next->next->index)]); node = node->next; } } @@ -1028,7 +1025,6 @@ print_operand_table (void) } /* Generate aarch64_insert_operand in C to the standard output. */ - static void print_operand_inserter (void) { @@ -1047,7 +1043,7 @@ print_operand_inserter (void) aarch64_operand_error *errors)\n"); printf ("{\n"); printf (" /* Use the index as the key. */\n"); - printf (" int key = self - aarch64_operands;\n"); + printf (" enum aarch64_opnd key = self - aarch64_operands;\n"); printf (" switch (key)\n"); printf (" {\n"); @@ -1061,7 +1057,7 @@ print_operand_inserter (void) int j = i + 1; const int len = strlen (opnd->inserter); operand *opnd2 = opnd + 1; - printf (" case %u:\n", (unsigned int)(opnd - operands)); + printf (" case AARCH64_OPND_%s:\n", opnd->str); opnd->processed = 1; for (; j < num; ++j, ++opnd2) { @@ -1070,7 +1066,8 @@ print_operand_inserter (void) && len == strlen (opnd2->inserter) && strncmp (opnd->inserter, opnd2->inserter, len) == 0) { - printf (" case %u:\n", (unsigned int)(opnd2 - operands)); + printf (" case AARCH64_OPND_%s:\n", opnd2->str); + opnd2->processed = 1; } } @@ -1104,7 +1101,7 @@ print_operand_extractor (void) aarch64_operand_error *errors)\n"); printf ("{\n"); printf (" /* Use the index as the key. */\n"); - printf (" int key = self - aarch64_operands;\n"); + printf (" enum aarch64_opnd key = self - aarch64_operands;\n"); printf (" switch (key)\n"); printf (" {\n"); @@ -1118,7 +1115,7 @@ print_operand_extractor (void) int j = i + 1; const int len = strlen (opnd->extractor); operand *opnd2 = opnd + 1; - printf (" case %u:\n", (unsigned int)(opnd - operands)); + printf (" case AARCH64_OPND_%s:\n", opnd->str); opnd->processed = 1; for (; j < num; ++j, ++opnd2) { @@ -1127,7 +1124,7 @@ print_operand_extractor (void) && len == strlen (opnd2->extractor) && strncmp (opnd->extractor, opnd2->extractor, len) == 0) { - printf (" case %u:\n", (unsigned int)(opnd2 - operands)); + printf (" case AARCH64_OPND_%s:\n", opnd2->str); opnd2->processed = 1; } } @@ -1141,6 +1138,86 @@ print_operand_extractor (void) printf ("}\n"); } +/* Generate a set of labels for the opcode table, so that we can refer to index + entries through stable names. The general format for the label is: + <opcode>_<mnemonic>(_operand_name)* + We currently do not need to use the qualifiers to discriminate further, and + hopefully never will. */ +#define ENUM_PFX "" +#define MAX_LABEL_LEN 100 +void +label_opcode_nodes (void) +{ + unsigned count = sizeof (aarch64_opcode_table) / sizeof (aarch64_opcode); + unsigned i; + const aarch64_opcode *opc; + + opcode_node_labels = malloc (count * sizeof (char *)); + + for (i = 0, opc = aarch64_opcode_table; i < count - 1; ++i, ++opc) + { + char buf[MAX_LABEL_LEN]; + char *p; + unsigned j; + size_t l; + int written; + + written = snprintf (buf, MAX_LABEL_LEN, "A64_OPID_%08x_%s", + opc->opcode, opc->name); + assert (written >= 0 + && written < MAX_LABEL_LEN); + p = buf + written; + + for (j = 0; + j < AARCH64_MAX_OPND_NUM && opc->operands[j] != AARCH64_OPND_NIL; + j++) + { + written = snprintf (p, MAX_LABEL_LEN - (p - buf), "_%s", + operands[opc->operands[j]].str); + assert (written >= 0 + && written < MAX_LABEL_LEN - (p - buf)); + p += written; + } + + /* Sanitize the opcode name into something that can be used as + an identifier. */ + for (p = buf; *p != '\0'; ++p) + if (!(isalpha (*p) || isdigit (*p) || *p == '_')) + *p = '_'; + + opcode_node_labels[i] = strdup (buf); + } + + opcode_node_labels[i] = "A64_OPID_MAX"; +} + +/* Emit the opcode labels as an enum */ +void +print_opcode_labels_defn (void) +{ + unsigned count = sizeof (aarch64_opcode_table) / sizeof (aarch64_opcode); + unsigned i; + + printf ("/* Mnemonic names for the indices in the aarch64_opcode table,\n" + " so that we can refer to the entries by name. This serves two\n" + " main purposes. Firstly, the names change rarely, if at all,\n" + " so diffs in the generated files as instructions are added to\n" + " the table are much smaller. Secondly, the names are useful\n" + " when viewing the generated code in, for example, a debugger,\n" + " giving a better indication of what is going on.\n\n"); + printf (" The format of the names is:\n" + "\tA64_OPID_<opcode>_<mnemonic>[_<operand_type>]*\n" + " The operand modifier information is not included in the names\n" + " as this would make them too long and is currently unnecessary\n" + " for generating a unique name. */\n\n"); + + printf ("enum aarch64_opcode_idx\n{\n"); + for (i = 0; i < count; ++i) + printf (" %s,\n", opcode_node_labels[i]); + printf ("};\n"); +} + + /* Table indexed by opcode enumerator stores the index of the corresponding opcode entry in aarch64_opcode_table. */ static unsigned op_enum_table [OP_TOTAL_NUM]; @@ -1183,18 +1260,19 @@ print_get_opcode (void) /* Print the table. */ printf ("\n"); - printf ("/* Indexed by an enum aarch64_op enumerator, the value is the offset of\n\ - the corresponding aarch64_opcode entry in the aarch64_opcode_table. */\n\n"); - printf ("static const unsigned op_enum_table [] =\n"); + printf ("/* Indexed by an enum aarch64_op enumerator, the value is the\n" + " offset of the corresponding aarch64_opcode entry in the\n" + " aarch64_opcode_table. */\n\n"); + printf ("static const enum aarch64_opcode_idx op_enum_table [] =\n"); printf ("{\n"); for (i = 0; i < num; ++i) - printf (" %u,\n", op_enum_table[i]); + printf (" %s,\n", opcode_node_labels[op_enum_table[i]]); printf ("};\n"); /* Print the function. */ printf ("\n"); - printf ("/* Given the opcode enumerator OP, return the pointer to the corresponding\n"); - printf (" opcode entry. */\n"); + printf ("/* Given the opcode enumerator OP, return the pointer to the\n" + " corresponding opcode entry. */\n"); printf ("\n"); printf ("const aarch64_opcode *\n"); printf ("aarch64_get_opcode (enum aarch64_op op)\n"); @@ -1226,6 +1304,7 @@ struct option long_options[] = {"gen-opc", no_argument, NULL, 'c'}, {"gen-asm", no_argument, NULL, 'a'}, {"gen-dis", no_argument, NULL, 's'}, + {"gen-idx", no_argument, NULL, 'i'}, {0, no_argument, NULL, 0} }; @@ -1241,7 +1320,9 @@ usage (FILE * stream, int status) { fprintf (stream, "Usage: %s [-V | --version] [-d | --debug] [--help]\n", program_name); - fprintf (stream, "\t[ [-c | --gen-opc] | [-a | --gen-asm] | [-s | --gen-dis] ]\n"); + fprintf (stream, + "\t[ [-c | --gen-opc] | [-a | --gen-asm] " + "| [-s | --gen-dis] | [ --gen-idx | -i ]]\n"); xexit (status); } @@ -1253,6 +1334,7 @@ main (int argc, char **argv) int gen_opcode_p = 0; int gen_assembler_p = 0; int gen_disassembler_p = 0; + int gen_indices_p = 0; program_name = *argv; xmalloc_set_program_name (program_name); @@ -1271,6 +1353,9 @@ main (int argc, char **argv) case '?': usage (stderr, 0); break; + case 'i': + gen_indices_p = 1; + break; case 'c': gen_opcode_p = 1; break; @@ -1288,10 +1373,11 @@ main (int argc, char **argv) if (argc == 1 || optind != argc) usage (stdout, 1); - if (gen_opcode_p + gen_assembler_p + gen_disassembler_p > 1) + if (gen_opcode_p + gen_assembler_p + gen_disassembler_p + gen_indices_p > 1) { - printf ("Please specify only one of the following options\n\ - [-c | --gen-opc] [-a | --gen-asm] [-s | --gen-dis]\n"); + printf ("Please specify only one of the following options\n\t" + "[-c | --gen-opc] [-a | --gen-asm] " + "[-s | --gen-dis] [-i | --gen-idx]\n"); xexit (2); } @@ -1301,35 +1387,42 @@ main (int argc, char **argv) if (debug) print_divide_result (decoder_tree); - printf ("/* This file is automatically generated by aarch64-gen. Do not edit! */\n"); - printf ("/* Copyright (C) 2012-2025 Free Software Foundation, Inc.\n\ - Contributed by ARM Ltd.\n\ -\n\ - This file is part of the GNU opcodes library.\n\ -\n\ - This library is free software; you can redistribute it and/or modify\n\ - it under the terms of the GNU General Public License as published by\n\ - the Free Software Foundation; either version 3, or (at your option)\n\ - any later version.\n\ -\n\ - It is distributed in the hope that it will be useful, but WITHOUT\n\ - ANY WARRANTY; without even the implied warranty of MERCHANTABILITY\n\ - or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public\n\ - License for more details.\n\ -\n\ - You should have received a copy of the GNU General Public License\n\ - along with this program; see the file COPYING3. If not,\n\ - see <http://www.gnu.org/licenses/>. */\n"); + label_opcode_nodes (); + + printf + ("/* This file is automatically generated by aarch64-gen. " + "Do not edit! */\n"); + printf + ("/* Copyright (C) 2012-2025 Free Software Foundation, Inc.\n" + " Contributed by Arm Ltd.\n\n" + " This file is part of the GNU opcodes library.\n\n" + " This library is free software; you can redistribute it and/or modify\n" + " it under the terms of the GNU General Public License as published by\n" + " the Free Software Foundation; either version 3, or (at your option)\n" + " any later version.\n\n" + " It is distributed in the hope that it will be useful, but WITHOUT\n" + " ANY WARRANTY; without even the implied warranty of MERCHANTABILITY\n" + " or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public\n" + " License for more details.\n\n" + " You should have received a copy of the GNU General Public License\n" + " along with this program; see the file COPYING3. If not,\n" + " see <http://www.gnu.org/licenses/>. */\n"); printf ("\n"); - printf ("#include \"sysdep.h\"\n"); - if (gen_opcode_p) - printf ("#include \"aarch64-opc.h\"\n"); - if (gen_assembler_p) - printf ("#include \"aarch64-asm.h\"\n"); - if (gen_disassembler_p) - printf ("#include \"aarch64-dis.h\"\n"); - printf ("\n"); + if (gen_indices_p) + print_opcode_labels_defn (); + else + { + printf ("#include \"sysdep.h\"\n"); + printf ("#include \"aarch64-tbl-2.h\"\n"); + if (gen_opcode_p) + printf ("#include \"aarch64-opc.h\"\n"); + if (gen_assembler_p) + printf ("#include \"aarch64-asm.h\"\n"); + if (gen_disassembler_p) + printf ("#include \"aarch64-dis.h\"\n"); + printf ("\n"); + } /* Generate opcode entry lookup for the disassembler. */ if (gen_disassembler_p) |