aarch64-gen.c revision 1.1.1.8 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.
5
6 This file is part of the GNU opcodes library.
7
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.
12
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.
17
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/>. */
21
22 #include "sysdep.h"
23 #include <stdio.h>
24 #include <stdlib.h>
25 #include <stdarg.h>
26
27 #include "libiberty.h"
28 #include "getopt.h"
29 #include "opcode/aarch64.h"
30
31 #define VERIFIER(x) NULL
32 #include "aarch64-tbl.h"
33
34 static int debug = 0;
35
36 /* Structure used in the decoding tree to group a list of aarch64_opcode
37 entries. */
38
39 struct opcode_node
40 {
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;
47 };
48
49 typedef struct opcode_node opcode_node;
50
51 /* Head of the list of the opcode_node after read_table. */
52 static opcode_node opcode_nodes_head;
53
54 /* Node in the decoding tree. */
55
56 struct bittree
57 {
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;
63 };
64
65 /* Allocate and initialize an opcode_node. */
66 static opcode_node*
67 new_opcode_node (void)
68 {
69 opcode_node* ent = malloc (sizeof (opcode_node));
70
71 if (!ent)
72 abort ();
73
74 ent->opcode = 0;
75 ent->mask = 0;
76 ent->index = -1;
77 ent->next = NULL;
78
79 return ent;
80 }
81
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};
89
90 /* Use top 2 bits to indiate which table. */
91 static unsigned int
92 initialize_index (const struct aarch64_opcode* table)
93 {
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;
103 }
104
105 static inline const struct aarch64_opcode *
106 index2table (unsigned int index)
107 {
108 return aarch64_opcode_tables[(index >> 30) & 0x3];
109 }
110
111 static inline unsigned int
112 real_index (unsigned int index)
113 {
114 return index & ((1 << 30) - 1);
115 }
116
117 /* Given OPCODE_NODE, return the corresponding aarch64_opcode*. */
118 static const aarch64_opcode*
119 get_aarch64_opcode (const opcode_node *opcode_node)
120 {
121 if (opcode_node == NULL)
122 return NULL;
123 return &index2table (opcode_node->index)[real_index (opcode_node->index)];
124 }
125
126 static void
127 read_table (const struct aarch64_opcode* table)
128 {
129 const struct aarch64_opcode *ent = table;
130 opcode_node **new_ent;
131 unsigned int index = initialize_index (table);
132 unsigned int errors = 0;
133
134 if (!ent->name)
135 return;
136
137 new_ent = &opcode_nodes_head.next;
138
139 while (*new_ent)
140 new_ent = &(*new_ent)->next;
141
142 do
143 {
144 bool match = false;
145
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))
152 {
153 index++;
154 continue;
155 }
156
157 /* Check tied_operand against operands[]. */
158 for (unsigned int i = 1; i < ARRAY_SIZE (ent->operands); ++i)
159 {
160 if (ent->operands[i] == AARCH64_OPND_NIL)
161 break;
162
163 if (ent->operands[i] != ent->operands[0])
164 continue;
165 match = true;
166
167 if (i != ent->tied_operand)
168 {
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;
173 }
174 }
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)
178 {
179 fprintf (stderr, "%s: no operands match, but tied=%u\n",
180 ent->name, ent->tied_operand);
181 ++errors;
182 }
183
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);
190
191 if (errors)
192 {
193 fprintf (stderr, "%u errors, exiting\n", errors);
194 xexit (3);
195 }
196 }
197
198 static inline void
199 print_one_opcode_node (opcode_node* ent)
200 {
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));
204 }
205
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)
210 {
211 opcode_node* ent = opcode_nodes_head.next;
212 printf ("print_opcode_nodes table:\n");
213 while (ent)
214 {
215 print_one_opcode_node (ent);
216 ent = ent->next;
217 }
218 }
219
220 static struct bittree*
221 new_bittree_node (void)
222 {
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;
231 }
232
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;
239
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.
244
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.
248
249 The function recursively call itself until OPCODE is undividable.
250
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). */
260
261 static void
262 divide_table_1 (struct bittree *bittree, opcode_node *opcode)
263 {
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;
270
271 ++depth;
272
273 if (debug)
274 printf ("Enter into depth %d\n", depth);
275
276 assert (opcode != NULL);
277
278 /* Succeed when there is only one opcode left. */
279 if (!opcode->next)
280 {
281 if (debug)
282 {
283 printf ("opcode isolated:\n");
284 print_one_opcode_node (opcode);
285 }
286 goto divide_table_1_finish;
287 }
288
289 divide_table_1_try_again:
290 mask_and = -1;
291 ent = opcode;
292 while (ent)
293 {
294 mask_and &= ent->mask;
295 ent = ent->next;
296 }
297
298 if (debug)
299 printf ("mask and result: %08x\n", (unsigned int)mask_and);
300
301 /* If no more bit to look into, we have to accept the reality then. */
302 if (!mask_and)
303 {
304 int i;
305 opcode_node *ptr;
306 if (debug)
307 {
308 ptr = opcode;
309 printf ("Isolated opcode group:\n");
310 do {
311 print_one_opcode_node (ptr);
312 ptr = ptr->next;
313 } while (ptr);
314 }
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;
321 }
322
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);
328
329 if (debug)
330 printf ("use bit %d\n", bitno);
331
332 /* Record in the bittree. */
333 bittree->bitno = bitno;
334
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)
342 {
343 if (ent->opcode & bitmask)
344 {
345 ent->mask &= (~bitmask);
346 *ptr1 = ent;
347 ent = ent->next;
348 (*ptr1)->next = NULL;
349 ptr1 = &(*ptr1)->next;
350 }
351 else
352 {
353 ent->mask &= (~bitmask);
354 *ptr0 = ent;
355 ent = ent->next;
356 (*ptr0)->next = NULL;
357 ptr0 = &(*ptr0)->next;
358 }
359 }
360
361 /* If BITNO can NOT divide the opcode group, try next bit. */
362 if (list0.next == NULL)
363 {
364 opcode = list1.next;
365 goto divide_table_1_try_again;
366 }
367 else if (list1.next == NULL)
368 {
369 opcode = list0.next;
370 goto divide_table_1_try_again;
371 }
372
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);
378
379 divide_table_1_finish:
380 if (debug)
381 printf ("Leave from depth %d\n", depth);
382 --depth;
383
384 /* Record the opcode entries on this leaf node. */
385 bittree->list = opcode;
386
387 return;
388 }
389
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)
394 {
395 struct bittree *bittree = new_bittree_node ();
396 divide_table_1 (bittree, opcode_nodes_head.next);
397 return bittree;
398 }
399
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)
404 {
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 ();
413 }
414
415 static void __attribute__ ((format (printf, 2, 3)))
416 indented_print (unsigned int indent, const char *format, ...)
417 {
418 va_list ap;
419 va_start (ap, format);
420 printf ("%*s", (int) indent, "");
421 vprintf (format, ap);
422 va_end (ap);
423 }
424
425 /* N.B. read the comment above divide_table_1 for the reason why the generated
426 decision tree function never returns NULL. */
427
428 static void
429 print_decision_tree_1 (unsigned int indent, struct bittree* bittree)
430 {
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);
437
438 /* Leaf node located. */
439 if (bittree->bits[0] == NULL && bittree->bits[1] == NULL)
440 {
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;
450 }
451
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';
464 }
465
466 /* Generate aarch64_opcode_lookup in C code to the standard output. */
467
468 static void
469 print_decision_tree (struct bittree* bittree)
470 {
471 if (debug)
472 printf ("Enter print_decision_tree\n");
473
474 printf ("/* Called by aarch64_opcode_lookup. */\n\n");
475
476 printf ("static int\n");
477 printf ("aarch64_opcode_lookup_1 (uint32_t word)\n");
478 printf ("{\n");
479
480 print_decision_tree_1 (2, bittree);
481
482 printf ("}\n\n");
483
484
485 printf ("/* Lookup opcode WORD in the opcode table. N.B. all alias\n");
486 printf (" opcodes are ignored here. */\n\n");
487
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");
493 }
494
495 static void
496 print_find_next_opcode_1 (struct bittree* bittree)
497 {
498 assert (bittree != NULL);
499
500 /* Leaf node located. */
501 if (bittree->bits[0] == NULL && bittree->bits[1] == NULL)
502 {
503 assert (bittree->list != NULL);
504 /* Find multiple opcode entries in one leaf node. */
505 if (bittree->list->next != NULL)
506 {
507 opcode_node *list = bittree->list;
508 while (list != NULL)
509 {
510 const aarch64_opcode *curr = get_aarch64_opcode (list);
511 const aarch64_opcode *next = get_aarch64_opcode (list->next);
512
513 printf (" case %u: ",
514 (unsigned int)(curr - aarch64_opcode_table));
515 if (list->next != NULL)
516 {
517 printf ("value = %u; break;\t", real_index (list->next->index));
518 printf ("/* %s --> %s. */\n", curr->name, next->name);
519 }
520 else
521 {
522 printf ("return NULL;\t\t");
523 printf ("/* %s --> NULL. */\n", curr->name);
524 }
525
526 list = list->next;
527 }
528 }
529 return;
530 }
531
532 /* Walk down the decoder tree. */
533 print_find_next_opcode_1 (bittree->bits[0]);
534 print_find_next_opcode_1 (bittree->bits[1]);
535 }
536
537 /* Generate aarch64_find_next_opcode in C code to the standard output. */
538
539 static void
540 print_find_next_opcode (struct bittree* bittree)
541 {
542 if (debug)
543 printf ("Enter print_find_next_opcode\n");
544
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");
554
555 print_find_next_opcode_1 (bittree);
556
557 printf (" default: return NULL;\n");
558 printf (" }\n\n");
559
560 printf (" return aarch64_opcode_table + value;\n");
561 printf ("}\n");
562 }
563
564 /* Release the dynamic memory resource allocated for the generation of the
565 decoder tree. */
566
567 static void
568 release_resource_decoder_tree (struct bittree* bittree)
569 {
570 assert (bittree != NULL);
571
572 /* Leaf node located. */
573 if (bittree->bits[0] == NULL && bittree->bits[1] == NULL)
574 {
575 assert (bittree->list != NULL);
576 /* Free opcode_nodes. */
577 opcode_node *list = bittree->list;
578 while (list != NULL)
579 {
580 opcode_node *next = list->next;
581 free (list);
582 list = next;
583 }
584 /* Free the tree node. */
585 free (bittree);
586 return;
587 }
588
589 /* Walk down the decoder tree. */
590 release_resource_decoder_tree (bittree->bits[0]);
591 release_resource_decoder_tree (bittree->bits[1]);
592
593 /* Free the tree node. */
594 free (bittree);
595 }
596
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. */
600
601 static void
602 print_find_real_opcode (const opcode_node *table, int num)
603 {
604 int i;
605
606 if (debug)
607 printf ("Enter print_find_real_opcode\n");
608
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");
618
619 for (i = 0; i < num; ++i)
620 {
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");
629 }
630
631 printf (" default: return NULL;\n");
632 printf (" }\n\n");
633
634 printf (" return aarch64_opcode_table + value;\n");
635 printf ("}\n");
636 }
637
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. */
641
642 static void
643 print_find_alias_opcode (const opcode_node *table, int num)
644 {
645 int i;
646
647 if (debug)
648 printf ("Enter print_find_alias_opcode\n");
649
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");
659
660 for (i = 0; i < num; ++i)
661 {
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);
668 }
669
670 printf (" default: return NULL;\n");
671 printf (" }\n\n");
672
673 printf (" return aarch64_opcode_table + value;\n");
674 printf ("}\n");
675 }
676
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. */
680
681 static void
682 print_find_next_alias_opcode (const opcode_node *table, int num)
683 {
684 int i;
685
686 if (debug)
687 printf ("Enter print_find_next_alias_opcode\n");
688
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");
698
699 for (i = 0; i < num; ++i)
700 {
701 const opcode_node *node = table + i;
702 assert (node->next);
703 if (node->next->next == NULL)
704 continue;
705 while (node->next->next)
706 {
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;
713 }
714 }
715
716 printf (" default: return NULL;\n");
717 printf (" }\n\n");
718
719 printf (" return aarch64_opcode_table + value;\n");
720 printf ("}\n");
721 }
722
723 /* Given OPCODE, establish and return a link list of alias nodes in the
724 preferred order. */
725
726 opcode_node *
727 find_alias_opcode (const aarch64_opcode *opcode)
728 {
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;
735
736 assert (opcode_has_alias (opcode));
737
738 i = 0;
739 if (opcode->name != NULL)
740 preferred[i++] = opcode;
741 ent = aarch64_opcode_table;
742 while (ent->name != NULL)
743 {
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))
750 {
751 assert (i < max_num_aliases);
752 preferred[i++] = ent;
753 if (debug)
754 printf ("found %s for %s.", ent->name, opcode->name);
755 }
756 ++ent;
757 }
758
759 if (debug)
760 {
761 int m;
762 printf ("un-orderd list: ");
763 for (m = 0; m < i; ++m)
764 printf ("%s, ", preferred[m]->name);
765 printf ("\n");
766 }
767
768 /* There must be at least one alias. */
769 assert (i >= 1);
770
771 /* Sort preferred array according to the priority (from the lowest to the
772 highest. */
773 if (i > 1)
774 {
775 int j, k;
776 for (j = 0; j < i - 1; ++j)
777 {
778 for (k = 0; k < i - 1 - j; ++k)
779 {
780 const aarch64_opcode *t;
781 t = preferred [k+1];
782 if (opcode_priority (t) < opcode_priority (preferred [k]))
783 {
784 preferred [k+1] = preferred [k];
785 preferred [k] = t;
786 }
787 }
788 }
789 }
790
791 if (debug)
792 {
793 int m;
794 printf ("orderd list: ");
795 for (m = 0; m < i; ++m)
796 printf ("%s, ", preferred[m]->name);
797 printf ("\n");
798 }
799
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)
805 {
806 const aarch64_opcode *alias = preferred [i];
807 opcode_node *node = new_opcode_node ();
808
809 if (debug)
810 printf ("add %s.\n", alias->name);
811
812 node->index = alias - aarch64_opcode_table;
813 *next = node;
814 next = &node->next;
815
816 --i;
817 }
818 *next = NULL;
819
820 return head.next;
821 }
822
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. */
826
827 opcode_node *
828 create_alias_info (int *num_ptr)
829 {
830 int i, num;
831 opcode_node *ret;
832 const aarch64_opcode *ent;
833
834 /* Calculate the total number of opcodes that have alias. */
835 num = 0;
836 ent = aarch64_opcode_table;
837 while (ent->name != NULL)
838 {
839 if (opcode_has_alias (ent))
840 {
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;
846 }
847 ++ent;
848 }
849 assert (num_ptr);
850 *num_ptr = num;
851
852 /* The array of real opcodes that have alias(es). */
853 ret = malloc (sizeof (opcode_node) * num);
854
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)
858 {
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);
866 }
867 assert (i == num);
868
869 return ret;
870 }
871
872 /* Release the dynamic memory resource allocated for the generation of the
873 alias information. */
874
875 void
876 release_resource_alias_info (opcode_node *alias_info, int num)
877 {
878 int i = 0;
879 opcode_node *node = alias_info;
880
881 /* Free opcode_node list. */
882 for (; i < num; ++i, ++node)
883 {
884 opcode_node *list = node->next;
885 do
886 {
887 opcode_node *next = list->next;
888 free (list);
889 list = next;
890 } while (list != NULL);
891 }
892
893 /* Free opcode_node array. */
894 free (alias_info);
895 }
896
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)
901 {
902 printf ("max_num_opcodes_at_leaf_node: %d\n", max_num_opcodes_at_leaf_node);
903 return;
904 }
905
906 /* Structure to help generate the operand table. */
908 struct operand
909 {
910 const char *class;
911 const char *inserter;
912 const char *extractor;
913 const char *str;
914 const char *flags;
915 const char *fields;
916 const char *desc;
917 unsigned processed : 1;
918 unsigned has_inserter : 1;
919 unsigned has_extractor : 1;
920 };
921
922 typedef struct operand operand;
923
924 #ifdef X
925 #undef X
926 #endif
927
928 #ifdef Y
929 #undef Y
930 #endif
931
932 #ifdef F
933 #undef F
934 #endif
935
936 /* Get the operand information in strings. */
937
938 static operand operands[] =
939 {
940 {"NIL", "0", "0", "", "0", "{0}", "<none>", 0, 0, 0},
941 #define F(...) #__VA_ARGS__
942 #define X(a,b,c,d,e,f,g) \
943 {#a, #b, #c, d, #e, "{"f"}", g, 0, 0, 0},
944 #define Y(a,b,d,e,f,g) \
945 {#a, "ins_"#b, "ext_"#b, d, #e, "{"f"}", g, 0, 0, 0},
946 AARCH64_OPERANDS
947 {"NIL", "0", "0", "", "0", "{0}", "DUMMY", 0, 0, 0},
948 };
949
950 #undef F
951 #undef X
952
953 static void
954 process_operand_table (void)
955 {
956 int i;
957 operand *opnd;
958 const int num = sizeof (operands) / sizeof (operand);
959
960 for (i = 0, opnd = operands; i < num; ++i, ++opnd)
961 {
962 opnd->has_inserter = opnd->inserter[0] != '0';
963 opnd->has_extractor = opnd->extractor[0] != '0';
964 }
965 }
966
967 /* Generate aarch64_operands in C to the standard output. */
968
969 static void
970 print_operand_table (void)
971 {
972 int i;
973 operand *opnd;
974 const int num = sizeof (operands) / sizeof (operand);
975
976 if (debug)
977 printf ("Enter print_operand_table\n");
978
979 printf ("\n");
980 printf ("const struct aarch64_operand aarch64_operands[] =\n");
981 printf ("{\n");
982
983 for (i = 0, opnd = operands; i < num; ++i, ++opnd)
984 {
985 char flags[256];
986 flags[0] = '\0';
987 if (opnd->flags[0] != '0')
988 sprintf (flags, "%s", opnd->flags);
989 if (opnd->has_inserter)
990 {
991 if (flags[0] != '\0')
992 strcat (flags, " | ");
993 strcat (flags, "OPD_F_HAS_INSERTER");
994 }
995 if (opnd->has_extractor)
996 {
997 if (flags[0] != '\0')
998 strcat (flags, " | ");
999 strcat (flags, "OPD_F_HAS_EXTRACTOR");
1000 }
1001 if (flags[0] == '\0')
1002 {
1003 flags[0] = '0';
1004 flags[1] = '\0';
1005 }
1006 printf (" {AARCH64_OPND_CLASS_%s, \"%s\", %s, %s, \"%s\"},\n",
1007 opnd->class, opnd->str, flags, opnd->fields, opnd->desc);
1008 }
1009 printf ("};\n");
1010 }
1011
1012 /* Generate aarch64_insert_operand in C to the standard output. */
1013
1014 static void
1015 print_operand_inserter (void)
1016 {
1017 int i;
1018 operand *opnd;
1019 const int num = sizeof (operands) / sizeof (operand);
1020
1021 if (debug)
1022 printf ("Enter print_operand_inserter\n");
1023
1024 printf ("\n");
1025 printf ("bool\n");
1026 printf ("aarch64_insert_operand (const aarch64_operand *self,\n\
1027 const aarch64_opnd_info *info,\n\
1028 aarch64_insn *code, const aarch64_inst *inst,\n\
1029 aarch64_operand_error *errors)\n");
1030 printf ("{\n");
1031 printf (" /* Use the index as the key. */\n");
1032 printf (" int key = self - aarch64_operands;\n");
1033 printf (" switch (key)\n");
1034 printf (" {\n");
1035
1036 for (i = 0, opnd = operands; i < num; ++i, ++opnd)
1037 opnd->processed = 0;
1038
1039 for (i = 0, opnd = operands; i < num; ++i, ++opnd)
1040 {
1041 if (!opnd->processed && opnd->has_inserter)
1042 {
1043 int j = i + 1;
1044 const int len = strlen (opnd->inserter);
1045 operand *opnd2 = opnd + 1;
1046 printf (" case %u:\n", (unsigned int)(opnd - operands));
1047 opnd->processed = 1;
1048 for (; j < num; ++j, ++opnd2)
1049 {
1050 if (!opnd2->processed
1051 && opnd2->has_inserter
1052 && len == strlen (opnd2->inserter)
1053 && strncmp (opnd->inserter, opnd2->inserter, len) == 0)
1054 {
1055 printf (" case %u:\n", (unsigned int)(opnd2 - operands));
1056 opnd2->processed = 1;
1057 }
1058 }
1059 printf (" return aarch64_%s (self, info, code, inst, errors);\n",
1060 opnd->inserter);
1061 }
1062 }
1063
1064 printf (" default: assert (0); abort ();\n");
1065 printf (" }\n");
1066 printf ("}\n");
1067 }
1068
1069 /* Generate aarch64_extract_operand in C to the standard output. */
1070
1071 static void
1072 print_operand_extractor (void)
1073 {
1074 int i;
1075 operand *opnd;
1076 const int num = sizeof (operands) / sizeof (operand);
1077
1078 if (debug)
1079 printf ("Enter print_operand_extractor\n");
1080
1081 printf ("\n");
1082 printf ("bool\n");
1083 printf ("aarch64_extract_operand (const aarch64_operand *self,\n\
1084 aarch64_opnd_info *info,\n\
1085 aarch64_insn code, const aarch64_inst *inst,\n\
1086 aarch64_operand_error *errors)\n");
1087 printf ("{\n");
1088 printf (" /* Use the index as the key. */\n");
1089 printf (" int key = self - aarch64_operands;\n");
1090 printf (" switch (key)\n");
1091 printf (" {\n");
1092
1093 for (i = 0, opnd = operands; i < num; ++i, ++opnd)
1094 opnd->processed = 0;
1095
1096 for (i = 0, opnd = operands; i < num; ++i, ++opnd)
1097 {
1098 if (!opnd->processed && opnd->has_extractor)
1099 {
1100 int j = i + 1;
1101 const int len = strlen (opnd->extractor);
1102 operand *opnd2 = opnd + 1;
1103 printf (" case %u:\n", (unsigned int)(opnd - operands));
1104 opnd->processed = 1;
1105 for (; j < num; ++j, ++opnd2)
1106 {
1107 if (!opnd2->processed
1108 && opnd2->has_extractor
1109 && len == strlen (opnd2->extractor)
1110 && strncmp (opnd->extractor, opnd2->extractor, len) == 0)
1111 {
1112 printf (" case %u:\n", (unsigned int)(opnd2 - operands));
1113 opnd2->processed = 1;
1114 }
1115 }
1116 printf (" return aarch64_%s (self, info, code, inst, errors);\n",
1117 opnd->extractor);
1118 }
1119 }
1120
1121 printf (" default: assert (0); abort ();\n");
1122 printf (" }\n");
1123 printf ("}\n");
1124 }
1125
1126 /* Table indexed by opcode enumerator stores the index of the corresponding
1128 opcode entry in aarch64_opcode_table. */
1129 static unsigned op_enum_table [OP_TOTAL_NUM];
1130
1131 /* Print out the routine which, given the opcode enumerator, returns the
1132 corresponding opcode entry pointer. */
1133
1134 static void
1135 print_get_opcode (void)
1136 {
1137 int i;
1138 const int num = OP_TOTAL_NUM;
1139 const aarch64_opcode *opcode;
1140
1141 if (debug)
1142 printf ("Enter print_get_opcode\n");
1143
1144 /* Fill in the internal table. */
1145 opcode = aarch64_opcode_table;
1146 while (opcode->name != NULL)
1147 {
1148 if (opcode->op != OP_NIL)
1149 {
1150 /* Assert opcode enumerator be unique, in other words, no shared by
1151 different opcodes. */
1152 if (op_enum_table[opcode->op] != 0)
1153 {
1154 fprintf (stderr, "Opcode %u is shared by different %s and %s.\n",
1155 opcode->op,
1156 aarch64_opcode_table[op_enum_table[opcode->op]].name,
1157 opcode->name);
1158 assert (0);
1159 abort ();
1160 }
1161 assert (opcode->op < OP_TOTAL_NUM);
1162 op_enum_table[opcode->op] = opcode - aarch64_opcode_table;
1163 }
1164 ++opcode;
1165 }
1166
1167 /* Print the table. */
1168 printf ("\n");
1169 printf ("/* Indexed by an enum aarch64_op enumerator, the value is the offset of\n\
1170 the corresponding aarch64_opcode entry in the aarch64_opcode_table. */\n\n");
1171 printf ("static const unsigned op_enum_table [] =\n");
1172 printf ("{\n");
1173 for (i = 0; i < num; ++i)
1174 printf (" %u,\n", op_enum_table[i]);
1175 printf ("};\n");
1176
1177 /* Print the function. */
1178 printf ("\n");
1179 printf ("/* Given the opcode enumerator OP, return the pointer to the corresponding\n");
1180 printf (" opcode entry. */\n");
1181 printf ("\n");
1182 printf ("const aarch64_opcode *\n");
1183 printf ("aarch64_get_opcode (enum aarch64_op op)\n");
1184 printf ("{\n");
1185 printf (" return aarch64_opcode_table + op_enum_table[op];\n");
1186 printf ("}\n");
1187 }
1188
1189 /* Print out the content of an opcode table (not in use). */
1190 static void ATTRIBUTE_UNUSED
1191 print_table (struct aarch64_opcode* table)
1192 {
1193 struct aarch64_opcode *ent = table;
1194 do
1195 {
1196 printf ("%s\t%08x\t%08x\n", ent->name, (unsigned int)ent->opcode,
1197 (unsigned int)ent->mask);
1198 } while ((++ent)->name);
1199 }
1200
1201 static const char * program_name = NULL;
1203
1204 /* Program options. */
1205 struct option long_options[] =
1206 {
1207 {"debug", no_argument, NULL, 'd'},
1208 {"version", no_argument, NULL, 'V'},
1209 {"help", no_argument, NULL, 'h'},
1210 {"gen-opc", no_argument, NULL, 'c'},
1211 {"gen-asm", no_argument, NULL, 'a'},
1212 {"gen-dis", no_argument, NULL, 's'},
1213 {0, no_argument, NULL, 0}
1214 };
1215
1216 static void
1217 print_version (void)
1218 {
1219 printf ("%s: version 1.0\n", program_name);
1220 xexit (0);
1221 }
1222
1223 static void
1224 usage (FILE * stream, int status)
1225 {
1226 fprintf (stream, "Usage: %s [-V | --version] [-d | --debug] [--help]\n",
1227 program_name);
1228 fprintf (stream, "\t[ [-c | --gen-opc] | [-a | --gen-asm] | [-s | --gen-dis] ]\n");
1229 xexit (status);
1230 }
1231
1232 int
1233 main (int argc, char **argv)
1234 {
1235 extern int chdir (char *);
1236 int c;
1237 int gen_opcode_p = 0;
1238 int gen_assembler_p = 0;
1239 int gen_disassembler_p = 0;
1240
1241 program_name = *argv;
1242 xmalloc_set_program_name (program_name);
1243
1244 while ((c = getopt_long (argc, argv, "vVdhacs", long_options, 0)) != EOF)
1245 switch (c)
1246 {
1247 case 'V':
1248 case 'v':
1249 print_version ();
1250 break;
1251 case 'd':
1252 debug = 1;
1253 break;
1254 case 'h':
1255 case '?':
1256 usage (stderr, 0);
1257 break;
1258 case 'c':
1259 gen_opcode_p = 1;
1260 break;
1261 case 'a':
1262 gen_assembler_p = 1;
1263 break;
1264 case 's':
1265 gen_disassembler_p = 1;
1266 break;
1267 default:
1268 case 0:
1269 break;
1270 }
1271
1272 if (argc == 1 || optind != argc)
1273 usage (stdout, 1);
1274
1275 if (gen_opcode_p + gen_assembler_p + gen_disassembler_p > 1)
1276 {
1277 printf ("Please specify only one of the following options\n\
1278 [-c | --gen-opc] [-a | --gen-asm] [-s | --gen-dis]\n");
1279 xexit (2);
1280 }
1281
1282 struct bittree *decoder_tree;
1283
1284 decoder_tree = initialize_decoder_tree ();
1285 if (debug)
1286 print_divide_result (decoder_tree);
1287
1288 printf ("/* This file is automatically generated by aarch64-gen. Do not edit! */\n");
1289 printf ("/* Copyright (C) 2012-2024 Free Software Foundation, Inc.\n\
1290 Contributed by ARM Ltd.\n\
1291 \n\
1292 This file is part of the GNU opcodes library.\n\
1293 \n\
1294 This library is free software; you can redistribute it and/or modify\n\
1295 it under the terms of the GNU General Public License as published by\n\
1296 the Free Software Foundation; either version 3, or (at your option)\n\
1297 any later version.\n\
1298 \n\
1299 It is distributed in the hope that it will be useful, but WITHOUT\n\
1300 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY\n\
1301 or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public\n\
1302 License for more details.\n\
1303 \n\
1304 You should have received a copy of the GNU General Public License\n\
1305 along with this program; see the file COPYING3. If not,\n\
1306 see <http://www.gnu.org/licenses/>. */\n");
1307
1308 printf ("\n");
1309 printf ("#include \"sysdep.h\"\n");
1310 if (gen_opcode_p)
1311 printf ("#include \"aarch64-opc.h\"\n");
1312 if (gen_assembler_p)
1313 printf ("#include \"aarch64-asm.h\"\n");
1314 if (gen_disassembler_p)
1315 printf ("#include \"aarch64-dis.h\"\n");
1316 printf ("\n");
1317
1318 /* Generate opcode entry lookup for the disassembler. */
1319 if (gen_disassembler_p)
1320 {
1321 print_decision_tree (decoder_tree);
1322 print_find_next_opcode (decoder_tree);
1323 release_resource_decoder_tree (decoder_tree);
1324 }
1325
1326 /* Generate alias opcode handling for the assembler or the disassembler. */
1327 if (gen_assembler_p || gen_disassembler_p)
1328 {
1329 int num;
1330 opcode_node *alias_info = create_alias_info (&num);
1331
1332 if (gen_assembler_p)
1333 print_find_real_opcode (alias_info, num);
1334
1335 if (gen_disassembler_p)
1336 {
1337 print_find_alias_opcode (alias_info, num);
1338 print_find_next_alias_opcode (alias_info, num);
1339 }
1340
1341 release_resource_alias_info (alias_info, num);
1342 }
1343
1344 /* Generate operand table. */
1345 process_operand_table ();
1346
1347 if (gen_assembler_p)
1348 print_operand_inserter ();
1349
1350 if (gen_disassembler_p)
1351 print_operand_extractor ();
1352
1353 if (gen_opcode_p)
1354 print_operand_table ();
1355
1356 /* Generate utility to return aarch64_opcode entry given an enumerator. */
1357 if (gen_opcode_p)
1358 print_get_opcode ();
1359
1360 exit (0);
1361 }
1362