diff options
author | Dan Albert <danalbert@google.com> | 2015-06-17 15:33:58 -0700 |
---|---|---|
committer | Dan Albert <danalbert@google.com> | 2015-06-17 15:33:58 -0700 |
commit | 7a1d76c6c5b354abbba43308d5061eb6ff96d3ea (patch) | |
tree | 78a639d039e517565afa35d7af021a6967bec0d9 /binutils-2.23/opcodes/aarch64-gen.c | |
parent | c39479f4ab4d372b518957871e1f205a03e7c3d6 (diff) | |
download | toolchain_binutils-7a1d76c6c5b354abbba43308d5061eb6ff96d3ea.tar.gz toolchain_binutils-7a1d76c6c5b354abbba43308d5061eb6ff96d3ea.tar.bz2 toolchain_binutils-7a1d76c6c5b354abbba43308d5061eb6ff96d3ea.zip |
Remove old versions of binutils.
Change-Id: If634d8d30cfa8c88ca3ba59691a0df4ee5596f85
Diffstat (limited to 'binutils-2.23/opcodes/aarch64-gen.c')
-rw-r--r-- | binutils-2.23/opcodes/aarch64-gen.c | 1317 |
1 files changed, 0 insertions, 1317 deletions
diff --git a/binutils-2.23/opcodes/aarch64-gen.c b/binutils-2.23/opcodes/aarch64-gen.c deleted file mode 100644 index b329cb6e..00000000 --- a/binutils-2.23/opcodes/aarch64-gen.c +++ /dev/null @@ -1,1317 +0,0 @@ -/* aarch64-gen.c -- Generate tables and routines for opcode lookup and - instruction encoding and decoding. - Copyright 2012, 2013 Free Software Foundation, Inc. - Contributed by ARM Ltd. - - This file is part of the GNU opcodes library. - - This library is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3, or (at your option) - any later version. - - It is distributed in the hope that it will be useful, but WITHOUT - ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public - License for more details. - - You should have received a copy of the GNU General Public License - along with this program; see the file COPYING3. If not, - see <http://www.gnu.org/licenses/>. */ - -#include "sysdep.h" -#include <stdio.h> -#include <stdlib.h> -#include <stdarg.h> - -#include "libiberty.h" -#include "getopt.h" -#include "opcode/aarch64.h" - -#include "aarch64-tbl.h" - -static int debug = 0; - -/* Structure used in the decoding tree to group a list of aarch64_opcode - entries. */ - -struct opcode_node -{ - aarch64_insn opcode; - aarch64_insn mask; - /* Index of the entry in the original table; the top 2 bits help - determine the table. */ - unsigned int index; - struct opcode_node *next; -}; - -typedef struct opcode_node opcode_node; - -/* Head of the list of the opcode_node after read_table. */ -static opcode_node opcode_nodes_head; - -/* Node in the decoding tree. */ - -struct bittree -{ - unsigned int bitno; - /* 0, 1, and X (don't care). */ - struct bittree *bits[2]; - /* List of opcodes; only valid for the leaf node. */ - opcode_node *list; -}; - -/* Allocate and initialize an opcode_node. */ -static opcode_node* -new_opcode_node (void) -{ - opcode_node* ent = malloc (sizeof (opcode_node)); - - if (!ent) - abort (); - - ent->opcode = 0; - ent->mask = 0; - ent->index = -1; - ent->next = NULL; - - return ent; -} - -/* Multiple tables are supported, although currently only one table is - in use. N.B. there are still some functions have the table name - 'aarch64_opcode_table' hard-coded in, e.g. print_find_next_opcode; - therefore some amount of work needs to be done if the full support - for multiple tables needs to be enabled. */ -static const struct aarch64_opcode *aarch64_opcode_tables[] = -{aarch64_opcode_table}; - -/* Use top 2 bits to indiate which table. */ -static unsigned int -initialize_index (const struct aarch64_opcode* table) -{ - int i; - const int num_of_tables = sizeof (aarch64_opcode_tables) - / sizeof (struct aarch64_opcode *); - for (i = 0; i < num_of_tables; ++i) - if (table == aarch64_opcode_tables [i]) - break; - if (i == num_of_tables) - abort (); - return (unsigned int)i << 30; -} - -static inline const struct aarch64_opcode * -index2table (unsigned int index) -{ - return aarch64_opcode_tables[(index >> 30) & 0x3]; -} - -static inline unsigned int -real_index (unsigned int index) -{ - return index & ((1 << 30) - 1); -} - -/* Given OPCODE_NODE, return the corresponding aarch64_opcode*. */ -static const aarch64_opcode* -get_aarch64_opcode (const opcode_node *opcode_node) -{ - if (opcode_node == NULL) - return NULL; - return &index2table (opcode_node->index)[real_index (opcode_node->index)]; -} - -static void -read_table (const struct aarch64_opcode* table) -{ - const struct aarch64_opcode *ent = table; - opcode_node **new_ent; - unsigned int index = initialize_index (table); - - if (!ent->name) - return; - - new_ent = &opcode_nodes_head.next; - - while (*new_ent) - new_ent = &(*new_ent)->next; - - do - { - /* F_PSEUDO needs to be used together with F_ALIAS to indicate an alias - opcode is a programmer friendly pseudo instruction available only in - the assembly code (thus will not show up in the disassembly). */ - assert (pseudo_opcode_p (ent) == FALSE || alias_opcode_p (ent) == TRUE); - /* Skip alias (inc. pseudo) opcode. */ - if (alias_opcode_p (ent) == TRUE) - { - index++; - continue; - } - *new_ent = new_opcode_node (); - (*new_ent)->opcode = ent->opcode; - (*new_ent)->mask = ent->mask; - (*new_ent)->index = index++; - new_ent = &((*new_ent)->next); - } while ((++ent)->name); -} - -static inline void -print_one_opcode_node (opcode_node* ent) -{ - printf ("%s\t%08x\t%08x\t%d\n", get_aarch64_opcode (ent)->name, - get_aarch64_opcode (ent)->opcode, get_aarch64_opcode (ent)->mask, - (int)real_index (ent->index)); -} - -/* As an internal debugging utility, print out the list of nodes pointed - by opcode_nodes_head. */ -static void -print_opcode_nodes (void) -{ - opcode_node* ent = opcode_nodes_head.next; - printf ("print_opcode_nodes table:\n"); - while (ent) - { - print_one_opcode_node (ent); - ent = ent->next; - } -} - -static struct bittree* -new_bittree_node (void) -{ - struct bittree* node; - node = malloc (sizeof (struct bittree)); - if (!node) - abort (); - node->bitno = -1; - node->bits[0] = NULL; - node->bits[1] = NULL; - return node; -} - -/* The largest number of opcode entries that exist at a leaf node of the - decoding decision tree. The reason that there can be more than one - opcode entry is because some opcodes have shared field that is partially - constrained and thus cannot be fully isolated using the algorithm - here. */ -static int max_num_opcodes_at_leaf_node = 0; - -/* Given a list of opcodes headed by *OPCODE, try to establish one bit that - is shared by all the opcodes in the list as one of base opcode bits. If - such a bit is found, divide the list of the opcodes into two based on the - value of the bit. - - Store the bit number in BITTREE->BITNO if the division succeeds. If unable - to determine such a bit or there is only one opcode in the list, the list - is decided to be undividable and OPCODE will be assigned to BITTREE->LIST. - - The function recursively call itself until OPCODE is undividable. - - N.B. the nature of this algrithm determines that given any value in the - 32-bit space, the computed decision tree will always be able to find one or - more opcodes entries for it, regardless whether there is a valid instruction - defined for this value or not. In order to detect the undefined values, - when the caller obtains the opcode entry/entries, it should at least compare - the bit-wise AND result of the value and the mask with the base opcode - value; if the two are different, it means that the value is undefined - (although the value may be still undefined when the comparison is the same, - in which case call aarch64_opcode_decode to carry out further checks). */ - -static void -divide_table_1 (struct bittree *bittree, opcode_node *opcode) -{ - aarch64_insn mask_and; - opcode_node *ent; - unsigned int bitno; - aarch64_insn bitmask; - opcode_node list0, list1, **ptr0, **ptr1; - static int depth = 0; - - ++depth; - - if (debug) - printf ("Enter into depth %d\n", depth); - - assert (opcode != NULL); - - /* Succeed when there is only one opcode left. */ - if (!opcode->next) - { - if (debug) - { - printf ("opcode isolated:\n"); - print_one_opcode_node (opcode); - } - goto divide_table_1_finish; - } - -divide_table_1_try_again: - mask_and = -1; - ent = opcode; - while (ent) - { - mask_and &= ent->mask; - ent = ent->next; - } - - if (debug) - printf ("mask and result: %08x\n", (unsigned int)mask_and); - - /* If no more bit to look into, we have to accept the reality then. */ - if (!mask_and) - { - int i; - opcode_node *ptr; - if (debug) - { - ptr = opcode; - printf ("Isolated opcode group:\n"); - do { - print_one_opcode_node (ptr); - ptr = ptr->next; - } while (ptr); - } - /* Count the number of opcodes. */ - for (i = 0, ptr = opcode; ptr; ++i) - ptr = ptr->next; - if (i > max_num_opcodes_at_leaf_node) - max_num_opcodes_at_leaf_node = i; - goto divide_table_1_finish; - } - - /* Pick up the right most bit that is 1. */ - bitno = 0; - while (!(mask_and & (1 << bitno))) - ++bitno; - bitmask = (1 << bitno); - - if (debug) - printf ("use bit %d\n", bitno); - - /* Record in the bittree. */ - bittree->bitno = bitno; - - /* Get two new opcode lists; adjust their masks. */ - list0.next = NULL; - list1.next = NULL; - ptr0 = &list0.next; - ptr1 = &list1.next; - ent = opcode; - while (ent) - { - if (ent->opcode & bitmask) - { - ent->mask &= (~bitmask); - *ptr1 = ent; - ent = ent->next; - (*ptr1)->next = NULL; - ptr1 = &(*ptr1)->next; - } - else - { - ent->mask &= (~bitmask); - *ptr0 = ent; - ent = ent->next; - (*ptr0)->next = NULL; - ptr0 = &(*ptr0)->next; - } - } - - /* If BITNO can NOT divide the opcode group, try next bit. */ - if (list0.next == NULL) - { - opcode = list1.next; - goto divide_table_1_try_again; - } - else if (list1.next == NULL) - { - opcode = list0.next; - goto divide_table_1_try_again; - } - - /* Further divide. */ - bittree->bits[0] = new_bittree_node (); - bittree->bits[1] = new_bittree_node (); - divide_table_1 (bittree->bits[0], list0.next); - divide_table_1 (bittree->bits[1], list1.next); - -divide_table_1_finish: - if (debug) - printf ("Leave from depth %d\n", depth); - --depth; - - /* Record the opcode entries on this leaf node. */ - bittree->list = opcode; - - return; -} - -/* Call divide_table_1 to divide the all the opcodes and thus create the - decoding decision tree. */ -static struct bittree* -divide_table (void) -{ - struct bittree *bittree = new_bittree_node (); - divide_table_1 (bittree, opcode_nodes_head.next); - return bittree; -} - -/* Read in all of the tables, create the decoding decision tree and return - the tree root. */ -static struct bittree* -initialize_decoder_tree (void) -{ - int i; - const int num_of_tables = (sizeof (aarch64_opcode_tables) - / sizeof (struct aarch64_opcode *)); - for (i = 0; i < num_of_tables; ++i) - read_table (aarch64_opcode_tables [i]); - if (debug) - print_opcode_nodes (); - return divide_table (); -} - -static void __attribute__ ((format (printf, 2, 3))) -indented_print (unsigned int indent, const char *format, ...) -{ - /* 80 number of spaces pluc a NULL terminator. */ - static const char spaces[81] = - " "; - va_list ap; - va_start (ap, format); - assert (indent <= 80); - printf ("%s", &spaces[80 - indent]); - vprintf (format, ap); - va_end (ap); -} - -/* N.B. read the comment above divide_table_1 for the reason why the generated - decision tree function never returns NULL. */ - -static void -print_decision_tree_1 (unsigned int indent, struct bittree* bittree) -{ - /* PATTERN is only used to generate comment in the code. */ - static char pattern[33] = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"; - assert (bittree != NULL); - - /* Leaf node located. */ - if (bittree->bits[0] == NULL && bittree->bits[1] == NULL) - { - 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)); - return; - } - - /* Walk down the decoder tree. */ - indented_print (indent, "if (((word >> %d) & 0x1) == 0)\n", bittree->bitno); - indented_print (indent, " {\n"); - pattern[bittree->bitno] = '0'; - print_decision_tree_1 (indent + 4, bittree->bits[0]); - indented_print (indent, " }\n"); - indented_print (indent, "else\n"); - indented_print (indent, " {\n"); - pattern[bittree->bitno] = '1'; - print_decision_tree_1 (indent + 4, bittree->bits[1]); - indented_print (indent, " }\n"); - pattern[bittree->bitno] = 'x'; -} - -/* Generate aarch64_opcode_lookup in C code to the standard output. */ - -static void -print_decision_tree (struct bittree* bittree) -{ - if (debug) - printf ("Enter print_decision_tree\n"); - - printf ("/* Called by aarch64_opcode_lookup. */\n\n"); - - printf ("static int\n"); - printf ("aarch64_opcode_lookup_1 (uint32_t word)\n"); - printf ("{\n"); - - print_decision_tree_1 (2, bittree); - - printf ("}\n\n"); - - - printf ("/* Lookup opcode WORD in the opcode table. N.B. all alias\n"); - printf (" opcodes are ignored here. */\n\n"); - - printf ("const aarch64_opcode *\n"); - printf ("aarch64_opcode_lookup (uint32_t word)\n"); - printf ("{\n"); - printf (" return aarch64_opcode_table + aarch64_opcode_lookup_1 (word);\n"); - printf ("}\n"); -} - -static void -print_find_next_opcode_1 (struct bittree* bittree) -{ - assert (bittree != NULL); - - /* Leaf node located. */ - if (bittree->bits[0] == NULL && bittree->bits[1] == NULL) - { - assert (bittree->list != NULL); - /* Find multiple opcode entries in one leaf node. */ - if (bittree->list->next != NULL) - { - opcode_node *list = bittree->list; - while (list != NULL) - { - 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)); - if (list->next != NULL) - { - printf ("value = %u; break;\t", real_index (list->next->index)); - printf ("/* %s --> %s. */\n", curr->name, next->name); - } - else - { - printf ("return NULL;\t\t"); - printf ("/* %s --> NULL. */\n", curr->name); - } - - list = list->next; - } - } - return; - } - - /* Walk down the decoder tree. */ - print_find_next_opcode_1 (bittree->bits[0]); - print_find_next_opcode_1 (bittree->bits[1]); -} - -/* Generate aarch64_find_next_opcode in C code to the standard output. */ - -static void -print_find_next_opcode (struct bittree* bittree) -{ - if (debug) - printf ("Enter print_find_next_opcode\n"); - - printf ("\n"); - printf ("const aarch64_opcode *\n"); - 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 (" switch (key)\n"); - printf (" {\n"); - - print_find_next_opcode_1 (bittree); - - printf (" default: return NULL;\n"); - printf (" }\n\n"); - - printf (" return aarch64_opcode_table + value;\n"); - printf ("}\n"); -} - -/* Release the dynamic memory resource allocated for the generation of the - decoder tree. */ - -static void -release_resource_decoder_tree (struct bittree* bittree) -{ - assert (bittree != NULL); - - /* Leaf node located. */ - if (bittree->bits[0] == NULL && bittree->bits[1] == NULL) - { - assert (bittree->list != NULL); - /* Free opcode_nodes. */ - opcode_node *list = bittree->list; - while (list != NULL) - { - opcode_node *next = list->next; - free (list); - list = next; - } - /* Free the tree node. */ - free (bittree); - return; - } - - /* Walk down the decoder tree. */ - release_resource_decoder_tree (bittree->bits[0]); - release_resource_decoder_tree (bittree->bits[1]); - - /* Free the tree node. */ - free (bittree); -} - -/* Generate aarch64_find_real_opcode in C code to the standard output. - TABLE points to the alias info table, while NUM indicates the number of - entries in the table. */ - -static void -print_find_real_opcode (const opcode_node *table, int num) -{ - int i; - - if (debug) - printf ("Enter print_find_real_opcode\n"); - - printf ("\n"); - printf ("const aarch64_opcode *\n"); - 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 (" switch (key)\n"); - printf (" {\n"); - - for (i = 0; i < num; ++i) - { - 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 (" break;\n"); - } - - printf (" default: return NULL;\n"); - printf (" }\n\n"); - - printf (" return aarch64_opcode_table + value;\n"); - printf ("}\n"); -} - -/* Generate aarch64_find_alias_opcode in C code to the standard output. - TABLE points to the alias info table, while NUM indicates the number of - entries in the table. */ - -static void -print_find_alias_opcode (const opcode_node *table, int num) -{ - int i; - - if (debug) - printf ("Enter print_find_alias_opcode\n"); - - printf ("\n"); - printf ("const aarch64_opcode *\n"); - 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 (" switch (key)\n"); - printf (" {\n"); - - for (i = 0; i < num; ++i) - { - 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 (" default: return NULL;\n"); - printf (" }\n\n"); - - printf (" return aarch64_opcode_table + value;\n"); - printf ("}\n"); -} - -/* Generate aarch64_find_next_alias_opcode in C code to the standard output. - TABLE points to the alias info table, while NUM indicates the number of - entries in the table. */ - -static void -print_find_next_alias_opcode (const opcode_node *table, int num) -{ - int i; - - if (debug) - printf ("Enter print_find_next_alias_opcode\n"); - - printf ("\n"); - printf ("const aarch64_opcode *\n"); - 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 (" switch (key)\n"); - printf (" {\n"); - - for (i = 0; i < num; ++i) - { - const opcode_node *node = table + i; - assert (node->next); - if (node->next->next == NULL) - 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); - node = node->next; - } - } - - printf (" default: return NULL;\n"); - printf (" }\n\n"); - - printf (" return aarch64_opcode_table + value;\n"); - printf ("}\n"); -} - -/* Given OPCODE, establish and return a link list of alias nodes in the - preferred order. */ - -opcode_node * -find_alias_opcode (const aarch64_opcode *opcode) -{ - int i; - /* Assume maximum of 8 disassemble preference candidates. */ - const int max_num_aliases = 8; - const aarch64_opcode *ent; - const aarch64_opcode *preferred[max_num_aliases]; - opcode_node head, **next; - - assert (opcode_has_alias (opcode)); - - i = 0; - ent = aarch64_opcode_table; - while (ent->name != NULL) - { - /* The mask of an alias opcode must be equal to or a super-set (i.e. - more constrained) of that of the aliased opcode; so is the base - opcode value. */ - if (alias_opcode_p (ent) == TRUE - && (ent->mask & opcode->mask) == opcode->mask - && (opcode->mask & ent->opcode) == (opcode->mask & opcode->opcode)) - { - assert (i < max_num_aliases); - preferred[i++] = ent; - if (debug) - printf ("found %s for %s.", ent->name, opcode->name); - } - ++ent; - } - - if (debug) - { - int m; - printf ("un-orderd list: "); - for (m = 0; m < i; ++m) - printf ("%s, ", preferred[m]->name); - printf ("\n"); - } - - /* There must be at least one alias. */ - assert (i >= 1); - - /* Sort preferred array according to the priority (from the lowest to the - highest. */ - if (i > 1) - { - int j, k; - for (j = 0; j < i - 1; ++j) - { - for (k = 0; k < i - 1 - j; ++k) - { - const aarch64_opcode *t; - t = preferred [k+1]; - if (opcode_priority (t) < opcode_priority (preferred [k])) - { - preferred [k+1] = preferred [k]; - preferred [k] = t; - } - } - } - } - - if (debug) - { - int m; - printf ("orderd list: "); - for (m = 0; m < i; ++m) - printf ("%s, ", preferred[m]->name); - printf ("\n"); - } - - /* Create a link-list of opcode_node with disassemble preference from - higher to lower. */ - next = &head.next; - --i; - while (i >= 0) - { - const aarch64_opcode *alias = preferred [i]; - opcode_node *node = new_opcode_node (); - - if (debug) - printf ("add %s.\n", alias->name); - - node->index = alias - aarch64_opcode_table; - *next = node; - next = &node->next; - - --i; - } - *next = NULL; - - return head.next; -} - -/* Create and return alias information. - Return the address of the created alias info table; return the number - of table entries in *NUM_PTR. */ - -opcode_node * -create_alias_info (int *num_ptr) -{ - int i, num; - opcode_node *ret; - const aarch64_opcode *ent; - - /* Calculate the total number of opcodes that have alias. */ - num = 0; - ent = aarch64_opcode_table; - while (ent->name != NULL) - { - if (opcode_has_alias (ent)) - { - /* Assert the alias relationship be flat-structured to keep - algorithms simple; not allow F_ALIAS and F_HAS_ALIAS both - specified. */ - assert (!alias_opcode_p (ent)); - ++num; - } - ++ent; - } - assert (num_ptr); - *num_ptr = num; - - /* The array of real opcodes that have alias(es). */ - ret = malloc (sizeof (opcode_node) * num); - - /* For each opcode, establish a list of alias nodes in a preferred - order. */ - for (i = 0, ent = aarch64_opcode_table; i < num; ++i, ++ent) - { - opcode_node *node = ret + i; - while (ent->name != NULL && !opcode_has_alias (ent)) - ++ent; - assert (ent->name != NULL); - node->index = ent - aarch64_opcode_table; - node->next = find_alias_opcode (ent); - assert (node->next); - } - assert (i == num); - - return ret; -} - -/* Release the dynamic memory resource allocated for the generation of the - alias information. */ - -void -release_resource_alias_info (opcode_node *alias_info, int num) -{ - int i = 0; - opcode_node *node = alias_info; - - /* Free opcode_node list. */ - for (; i < num; ++i, ++node) - { - opcode_node *list = node->next; - do - { - opcode_node *next = list->next; - free (list); - list = next; - } while (list != NULL); - } - - /* Free opcode_node array. */ - free (alias_info); -} - -/* As a debugging utility, print out the result of the table division, although - it is not doing much this moment. */ -static void -print_divide_result (const struct bittree *bittree ATTRIBUTE_UNUSED) -{ - printf ("max_num_opcodes_at_leaf_node: %d\n", max_num_opcodes_at_leaf_node); - return; -} - -/* Structure to help generate the operand table. */ -struct operand -{ - const char *class; - const char *inserter; - const char *extractor; - const char *str; - const char *flags; - const char *fields; - const char *desc; - unsigned processed : 1; - unsigned has_inserter : 1; - unsigned has_extractor : 1; -}; - -typedef struct operand operand; - -#ifdef X -#undef X -#endif - -#ifdef Y -#undef Y -#endif - -#ifdef F -#undef F -#endif - -/* Get the operand information in strings. */ - -static operand operands[] = -{ - {"NIL", "0", "0", "", "0", "{0}", "<none>", 0, 0, 0}, -#define F(...) #__VA_ARGS__ -#define X(a,b,c,d,e,f,g) \ - {#a, #b, #c, d, #e, "{"f"}", g, 0, 0, 0}, -#define Y(a,b,d,e,f,g) \ - {#a, "ins_"#b, "ext_"#b, d, #e, "{"f"}", g, 0, 0, 0}, - AARCH64_OPERANDS - {"NIL", "0", "0", "", "0", "{0}", "DUMMY", 0, 0, 0}, -}; - -#undef F -#undef X - -static void -process_operand_table (void) -{ - int i; - operand *opnd; - const int num = sizeof (operands) / sizeof (operand); - - for (i = 0, opnd = operands; i < num; ++i, ++opnd) - { - opnd->has_inserter = opnd->inserter[0] != '0'; - opnd->has_extractor = opnd->extractor[0] != '0'; - } -} - -/* Generate aarch64_operands in C to the standard output. */ - -static void -print_operand_table (void) -{ - int i; - operand *opnd; - const int num = sizeof (operands) / sizeof (operand); - - if (debug) - printf ("Enter print_operand_table\n"); - - printf ("\n"); - printf ("const struct aarch64_operand aarch64_operands[] =\n"); - printf ("{\n"); - - for (i = 0, opnd = operands; i < num; ++i, ++opnd) - { - char flags[256]; - flags[0] = '\0'; - if (opnd->flags[0] != '0') - sprintf (flags, "%s", opnd->flags); - if (opnd->has_inserter) - { - if (flags[0] != '\0') - strcat (flags, " | "); - strcat (flags, "OPD_F_HAS_INSERTER"); - } - if (opnd->has_extractor) - { - if (flags[0] != '\0') - strcat (flags, " | "); - strcat (flags, "OPD_F_HAS_EXTRACTOR"); - } - if (flags[0] == '\0') - { - flags[0] = '0'; - flags[1] = '\0'; - } - printf (" {AARCH64_OPND_CLASS_%s, \"%s\", %s, %s, \"%s\"},\n", - opnd->class, opnd->str, flags, opnd->fields, opnd->desc); - } - printf ("};\n"); -} - -/* Generate aarch64_insert_operand in C to the standard output. */ - -static void -print_operand_inserter (void) -{ - int i; - operand *opnd; - const int num = sizeof (operands) / sizeof (operand); - - if (debug) - printf ("Enter print_operand_inserter\n"); - - printf ("\n"); - printf ("const char*\n"); - printf ("aarch64_insert_operand (const aarch64_operand *self,\n\ - const aarch64_opnd_info *info,\n\ - aarch64_insn *code, const aarch64_inst *inst)\n"); - printf ("{\n"); - printf (" /* Use the index as the key. */\n"); - printf (" int key = self - aarch64_operands;\n"); - printf (" switch (key)\n"); - printf (" {\n"); - - for (i = 0, opnd = operands; i < num; ++i, ++opnd) - opnd->processed = 0; - - for (i = 0, opnd = operands; i < num; ++i, ++opnd) - { - if (!opnd->processed && opnd->has_inserter) - { - int j = i + 1; - const int len = strlen (opnd->inserter); - operand *opnd2 = opnd + 1; - printf (" case %u:\n", (unsigned int)(opnd - operands)); - opnd->processed = 1; - for (; j < num; ++j, ++opnd2) - { - if (!opnd2->processed - && opnd2->has_inserter - && len == strlen (opnd2->inserter) - && strncmp (opnd->inserter, opnd2->inserter, len) == 0) - { - printf (" case %u:\n", (unsigned int)(opnd2 - operands)); - opnd2->processed = 1; - } - } - printf (" return aarch64_%s (self, info, code, inst);\n", - opnd->inserter); - } - } - - printf (" default: assert (0); abort ();\n"); - printf (" }\n"); - printf ("}\n"); -} - -/* Generate aarch64_extract_operand in C to the standard output. */ - -static void -print_operand_extractor (void) -{ - int i; - operand *opnd; - const int num = sizeof (operands) / sizeof (operand); - - if (debug) - printf ("Enter print_operand_extractor\n"); - - printf ("\n"); - printf ("int\n"); - printf ("aarch64_extract_operand (const aarch64_operand *self,\n\ - aarch64_opnd_info *info,\n\ - aarch64_insn code, const aarch64_inst *inst)\n"); - printf ("{\n"); - printf (" /* Use the index as the key. */\n"); - printf (" int key = self - aarch64_operands;\n"); - printf (" switch (key)\n"); - printf (" {\n"); - - for (i = 0, opnd = operands; i < num; ++i, ++opnd) - opnd->processed = 0; - - for (i = 0, opnd = operands; i < num; ++i, ++opnd) - { - if (!opnd->processed && opnd->has_extractor) - { - int j = i + 1; - const int len = strlen (opnd->extractor); - operand *opnd2 = opnd + 1; - printf (" case %u:\n", (unsigned int)(opnd - operands)); - opnd->processed = 1; - for (; j < num; ++j, ++opnd2) - { - if (!opnd2->processed - && opnd2->has_extractor - && len == strlen (opnd2->extractor) - && strncmp (opnd->extractor, opnd2->extractor, len) == 0) - { - printf (" case %u:\n", (unsigned int)(opnd2 - operands)); - opnd2->processed = 1; - } - } - printf (" return aarch64_%s (self, info, code, inst);\n", - opnd->extractor); - } - } - - printf (" default: assert (0); abort ();\n"); - printf (" }\n"); - 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]; - -/* Print out the routine which, given the opcode enumerator, returns the - corresponding opcode entry pointer. */ - -static void -print_get_opcode (void) -{ - int i; - const int num = OP_TOTAL_NUM; - const aarch64_opcode *opcode; - - if (debug) - printf ("Enter print_get_opcode\n"); - - /* Fill in the internal table. */ - opcode = aarch64_opcode_table; - while (opcode->name != NULL) - { - if (opcode->op != OP_NIL) - { - /* Assert opcode enumerator be unique, in other words, no shared by - different opcodes. */ - if (op_enum_table[opcode->op] != 0) - { - fprintf (stderr, "Opcode %u is shared by different %s and %s.\n", - opcode->op, - aarch64_opcode_table[op_enum_table[opcode->op]].name, - opcode->name); - assert (0); - abort (); - } - assert (opcode->op < OP_TOTAL_NUM); - op_enum_table[opcode->op] = opcode - aarch64_opcode_table; - } - ++opcode; - } - - /* 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 ("{\n"); - for (i = 0; i < num; ++i) - printf (" %u,\n", 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 ("\n"); - printf ("const aarch64_opcode *\n"); - printf ("aarch64_get_opcode (enum aarch64_op op)\n"); - printf ("{\n"); - printf (" return aarch64_opcode_table + op_enum_table[op];\n"); - printf ("}\n"); -} - -/* Print out the content of an opcode table (not in use). */ -static void ATTRIBUTE_UNUSED -print_table (struct aarch64_opcode* table) -{ - struct aarch64_opcode *ent = table; - do - { - printf ("%s\t%08x\t%08x\n", ent->name, (unsigned int)ent->opcode, - (unsigned int)ent->mask); - } while ((++ent)->name); -} - -static const char * program_name = NULL; - -/* Program options. */ -struct option long_options[] = -{ - {"debug", no_argument, NULL, 'd'}, - {"version", no_argument, NULL, 'V'}, - {"help", no_argument, NULL, 'h'}, - {"gen-opc", no_argument, NULL, 'c'}, - {"gen-asm", no_argument, NULL, 'a'}, - {"gen-dis", no_argument, NULL, 's'}, - {0, no_argument, NULL, 0} -}; - -static void -print_version (void) -{ - printf ("%s: version 1.0\n", program_name); - xexit (0); -} - -static void -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"); - xexit (status); -} - -int -main (int argc, char **argv) -{ - extern int chdir (char *); - int c; - int gen_opcode_p = 0; - int gen_assembler_p = 0; - int gen_disassembler_p = 0; - - program_name = *argv; - xmalloc_set_program_name (program_name); - - while ((c = getopt_long (argc, argv, "vVdhacs", long_options, 0)) != EOF) - switch (c) - { - case 'V': - case 'v': - print_version (); - break; - case 'd': - debug = 1; - break; - case 'h': - case '?': - usage (stderr, 0); - break; - case 'c': - gen_opcode_p = 1; - break; - case 'a': - gen_assembler_p = 1; - break; - case 's': - gen_disassembler_p = 1; - break; - default: - case 0: - break; - } - - if (argc == 1 || optind != argc) - usage (stdout, 1); - - if (gen_opcode_p + gen_assembler_p + gen_disassembler_p > 1) - { - printf ("Please specify only one of the following options\n\ - [-c | --gen-opc] [-a | --gen-asm] [-s | --gen-dis]\n"); - xexit (2); - } - - struct bittree *decoder_tree; - - decoder_tree = initialize_decoder_tree (); - if (debug) - print_divide_result (decoder_tree); - - printf ("/* This file is automatically generated by aarch64-gen. Do not edit! */\n"); - printf ("/* Copyright 2012, 2013 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"); - - /* Generate opcode entry lookup for the disassembler. */ - if (gen_disassembler_p) - { - print_decision_tree (decoder_tree); - print_find_next_opcode (decoder_tree); - release_resource_decoder_tree (decoder_tree); - } - - /* Generate alias opcode handling for the assembler or the disassembler. */ - if (gen_assembler_p || gen_disassembler_p) - { - int num; - opcode_node *alias_info = create_alias_info (&num); - - if (gen_assembler_p) - print_find_real_opcode (alias_info, num); - - if (gen_disassembler_p) - { - print_find_alias_opcode (alias_info, num); - print_find_next_alias_opcode (alias_info, num); - } - - release_resource_alias_info (alias_info, num); - } - - /* Generate operand table. */ - process_operand_table (); - - if (gen_assembler_p) - print_operand_inserter (); - - if (gen_disassembler_p) - print_operand_extractor (); - - if (gen_opcode_p) - print_operand_table (); - - /* Generate utility to return aarch64_opcode entry given an enumerator. */ - if (gen_opcode_p) - print_get_opcode (); - - exit (0); -} |