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)
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/>. */
27 #include "libiberty.h"
29 #include "opcode/aarch64.h"
31 #define VERIFIER(x) NULL
32 #include "aarch64-tbl.h"
36 /* Structure used in the decoding tree to group a list of aarch64_opcode
43 /* Index of the entry in the original table; the top 2 bits help
44 determine the table. */
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. */
59 /* 0, 1, and X (don't care). */
60 struct bittree
*bits
[2];
61 /* List of opcodes; only valid for the leaf node. */
65 /* Allocate and initialize an opcode_node. */
67 new_opcode_node (void)
69 opcode_node
* ent
= malloc (sizeof (opcode_node
));
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. */
92 initialize_index (const struct aarch64_opcode
* table
)
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
])
100 if (i
== num_of_tables
)
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
)
123 return &index2table (opcode_node
->index
)[real_index (opcode_node
->index
)];
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;
137 new_ent
= &opcode_nodes_head
.next
;
140 new_ent
= &(*new_ent
)->next
;
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
))
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
)
163 if (ent
->operands
[i
] != ent
->operands
[0])
167 if (i
!= ent
->tied_operand
)
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
);
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
);
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
);
193 fprintf (stderr
, "%u errors, exiting\n", errors
);
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. */
209 print_opcode_nodes (void)
211 opcode_node
* ent
= opcode_nodes_head
.next
;
212 printf ("print_opcode_nodes table:\n");
215 print_one_opcode_node (ent
);
220 static struct bittree
*
221 new_bittree_node (void)
223 struct bittree
* node
;
224 node
= malloc (sizeof (struct bittree
));
228 node
->bits
[0] = NULL
;
229 node
->bits
[1] = NULL
;
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
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
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). */
262 divide_table_1 (struct bittree
*bittree
, opcode_node
*opcode
)
264 aarch64_insn mask_and
;
267 aarch64_insn bitmask
;
268 opcode_node list0
, list1
, **ptr0
, **ptr1
;
269 static int depth
= 0;
274 printf ("Enter into depth %d\n", depth
);
276 assert (opcode
!= NULL
);
278 /* Succeed when there is only one opcode left. */
283 printf ("opcode isolated:\n");
284 print_one_opcode_node (opcode
);
286 goto divide_table_1_finish
;
289 divide_table_1_try_again
:
294 mask_and
&= ent
->mask
;
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. */
309 printf ("Isolated opcode group:\n");
311 print_one_opcode_node (ptr
);
315 /* Count the number of opcodes. */
316 for (i
= 0, ptr
= opcode
; ptr
; ++i
)
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. */
325 while (!(mask_and
& (1 << bitno
)))
327 bitmask
= (1 << bitno
);
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. */
343 if (ent
->opcode
& bitmask
)
345 ent
->mask
&= (~bitmask
);
348 (*ptr1
)->next
= NULL
;
349 ptr1
= &(*ptr1
)->next
;
353 ent
->mask
&= (~bitmask
);
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
)
365 goto divide_table_1_try_again
;
367 else if (list1
.next
== NULL
)
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
:
381 printf ("Leave from depth %d\n", depth
);
384 /* Record the opcode entries on this leaf node. */
385 bittree
->list
= opcode
;
390 /* Call divide_table_1 to divide the all the opcodes and thus create the
391 decoding decision tree. */
392 static struct bittree
*
395 struct bittree
*bittree
= new_bittree_node ();
396 divide_table_1 (bittree
, opcode_nodes_head
.next
);
400 /* Read in all of the tables, create the decoding decision tree and return
402 static struct bittree
*
403 initialize_decoder_tree (void)
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
]);
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
, ...)
419 va_start (ap
, format
);
420 printf ("%*s", (int) indent
, "");
421 vprintf (format
, ap
);
425 /* N.B. read the comment above divide_table_1 for the reason why the generated
426 decision tree function never returns NULL. */
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
));
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. */
469 print_decision_tree (struct bittree
* bittree
)
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");
480 print_decision_tree_1 (2, bittree
);
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");
491 printf (" return aarch64_opcode_table + aarch64_opcode_lookup_1 (word);\n");
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
;
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
);
522 printf ("return NULL;\t\t");
523 printf ("/* %s --> NULL. */\n", curr
->name
);
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. */
540 print_find_next_opcode (struct bittree
* bittree
)
543 printf ("Enter print_find_next_opcode\n");
546 printf ("const aarch64_opcode *\n");
547 printf ("aarch64_find_next_opcode (const aarch64_opcode *opcode)\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");
555 print_find_next_opcode_1 (bittree
);
557 printf (" default: return NULL;\n");
560 printf (" return aarch64_opcode_table + value;\n");
564 /* Release the dynamic memory resource allocated for the generation of the
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
;
580 opcode_node
*next
= list
->next
;
584 /* Free the tree node. */
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. */
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. */
602 print_find_real_opcode (const opcode_node
*table
, int num
)
607 printf ("Enter print_find_real_opcode\n");
610 printf ("const aarch64_opcode *\n");
611 printf ("aarch64_find_real_opcode (const aarch64_opcode *opcode)\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");
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");
634 printf (" return aarch64_opcode_table + value;\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. */
643 print_find_alias_opcode (const opcode_node
*table
, int num
)
648 printf ("Enter print_find_alias_opcode\n");
651 printf ("const aarch64_opcode *\n");
652 printf ("aarch64_find_alias_opcode (const aarch64_opcode *opcode)\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");
660 for (i
= 0; i
< num
; ++i
)
662 const opcode_node
*node
= table
+ i
;
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");
673 printf (" return aarch64_opcode_table + value;\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. */
682 print_find_next_alias_opcode (const opcode_node
*table
, int num
)
687 printf ("Enter print_find_next_alias_opcode\n");
690 printf ("const aarch64_opcode *\n");
691 printf ("aarch64_find_next_alias_opcode (const aarch64_opcode *opcode)\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");
699 for (i
= 0; i
< num
; ++i
)
701 const opcode_node
*node
= table
+ i
;
703 if (node
->next
->next
== NULL
)
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
);
716 printf (" default: return NULL;\n");
719 printf (" return aarch64_opcode_table + value;\n");
723 /* Given OPCODE, establish and return a link list of alias nodes in the
727 find_alias_opcode (const aarch64_opcode
*opcode
)
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
));
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
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
;
754 printf ("found %s for %s.", ent
->name
, opcode
->name
);
762 printf ("un-orderd list: ");
763 for (m
= 0; m
< i
; ++m
)
764 printf ("%s, ", preferred
[m
]->name
);
768 /* There must be at least one alias. */
771 /* Sort preferred array according to the priority (from the lowest to the
776 for (j
= 0; j
< i
- 1; ++j
)
778 for (k
= 0; k
< i
- 1 - j
; ++k
)
780 const aarch64_opcode
*t
;
782 if (opcode_priority (t
) < opcode_priority (preferred
[k
]))
784 preferred
[k
+1] = preferred
[k
];
794 printf ("orderd list: ");
795 for (m
= 0; m
< i
; ++m
)
796 printf ("%s, ", preferred
[m
]->name
);
800 /* Create a link-list of opcode_node with disassemble preference from
806 const aarch64_opcode
*alias
= preferred
[i
];
807 opcode_node
*node
= new_opcode_node ();
810 printf ("add %s.\n", alias
->name
);
812 node
->index
= alias
- aarch64_opcode_table
;
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. */
828 create_alias_info (int *num_ptr
)
832 const aarch64_opcode
*ent
;
834 /* Calculate the total number of opcodes that have alias. */
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
844 assert (!alias_opcode_p (ent
));
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
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
))
862 assert (ent
->name
!= NULL
);
863 node
->index
= ent
- aarch64_opcode_table
;
864 node
->next
= find_alias_opcode (ent
);
872 /* Release the dynamic memory resource allocated for the generation of the
873 alias information. */
876 release_resource_alias_info (opcode_node
*alias_info
, int num
)
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
;
890 } while (list
!= NULL
);
893 /* Free opcode_node array. */
897 /* As a debugging utility, print out the result of the table division, although
898 it is not doing much this moment. */
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
);
906 /* Structure to help generate the operand table. */
910 const char *inserter
;
911 const char *extractor
;
916 unsigned processed
: 1;
917 unsigned has_inserter
: 1;
918 unsigned has_extractor
: 1;
921 typedef struct operand operand
;
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},
946 {"NIL", "0", "0", "", "0", "{0}", "DUMMY", 0, 0, 0},
953 process_operand_table (void)
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. */
969 print_operand_table (void)
973 const int num
= sizeof (operands
) / sizeof (operand
);
976 printf ("Enter print_operand_table\n");
979 printf ("const struct aarch64_operand aarch64_operands[] =\n");
982 for (i
= 0, opnd
= operands
; i
< num
; ++i
, ++opnd
)
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')
1005 printf (" {AARCH64_OPND_CLASS_%s, \"%s\", %s, %s, \"%s\"},\n",
1006 opnd
->class, opnd
->str
, flags
, opnd
->fields
, opnd
->desc
);
1011 /* Generate aarch64_insert_operand in C to the standard output. */
1014 print_operand_inserter (void)
1018 const int num
= sizeof (operands
) / sizeof (operand
);
1021 printf ("Enter print_operand_inserter\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");
1030 printf (" /* Use the index as the key. */\n");
1031 printf (" int key = self - aarch64_operands;\n");
1032 printf (" switch (key)\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
)
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",
1063 printf (" default: assert (0); abort ();\n");
1068 /* Generate aarch64_extract_operand in C to the standard output. */
1071 print_operand_extractor (void)
1075 const int num
= sizeof (operands
) / sizeof (operand
);
1078 printf ("Enter print_operand_extractor\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");
1087 printf (" /* Use the index as the key. */\n");
1088 printf (" int key = self - aarch64_operands;\n");
1089 printf (" switch (key)\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
)
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",
1120 printf (" default: assert (0); abort ();\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. */
1133 print_get_opcode (void)
1136 const int num
= OP_TOTAL_NUM
;
1137 const aarch64_opcode
*opcode
;
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",
1154 aarch64_opcode_table
[op_enum_table
[opcode
->op
]].name
,
1159 assert (opcode
->op
< OP_TOTAL_NUM
);
1160 op_enum_table
[opcode
->op
] = opcode
- aarch64_opcode_table
;
1165 /* Print the table. */
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");
1171 for (i
= 0; i
< num
; ++i
)
1172 printf (" %u,\n", op_enum_table
[i
]);
1175 /* Print the function. */
1177 printf ("/* Given the opcode enumerator OP, return the pointer to the corresponding\n");
1178 printf (" opcode entry. */\n");
1180 printf ("const aarch64_opcode *\n");
1181 printf ("aarch64_get_opcode (enum aarch64_op op)\n");
1183 printf (" return aarch64_opcode_table + op_enum_table[op];\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}
1214 print_version (void)
1216 printf ("%s: version 1.0\n", program_name
);
1221 usage (FILE * stream
, int status
)
1223 fprintf (stream
, "Usage: %s [-V | --version] [-d | --debug] [--help]\n",
1225 fprintf (stream
, "\t[ [-c | --gen-opc] | [-a | --gen-asm] | [-s | --gen-dis] ]\n");
1230 main (int argc
, char **argv
)
1232 extern int chdir (char *);
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
)
1259 gen_assembler_p
= 1;
1262 gen_disassembler_p
= 1;
1269 if (argc
== 1 || optind
!= argc
)
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");
1279 struct bittree
*decoder_tree
;
1281 decoder_tree
= initialize_decoder_tree ();
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");
1306 printf ("#include \"sysdep.h\"\n");
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");
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
)
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 ();
1351 print_operand_table ();
1353 /* Generate utility to return aarch64_opcode entry given an enumerator. */
1355 print_get_opcode ();