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