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