[gdb/testsuite] Fix gdb.threads/threadcrash.exp with glibc debuginfo
[binutils-gdb.git] / opcodes / aarch64-gen.c
blob02dcde1f676f9d4a4cc62fb9eae392eb9a556801
1 /* aarch64-gen.c -- Generate tables and routines for opcode lookup and
2 instruction encoding and decoding.
3 Copyright (C) 2012-2024 Free Software Foundation, Inc.
4 Contributed by ARM Ltd.
6 This file is part of the GNU opcodes library.
8 This library is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 3, or (at your option)
11 any later version.
13 It is distributed in the hope that it will be useful, but WITHOUT
14 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
15 or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
16 License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program; see the file COPYING3. If not,
20 see <http://www.gnu.org/licenses/>. */
22 #include "sysdep.h"
23 #include <stdio.h>
24 #include <stdlib.h>
25 #include <stdarg.h>
27 #include "libiberty.h"
28 #include "getopt.h"
29 #include "opcode/aarch64.h"
31 #define VERIFIER(x) NULL
32 #include "aarch64-tbl.h"
34 static int debug = 0;
36 /* Structure used in the decoding tree to group a list of aarch64_opcode
37 entries. */
39 struct opcode_node
41 aarch64_insn opcode;
42 aarch64_insn mask;
43 /* Index of the entry in the original table; the top 2 bits help
44 determine the table. */
45 unsigned int index;
46 struct opcode_node *next;
49 typedef struct opcode_node opcode_node;
51 /* Head of the list of the opcode_node after read_table. */
52 static opcode_node opcode_nodes_head;
54 /* Node in the decoding tree. */
56 struct bittree
58 unsigned int bitno;
59 /* 0, 1, and X (don't care). */
60 struct bittree *bits[2];
61 /* List of opcodes; only valid for the leaf node. */
62 opcode_node *list;
65 /* Allocate and initialize an opcode_node. */
66 static opcode_node*
67 new_opcode_node (void)
69 opcode_node* ent = malloc (sizeof (opcode_node));
71 if (!ent)
72 abort ();
74 ent->opcode = 0;
75 ent->mask = 0;
76 ent->index = -1;
77 ent->next = NULL;
79 return ent;
82 /* Multiple tables are supported, although currently only one table is
83 in use. N.B. there are still some functions have the table name
84 'aarch64_opcode_table' hard-coded in, e.g. print_find_next_opcode;
85 therefore some amount of work needs to be done if the full support
86 for multiple tables needs to be enabled. */
87 static const struct aarch64_opcode * const aarch64_opcode_tables[] =
88 {aarch64_opcode_table};
90 /* Use top 2 bits to indiate which table. */
91 static unsigned int
92 initialize_index (const struct aarch64_opcode* table)
94 int i;
95 const int num_of_tables = sizeof (aarch64_opcode_tables)
96 / sizeof (struct aarch64_opcode *);
97 for (i = 0; i < num_of_tables; ++i)
98 if (table == aarch64_opcode_tables [i])
99 break;
100 if (i == num_of_tables)
101 abort ();
102 return (unsigned int)i << 30;
105 static inline const struct aarch64_opcode *
106 index2table (unsigned int index)
108 return aarch64_opcode_tables[(index >> 30) & 0x3];
111 static inline unsigned int
112 real_index (unsigned int index)
114 return index & ((1 << 30) - 1);
117 /* Given OPCODE_NODE, return the corresponding aarch64_opcode*. */
118 static const aarch64_opcode*
119 get_aarch64_opcode (const opcode_node *opcode_node)
121 if (opcode_node == NULL)
122 return NULL;
123 return &index2table (opcode_node->index)[real_index (opcode_node->index)];
126 static void
127 read_table (const struct aarch64_opcode* table)
129 const struct aarch64_opcode *ent = table;
130 opcode_node **new_ent;
131 unsigned int index = initialize_index (table);
132 unsigned int errors = 0;
134 if (!ent->name)
135 return;
137 new_ent = &opcode_nodes_head.next;
139 while (*new_ent)
140 new_ent = &(*new_ent)->next;
144 bool match = false;
146 /* F_PSEUDO needs to be used together with F_ALIAS to indicate an alias
147 opcode is a programmer friendly pseudo instruction available only in
148 the assembly code (thus will not show up in the disassembly). */
149 assert (!pseudo_opcode_p (ent) || alias_opcode_p (ent));
150 /* Skip alias (inc. pseudo) opcode. */
151 if (alias_opcode_p (ent))
153 index++;
154 continue;
157 /* Check tied_operand against operands[]. */
158 for (unsigned int i = 1; i < ARRAY_SIZE (ent->operands); ++i)
160 if (ent->operands[i] == AARCH64_OPND_NIL)
161 break;
163 if (ent->operands[i] != ent->operands[0])
164 continue;
165 match = true;
167 if (i != ent->tied_operand)
169 fprintf (stderr,
170 "%s (%08x,%08x): operands 1 and %u match, but tied=%u\n",
171 ent->name, ent->opcode, ent->mask, i + 1, ent->tied_operand);
172 ++errors;
175 if (!match && ent->tied_operand
176 /* SME LDR/STR (array vector) tie together inner immediates only. */
177 && ent->iclass != sme_ldr && ent->iclass != sme_str)
179 fprintf (stderr, "%s: no operands match, but tied=%u\n",
180 ent->name, ent->tied_operand);
181 ++errors;
184 *new_ent = new_opcode_node ();
185 (*new_ent)->opcode = ent->opcode;
186 (*new_ent)->mask = ent->mask;
187 (*new_ent)->index = index++;
188 new_ent = &((*new_ent)->next);
189 } while ((++ent)->name);
191 if (errors)
193 fprintf (stderr, "%u errors, exiting\n", errors);
194 xexit (3);
198 static inline void
199 print_one_opcode_node (opcode_node* ent)
201 printf ("%s\t%08x\t%08x\t%d\n", get_aarch64_opcode (ent)->name,
202 get_aarch64_opcode (ent)->opcode, get_aarch64_opcode (ent)->mask,
203 (int)real_index (ent->index));
206 /* As an internal debugging utility, print out the list of nodes pointed
207 by opcode_nodes_head. */
208 static void
209 print_opcode_nodes (void)
211 opcode_node* ent = opcode_nodes_head.next;
212 printf ("print_opcode_nodes table:\n");
213 while (ent)
215 print_one_opcode_node (ent);
216 ent = ent->next;
220 static struct bittree*
221 new_bittree_node (void)
223 struct bittree* node;
224 node = malloc (sizeof (struct bittree));
225 if (!node)
226 abort ();
227 node->bitno = -1;
228 node->bits[0] = NULL;
229 node->bits[1] = NULL;
230 return node;
233 /* The largest number of opcode entries that exist at a leaf node of the
234 decoding decision tree. The reason that there can be more than one
235 opcode entry is because some opcodes have shared field that is partially
236 constrained and thus cannot be fully isolated using the algorithm
237 here. */
238 static int max_num_opcodes_at_leaf_node = 0;
240 /* Given a list of opcodes headed by *OPCODE, try to establish one bit that
241 is shared by all the opcodes in the list as one of base opcode bits. If
242 such a bit is found, divide the list of the opcodes into two based on the
243 value of the bit.
245 Store the bit number in BITTREE->BITNO if the division succeeds. If unable
246 to determine such a bit or there is only one opcode in the list, the list
247 is decided to be undividable and OPCODE will be assigned to BITTREE->LIST.
249 The function recursively call itself until OPCODE is undividable.
251 N.B. the nature of this algrithm determines that given any value in the
252 32-bit space, the computed decision tree will always be able to find one or
253 more opcodes entries for it, regardless whether there is a valid instruction
254 defined for this value or not. In order to detect the undefined values,
255 when the caller obtains the opcode entry/entries, it should at least compare
256 the bit-wise AND result of the value and the mask with the base opcode
257 value; if the two are different, it means that the value is undefined
258 (although the value may be still undefined when the comparison is the same,
259 in which case call aarch64_opcode_decode to carry out further checks). */
261 static void
262 divide_table_1 (struct bittree *bittree, opcode_node *opcode)
264 aarch64_insn mask_and;
265 opcode_node *ent;
266 unsigned int bitno;
267 aarch64_insn bitmask;
268 opcode_node list0, list1, **ptr0, **ptr1;
269 static int depth = 0;
271 ++depth;
273 if (debug)
274 printf ("Enter into depth %d\n", depth);
276 assert (opcode != NULL);
278 /* Succeed when there is only one opcode left. */
279 if (!opcode->next)
281 if (debug)
283 printf ("opcode isolated:\n");
284 print_one_opcode_node (opcode);
286 goto divide_table_1_finish;
289 divide_table_1_try_again:
290 mask_and = -1;
291 ent = opcode;
292 while (ent)
294 mask_and &= ent->mask;
295 ent = ent->next;
298 if (debug)
299 printf ("mask and result: %08x\n", (unsigned int)mask_and);
301 /* If no more bit to look into, we have to accept the reality then. */
302 if (!mask_and)
304 int i;
305 opcode_node *ptr;
306 if (debug)
308 ptr = opcode;
309 printf ("Isolated opcode group:\n");
310 do {
311 print_one_opcode_node (ptr);
312 ptr = ptr->next;
313 } while (ptr);
315 /* Count the number of opcodes. */
316 for (i = 0, ptr = opcode; ptr; ++i)
317 ptr = ptr->next;
318 if (i > max_num_opcodes_at_leaf_node)
319 max_num_opcodes_at_leaf_node = i;
320 goto divide_table_1_finish;
323 /* Pick up the right most bit that is 1. */
324 bitno = 0;
325 while (!(mask_and & (1 << bitno)))
326 ++bitno;
327 bitmask = (1 << bitno);
329 if (debug)
330 printf ("use bit %d\n", bitno);
332 /* Record in the bittree. */
333 bittree->bitno = bitno;
335 /* Get two new opcode lists; adjust their masks. */
336 list0.next = NULL;
337 list1.next = NULL;
338 ptr0 = &list0.next;
339 ptr1 = &list1.next;
340 ent = opcode;
341 while (ent)
343 if (ent->opcode & bitmask)
345 ent->mask &= (~bitmask);
346 *ptr1 = ent;
347 ent = ent->next;
348 (*ptr1)->next = NULL;
349 ptr1 = &(*ptr1)->next;
351 else
353 ent->mask &= (~bitmask);
354 *ptr0 = ent;
355 ent = ent->next;
356 (*ptr0)->next = NULL;
357 ptr0 = &(*ptr0)->next;
361 /* If BITNO can NOT divide the opcode group, try next bit. */
362 if (list0.next == NULL)
364 opcode = list1.next;
365 goto divide_table_1_try_again;
367 else if (list1.next == NULL)
369 opcode = list0.next;
370 goto divide_table_1_try_again;
373 /* Further divide. */
374 bittree->bits[0] = new_bittree_node ();
375 bittree->bits[1] = new_bittree_node ();
376 divide_table_1 (bittree->bits[0], list0.next);
377 divide_table_1 (bittree->bits[1], list1.next);
379 divide_table_1_finish:
380 if (debug)
381 printf ("Leave from depth %d\n", depth);
382 --depth;
384 /* Record the opcode entries on this leaf node. */
385 bittree->list = opcode;
387 return;
390 /* Call divide_table_1 to divide the all the opcodes and thus create the
391 decoding decision tree. */
392 static struct bittree *
393 divide_table (void)
395 struct bittree *bittree = new_bittree_node ();
396 divide_table_1 (bittree, opcode_nodes_head.next);
397 return bittree;
400 /* Read in all of the tables, create the decoding decision tree and return
401 the tree root. */
402 static struct bittree *
403 initialize_decoder_tree (void)
405 int i;
406 const int num_of_tables = (sizeof (aarch64_opcode_tables)
407 / sizeof (struct aarch64_opcode *));
408 for (i = 0; i < num_of_tables; ++i)
409 read_table (aarch64_opcode_tables [i]);
410 if (debug)
411 print_opcode_nodes ();
412 return divide_table ();
415 static void __attribute__ ((format (printf, 2, 3)))
416 indented_print (unsigned int indent, const char *format, ...)
418 va_list ap;
419 va_start (ap, format);
420 printf ("%*s", (int) indent, "");
421 vprintf (format, ap);
422 va_end (ap);
425 /* N.B. read the comment above divide_table_1 for the reason why the generated
426 decision tree function never returns NULL. */
428 static void
429 print_decision_tree_1 (unsigned int indent, struct bittree* bittree)
431 /* PATTERN is only used to generate comment in the code. */
432 static char pattern[33] = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx";
433 /* Low bits in PATTERN will be printed first which then look as the high
434 bits in comment. We need to reverse the index to get correct print. */
435 unsigned int msb = sizeof (pattern) - 2;
436 assert (bittree != NULL);
438 /* Leaf node located. */
439 if (bittree->bits[0] == NULL && bittree->bits[1] == NULL)
441 assert (bittree->list != NULL);
442 indented_print (indent, "/* 33222222222211111111110000000000\n");
443 indented_print (indent, " 10987654321098765432109876543210\n");
444 indented_print (indent, " %s\n", pattern);
445 indented_print (indent, " %s. */\n",
446 get_aarch64_opcode (bittree->list)->name);
447 indented_print (indent, "return %u;\n",
448 real_index (bittree->list->index));
449 return;
452 /* Walk down the decoder tree. */
453 indented_print (indent, "if (((word >> %d) & 0x1) == 0)\n", bittree->bitno);
454 indented_print (indent, " {\n");
455 pattern[msb - bittree->bitno] = '0';
456 print_decision_tree_1 (indent + 4, bittree->bits[0]);
457 indented_print (indent, " }\n");
458 indented_print (indent, "else\n");
459 indented_print (indent, " {\n");
460 pattern[msb - bittree->bitno] = '1';
461 print_decision_tree_1 (indent + 4, bittree->bits[1]);
462 indented_print (indent, " }\n");
463 pattern[msb - bittree->bitno] = 'x';
466 /* Generate aarch64_opcode_lookup in C code to the standard output. */
468 static void
469 print_decision_tree (struct bittree* bittree)
471 if (debug)
472 printf ("Enter print_decision_tree\n");
474 printf ("/* Called by aarch64_opcode_lookup. */\n\n");
476 printf ("static int\n");
477 printf ("aarch64_opcode_lookup_1 (uint32_t word)\n");
478 printf ("{\n");
480 print_decision_tree_1 (2, bittree);
482 printf ("}\n\n");
485 printf ("/* Lookup opcode WORD in the opcode table. N.B. all alias\n");
486 printf (" opcodes are ignored here. */\n\n");
488 printf ("const aarch64_opcode *\n");
489 printf ("aarch64_opcode_lookup (uint32_t word)\n");
490 printf ("{\n");
491 printf (" return aarch64_opcode_table + aarch64_opcode_lookup_1 (word);\n");
492 printf ("}\n");
495 static void
496 print_find_next_opcode_1 (struct bittree* bittree)
498 assert (bittree != NULL);
500 /* Leaf node located. */
501 if (bittree->bits[0] == NULL && bittree->bits[1] == NULL)
503 assert (bittree->list != NULL);
504 /* Find multiple opcode entries in one leaf node. */
505 if (bittree->list->next != NULL)
507 opcode_node *list = bittree->list;
508 while (list != NULL)
510 const aarch64_opcode *curr = get_aarch64_opcode (list);
511 const aarch64_opcode *next = get_aarch64_opcode (list->next);
513 printf (" case %u: ",
514 (unsigned int)(curr - aarch64_opcode_table));
515 if (list->next != NULL)
517 printf ("value = %u; break;\t", real_index (list->next->index));
518 printf ("/* %s --> %s. */\n", curr->name, next->name);
520 else
522 printf ("return NULL;\t\t");
523 printf ("/* %s --> NULL. */\n", curr->name);
526 list = list->next;
529 return;
532 /* Walk down the decoder tree. */
533 print_find_next_opcode_1 (bittree->bits[0]);
534 print_find_next_opcode_1 (bittree->bits[1]);
537 /* Generate aarch64_find_next_opcode in C code to the standard output. */
539 static void
540 print_find_next_opcode (struct bittree* bittree)
542 if (debug)
543 printf ("Enter print_find_next_opcode\n");
545 printf ("\n");
546 printf ("const aarch64_opcode *\n");
547 printf ("aarch64_find_next_opcode (const aarch64_opcode *opcode)\n");
548 printf ("{\n");
549 printf (" /* Use the index as the key to locate the next opcode. */\n");
550 printf (" int key = opcode - aarch64_opcode_table;\n");
551 printf (" int value;\n");
552 printf (" switch (key)\n");
553 printf (" {\n");
555 print_find_next_opcode_1 (bittree);
557 printf (" default: return NULL;\n");
558 printf (" }\n\n");
560 printf (" return aarch64_opcode_table + value;\n");
561 printf ("}\n");
564 /* Release the dynamic memory resource allocated for the generation of the
565 decoder tree. */
567 static void
568 release_resource_decoder_tree (struct bittree* bittree)
570 assert (bittree != NULL);
572 /* Leaf node located. */
573 if (bittree->bits[0] == NULL && bittree->bits[1] == NULL)
575 assert (bittree->list != NULL);
576 /* Free opcode_nodes. */
577 opcode_node *list = bittree->list;
578 while (list != NULL)
580 opcode_node *next = list->next;
581 free (list);
582 list = next;
584 /* Free the tree node. */
585 free (bittree);
586 return;
589 /* Walk down the decoder tree. */
590 release_resource_decoder_tree (bittree->bits[0]);
591 release_resource_decoder_tree (bittree->bits[1]);
593 /* Free the tree node. */
594 free (bittree);
597 /* Generate aarch64_find_real_opcode in C code to the standard output.
598 TABLE points to the alias info table, while NUM indicates the number of
599 entries in the table. */
601 static void
602 print_find_real_opcode (const opcode_node *table, int num)
604 int i;
606 if (debug)
607 printf ("Enter print_find_real_opcode\n");
609 printf ("\n");
610 printf ("const aarch64_opcode *\n");
611 printf ("aarch64_find_real_opcode (const aarch64_opcode *opcode)\n");
612 printf ("{\n");
613 printf (" /* Use the index as the key to locate the real opcode. */\n");
614 printf (" int key = opcode - aarch64_opcode_table;\n");
615 printf (" int value;\n");
616 printf (" switch (key)\n");
617 printf (" {\n");
619 for (i = 0; i < num; ++i)
621 const opcode_node *real = table + i;
622 const opcode_node *alias = real->next;
623 for (; alias; alias = alias->next)
624 printf (" case %u:\t/* %s */\n", real_index (alias->index),
625 get_aarch64_opcode (alias)->name);
626 printf (" value = %u;\t/* --> %s. */\n", real_index (real->index),
627 get_aarch64_opcode (real)->name);
628 printf (" break;\n");
631 printf (" default: return NULL;\n");
632 printf (" }\n\n");
634 printf (" return aarch64_opcode_table + value;\n");
635 printf ("}\n");
638 /* Generate aarch64_find_alias_opcode in C code to the standard output.
639 TABLE points to the alias info table, while NUM indicates the number of
640 entries in the table. */
642 static void
643 print_find_alias_opcode (const opcode_node *table, int num)
645 int i;
647 if (debug)
648 printf ("Enter print_find_alias_opcode\n");
650 printf ("\n");
651 printf ("const aarch64_opcode *\n");
652 printf ("aarch64_find_alias_opcode (const aarch64_opcode *opcode)\n");
653 printf ("{\n");
654 printf (" /* Use the index as the key to locate the alias opcode. */\n");
655 printf (" int key = opcode - aarch64_opcode_table;\n");
656 printf (" int value;\n");
657 printf (" switch (key)\n");
658 printf (" {\n");
660 for (i = 0; i < num; ++i)
662 const opcode_node *node = table + i;
663 assert (node->next);
664 printf (" case %u: value = %u; break;", real_index (node->index),
665 real_index (node->next->index));
666 printf ("\t/* %s --> %s. */\n", get_aarch64_opcode (node)->name,
667 get_aarch64_opcode (node->next)->name);
670 printf (" default: return NULL;\n");
671 printf (" }\n\n");
673 printf (" return aarch64_opcode_table + value;\n");
674 printf ("}\n");
677 /* Generate aarch64_find_next_alias_opcode in C code to the standard output.
678 TABLE points to the alias info table, while NUM indicates the number of
679 entries in the table. */
681 static void
682 print_find_next_alias_opcode (const opcode_node *table, int num)
684 int i;
686 if (debug)
687 printf ("Enter print_find_next_alias_opcode\n");
689 printf ("\n");
690 printf ("const aarch64_opcode *\n");
691 printf ("aarch64_find_next_alias_opcode (const aarch64_opcode *opcode)\n");
692 printf ("{\n");
693 printf (" /* Use the index as the key to locate the next opcode. */\n");
694 printf (" int key = opcode - aarch64_opcode_table;\n");
695 printf (" int value;\n");
696 printf (" switch (key)\n");
697 printf (" {\n");
699 for (i = 0; i < num; ++i)
701 const opcode_node *node = table + i;
702 assert (node->next);
703 if (node->next->next == NULL)
704 continue;
705 while (node->next->next)
707 printf (" case %u: value = %u; break;", real_index (node->next->index),
708 real_index (node->next->next->index));
709 printf ("\t/* %s --> %s. */\n",
710 get_aarch64_opcode (node->next)->name,
711 get_aarch64_opcode (node->next->next)->name);
712 node = node->next;
716 printf (" default: return NULL;\n");
717 printf (" }\n\n");
719 printf (" return aarch64_opcode_table + value;\n");
720 printf ("}\n");
723 /* Given OPCODE, establish and return a link list of alias nodes in the
724 preferred order. */
726 opcode_node *
727 find_alias_opcode (const aarch64_opcode *opcode)
729 int i;
730 /* Assume maximum of 32 disassemble preference candidates. */
731 const int max_num_aliases = 32;
732 const aarch64_opcode *ent;
733 const aarch64_opcode *preferred[max_num_aliases + 1];
734 opcode_node head, **next;
736 assert (opcode_has_alias (opcode));
738 i = 0;
739 if (opcode->name != NULL)
740 preferred[i++] = opcode;
741 ent = aarch64_opcode_table;
742 while (ent->name != NULL)
744 /* The mask of an alias opcode must be equal to or a super-set (i.e.
745 more constrained) of that of the aliased opcode; so is the base
746 opcode value. */
747 if (alias_opcode_p (ent)
748 && (ent->mask & opcode->mask) == opcode->mask
749 && (opcode->mask & ent->opcode) == (opcode->mask & opcode->opcode))
751 assert (i < max_num_aliases);
752 preferred[i++] = ent;
753 if (debug)
754 printf ("found %s for %s.", ent->name, opcode->name);
756 ++ent;
759 if (debug)
761 int m;
762 printf ("un-orderd list: ");
763 for (m = 0; m < i; ++m)
764 printf ("%s, ", preferred[m]->name);
765 printf ("\n");
768 /* There must be at least one alias. */
769 assert (i >= 1);
771 /* Sort preferred array according to the priority (from the lowest to the
772 highest. */
773 if (i > 1)
775 int j, k;
776 for (j = 0; j < i - 1; ++j)
778 for (k = 0; k < i - 1 - j; ++k)
780 const aarch64_opcode *t;
781 t = preferred [k+1];
782 if (opcode_priority (t) < opcode_priority (preferred [k]))
784 preferred [k+1] = preferred [k];
785 preferred [k] = t;
791 if (debug)
793 int m;
794 printf ("orderd list: ");
795 for (m = 0; m < i; ++m)
796 printf ("%s, ", preferred[m]->name);
797 printf ("\n");
800 /* Create a link-list of opcode_node with disassemble preference from
801 higher to lower. */
802 next = &head.next;
803 --i;
804 while (i >= 0)
806 const aarch64_opcode *alias = preferred [i];
807 opcode_node *node = new_opcode_node ();
809 if (debug)
810 printf ("add %s.\n", alias->name);
812 node->index = alias - aarch64_opcode_table;
813 *next = node;
814 next = &node->next;
816 --i;
818 *next = NULL;
820 return head.next;
823 /* Create and return alias information.
824 Return the address of the created alias info table; return the number
825 of table entries in *NUM_PTR. */
827 opcode_node *
828 create_alias_info (int *num_ptr)
830 int i, num;
831 opcode_node *ret;
832 const aarch64_opcode *ent;
834 /* Calculate the total number of opcodes that have alias. */
835 num = 0;
836 ent = aarch64_opcode_table;
837 while (ent->name != NULL)
839 if (opcode_has_alias (ent))
841 /* Assert the alias relationship be flat-structured to keep
842 algorithms simple; not allow F_ALIAS and F_HAS_ALIAS both
843 specified. */
844 assert (!alias_opcode_p (ent));
845 ++num;
847 ++ent;
849 assert (num_ptr);
850 *num_ptr = num;
852 /* The array of real opcodes that have alias(es). */
853 ret = malloc (sizeof (opcode_node) * num);
855 /* For each opcode, establish a list of alias nodes in a preferred
856 order. */
857 for (i = 0, ent = aarch64_opcode_table; i < num; ++i, ++ent)
859 opcode_node *node = ret + i;
860 while (ent->name != NULL && !opcode_has_alias (ent))
861 ++ent;
862 assert (ent->name != NULL);
863 node->index = ent - aarch64_opcode_table;
864 node->next = find_alias_opcode (ent);
865 assert (node->next);
867 assert (i == num);
869 return ret;
872 /* Release the dynamic memory resource allocated for the generation of the
873 alias information. */
875 void
876 release_resource_alias_info (opcode_node *alias_info, int num)
878 int i = 0;
879 opcode_node *node = alias_info;
881 /* Free opcode_node list. */
882 for (; i < num; ++i, ++node)
884 opcode_node *list = node->next;
887 opcode_node *next = list->next;
888 free (list);
889 list = next;
890 } while (list != NULL);
893 /* Free opcode_node array. */
894 free (alias_info);
897 /* As a debugging utility, print out the result of the table division, although
898 it is not doing much this moment. */
899 static void
900 print_divide_result (const struct bittree *bittree ATTRIBUTE_UNUSED)
902 printf ("max_num_opcodes_at_leaf_node: %d\n", max_num_opcodes_at_leaf_node);
903 return;
906 /* Structure to help generate the operand table. */
907 struct operand
909 const char *class;
910 const char *inserter;
911 const char *extractor;
912 const char *str;
913 const char *flags;
914 const char *fields;
915 const char *desc;
916 unsigned processed : 1;
917 unsigned has_inserter : 1;
918 unsigned has_extractor : 1;
921 typedef struct operand operand;
923 #ifdef X
924 #undef X
925 #endif
927 #ifdef Y
928 #undef Y
929 #endif
931 #ifdef F
932 #undef F
933 #endif
935 /* Get the operand information in strings. */
937 static operand operands[] =
939 {"NIL", "0", "0", "", "0", "{0}", "<none>", 0, 0, 0},
940 #define F(...) #__VA_ARGS__
941 #define X(a,b,c,d,e,f,g) \
942 {#a, #b, #c, d, #e, "{"f"}", g, 0, 0, 0},
943 #define Y(a,b,d,e,f,g) \
944 {#a, "ins_"#b, "ext_"#b, d, #e, "{"f"}", g, 0, 0, 0},
945 AARCH64_OPERANDS
946 {"NIL", "0", "0", "", "0", "{0}", "DUMMY", 0, 0, 0},
949 #undef F
950 #undef X
952 static void
953 process_operand_table (void)
955 int i;
956 operand *opnd;
957 const int num = sizeof (operands) / sizeof (operand);
959 for (i = 0, opnd = operands; i < num; ++i, ++opnd)
961 opnd->has_inserter = opnd->inserter[0] != '0';
962 opnd->has_extractor = opnd->extractor[0] != '0';
966 /* Generate aarch64_operands in C to the standard output. */
968 static void
969 print_operand_table (void)
971 int i;
972 operand *opnd;
973 const int num = sizeof (operands) / sizeof (operand);
975 if (debug)
976 printf ("Enter print_operand_table\n");
978 printf ("\n");
979 printf ("const struct aarch64_operand aarch64_operands[] =\n");
980 printf ("{\n");
982 for (i = 0, opnd = operands; i < num; ++i, ++opnd)
984 char flags[256];
985 flags[0] = '\0';
986 if (opnd->flags[0] != '0')
987 sprintf (flags, "%s", opnd->flags);
988 if (opnd->has_inserter)
990 if (flags[0] != '\0')
991 strcat (flags, " | ");
992 strcat (flags, "OPD_F_HAS_INSERTER");
994 if (opnd->has_extractor)
996 if (flags[0] != '\0')
997 strcat (flags, " | ");
998 strcat (flags, "OPD_F_HAS_EXTRACTOR");
1000 if (flags[0] == '\0')
1002 flags[0] = '0';
1003 flags[1] = '\0';
1005 printf (" {AARCH64_OPND_CLASS_%s, \"%s\", %s, %s, \"%s\"},\n",
1006 opnd->class, opnd->str, flags, opnd->fields, opnd->desc);
1008 printf ("};\n");
1011 /* Generate aarch64_insert_operand in C to the standard output. */
1013 static void
1014 print_operand_inserter (void)
1016 int i;
1017 operand *opnd;
1018 const int num = sizeof (operands) / sizeof (operand);
1020 if (debug)
1021 printf ("Enter print_operand_inserter\n");
1023 printf ("\n");
1024 printf ("bool\n");
1025 printf ("aarch64_insert_operand (const aarch64_operand *self,\n\
1026 const aarch64_opnd_info *info,\n\
1027 aarch64_insn *code, const aarch64_inst *inst,\n\
1028 aarch64_operand_error *errors)\n");
1029 printf ("{\n");
1030 printf (" /* Use the index as the key. */\n");
1031 printf (" int key = self - aarch64_operands;\n");
1032 printf (" switch (key)\n");
1033 printf (" {\n");
1035 for (i = 0, opnd = operands; i < num; ++i, ++opnd)
1036 opnd->processed = 0;
1038 for (i = 0, opnd = operands; i < num; ++i, ++opnd)
1040 if (!opnd->processed && opnd->has_inserter)
1042 int j = i + 1;
1043 const int len = strlen (opnd->inserter);
1044 operand *opnd2 = opnd + 1;
1045 printf (" case %u:\n", (unsigned int)(opnd - operands));
1046 opnd->processed = 1;
1047 for (; j < num; ++j, ++opnd2)
1049 if (!opnd2->processed
1050 && opnd2->has_inserter
1051 && len == strlen (opnd2->inserter)
1052 && strncmp (opnd->inserter, opnd2->inserter, len) == 0)
1054 printf (" case %u:\n", (unsigned int)(opnd2 - operands));
1055 opnd2->processed = 1;
1058 printf (" return aarch64_%s (self, info, code, inst, errors);\n",
1059 opnd->inserter);
1063 printf (" default: assert (0); abort ();\n");
1064 printf (" }\n");
1065 printf ("}\n");
1068 /* Generate aarch64_extract_operand in C to the standard output. */
1070 static void
1071 print_operand_extractor (void)
1073 int i;
1074 operand *opnd;
1075 const int num = sizeof (operands) / sizeof (operand);
1077 if (debug)
1078 printf ("Enter print_operand_extractor\n");
1080 printf ("\n");
1081 printf ("bool\n");
1082 printf ("aarch64_extract_operand (const aarch64_operand *self,\n\
1083 aarch64_opnd_info *info,\n\
1084 aarch64_insn code, const aarch64_inst *inst,\n\
1085 aarch64_operand_error *errors)\n");
1086 printf ("{\n");
1087 printf (" /* Use the index as the key. */\n");
1088 printf (" int key = self - aarch64_operands;\n");
1089 printf (" switch (key)\n");
1090 printf (" {\n");
1092 for (i = 0, opnd = operands; i < num; ++i, ++opnd)
1093 opnd->processed = 0;
1095 for (i = 0, opnd = operands; i < num; ++i, ++opnd)
1097 if (!opnd->processed && opnd->has_extractor)
1099 int j = i + 1;
1100 const int len = strlen (opnd->extractor);
1101 operand *opnd2 = opnd + 1;
1102 printf (" case %u:\n", (unsigned int)(opnd - operands));
1103 opnd->processed = 1;
1104 for (; j < num; ++j, ++opnd2)
1106 if (!opnd2->processed
1107 && opnd2->has_extractor
1108 && len == strlen (opnd2->extractor)
1109 && strncmp (opnd->extractor, opnd2->extractor, len) == 0)
1111 printf (" case %u:\n", (unsigned int)(opnd2 - operands));
1112 opnd2->processed = 1;
1115 printf (" return aarch64_%s (self, info, code, inst, errors);\n",
1116 opnd->extractor);
1120 printf (" default: assert (0); abort ();\n");
1121 printf (" }\n");
1122 printf ("}\n");
1125 /* Table indexed by opcode enumerator stores the index of the corresponding
1126 opcode entry in aarch64_opcode_table. */
1127 static unsigned op_enum_table [OP_TOTAL_NUM];
1129 /* Print out the routine which, given the opcode enumerator, returns the
1130 corresponding opcode entry pointer. */
1132 static void
1133 print_get_opcode (void)
1135 int i;
1136 const int num = OP_TOTAL_NUM;
1137 const aarch64_opcode *opcode;
1139 if (debug)
1140 printf ("Enter print_get_opcode\n");
1142 /* Fill in the internal table. */
1143 opcode = aarch64_opcode_table;
1144 while (opcode->name != NULL)
1146 if (opcode->op != OP_NIL)
1148 /* Assert opcode enumerator be unique, in other words, no shared by
1149 different opcodes. */
1150 if (op_enum_table[opcode->op] != 0)
1152 fprintf (stderr, "Opcode %u is shared by different %s and %s.\n",
1153 opcode->op,
1154 aarch64_opcode_table[op_enum_table[opcode->op]].name,
1155 opcode->name);
1156 assert (0);
1157 abort ();
1159 assert (opcode->op < OP_TOTAL_NUM);
1160 op_enum_table[opcode->op] = opcode - aarch64_opcode_table;
1162 ++opcode;
1165 /* Print the table. */
1166 printf ("\n");
1167 printf ("/* Indexed by an enum aarch64_op enumerator, the value is the offset of\n\
1168 the corresponding aarch64_opcode entry in the aarch64_opcode_table. */\n\n");
1169 printf ("static const unsigned op_enum_table [] =\n");
1170 printf ("{\n");
1171 for (i = 0; i < num; ++i)
1172 printf (" %u,\n", op_enum_table[i]);
1173 printf ("};\n");
1175 /* Print the function. */
1176 printf ("\n");
1177 printf ("/* Given the opcode enumerator OP, return the pointer to the corresponding\n");
1178 printf (" opcode entry. */\n");
1179 printf ("\n");
1180 printf ("const aarch64_opcode *\n");
1181 printf ("aarch64_get_opcode (enum aarch64_op op)\n");
1182 printf ("{\n");
1183 printf (" return aarch64_opcode_table + op_enum_table[op];\n");
1184 printf ("}\n");
1187 /* Print out the content of an opcode table (not in use). */
1188 static void ATTRIBUTE_UNUSED
1189 print_table (struct aarch64_opcode* table)
1191 struct aarch64_opcode *ent = table;
1194 printf ("%s\t%08x\t%08x\n", ent->name, (unsigned int)ent->opcode,
1195 (unsigned int)ent->mask);
1196 } while ((++ent)->name);
1199 static const char * program_name = NULL;
1201 /* Program options. */
1202 struct option long_options[] =
1204 {"debug", no_argument, NULL, 'd'},
1205 {"version", no_argument, NULL, 'V'},
1206 {"help", no_argument, NULL, 'h'},
1207 {"gen-opc", no_argument, NULL, 'c'},
1208 {"gen-asm", no_argument, NULL, 'a'},
1209 {"gen-dis", no_argument, NULL, 's'},
1210 {0, no_argument, NULL, 0}
1213 static void
1214 print_version (void)
1216 printf ("%s: version 1.0\n", program_name);
1217 xexit (0);
1220 static void
1221 usage (FILE * stream, int status)
1223 fprintf (stream, "Usage: %s [-V | --version] [-d | --debug] [--help]\n",
1224 program_name);
1225 fprintf (stream, "\t[ [-c | --gen-opc] | [-a | --gen-asm] | [-s | --gen-dis] ]\n");
1226 xexit (status);
1230 main (int argc, char **argv)
1232 extern int chdir (char *);
1233 int c;
1234 int gen_opcode_p = 0;
1235 int gen_assembler_p = 0;
1236 int gen_disassembler_p = 0;
1238 program_name = *argv;
1239 xmalloc_set_program_name (program_name);
1241 while ((c = getopt_long (argc, argv, "vVdhacs", long_options, 0)) != EOF)
1242 switch (c)
1244 case 'V':
1245 case 'v':
1246 print_version ();
1247 break;
1248 case 'd':
1249 debug = 1;
1250 break;
1251 case 'h':
1252 case '?':
1253 usage (stderr, 0);
1254 break;
1255 case 'c':
1256 gen_opcode_p = 1;
1257 break;
1258 case 'a':
1259 gen_assembler_p = 1;
1260 break;
1261 case 's':
1262 gen_disassembler_p = 1;
1263 break;
1264 default:
1265 case 0:
1266 break;
1269 if (argc == 1 || optind != argc)
1270 usage (stdout, 1);
1272 if (gen_opcode_p + gen_assembler_p + gen_disassembler_p > 1)
1274 printf ("Please specify only one of the following options\n\
1275 [-c | --gen-opc] [-a | --gen-asm] [-s | --gen-dis]\n");
1276 xexit (2);
1279 struct bittree *decoder_tree;
1281 decoder_tree = initialize_decoder_tree ();
1282 if (debug)
1283 print_divide_result (decoder_tree);
1285 printf ("/* This file is automatically generated by aarch64-gen. Do not edit! */\n");
1286 printf ("/* Copyright (C) 2012-2024 Free Software Foundation, Inc.\n\
1287 Contributed by ARM Ltd.\n\
1289 This file is part of the GNU opcodes library.\n\
1291 This library is free software; you can redistribute it and/or modify\n\
1292 it under the terms of the GNU General Public License as published by\n\
1293 the Free Software Foundation; either version 3, or (at your option)\n\
1294 any later version.\n\
1296 It is distributed in the hope that it will be useful, but WITHOUT\n\
1297 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY\n\
1298 or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public\n\
1299 License for more details.\n\
1301 You should have received a copy of the GNU General Public License\n\
1302 along with this program; see the file COPYING3. If not,\n\
1303 see <http://www.gnu.org/licenses/>. */\n");
1305 printf ("\n");
1306 printf ("#include \"sysdep.h\"\n");
1307 if (gen_opcode_p)
1308 printf ("#include \"aarch64-opc.h\"\n");
1309 if (gen_assembler_p)
1310 printf ("#include \"aarch64-asm.h\"\n");
1311 if (gen_disassembler_p)
1312 printf ("#include \"aarch64-dis.h\"\n");
1313 printf ("\n");
1315 /* Generate opcode entry lookup for the disassembler. */
1316 if (gen_disassembler_p)
1318 print_decision_tree (decoder_tree);
1319 print_find_next_opcode (decoder_tree);
1320 release_resource_decoder_tree (decoder_tree);
1323 /* Generate alias opcode handling for the assembler or the disassembler. */
1324 if (gen_assembler_p || gen_disassembler_p)
1326 int num;
1327 opcode_node *alias_info = create_alias_info (&num);
1329 if (gen_assembler_p)
1330 print_find_real_opcode (alias_info, num);
1332 if (gen_disassembler_p)
1334 print_find_alias_opcode (alias_info, num);
1335 print_find_next_alias_opcode (alias_info, num);
1338 release_resource_alias_info (alias_info, num);
1341 /* Generate operand table. */
1342 process_operand_table ();
1344 if (gen_assembler_p)
1345 print_operand_inserter ();
1347 if (gen_disassembler_p)
1348 print_operand_extractor ();
1350 if (gen_opcode_p)
1351 print_operand_table ();
1353 /* Generate utility to return aarch64_opcode entry given an enumerator. */
1354 if (gen_opcode_p)
1355 print_get_opcode ();
1357 exit (0);