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