Home | History | Annotate | Line # | Download | only in opcodes
aarch64-gen.c revision 1.1.1.4
      1      1.1  christos /* aarch64-gen.c -- Generate tables and routines for opcode lookup and
      2      1.1  christos    instruction encoding and decoding.
      3  1.1.1.4  christos    Copyright (C) 2012-2018 Free Software Foundation, Inc.
      4      1.1  christos    Contributed by ARM Ltd.
      5      1.1  christos 
      6      1.1  christos    This file is part of the GNU opcodes library.
      7      1.1  christos 
      8      1.1  christos    This library is free software; you can redistribute it and/or modify
      9      1.1  christos    it under the terms of the GNU General Public License as published by
     10      1.1  christos    the Free Software Foundation; either version 3, or (at your option)
     11      1.1  christos    any later version.
     12      1.1  christos 
     13      1.1  christos    It is distributed in the hope that it will be useful, but WITHOUT
     14      1.1  christos    ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
     15      1.1  christos    or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
     16      1.1  christos    License for more details.
     17      1.1  christos 
     18      1.1  christos    You should have received a copy of the GNU General Public License
     19      1.1  christos    along with this program; see the file COPYING3. If not,
     20      1.1  christos    see <http://www.gnu.org/licenses/>.  */
     21      1.1  christos 
     22      1.1  christos #include "sysdep.h"
     23      1.1  christos #include <stdio.h>
     24      1.1  christos #include <stdlib.h>
     25      1.1  christos #include <stdarg.h>
     26      1.1  christos 
     27      1.1  christos #include "libiberty.h"
     28      1.1  christos #include "getopt.h"
     29      1.1  christos #include "opcode/aarch64.h"
     30      1.1  christos 
     31  1.1.1.3  christos #define VERIFIER(x) NULL
     32      1.1  christos #include "aarch64-tbl.h"
     33      1.1  christos 
     34      1.1  christos static int debug = 0;
     35      1.1  christos 
     36      1.1  christos /* Structure used in the decoding tree to group a list of aarch64_opcode
     37      1.1  christos    entries.  */
     38      1.1  christos 
     39      1.1  christos struct opcode_node
     40      1.1  christos {
     41      1.1  christos   aarch64_insn opcode;
     42      1.1  christos   aarch64_insn mask;
     43      1.1  christos   /* Index of the entry in the original table; the top 2 bits help
     44      1.1  christos      determine the table.  */
     45      1.1  christos   unsigned int index;
     46      1.1  christos   struct opcode_node *next;
     47      1.1  christos };
     48      1.1  christos 
     49      1.1  christos typedef struct opcode_node opcode_node;
     50      1.1  christos 
     51      1.1  christos /* Head of the list of the opcode_node after read_table.  */
     52      1.1  christos static opcode_node opcode_nodes_head;
     53      1.1  christos 
     54      1.1  christos /* Node in the decoding tree.  */
     55      1.1  christos 
     56      1.1  christos struct bittree
     57      1.1  christos {
     58      1.1  christos   unsigned int bitno;
     59      1.1  christos   /* 0, 1, and X (don't care).  */
     60      1.1  christos   struct bittree *bits[2];
     61      1.1  christos   /* List of opcodes; only valid for the leaf node.  */
     62      1.1  christos   opcode_node *list;
     63      1.1  christos };
     64      1.1  christos 
     65      1.1  christos /* Allocate and initialize an opcode_node.  */
     66      1.1  christos static opcode_node*
     67      1.1  christos new_opcode_node (void)
     68      1.1  christos {
     69      1.1  christos   opcode_node* ent = malloc (sizeof (opcode_node));
     70      1.1  christos 
     71      1.1  christos   if (!ent)
     72      1.1  christos     abort ();
     73      1.1  christos 
     74      1.1  christos   ent->opcode = 0;
     75      1.1  christos   ent->mask = 0;
     76      1.1  christos   ent->index = -1;
     77      1.1  christos   ent->next = NULL;
     78      1.1  christos 
     79      1.1  christos   return ent;
     80      1.1  christos }
     81      1.1  christos 
     82      1.1  christos /* Multiple tables are supported, although currently only one table is
     83      1.1  christos    in use.  N.B. there are still some functions have the table name
     84      1.1  christos    'aarch64_opcode_table' hard-coded in, e.g. print_find_next_opcode;
     85      1.1  christos    therefore some amount of work needs to be done if the full support
     86      1.1  christos    for multiple tables needs to be enabled.  */
     87      1.1  christos static const struct aarch64_opcode *aarch64_opcode_tables[] =
     88      1.1  christos {aarch64_opcode_table};
     89      1.1  christos 
     90      1.1  christos /* Use top 2 bits to indiate which table.  */
     91      1.1  christos static unsigned int
     92      1.1  christos initialize_index (const struct aarch64_opcode* table)
     93      1.1  christos {
     94      1.1  christos   int i;
     95      1.1  christos   const int num_of_tables = sizeof (aarch64_opcode_tables)
     96      1.1  christos     / sizeof (struct aarch64_opcode *);
     97      1.1  christos   for (i = 0; i < num_of_tables; ++i)
     98      1.1  christos     if (table == aarch64_opcode_tables [i])
     99      1.1  christos       break;
    100      1.1  christos   if (i == num_of_tables)
    101      1.1  christos     abort ();
    102      1.1  christos   return (unsigned int)i << 30;
    103      1.1  christos }
    104      1.1  christos 
    105      1.1  christos static inline const struct aarch64_opcode *
    106      1.1  christos index2table (unsigned int index)
    107      1.1  christos {
    108      1.1  christos   return aarch64_opcode_tables[(index >> 30) & 0x3];
    109      1.1  christos }
    110      1.1  christos 
    111      1.1  christos static inline unsigned int
    112      1.1  christos real_index (unsigned int index)
    113      1.1  christos {
    114      1.1  christos   return index & ((1 << 30) - 1);
    115      1.1  christos }
    116      1.1  christos 
    117      1.1  christos /* Given OPCODE_NODE, return the corresponding aarch64_opcode*.  */
    118      1.1  christos static const aarch64_opcode*
    119      1.1  christos get_aarch64_opcode (const opcode_node *opcode_node)
    120      1.1  christos {
    121      1.1  christos   if (opcode_node == NULL)
    122      1.1  christos     return NULL;
    123      1.1  christos   return &index2table (opcode_node->index)[real_index (opcode_node->index)];
    124      1.1  christos }
    125      1.1  christos 
    126      1.1  christos static void
    127      1.1  christos read_table (const struct aarch64_opcode* table)
    128      1.1  christos {
    129      1.1  christos   const struct aarch64_opcode *ent = table;
    130      1.1  christos   opcode_node **new_ent;
    131      1.1  christos   unsigned int index = initialize_index (table);
    132      1.1  christos 
    133      1.1  christos   if (!ent->name)
    134      1.1  christos     return;
    135      1.1  christos 
    136      1.1  christos   new_ent = &opcode_nodes_head.next;
    137      1.1  christos 
    138      1.1  christos   while (*new_ent)
    139      1.1  christos     new_ent = &(*new_ent)->next;
    140      1.1  christos 
    141      1.1  christos   do
    142      1.1  christos     {
    143      1.1  christos       /* F_PSEUDO needs to be used together with F_ALIAS to indicate an alias
    144      1.1  christos 	 opcode is a programmer friendly pseudo instruction available only in
    145      1.1  christos 	 the assembly code (thus will not show up in the disassembly).  */
    146  1.1.1.4  christos       assert (!pseudo_opcode_p (ent) || alias_opcode_p (ent));
    147      1.1  christos       /* Skip alias (inc. pseudo) opcode.  */
    148  1.1.1.4  christos       if (alias_opcode_p (ent))
    149      1.1  christos 	{
    150      1.1  christos 	  index++;
    151      1.1  christos 	  continue;
    152      1.1  christos 	}
    153      1.1  christos       *new_ent = new_opcode_node ();
    154      1.1  christos       (*new_ent)->opcode = ent->opcode;
    155      1.1  christos       (*new_ent)->mask = ent->mask;
    156      1.1  christos       (*new_ent)->index = index++;
    157      1.1  christos       new_ent = &((*new_ent)->next);
    158      1.1  christos     } while ((++ent)->name);
    159      1.1  christos }
    160      1.1  christos 
    161      1.1  christos static inline void
    162      1.1  christos print_one_opcode_node (opcode_node* ent)
    163      1.1  christos {
    164      1.1  christos   printf ("%s\t%08x\t%08x\t%d\n", get_aarch64_opcode (ent)->name,
    165      1.1  christos 	  get_aarch64_opcode (ent)->opcode, get_aarch64_opcode (ent)->mask,
    166      1.1  christos 	  (int)real_index (ent->index));
    167      1.1  christos }
    168      1.1  christos 
    169      1.1  christos /* As an internal debugging utility, print out the list of nodes pointed
    170      1.1  christos    by opcode_nodes_head.  */
    171      1.1  christos static void
    172      1.1  christos print_opcode_nodes (void)
    173      1.1  christos {
    174      1.1  christos   opcode_node* ent = opcode_nodes_head.next;
    175      1.1  christos   printf ("print_opcode_nodes table:\n");
    176      1.1  christos   while (ent)
    177      1.1  christos     {
    178      1.1  christos       print_one_opcode_node (ent);
    179      1.1  christos       ent = ent->next;
    180      1.1  christos     }
    181      1.1  christos }
    182      1.1  christos 
    183      1.1  christos static struct bittree*
    184      1.1  christos new_bittree_node (void)
    185      1.1  christos {
    186      1.1  christos   struct bittree* node;
    187      1.1  christos   node = malloc (sizeof (struct bittree));
    188      1.1  christos   if (!node)
    189      1.1  christos     abort ();
    190      1.1  christos   node->bitno = -1;
    191      1.1  christos   node->bits[0] = NULL;
    192      1.1  christos   node->bits[1] = NULL;
    193      1.1  christos   return node;
    194      1.1  christos }
    195      1.1  christos 
    196      1.1  christos /* The largest number of opcode entries that exist at a leaf node of the
    197      1.1  christos    decoding decision tree.  The reason that there can be more than one
    198      1.1  christos    opcode entry is because some opcodes have shared field that is partially
    199      1.1  christos    constrained and thus cannot be fully isolated using the algorithm
    200      1.1  christos    here.  */
    201      1.1  christos static int max_num_opcodes_at_leaf_node = 0;
    202      1.1  christos 
    203      1.1  christos /* Given a list of opcodes headed by *OPCODE, try to establish one bit that
    204      1.1  christos    is shared by all the opcodes in the list as one of base opcode bits.  If
    205      1.1  christos    such a bit is found, divide the list of the opcodes into two based on the
    206      1.1  christos    value of the bit.
    207      1.1  christos 
    208      1.1  christos    Store the bit number in BITTREE->BITNO if the division succeeds.  If unable
    209      1.1  christos    to determine such a bit or there is only one opcode in the list, the list
    210      1.1  christos    is decided to be undividable and OPCODE will be assigned to BITTREE->LIST.
    211      1.1  christos 
    212      1.1  christos    The function recursively call itself until OPCODE is undividable.
    213  1.1.1.2  christos 
    214      1.1  christos    N.B. the nature of this algrithm determines that given any value in the
    215      1.1  christos    32-bit space, the computed decision tree will always be able to find one or
    216      1.1  christos    more opcodes entries for it, regardless whether there is a valid instruction
    217      1.1  christos    defined for this value or not.  In order to detect the undefined values,
    218      1.1  christos    when the caller obtains the opcode entry/entries, it should at least compare
    219      1.1  christos    the bit-wise AND result of the value and the mask with the base opcode
    220      1.1  christos    value; if the two are different, it means that the value is undefined
    221      1.1  christos    (although the value may be still undefined when the comparison is the same,
    222      1.1  christos    in which case call aarch64_opcode_decode to carry out further checks).  */
    223      1.1  christos 
    224      1.1  christos static void
    225      1.1  christos divide_table_1 (struct bittree *bittree, opcode_node *opcode)
    226      1.1  christos {
    227      1.1  christos   aarch64_insn mask_and;
    228      1.1  christos   opcode_node *ent;
    229      1.1  christos   unsigned int bitno;
    230      1.1  christos   aarch64_insn bitmask;
    231      1.1  christos   opcode_node list0, list1, **ptr0, **ptr1;
    232      1.1  christos   static int depth = 0;
    233      1.1  christos 
    234      1.1  christos   ++depth;
    235      1.1  christos 
    236      1.1  christos   if (debug)
    237      1.1  christos     printf ("Enter into depth %d\n", depth);
    238      1.1  christos 
    239      1.1  christos   assert (opcode != NULL);
    240      1.1  christos 
    241      1.1  christos   /* Succeed when there is only one opcode left.  */
    242      1.1  christos   if (!opcode->next)
    243      1.1  christos     {
    244      1.1  christos       if (debug)
    245      1.1  christos 	{
    246      1.1  christos 	  printf ("opcode isolated:\n");
    247      1.1  christos 	  print_one_opcode_node (opcode);
    248      1.1  christos 	}
    249      1.1  christos       goto divide_table_1_finish;
    250      1.1  christos     }
    251      1.1  christos 
    252      1.1  christos divide_table_1_try_again:
    253      1.1  christos   mask_and = -1;
    254      1.1  christos   ent = opcode;
    255      1.1  christos   while (ent)
    256      1.1  christos     {
    257      1.1  christos       mask_and &= ent->mask;
    258      1.1  christos       ent = ent->next;
    259      1.1  christos     }
    260      1.1  christos 
    261      1.1  christos   if (debug)
    262      1.1  christos     printf ("mask and result: %08x\n", (unsigned int)mask_and);
    263      1.1  christos 
    264      1.1  christos   /* If no more bit to look into, we have to accept the reality then.  */
    265      1.1  christos   if (!mask_and)
    266      1.1  christos     {
    267      1.1  christos       int i;
    268      1.1  christos       opcode_node *ptr;
    269      1.1  christos       if (debug)
    270      1.1  christos 	{
    271      1.1  christos 	  ptr = opcode;
    272      1.1  christos 	  printf ("Isolated opcode group:\n");
    273      1.1  christos 	  do {
    274      1.1  christos 	      print_one_opcode_node (ptr);
    275      1.1  christos 	      ptr = ptr->next;
    276      1.1  christos 	  } while (ptr);
    277      1.1  christos 	}
    278      1.1  christos       /* Count the number of opcodes.  */
    279      1.1  christos       for (i = 0, ptr = opcode; ptr; ++i)
    280      1.1  christos 	ptr = ptr->next;
    281      1.1  christos       if (i > max_num_opcodes_at_leaf_node)
    282      1.1  christos 	max_num_opcodes_at_leaf_node = i;
    283      1.1  christos       goto divide_table_1_finish;
    284      1.1  christos     }
    285      1.1  christos 
    286      1.1  christos   /* Pick up the right most bit that is 1.  */
    287      1.1  christos   bitno = 0;
    288      1.1  christos   while (!(mask_and & (1 << bitno)))
    289      1.1  christos     ++bitno;
    290      1.1  christos   bitmask = (1 << bitno);
    291      1.1  christos 
    292      1.1  christos   if (debug)
    293      1.1  christos     printf ("use bit %d\n", bitno);
    294      1.1  christos 
    295      1.1  christos   /* Record in the bittree.  */
    296      1.1  christos   bittree->bitno = bitno;
    297      1.1  christos 
    298      1.1  christos   /* Get two new opcode lists; adjust their masks.  */
    299      1.1  christos   list0.next = NULL;
    300      1.1  christos   list1.next = NULL;
    301      1.1  christos   ptr0 = &list0.next;
    302      1.1  christos   ptr1 = &list1.next;
    303      1.1  christos   ent = opcode;
    304      1.1  christos   while (ent)
    305      1.1  christos     {
    306      1.1  christos       if (ent->opcode & bitmask)
    307      1.1  christos 	{
    308      1.1  christos 	  ent->mask &= (~bitmask);
    309      1.1  christos 	  *ptr1 = ent;
    310      1.1  christos 	  ent = ent->next;
    311      1.1  christos 	  (*ptr1)->next = NULL;
    312      1.1  christos 	  ptr1 = &(*ptr1)->next;
    313      1.1  christos 	}
    314      1.1  christos       else
    315      1.1  christos 	{
    316      1.1  christos 	  ent->mask &= (~bitmask);
    317      1.1  christos 	  *ptr0 = ent;
    318      1.1  christos 	  ent = ent->next;
    319      1.1  christos 	  (*ptr0)->next = NULL;
    320      1.1  christos 	  ptr0 = &(*ptr0)->next;
    321      1.1  christos 	}
    322      1.1  christos     }
    323      1.1  christos 
    324      1.1  christos   /* If BITNO can NOT divide the opcode group, try next bit.  */
    325      1.1  christos   if (list0.next == NULL)
    326      1.1  christos     {
    327      1.1  christos       opcode = list1.next;
    328      1.1  christos       goto divide_table_1_try_again;
    329      1.1  christos     }
    330      1.1  christos   else if (list1.next == NULL)
    331      1.1  christos     {
    332      1.1  christos       opcode = list0.next;
    333      1.1  christos       goto divide_table_1_try_again;
    334      1.1  christos     }
    335      1.1  christos 
    336      1.1  christos   /* Further divide.  */
    337      1.1  christos   bittree->bits[0] = new_bittree_node ();
    338      1.1  christos   bittree->bits[1] = new_bittree_node ();
    339      1.1  christos   divide_table_1 (bittree->bits[0], list0.next);
    340      1.1  christos   divide_table_1 (bittree->bits[1], list1.next);
    341      1.1  christos 
    342      1.1  christos divide_table_1_finish:
    343      1.1  christos   if (debug)
    344      1.1  christos     printf ("Leave from depth %d\n", depth);
    345      1.1  christos   --depth;
    346      1.1  christos 
    347      1.1  christos   /* Record the opcode entries on this leaf node.  */
    348      1.1  christos   bittree->list = opcode;
    349      1.1  christos 
    350      1.1  christos   return;
    351      1.1  christos }
    352      1.1  christos 
    353      1.1  christos /* Call divide_table_1 to divide the all the opcodes and thus create the
    354      1.1  christos    decoding decision tree.  */
    355  1.1.1.2  christos static struct bittree *
    356      1.1  christos divide_table (void)
    357      1.1  christos {
    358      1.1  christos   struct bittree *bittree = new_bittree_node ();
    359      1.1  christos   divide_table_1 (bittree, opcode_nodes_head.next);
    360      1.1  christos   return bittree;
    361      1.1  christos }
    362      1.1  christos 
    363      1.1  christos /* Read in all of the tables, create the decoding decision tree and return
    364      1.1  christos    the tree root.  */
    365  1.1.1.2  christos static struct bittree *
    366      1.1  christos initialize_decoder_tree (void)
    367      1.1  christos {
    368      1.1  christos   int i;
    369      1.1  christos   const int num_of_tables = (sizeof (aarch64_opcode_tables)
    370      1.1  christos 			     / sizeof (struct aarch64_opcode *));
    371      1.1  christos   for (i = 0; i < num_of_tables; ++i)
    372      1.1  christos     read_table (aarch64_opcode_tables [i]);
    373      1.1  christos   if (debug)
    374      1.1  christos     print_opcode_nodes ();
    375      1.1  christos   return divide_table ();
    376      1.1  christos }
    377      1.1  christos 
    378      1.1  christos static void __attribute__ ((format (printf, 2, 3)))
    379      1.1  christos indented_print (unsigned int indent, const char *format, ...)
    380      1.1  christos {
    381      1.1  christos   va_list ap;
    382      1.1  christos   va_start (ap, format);
    383  1.1.1.4  christos   printf ("%*s", (int) indent, "");
    384      1.1  christos   vprintf (format, ap);
    385      1.1  christos   va_end (ap);
    386      1.1  christos }
    387      1.1  christos 
    388      1.1  christos /* N.B. read the comment above divide_table_1 for the reason why the generated
    389      1.1  christos    decision tree function never returns NULL.  */
    390      1.1  christos 
    391      1.1  christos static void
    392      1.1  christos print_decision_tree_1 (unsigned int indent, struct bittree* bittree)
    393      1.1  christos {
    394      1.1  christos   /* PATTERN is only used to generate comment in the code.  */
    395      1.1  christos   static char pattern[33] = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx";
    396  1.1.1.4  christos   /* Low bits in PATTERN will be printed first which then look as the high
    397  1.1.1.4  christos      bits in comment.  We need to reverse the index to get correct print.  */
    398  1.1.1.4  christos   unsigned int msb = sizeof (pattern) - 2;
    399      1.1  christos   assert (bittree != NULL);
    400      1.1  christos 
    401      1.1  christos   /* Leaf node located.  */
    402      1.1  christos   if (bittree->bits[0] == NULL && bittree->bits[1] == NULL)
    403      1.1  christos     {
    404      1.1  christos       assert (bittree->list != NULL);
    405      1.1  christos       indented_print (indent, "/* 33222222222211111111110000000000\n");
    406      1.1  christos       indented_print (indent, "   10987654321098765432109876543210\n");
    407      1.1  christos       indented_print (indent, "   %s\n", pattern);
    408      1.1  christos       indented_print (indent, "   %s.  */\n",
    409      1.1  christos 		      get_aarch64_opcode (bittree->list)->name);
    410      1.1  christos       indented_print (indent, "return %u;\n",
    411      1.1  christos 		      real_index (bittree->list->index));
    412      1.1  christos       return;
    413      1.1  christos     }
    414      1.1  christos 
    415      1.1  christos   /* Walk down the decoder tree.  */
    416      1.1  christos   indented_print (indent, "if (((word >> %d) & 0x1) == 0)\n", bittree->bitno);
    417      1.1  christos   indented_print (indent, "  {\n");
    418  1.1.1.4  christos   pattern[msb - bittree->bitno] = '0';
    419      1.1  christos   print_decision_tree_1 (indent + 4, bittree->bits[0]);
    420      1.1  christos   indented_print (indent, "  }\n");
    421      1.1  christos   indented_print (indent, "else\n");
    422      1.1  christos   indented_print (indent, "  {\n");
    423  1.1.1.4  christos   pattern[msb - bittree->bitno] = '1';
    424      1.1  christos   print_decision_tree_1 (indent + 4, bittree->bits[1]);
    425      1.1  christos   indented_print (indent, "  }\n");
    426  1.1.1.4  christos   pattern[msb - bittree->bitno] = 'x';
    427      1.1  christos }
    428      1.1  christos 
    429      1.1  christos /* Generate aarch64_opcode_lookup in C code to the standard output.  */
    430      1.1  christos 
    431      1.1  christos static void
    432      1.1  christos print_decision_tree (struct bittree* bittree)
    433      1.1  christos {
    434      1.1  christos   if (debug)
    435      1.1  christos     printf ("Enter print_decision_tree\n");
    436      1.1  christos 
    437      1.1  christos   printf ("/* Called by aarch64_opcode_lookup.  */\n\n");
    438      1.1  christos 
    439      1.1  christos   printf ("static int\n");
    440      1.1  christos   printf ("aarch64_opcode_lookup_1 (uint32_t word)\n");
    441      1.1  christos   printf ("{\n");
    442      1.1  christos 
    443      1.1  christos   print_decision_tree_1 (2, bittree);
    444      1.1  christos 
    445      1.1  christos   printf ("}\n\n");
    446      1.1  christos 
    447      1.1  christos 
    448      1.1  christos   printf ("/* Lookup opcode WORD in the opcode table.  N.B. all alias\n");
    449      1.1  christos   printf ("   opcodes are ignored here.  */\n\n");
    450      1.1  christos 
    451      1.1  christos   printf ("const aarch64_opcode *\n");
    452      1.1  christos   printf ("aarch64_opcode_lookup (uint32_t word)\n");
    453      1.1  christos   printf ("{\n");
    454      1.1  christos   printf ("  return aarch64_opcode_table + aarch64_opcode_lookup_1 (word);\n");
    455      1.1  christos   printf ("}\n");
    456      1.1  christos }
    457      1.1  christos 
    458      1.1  christos static void
    459      1.1  christos print_find_next_opcode_1 (struct bittree* bittree)
    460      1.1  christos {
    461      1.1  christos   assert (bittree != NULL);
    462      1.1  christos 
    463      1.1  christos   /* Leaf node located.  */
    464      1.1  christos   if (bittree->bits[0] == NULL && bittree->bits[1] == NULL)
    465      1.1  christos     {
    466      1.1  christos       assert (bittree->list != NULL);
    467      1.1  christos       /* Find multiple opcode entries in one leaf node.  */
    468      1.1  christos       if (bittree->list->next != NULL)
    469      1.1  christos 	{
    470      1.1  christos 	  opcode_node *list = bittree->list;
    471      1.1  christos 	  while (list != NULL)
    472      1.1  christos 	    {
    473      1.1  christos 	      const aarch64_opcode *curr = get_aarch64_opcode (list);
    474      1.1  christos 	      const aarch64_opcode *next = get_aarch64_opcode (list->next);
    475      1.1  christos 
    476      1.1  christos 	      printf ("    case %u: ",
    477      1.1  christos 		      (unsigned int)(curr - aarch64_opcode_table));
    478      1.1  christos 	      if (list->next != NULL)
    479      1.1  christos 		{
    480      1.1  christos 		  printf ("value = %u; break;\t", real_index (list->next->index));
    481      1.1  christos 		  printf ("/* %s --> %s.  */\n", curr->name, next->name);
    482      1.1  christos 		}
    483      1.1  christos 	      else
    484      1.1  christos 		{
    485      1.1  christos 		  printf ("return NULL;\t\t");
    486      1.1  christos 		  printf ("/* %s --> NULL.  */\n", curr->name);
    487      1.1  christos 		}
    488      1.1  christos 
    489      1.1  christos 	      list = list->next;
    490      1.1  christos 	    }
    491      1.1  christos 	}
    492      1.1  christos       return;
    493      1.1  christos     }
    494      1.1  christos 
    495      1.1  christos   /* Walk down the decoder tree.  */
    496      1.1  christos   print_find_next_opcode_1 (bittree->bits[0]);
    497      1.1  christos   print_find_next_opcode_1 (bittree->bits[1]);
    498      1.1  christos }
    499      1.1  christos 
    500      1.1  christos /* Generate aarch64_find_next_opcode in C code to the standard output.  */
    501      1.1  christos 
    502      1.1  christos static void
    503      1.1  christos print_find_next_opcode (struct bittree* bittree)
    504      1.1  christos {
    505      1.1  christos   if (debug)
    506      1.1  christos     printf ("Enter print_find_next_opcode\n");
    507      1.1  christos 
    508      1.1  christos   printf ("\n");
    509      1.1  christos   printf ("const aarch64_opcode *\n");
    510      1.1  christos   printf ("aarch64_find_next_opcode (const aarch64_opcode *opcode)\n");
    511      1.1  christos   printf ("{\n");
    512      1.1  christos   printf ("  /* Use the index as the key to locate the next opcode.  */\n");
    513      1.1  christos   printf ("  int key = opcode - aarch64_opcode_table;\n");
    514      1.1  christos   printf ("  int value;\n");
    515      1.1  christos   printf ("  switch (key)\n");
    516      1.1  christos   printf ("    {\n");
    517      1.1  christos 
    518      1.1  christos   print_find_next_opcode_1 (bittree);
    519      1.1  christos 
    520      1.1  christos   printf ("    default: return NULL;\n");
    521      1.1  christos   printf ("    }\n\n");
    522      1.1  christos 
    523      1.1  christos   printf ("  return aarch64_opcode_table + value;\n");
    524      1.1  christos   printf ("}\n");
    525      1.1  christos }
    526      1.1  christos 
    527      1.1  christos /* Release the dynamic memory resource allocated for the generation of the
    528      1.1  christos    decoder tree.  */
    529      1.1  christos 
    530      1.1  christos static void
    531      1.1  christos release_resource_decoder_tree (struct bittree* bittree)
    532      1.1  christos {
    533      1.1  christos   assert (bittree != NULL);
    534      1.1  christos 
    535      1.1  christos   /* Leaf node located.  */
    536      1.1  christos   if (bittree->bits[0] == NULL && bittree->bits[1] == NULL)
    537      1.1  christos     {
    538      1.1  christos       assert (bittree->list != NULL);
    539      1.1  christos       /* Free opcode_nodes.  */
    540      1.1  christos       opcode_node *list = bittree->list;
    541      1.1  christos       while (list != NULL)
    542      1.1  christos 	{
    543      1.1  christos 	  opcode_node *next = list->next;
    544      1.1  christos 	  free (list);
    545      1.1  christos 	  list = next;
    546      1.1  christos 	}
    547      1.1  christos       /* Free the tree node.  */
    548      1.1  christos       free (bittree);
    549      1.1  christos       return;
    550      1.1  christos     }
    551      1.1  christos 
    552      1.1  christos   /* Walk down the decoder tree.  */
    553      1.1  christos   release_resource_decoder_tree (bittree->bits[0]);
    554      1.1  christos   release_resource_decoder_tree (bittree->bits[1]);
    555      1.1  christos 
    556      1.1  christos   /* Free the tree node.  */
    557      1.1  christos   free (bittree);
    558      1.1  christos }
    559      1.1  christos 
    560      1.1  christos /* Generate aarch64_find_real_opcode in C code to the standard output.
    561      1.1  christos    TABLE points to the alias info table, while NUM indicates the number of
    562      1.1  christos    entries in the table.  */
    563      1.1  christos 
    564      1.1  christos static void
    565      1.1  christos print_find_real_opcode (const opcode_node *table, int num)
    566      1.1  christos {
    567      1.1  christos   int i;
    568      1.1  christos 
    569      1.1  christos   if (debug)
    570      1.1  christos     printf ("Enter print_find_real_opcode\n");
    571      1.1  christos 
    572      1.1  christos   printf ("\n");
    573      1.1  christos   printf ("const aarch64_opcode *\n");
    574      1.1  christos   printf ("aarch64_find_real_opcode (const aarch64_opcode *opcode)\n");
    575      1.1  christos   printf ("{\n");
    576      1.1  christos   printf ("  /* Use the index as the key to locate the real opcode.  */\n");
    577      1.1  christos   printf ("  int key = opcode - aarch64_opcode_table;\n");
    578      1.1  christos   printf ("  int value;\n");
    579      1.1  christos   printf ("  switch (key)\n");
    580      1.1  christos   printf ("    {\n");
    581      1.1  christos 
    582      1.1  christos   for (i = 0; i < num; ++i)
    583      1.1  christos     {
    584      1.1  christos       const opcode_node *real = table + i;
    585      1.1  christos       const opcode_node *alias = real->next;
    586      1.1  christos       for (; alias; alias = alias->next)
    587      1.1  christos 	printf ("    case %u:\t/* %s */\n", real_index (alias->index),
    588      1.1  christos 		get_aarch64_opcode (alias)->name);
    589      1.1  christos       printf ("      value = %u;\t/* --> %s.  */\n", real_index (real->index),
    590      1.1  christos 	      get_aarch64_opcode (real)->name);
    591      1.1  christos       printf ("      break;\n");
    592      1.1  christos     }
    593      1.1  christos 
    594      1.1  christos   printf ("    default: return NULL;\n");
    595      1.1  christos   printf ("    }\n\n");
    596      1.1  christos 
    597      1.1  christos   printf ("  return aarch64_opcode_table + value;\n");
    598      1.1  christos   printf ("}\n");
    599      1.1  christos }
    600      1.1  christos 
    601      1.1  christos /* Generate aarch64_find_alias_opcode in C code to the standard output.
    602      1.1  christos    TABLE points to the alias info table, while NUM indicates the number of
    603      1.1  christos    entries in the table.  */
    604      1.1  christos 
    605      1.1  christos static void
    606      1.1  christos print_find_alias_opcode (const opcode_node *table, int num)
    607      1.1  christos {
    608      1.1  christos   int i;
    609      1.1  christos 
    610      1.1  christos   if (debug)
    611      1.1  christos     printf ("Enter print_find_alias_opcode\n");
    612      1.1  christos 
    613      1.1  christos   printf ("\n");
    614      1.1  christos   printf ("const aarch64_opcode *\n");
    615      1.1  christos   printf ("aarch64_find_alias_opcode (const aarch64_opcode *opcode)\n");
    616      1.1  christos   printf ("{\n");
    617      1.1  christos   printf ("  /* Use the index as the key to locate the alias opcode.  */\n");
    618      1.1  christos   printf ("  int key = opcode - aarch64_opcode_table;\n");
    619      1.1  christos   printf ("  int value;\n");
    620      1.1  christos   printf ("  switch (key)\n");
    621      1.1  christos   printf ("    {\n");
    622      1.1  christos 
    623      1.1  christos   for (i = 0; i < num; ++i)
    624      1.1  christos     {
    625      1.1  christos       const opcode_node *node = table + i;
    626      1.1  christos       assert (node->next);
    627      1.1  christos       printf ("    case %u: value = %u; break;", real_index (node->index),
    628      1.1  christos 	      real_index (node->next->index));
    629      1.1  christos       printf ("\t/* %s --> %s.  */\n", get_aarch64_opcode (node)->name,
    630      1.1  christos 	      get_aarch64_opcode (node->next)->name);
    631      1.1  christos     }
    632      1.1  christos 
    633      1.1  christos   printf ("    default: return NULL;\n");
    634      1.1  christos   printf ("    }\n\n");
    635      1.1  christos 
    636      1.1  christos   printf ("  return aarch64_opcode_table + value;\n");
    637      1.1  christos   printf ("}\n");
    638      1.1  christos }
    639      1.1  christos 
    640      1.1  christos /* Generate aarch64_find_next_alias_opcode in C code to the standard output.
    641      1.1  christos    TABLE points to the alias info table, while NUM indicates the number of
    642      1.1  christos    entries in the table.  */
    643      1.1  christos 
    644      1.1  christos static void
    645      1.1  christos print_find_next_alias_opcode (const opcode_node *table, int num)
    646      1.1  christos {
    647      1.1  christos   int i;
    648      1.1  christos 
    649      1.1  christos   if (debug)
    650      1.1  christos     printf ("Enter print_find_next_alias_opcode\n");
    651      1.1  christos 
    652      1.1  christos   printf ("\n");
    653      1.1  christos   printf ("const aarch64_opcode *\n");
    654      1.1  christos   printf ("aarch64_find_next_alias_opcode (const aarch64_opcode *opcode)\n");
    655      1.1  christos   printf ("{\n");
    656      1.1  christos   printf ("  /* Use the index as the key to locate the next opcode.  */\n");
    657      1.1  christos   printf ("  int key = opcode - aarch64_opcode_table;\n");
    658      1.1  christos   printf ("  int value;\n");
    659      1.1  christos   printf ("  switch (key)\n");
    660      1.1  christos   printf ("    {\n");
    661      1.1  christos 
    662      1.1  christos   for (i = 0; i < num; ++i)
    663      1.1  christos     {
    664      1.1  christos       const opcode_node *node = table + i;
    665      1.1  christos       assert (node->next);
    666      1.1  christos       if (node->next->next == NULL)
    667      1.1  christos 	continue;
    668      1.1  christos       while (node->next->next)
    669      1.1  christos 	{
    670      1.1  christos 	  printf ("    case %u: value = %u; break;", real_index (node->next->index),
    671      1.1  christos 		 real_index (node->next->next->index));
    672      1.1  christos 	  printf ("\t/* %s --> %s.  */\n",
    673      1.1  christos 		  get_aarch64_opcode (node->next)->name,
    674      1.1  christos 		  get_aarch64_opcode (node->next->next)->name);
    675      1.1  christos 	  node = node->next;
    676      1.1  christos 	}
    677      1.1  christos     }
    678      1.1  christos 
    679      1.1  christos   printf ("    default: return NULL;\n");
    680      1.1  christos   printf ("    }\n\n");
    681      1.1  christos 
    682      1.1  christos   printf ("  return aarch64_opcode_table + value;\n");
    683      1.1  christos   printf ("}\n");
    684      1.1  christos }
    685      1.1  christos 
    686      1.1  christos /* Given OPCODE, establish and return a link list of alias nodes in the
    687      1.1  christos    preferred order.  */
    688      1.1  christos 
    689      1.1  christos opcode_node *
    690      1.1  christos find_alias_opcode (const aarch64_opcode *opcode)
    691      1.1  christos {
    692      1.1  christos   int i;
    693  1.1.1.4  christos   /* Assume maximum of 32 disassemble preference candidates.  */
    694  1.1.1.4  christos   const int max_num_aliases = 32;
    695      1.1  christos   const aarch64_opcode *ent;
    696  1.1.1.2  christos   const aarch64_opcode *preferred[max_num_aliases + 1];
    697      1.1  christos   opcode_node head, **next;
    698      1.1  christos 
    699      1.1  christos   assert (opcode_has_alias (opcode));
    700      1.1  christos 
    701      1.1  christos   i = 0;
    702  1.1.1.2  christos   if (opcode->name != NULL)
    703  1.1.1.2  christos     preferred[i++] = opcode;
    704      1.1  christos   ent = aarch64_opcode_table;
    705      1.1  christos   while (ent->name != NULL)
    706      1.1  christos     {
    707      1.1  christos       /* The mask of an alias opcode must be equal to or a super-set (i.e.
    708      1.1  christos 	 more constrained) of that of the aliased opcode; so is the base
    709      1.1  christos 	 opcode value.  */
    710  1.1.1.4  christos       if (alias_opcode_p (ent)
    711      1.1  christos 	  && (ent->mask & opcode->mask) == opcode->mask
    712      1.1  christos 	  && (opcode->mask & ent->opcode) == (opcode->mask & opcode->opcode))
    713      1.1  christos 	{
    714      1.1  christos 	  assert (i < max_num_aliases);
    715      1.1  christos 	  preferred[i++] = ent;
    716      1.1  christos 	  if (debug)
    717      1.1  christos 	    printf ("found %s for %s.", ent->name, opcode->name);
    718      1.1  christos 	}
    719      1.1  christos       ++ent;
    720      1.1  christos     }
    721      1.1  christos 
    722      1.1  christos   if (debug)
    723      1.1  christos     {
    724      1.1  christos       int m;
    725      1.1  christos       printf ("un-orderd list: ");
    726      1.1  christos       for (m = 0; m < i; ++m)
    727      1.1  christos 	printf ("%s, ", preferred[m]->name);
    728      1.1  christos       printf ("\n");
    729      1.1  christos     }
    730      1.1  christos 
    731      1.1  christos   /* There must be at least one alias.  */
    732      1.1  christos   assert (i >= 1);
    733      1.1  christos 
    734      1.1  christos   /* Sort preferred array according to the priority (from the lowest to the
    735      1.1  christos      highest.  */
    736      1.1  christos   if (i > 1)
    737      1.1  christos     {
    738      1.1  christos       int j, k;
    739      1.1  christos       for (j = 0; j < i - 1; ++j)
    740      1.1  christos 	{
    741      1.1  christos 	  for (k = 0; k < i - 1 - j; ++k)
    742      1.1  christos 	    {
    743      1.1  christos 	      const aarch64_opcode *t;
    744      1.1  christos 	      t = preferred [k+1];
    745      1.1  christos 	      if (opcode_priority (t) < opcode_priority (preferred [k]))
    746      1.1  christos 		{
    747      1.1  christos 		  preferred [k+1] = preferred [k];
    748      1.1  christos 		  preferred [k] = t;
    749      1.1  christos 		}
    750      1.1  christos 	    }
    751      1.1  christos 	}
    752      1.1  christos     }
    753      1.1  christos 
    754      1.1  christos   if (debug)
    755      1.1  christos     {
    756      1.1  christos       int m;
    757      1.1  christos       printf ("orderd list: ");
    758      1.1  christos       for (m = 0; m < i; ++m)
    759      1.1  christos 	printf ("%s, ", preferred[m]->name);
    760      1.1  christos       printf ("\n");
    761      1.1  christos     }
    762      1.1  christos 
    763      1.1  christos   /* Create a link-list of opcode_node with disassemble preference from
    764      1.1  christos      higher to lower.  */
    765      1.1  christos   next = &head.next;
    766      1.1  christos   --i;
    767      1.1  christos   while (i >= 0)
    768      1.1  christos     {
    769      1.1  christos       const aarch64_opcode *alias = preferred [i];
    770      1.1  christos       opcode_node *node = new_opcode_node ();
    771      1.1  christos 
    772      1.1  christos       if (debug)
    773      1.1  christos 	printf ("add %s.\n", alias->name);
    774      1.1  christos 
    775      1.1  christos       node->index = alias - aarch64_opcode_table;
    776      1.1  christos       *next = node;
    777      1.1  christos       next = &node->next;
    778      1.1  christos 
    779      1.1  christos       --i;
    780      1.1  christos     }
    781      1.1  christos   *next = NULL;
    782      1.1  christos 
    783      1.1  christos   return head.next;
    784      1.1  christos }
    785      1.1  christos 
    786      1.1  christos /* Create and return alias information.
    787      1.1  christos    Return the address of the created alias info table; return the number
    788      1.1  christos    of table entries in *NUM_PTR.  */
    789      1.1  christos 
    790      1.1  christos opcode_node *
    791      1.1  christos create_alias_info (int *num_ptr)
    792      1.1  christos {
    793      1.1  christos   int i, num;
    794      1.1  christos   opcode_node *ret;
    795      1.1  christos   const aarch64_opcode *ent;
    796      1.1  christos 
    797      1.1  christos   /* Calculate the total number of opcodes that have alias.  */
    798      1.1  christos   num = 0;
    799      1.1  christos   ent = aarch64_opcode_table;
    800      1.1  christos   while (ent->name != NULL)
    801      1.1  christos     {
    802      1.1  christos       if (opcode_has_alias (ent))
    803      1.1  christos 	{
    804      1.1  christos 	  /* Assert the alias relationship be flat-structured to keep
    805      1.1  christos 	     algorithms simple; not allow F_ALIAS and F_HAS_ALIAS both
    806      1.1  christos 	     specified.  */
    807      1.1  christos 	  assert (!alias_opcode_p (ent));
    808      1.1  christos 	  ++num;
    809      1.1  christos 	}
    810      1.1  christos       ++ent;
    811      1.1  christos     }
    812      1.1  christos   assert (num_ptr);
    813      1.1  christos   *num_ptr = num;
    814      1.1  christos 
    815      1.1  christos   /* The array of real opcodes that have alias(es).  */
    816      1.1  christos   ret = malloc (sizeof (opcode_node) * num);
    817      1.1  christos 
    818      1.1  christos   /* For each opcode, establish a list of alias nodes in a preferred
    819      1.1  christos      order.  */
    820      1.1  christos   for (i = 0, ent = aarch64_opcode_table; i < num; ++i, ++ent)
    821      1.1  christos     {
    822      1.1  christos       opcode_node *node = ret + i;
    823      1.1  christos       while (ent->name != NULL && !opcode_has_alias (ent))
    824      1.1  christos 	++ent;
    825      1.1  christos       assert (ent->name != NULL);
    826      1.1  christos       node->index = ent - aarch64_opcode_table;
    827      1.1  christos       node->next = find_alias_opcode (ent);
    828      1.1  christos       assert (node->next);
    829      1.1  christos     }
    830      1.1  christos   assert (i == num);
    831      1.1  christos 
    832      1.1  christos   return ret;
    833      1.1  christos }
    834      1.1  christos 
    835      1.1  christos /* Release the dynamic memory resource allocated for the generation of the
    836      1.1  christos    alias information.  */
    837      1.1  christos 
    838      1.1  christos void
    839      1.1  christos release_resource_alias_info (opcode_node *alias_info, int num)
    840      1.1  christos {
    841      1.1  christos   int i = 0;
    842      1.1  christos   opcode_node *node = alias_info;
    843      1.1  christos 
    844      1.1  christos   /* Free opcode_node list.  */
    845      1.1  christos   for (; i < num; ++i, ++node)
    846      1.1  christos     {
    847      1.1  christos       opcode_node *list = node->next;
    848      1.1  christos       do
    849      1.1  christos 	{
    850      1.1  christos 	  opcode_node *next = list->next;
    851      1.1  christos 	  free (list);
    852      1.1  christos 	  list = next;
    853      1.1  christos 	} while (list != NULL);
    854      1.1  christos     }
    855      1.1  christos 
    856      1.1  christos   /* Free opcode_node array.  */
    857      1.1  christos   free (alias_info);
    858      1.1  christos }
    859      1.1  christos 
    860      1.1  christos /* As a debugging utility, print out the result of the table division, although
    861      1.1  christos    it is not doing much this moment.  */
    862      1.1  christos static void
    863      1.1  christos print_divide_result (const struct bittree *bittree ATTRIBUTE_UNUSED)
    864      1.1  christos {
    865      1.1  christos   printf ("max_num_opcodes_at_leaf_node: %d\n", max_num_opcodes_at_leaf_node);
    866      1.1  christos   return;
    867      1.1  christos }
    868      1.1  christos 
    869      1.1  christos /* Structure to help generate the operand table.  */
    871      1.1  christos struct operand
    872      1.1  christos {
    873      1.1  christos   const char *class;
    874      1.1  christos   const char *inserter;
    875      1.1  christos   const char *extractor;
    876      1.1  christos   const char *str;
    877      1.1  christos   const char *flags;
    878      1.1  christos   const char *fields;
    879      1.1  christos   const char *desc;
    880      1.1  christos   unsigned processed : 1;
    881      1.1  christos   unsigned has_inserter : 1;
    882      1.1  christos   unsigned has_extractor : 1;
    883      1.1  christos };
    884      1.1  christos 
    885      1.1  christos typedef struct operand operand;
    886      1.1  christos 
    887      1.1  christos #ifdef X
    888      1.1  christos #undef X
    889      1.1  christos #endif
    890      1.1  christos 
    891      1.1  christos #ifdef Y
    892      1.1  christos #undef Y
    893      1.1  christos #endif
    894      1.1  christos 
    895      1.1  christos #ifdef F
    896      1.1  christos #undef F
    897      1.1  christos #endif
    898      1.1  christos 
    899      1.1  christos /* Get the operand information in strings.  */
    900      1.1  christos 
    901      1.1  christos static operand operands[] =
    902      1.1  christos {
    903      1.1  christos     {"NIL", "0", "0", "", "0", "{0}", "<none>", 0, 0, 0},
    904      1.1  christos #define F(...)	#__VA_ARGS__
    905      1.1  christos #define X(a,b,c,d,e,f,g)	\
    906      1.1  christos     {#a, #b, #c, d, #e, "{"f"}", g, 0, 0, 0},
    907      1.1  christos #define Y(a,b,d,e,f,g)		\
    908      1.1  christos     {#a, "ins_"#b, "ext_"#b, d, #e, "{"f"}", g, 0, 0, 0},
    909      1.1  christos     AARCH64_OPERANDS
    910      1.1  christos     {"NIL", "0", "0", "", "0", "{0}", "DUMMY", 0, 0, 0},
    911      1.1  christos };
    912      1.1  christos 
    913      1.1  christos #undef F
    914      1.1  christos #undef X
    915      1.1  christos 
    916      1.1  christos static void
    917      1.1  christos process_operand_table (void)
    918      1.1  christos {
    919      1.1  christos   int i;
    920      1.1  christos   operand *opnd;
    921      1.1  christos   const int num = sizeof (operands) / sizeof (operand);
    922      1.1  christos 
    923      1.1  christos   for (i = 0, opnd = operands; i < num; ++i, ++opnd)
    924      1.1  christos     {
    925      1.1  christos       opnd->has_inserter = opnd->inserter[0] != '0';
    926      1.1  christos       opnd->has_extractor = opnd->extractor[0] != '0';
    927      1.1  christos     }
    928      1.1  christos }
    929      1.1  christos 
    930      1.1  christos /* Generate aarch64_operands in C to the standard output.  */
    931      1.1  christos 
    932      1.1  christos static void
    933      1.1  christos print_operand_table (void)
    934      1.1  christos {
    935      1.1  christos   int i;
    936      1.1  christos   operand *opnd;
    937      1.1  christos   const int num = sizeof (operands) / sizeof (operand);
    938      1.1  christos 
    939      1.1  christos   if (debug)
    940      1.1  christos     printf ("Enter print_operand_table\n");
    941      1.1  christos 
    942      1.1  christos   printf ("\n");
    943      1.1  christos   printf ("const struct aarch64_operand aarch64_operands[] =\n");
    944      1.1  christos   printf ("{\n");
    945      1.1  christos 
    946      1.1  christos   for (i = 0, opnd = operands; i < num; ++i, ++opnd)
    947      1.1  christos     {
    948      1.1  christos       char flags[256];
    949      1.1  christos       flags[0] = '\0';
    950      1.1  christos       if (opnd->flags[0] != '0')
    951      1.1  christos 	sprintf (flags, "%s", opnd->flags);
    952      1.1  christos       if (opnd->has_inserter)
    953      1.1  christos 	{
    954      1.1  christos 	  if (flags[0] != '\0')
    955      1.1  christos 	    strcat (flags, " | ");
    956      1.1  christos 	  strcat (flags, "OPD_F_HAS_INSERTER");
    957      1.1  christos 	}
    958      1.1  christos       if (opnd->has_extractor)
    959      1.1  christos 	{
    960      1.1  christos 	  if (flags[0] != '\0')
    961      1.1  christos 	    strcat (flags, " | ");
    962      1.1  christos 	  strcat (flags, "OPD_F_HAS_EXTRACTOR");
    963      1.1  christos 	}
    964      1.1  christos       if (flags[0] == '\0')
    965      1.1  christos 	{
    966      1.1  christos 	  flags[0] = '0';
    967      1.1  christos 	  flags[1] = '\0';
    968      1.1  christos 	}
    969      1.1  christos     printf ("  {AARCH64_OPND_CLASS_%s, \"%s\", %s, %s, \"%s\"},\n",
    970      1.1  christos 	    opnd->class, opnd->str, flags, opnd->fields, opnd->desc);
    971      1.1  christos     }
    972      1.1  christos   printf ("};\n");
    973      1.1  christos }
    974      1.1  christos 
    975      1.1  christos /* Generate aarch64_insert_operand in C to the standard output.  */
    976      1.1  christos 
    977      1.1  christos static void
    978      1.1  christos print_operand_inserter (void)
    979      1.1  christos {
    980      1.1  christos   int i;
    981      1.1  christos   operand *opnd;
    982      1.1  christos   const int num = sizeof (operands) / sizeof (operand);
    983      1.1  christos 
    984      1.1  christos   if (debug)
    985      1.1  christos     printf ("Enter print_operand_inserter\n");
    986      1.1  christos 
    987      1.1  christos   printf ("\n");
    988      1.1  christos   printf ("const char*\n");
    989      1.1  christos   printf ("aarch64_insert_operand (const aarch64_operand *self,\n\
    990      1.1  christos 			   const aarch64_opnd_info *info,\n\
    991      1.1  christos 			   aarch64_insn *code, const aarch64_inst *inst)\n");
    992      1.1  christos   printf ("{\n");
    993      1.1  christos   printf ("  /* Use the index as the key.  */\n");
    994      1.1  christos   printf ("  int key = self - aarch64_operands;\n");
    995      1.1  christos   printf ("  switch (key)\n");
    996      1.1  christos   printf ("    {\n");
    997      1.1  christos 
    998      1.1  christos   for (i = 0, opnd = operands; i < num; ++i, ++opnd)
    999      1.1  christos     opnd->processed = 0;
   1000      1.1  christos 
   1001      1.1  christos   for (i = 0, opnd = operands; i < num; ++i, ++opnd)
   1002      1.1  christos     {
   1003      1.1  christos       if (!opnd->processed && opnd->has_inserter)
   1004      1.1  christos 	{
   1005      1.1  christos 	  int j = i + 1;
   1006      1.1  christos 	  const int len = strlen (opnd->inserter);
   1007      1.1  christos 	  operand *opnd2 = opnd + 1;
   1008      1.1  christos 	  printf ("    case %u:\n", (unsigned int)(opnd - operands));
   1009      1.1  christos 	  opnd->processed = 1;
   1010      1.1  christos 	  for (; j < num; ++j, ++opnd2)
   1011      1.1  christos 	    {
   1012      1.1  christos 	      if (!opnd2->processed
   1013      1.1  christos 		  && opnd2->has_inserter
   1014      1.1  christos 		  && len == strlen (opnd2->inserter)
   1015      1.1  christos 		  && strncmp (opnd->inserter, opnd2->inserter, len) == 0)
   1016      1.1  christos 		{
   1017      1.1  christos 		  printf ("    case %u:\n", (unsigned int)(opnd2 - operands));
   1018      1.1  christos 		  opnd2->processed = 1;
   1019      1.1  christos 		}
   1020      1.1  christos 	    }
   1021      1.1  christos 	  printf ("      return aarch64_%s (self, info, code, inst);\n",
   1022      1.1  christos 		  opnd->inserter);
   1023      1.1  christos 	}
   1024      1.1  christos     }
   1025      1.1  christos 
   1026      1.1  christos   printf ("    default: assert (0); abort ();\n");
   1027      1.1  christos   printf ("    }\n");
   1028      1.1  christos   printf ("}\n");
   1029      1.1  christos }
   1030      1.1  christos 
   1031      1.1  christos /* Generate aarch64_extract_operand in C to the standard output.  */
   1032      1.1  christos 
   1033      1.1  christos static void
   1034      1.1  christos print_operand_extractor (void)
   1035      1.1  christos {
   1036      1.1  christos   int i;
   1037      1.1  christos   operand *opnd;
   1038      1.1  christos   const int num = sizeof (operands) / sizeof (operand);
   1039      1.1  christos 
   1040      1.1  christos   if (debug)
   1041      1.1  christos     printf ("Enter print_operand_extractor\n");
   1042      1.1  christos 
   1043      1.1  christos   printf ("\n");
   1044      1.1  christos   printf ("int\n");
   1045      1.1  christos   printf ("aarch64_extract_operand (const aarch64_operand *self,\n\
   1046      1.1  christos 			   aarch64_opnd_info *info,\n\
   1047      1.1  christos 			   aarch64_insn code, const aarch64_inst *inst)\n");
   1048      1.1  christos   printf ("{\n");
   1049      1.1  christos   printf ("  /* Use the index as the key.  */\n");
   1050      1.1  christos   printf ("  int key = self - aarch64_operands;\n");
   1051      1.1  christos   printf ("  switch (key)\n");
   1052      1.1  christos   printf ("    {\n");
   1053      1.1  christos 
   1054      1.1  christos   for (i = 0, opnd = operands; i < num; ++i, ++opnd)
   1055      1.1  christos     opnd->processed = 0;
   1056      1.1  christos 
   1057      1.1  christos   for (i = 0, opnd = operands; i < num; ++i, ++opnd)
   1058      1.1  christos     {
   1059      1.1  christos       if (!opnd->processed && opnd->has_extractor)
   1060      1.1  christos 	{
   1061      1.1  christos 	  int j = i + 1;
   1062      1.1  christos 	  const int len = strlen (opnd->extractor);
   1063      1.1  christos 	  operand *opnd2 = opnd + 1;
   1064      1.1  christos 	  printf ("    case %u:\n", (unsigned int)(opnd - operands));
   1065      1.1  christos 	  opnd->processed = 1;
   1066      1.1  christos 	  for (; j < num; ++j, ++opnd2)
   1067      1.1  christos 	    {
   1068      1.1  christos 	      if (!opnd2->processed
   1069      1.1  christos 		  && opnd2->has_extractor
   1070      1.1  christos 		  && len == strlen (opnd2->extractor)
   1071      1.1  christos 		  && strncmp (opnd->extractor, opnd2->extractor, len) == 0)
   1072      1.1  christos 		{
   1073      1.1  christos 		  printf ("    case %u:\n", (unsigned int)(opnd2 - operands));
   1074      1.1  christos 		  opnd2->processed = 1;
   1075      1.1  christos 		}
   1076      1.1  christos 	    }
   1077      1.1  christos 	  printf ("      return aarch64_%s (self, info, code, inst);\n",
   1078      1.1  christos 		  opnd->extractor);
   1079      1.1  christos 	}
   1080      1.1  christos     }
   1081      1.1  christos 
   1082      1.1  christos   printf ("    default: assert (0); abort ();\n");
   1083      1.1  christos   printf ("    }\n");
   1084      1.1  christos   printf ("}\n");
   1085      1.1  christos }
   1086      1.1  christos 
   1087      1.1  christos /* Table indexed by opcode enumerator stores the index of the corresponding
   1089      1.1  christos    opcode entry in aarch64_opcode_table.  */
   1090      1.1  christos static unsigned op_enum_table [OP_TOTAL_NUM];
   1091      1.1  christos 
   1092      1.1  christos /* Print out the routine which, given the opcode enumerator, returns the
   1093      1.1  christos    corresponding opcode entry pointer.  */
   1094      1.1  christos 
   1095      1.1  christos static void
   1096      1.1  christos print_get_opcode (void)
   1097      1.1  christos {
   1098      1.1  christos   int i;
   1099      1.1  christos   const int num = OP_TOTAL_NUM;
   1100      1.1  christos   const aarch64_opcode *opcode;
   1101      1.1  christos 
   1102      1.1  christos   if (debug)
   1103      1.1  christos     printf ("Enter print_get_opcode\n");
   1104      1.1  christos 
   1105      1.1  christos   /* Fill in the internal table.  */
   1106      1.1  christos   opcode = aarch64_opcode_table;
   1107      1.1  christos   while (opcode->name != NULL)
   1108      1.1  christos     {
   1109      1.1  christos       if (opcode->op != OP_NIL)
   1110      1.1  christos 	{
   1111      1.1  christos 	  /* Assert opcode enumerator be unique, in other words, no shared by
   1112      1.1  christos 	     different opcodes.  */
   1113      1.1  christos 	  if (op_enum_table[opcode->op] != 0)
   1114      1.1  christos 	    {
   1115      1.1  christos 	      fprintf (stderr, "Opcode %u is shared by different %s and %s.\n",
   1116      1.1  christos 		       opcode->op,
   1117      1.1  christos 		       aarch64_opcode_table[op_enum_table[opcode->op]].name,
   1118      1.1  christos 		       opcode->name);
   1119      1.1  christos 	      assert (0);
   1120      1.1  christos 	      abort ();
   1121      1.1  christos 	    }
   1122      1.1  christos 	  assert (opcode->op < OP_TOTAL_NUM);
   1123      1.1  christos 	  op_enum_table[opcode->op] = opcode - aarch64_opcode_table;
   1124      1.1  christos 	}
   1125      1.1  christos       ++opcode;
   1126      1.1  christos     }
   1127      1.1  christos 
   1128      1.1  christos   /* Print the table.  */
   1129      1.1  christos   printf ("\n");
   1130      1.1  christos   printf ("/* Indexed by an enum aarch64_op enumerator, the value is the offset of\n\
   1131      1.1  christos    the corresponding aarch64_opcode entry in the aarch64_opcode_table.  */\n\n");
   1132      1.1  christos   printf ("static const unsigned op_enum_table [] =\n");
   1133      1.1  christos   printf ("{\n");
   1134      1.1  christos   for (i = 0; i < num; ++i)
   1135      1.1  christos     printf ("  %u,\n", op_enum_table[i]);
   1136      1.1  christos   printf ("};\n");
   1137      1.1  christos 
   1138      1.1  christos   /* Print the function.  */
   1139      1.1  christos   printf ("\n");
   1140      1.1  christos   printf ("/* Given the opcode enumerator OP, return the pointer to the corresponding\n");
   1141      1.1  christos   printf ("   opcode entry.  */\n");
   1142      1.1  christos   printf ("\n");
   1143      1.1  christos   printf ("const aarch64_opcode *\n");
   1144      1.1  christos   printf ("aarch64_get_opcode (enum aarch64_op op)\n");
   1145      1.1  christos   printf ("{\n");
   1146      1.1  christos   printf ("  return aarch64_opcode_table + op_enum_table[op];\n");
   1147      1.1  christos   printf ("}\n");
   1148      1.1  christos }
   1149      1.1  christos 
   1150      1.1  christos /* Print out the content of an opcode table (not in use).  */
   1151      1.1  christos static void ATTRIBUTE_UNUSED
   1152      1.1  christos print_table (struct aarch64_opcode* table)
   1153      1.1  christos {
   1154      1.1  christos   struct aarch64_opcode *ent = table;
   1155      1.1  christos   do
   1156      1.1  christos     {
   1157      1.1  christos       printf ("%s\t%08x\t%08x\n", ent->name, (unsigned int)ent->opcode,
   1158      1.1  christos 	      (unsigned int)ent->mask);
   1159      1.1  christos     } while ((++ent)->name);
   1160      1.1  christos }
   1161      1.1  christos 
   1162      1.1  christos static const char * program_name = NULL;
   1164      1.1  christos 
   1165      1.1  christos /* Program options.  */
   1166      1.1  christos struct option long_options[] =
   1167      1.1  christos {
   1168      1.1  christos   {"debug",   no_argument,       NULL, 'd'},
   1169      1.1  christos   {"version", no_argument,       NULL, 'V'},
   1170      1.1  christos   {"help",    no_argument,       NULL, 'h'},
   1171      1.1  christos   {"gen-opc", no_argument,       NULL, 'c'},
   1172      1.1  christos   {"gen-asm", no_argument,       NULL, 'a'},
   1173      1.1  christos   {"gen-dis", no_argument,       NULL, 's'},
   1174      1.1  christos   {0,         no_argument,       NULL, 0}
   1175      1.1  christos };
   1176      1.1  christos 
   1177      1.1  christos static void
   1178      1.1  christos print_version (void)
   1179      1.1  christos {
   1180      1.1  christos   printf ("%s: version 1.0\n", program_name);
   1181      1.1  christos   xexit (0);
   1182      1.1  christos }
   1183      1.1  christos 
   1184      1.1  christos static void
   1185      1.1  christos usage (FILE * stream, int status)
   1186      1.1  christos {
   1187      1.1  christos   fprintf (stream, "Usage: %s [-V | --version] [-d | --debug] [--help]\n",
   1188      1.1  christos 	   program_name);
   1189      1.1  christos   fprintf (stream, "\t[ [-c | --gen-opc] | [-a | --gen-asm] | [-s | --gen-dis] ]\n");
   1190      1.1  christos   xexit (status);
   1191      1.1  christos }
   1192      1.1  christos 
   1193      1.1  christos int
   1194      1.1  christos main (int argc, char **argv)
   1195      1.1  christos {
   1196      1.1  christos   extern int chdir (char *);
   1197      1.1  christos   int c;
   1198      1.1  christos   int gen_opcode_p = 0;
   1199      1.1  christos   int gen_assembler_p = 0;
   1200      1.1  christos   int gen_disassembler_p = 0;
   1201      1.1  christos 
   1202      1.1  christos   program_name = *argv;
   1203      1.1  christos   xmalloc_set_program_name (program_name);
   1204      1.1  christos 
   1205      1.1  christos   while ((c = getopt_long (argc, argv, "vVdhacs", long_options, 0)) != EOF)
   1206      1.1  christos     switch (c)
   1207      1.1  christos       {
   1208      1.1  christos       case 'V':
   1209      1.1  christos       case 'v':
   1210      1.1  christos 	print_version ();
   1211      1.1  christos 	break;
   1212      1.1  christos       case 'd':
   1213      1.1  christos 	debug = 1;
   1214      1.1  christos 	break;
   1215      1.1  christos       case 'h':
   1216      1.1  christos       case '?':
   1217      1.1  christos 	usage (stderr, 0);
   1218      1.1  christos 	break;
   1219      1.1  christos       case 'c':
   1220      1.1  christos 	gen_opcode_p = 1;
   1221      1.1  christos 	break;
   1222      1.1  christos       case 'a':
   1223      1.1  christos 	gen_assembler_p = 1;
   1224      1.1  christos 	break;
   1225      1.1  christos       case 's':
   1226      1.1  christos 	gen_disassembler_p = 1;
   1227      1.1  christos 	break;
   1228      1.1  christos       default:
   1229      1.1  christos       case 0:
   1230      1.1  christos 	break;
   1231      1.1  christos       }
   1232      1.1  christos 
   1233      1.1  christos   if (argc == 1 || optind != argc)
   1234      1.1  christos     usage (stdout, 1);
   1235      1.1  christos 
   1236      1.1  christos   if (gen_opcode_p + gen_assembler_p + gen_disassembler_p > 1)
   1237      1.1  christos     {
   1238      1.1  christos       printf ("Please specify only one of the following options\n\
   1239      1.1  christos 	      [-c | --gen-opc] [-a | --gen-asm] [-s | --gen-dis]\n");
   1240      1.1  christos       xexit (2);
   1241      1.1  christos     }
   1242      1.1  christos 
   1243      1.1  christos   struct bittree *decoder_tree;
   1244      1.1  christos 
   1245      1.1  christos   decoder_tree = initialize_decoder_tree ();
   1246      1.1  christos   if (debug)
   1247  1.1.1.4  christos     print_divide_result (decoder_tree);
   1248      1.1  christos 
   1249      1.1  christos   printf ("/* This file is automatically generated by aarch64-gen.  Do not edit!  */\n");
   1250      1.1  christos   printf ("/* Copyright (C) 2012-2018 Free Software Foundation, Inc.\n\
   1251      1.1  christos    Contributed by ARM Ltd.\n\
   1252      1.1  christos \n\
   1253      1.1  christos    This file is part of the GNU opcodes library.\n\
   1254      1.1  christos \n\
   1255      1.1  christos    This library is free software; you can redistribute it and/or modify\n\
   1256      1.1  christos    it under the terms of the GNU General Public License as published by\n\
   1257      1.1  christos    the Free Software Foundation; either version 3, or (at your option)\n\
   1258      1.1  christos    any later version.\n\
   1259      1.1  christos \n\
   1260      1.1  christos    It is distributed in the hope that it will be useful, but WITHOUT\n\
   1261      1.1  christos    ANY WARRANTY; without even the implied warranty of MERCHANTABILITY\n\
   1262      1.1  christos    or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public\n\
   1263      1.1  christos    License for more details.\n\
   1264      1.1  christos \n\
   1265      1.1  christos    You should have received a copy of the GNU General Public License\n\
   1266      1.1  christos    along with this program; see the file COPYING3. If not,\n\
   1267      1.1  christos    see <http://www.gnu.org/licenses/>.  */\n");
   1268      1.1  christos 
   1269      1.1  christos   printf ("\n");
   1270      1.1  christos   printf ("#include \"sysdep.h\"\n");
   1271      1.1  christos   if (gen_opcode_p)
   1272      1.1  christos     printf ("#include \"aarch64-opc.h\"\n");
   1273      1.1  christos   if (gen_assembler_p)
   1274      1.1  christos     printf ("#include \"aarch64-asm.h\"\n");
   1275      1.1  christos   if (gen_disassembler_p)
   1276      1.1  christos     printf ("#include \"aarch64-dis.h\"\n");
   1277      1.1  christos   printf ("\n");
   1278      1.1  christos 
   1279      1.1  christos   /* Generate opcode entry lookup for the disassembler.  */
   1280      1.1  christos   if (gen_disassembler_p)
   1281      1.1  christos     {
   1282      1.1  christos       print_decision_tree (decoder_tree);
   1283      1.1  christos       print_find_next_opcode (decoder_tree);
   1284      1.1  christos       release_resource_decoder_tree (decoder_tree);
   1285      1.1  christos     }
   1286      1.1  christos 
   1287      1.1  christos   /* Generate alias opcode handling for the assembler or the disassembler.  */
   1288      1.1  christos   if (gen_assembler_p || gen_disassembler_p)
   1289      1.1  christos     {
   1290      1.1  christos       int num;
   1291      1.1  christos       opcode_node *alias_info = create_alias_info (&num);
   1292      1.1  christos 
   1293      1.1  christos       if (gen_assembler_p)
   1294      1.1  christos 	print_find_real_opcode (alias_info, num);
   1295      1.1  christos 
   1296      1.1  christos       if (gen_disassembler_p)
   1297      1.1  christos 	{
   1298      1.1  christos 	  print_find_alias_opcode (alias_info, num);
   1299      1.1  christos 	  print_find_next_alias_opcode (alias_info, num);
   1300      1.1  christos 	}
   1301      1.1  christos 
   1302      1.1  christos       release_resource_alias_info (alias_info, num);
   1303      1.1  christos     }
   1304      1.1  christos 
   1305      1.1  christos   /* Generate operand table.  */
   1306      1.1  christos   process_operand_table ();
   1307      1.1  christos 
   1308      1.1  christos   if (gen_assembler_p)
   1309      1.1  christos     print_operand_inserter ();
   1310      1.1  christos 
   1311      1.1  christos   if (gen_disassembler_p)
   1312      1.1  christos     print_operand_extractor ();
   1313      1.1  christos 
   1314      1.1  christos   if (gen_opcode_p)
   1315      1.1  christos     print_operand_table ();
   1316      1.1  christos 
   1317      1.1  christos   /* Generate utility to return aarch64_opcode entry given an enumerator.  */
   1318      1.1  christos   if (gen_opcode_p)
   1319      1.1  christos     print_get_opcode ();
   1320                    
   1321                      exit (0);
   1322                    }
   1323