1 /* aarch64-gen.c -- Generate tables and routines for opcode lookup and
2 instruction encoding and decoding.
3 Copyright 2012 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 #include "aarch64-tbl.h"
35 /* Structure used in the decoding tree to group a list of aarch64_opcode
42 /* Index of the entry in the original table; the top 2 bits help
43 determine the table. */
45 struct opcode_node
*next
;
48 typedef struct opcode_node opcode_node
;
50 /* Head of the list of the opcode_node after read_table. */
51 static opcode_node opcode_nodes_head
;
53 /* Node in the decoding tree. */
58 /* 0, 1, and X (don't care). */
59 struct bittree
*bits
[2];
60 /* List of opcodes; only valid for the leaf node. */
64 /* Allocate and initialize an opcode_node. */
66 new_opcode_node (void)
68 opcode_node
* ent
= malloc (sizeof (opcode_node
));
81 /* Multiple tables are supported, although currently only one table is
82 in use. N.B. there are still some functions have the table name
83 'aarch64_opcode_table' hard-coded in, e.g. print_find_next_opcode;
84 therefore some amount of work needs to be done if the full support
85 for multiple tables needs to be enabled. */
86 static const struct aarch64_opcode
*aarch64_opcode_tables
[] =
87 {aarch64_opcode_table
};
89 /* Use top 2 bits to indiate which table. */
91 initialize_index (const struct aarch64_opcode
* table
)
94 const int num_of_tables
= sizeof (aarch64_opcode_tables
)
95 / sizeof (struct aarch64_opcode
*);
96 for (i
= 0; i
< num_of_tables
; ++i
)
97 if (table
== aarch64_opcode_tables
[i
])
99 if (i
== num_of_tables
)
101 return (unsigned int)i
<< 30;
104 static inline const struct aarch64_opcode
*
105 index2table (unsigned int index
)
107 return aarch64_opcode_tables
[(index
>> 30) & 0x3];
110 static inline unsigned int
111 real_index (unsigned int index
)
113 return index
& ((1 << 30) - 1);
116 /* Given OPCODE_NODE, return the corresponding aarch64_opcode*. */
117 static const aarch64_opcode
*
118 get_aarch64_opcode (const opcode_node
*opcode_node
)
120 if (opcode_node
== NULL
)
122 return &index2table (opcode_node
->index
)[real_index (opcode_node
->index
)];
126 read_table (const struct aarch64_opcode
* table
)
128 const struct aarch64_opcode
*ent
= table
;
129 opcode_node
**new_ent
;
130 unsigned int index
= initialize_index (table
);
135 new_ent
= &opcode_nodes_head
.next
;
138 new_ent
= &(*new_ent
)->next
;
142 /* F_PSEUDO needs to be used together with F_ALIAS to indicate an alias
143 opcode is a programmer friendly pseudo instruction available only in
144 the assembly code (thus will not show up in the disassembly). */
145 assert (pseudo_opcode_p (ent
) == FALSE
|| alias_opcode_p (ent
) == TRUE
);
146 /* Skip alias (inc. pseudo) opcode. */
147 if (alias_opcode_p (ent
) == TRUE
)
152 *new_ent
= new_opcode_node ();
153 (*new_ent
)->opcode
= ent
->opcode
;
154 (*new_ent
)->mask
= ent
->mask
;
155 (*new_ent
)->index
= index
++;
156 new_ent
= &((*new_ent
)->next
);
157 } while ((++ent
)->name
);
161 print_one_opcode_node (opcode_node
* ent
)
163 printf ("%s\t%08x\t%08x\t%d\n", get_aarch64_opcode (ent
)->name
,
164 get_aarch64_opcode (ent
)->opcode
, get_aarch64_opcode (ent
)->mask
,
165 (int)real_index (ent
->index
));
168 /* As an internal debugging utility, print out the list of nodes pointed
169 by opcode_nodes_head. */
171 print_opcode_nodes (void)
173 opcode_node
* ent
= opcode_nodes_head
.next
;
174 printf ("print_opcode_nodes table:\n");
177 print_one_opcode_node (ent
);
182 static struct bittree
*
183 new_bittree_node (void)
185 struct bittree
* node
;
186 node
= malloc (sizeof (struct bittree
));
190 node
->bits
[0] = NULL
;
191 node
->bits
[1] = NULL
;
195 /* The largest number of opcode entries that exist at a leaf node of the
196 decoding decision tree. The reason that there can be more than one
197 opcode entry is because some opcodes have shared field that is partially
198 constrained and thus cannot be fully isolated using the algorithm
200 static int max_num_opcodes_at_leaf_node
= 0;
202 /* Given a list of opcodes headed by *OPCODE, try to establish one bit that
203 is shared by all the opcodes in the list as one of base opcode bits. If
204 such a bit is found, divide the list of the opcodes into two based on the
207 Store the bit number in BITTREE->BITNO if the division succeeds. If unable
208 to determine such a bit or there is only one opcode in the list, the list
209 is decided to be undividable and OPCODE will be assigned to BITTREE->LIST.
211 The function recursively call itself until OPCODE is undividable.
213 N.B. the nature of this algrithm determines that given any value in the
214 32-bit space, the computed decision tree will always be able to find one or
215 more opcodes entries for it, regardless whether there is a valid instruction
216 defined for this value or not. In order to detect the undefined values,
217 when the caller obtains the opcode entry/entries, it should at least compare
218 the bit-wise AND result of the value and the mask with the base opcode
219 value; if the two are different, it means that the value is undefined
220 (although the value may be still undefined when the comparison is the same,
221 in which case call aarch64_opcode_decode to carry out further checks). */
224 divide_table_1 (struct bittree
*bittree
, opcode_node
*opcode
)
226 aarch64_insn mask_and
;
229 aarch64_insn bitmask
;
230 opcode_node list0
, list1
, **ptr0
, **ptr1
;
231 static int depth
= 0;
236 printf ("Enter into depth %d\n", depth
);
238 assert (opcode
!= NULL
);
240 /* Succeed when there is only one opcode left. */
245 printf ("opcode isolated:\n");
246 print_one_opcode_node (opcode
);
248 goto divide_table_1_finish
;
251 divide_table_1_try_again
:
256 mask_and
&= ent
->mask
;
261 printf ("mask and result: %08x\n", (unsigned int)mask_and
);
263 /* If no more bit to look into, we have to accept the reality then. */
271 printf ("Isolated opcode group:\n");
273 print_one_opcode_node (ptr
);
277 /* Count the number of opcodes. */
278 for (i
= 0, ptr
= opcode
; ptr
; ++i
)
280 if (i
> max_num_opcodes_at_leaf_node
)
281 max_num_opcodes_at_leaf_node
= i
;
282 goto divide_table_1_finish
;
285 /* Pick up the right most bit that is 1. */
287 while (!(mask_and
& (1 << bitno
)))
289 bitmask
= (1 << bitno
);
292 printf ("use bit %d\n", bitno
);
294 /* Record in the bittree. */
295 bittree
->bitno
= bitno
;
297 /* Get two new opcode lists; adjust their masks. */
305 if (ent
->opcode
& bitmask
)
307 ent
->mask
&= (~bitmask
);
310 (*ptr1
)->next
= NULL
;
311 ptr1
= &(*ptr1
)->next
;
315 ent
->mask
&= (~bitmask
);
318 (*ptr0
)->next
= NULL
;
319 ptr0
= &(*ptr0
)->next
;
323 /* If BITNO can NOT divide the opcode group, try next bit. */
324 if (list0
.next
== NULL
)
327 goto divide_table_1_try_again
;
329 else if (list1
.next
== NULL
)
332 goto divide_table_1_try_again
;
335 /* Further divide. */
336 bittree
->bits
[0] = new_bittree_node ();
337 bittree
->bits
[1] = new_bittree_node ();
338 divide_table_1 (bittree
->bits
[0], list0
.next
);
339 divide_table_1 (bittree
->bits
[1], list1
.next
);
341 divide_table_1_finish
:
343 printf ("Leave from depth %d\n", depth
);
346 /* Record the opcode entries on this leaf node. */
347 bittree
->list
= opcode
;
352 /* Call divide_table_1 to divide the all the opcodes and thus create the
353 decoding decision tree. */
354 static struct bittree
*
357 struct bittree
*bittree
= new_bittree_node ();
358 divide_table_1 (bittree
, opcode_nodes_head
.next
);
362 /* Read in all of the tables, create the decoding decision tree and return
364 static struct bittree
*
365 initialize_decoder_tree (void)
368 const int num_of_tables
= (sizeof (aarch64_opcode_tables
)
369 / sizeof (struct aarch64_opcode
*));
370 for (i
= 0; i
< num_of_tables
; ++i
)
371 read_table (aarch64_opcode_tables
[i
]);
373 print_opcode_nodes ();
374 return divide_table ();
377 static void __attribute__ ((format (printf
, 2, 3)))
378 indented_print (unsigned int indent
, const char *format
, ...)
380 /* 80 number of spaces pluc a NULL terminator. */
381 static const char spaces
[81] =
384 va_start (ap
, format
);
385 assert (indent
<= 80);
386 printf ("%s", &spaces
[80 - indent
]);
387 vprintf (format
, ap
);
391 /* N.B. read the comment above divide_table_1 for the reason why the generated
392 decision tree function never returns NULL. */
395 print_decision_tree_1 (unsigned int indent
, struct bittree
* bittree
)
397 /* PATTERN is only used to generate comment in the code. */
398 static char pattern
[33] = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx";
399 assert (bittree
!= NULL
);
401 /* Leaf node located. */
402 if (bittree
->bits
[0] == NULL
&& bittree
->bits
[1] == NULL
)
404 assert (bittree
->list
!= NULL
);
405 indented_print (indent
, "/* 33222222222211111111110000000000\n");
406 indented_print (indent
, " 10987654321098765432109876543210\n");
407 indented_print (indent
, " %s\n", pattern
);
408 indented_print (indent
, " %s. */\n",
409 get_aarch64_opcode (bittree
->list
)->name
);
410 indented_print (indent
, "return %u;\n",
411 real_index (bittree
->list
->index
));
415 /* Walk down the decoder tree. */
416 indented_print (indent
, "if (((word >> %d) & 0x1) == 0)\n", bittree
->bitno
);
417 indented_print (indent
, " {\n");
418 pattern
[bittree
->bitno
] = '0';
419 print_decision_tree_1 (indent
+ 4, bittree
->bits
[0]);
420 indented_print (indent
, " }\n");
421 indented_print (indent
, "else\n");
422 indented_print (indent
, " {\n");
423 pattern
[bittree
->bitno
] = '1';
424 print_decision_tree_1 (indent
+ 4, bittree
->bits
[1]);
425 indented_print (indent
, " }\n");
426 pattern
[bittree
->bitno
] = 'x';
429 /* Generate aarch64_opcode_lookup in C code to the standard output. */
432 print_decision_tree (struct bittree
* bittree
)
435 printf ("Enter print_decision_tree\n");
437 printf ("/* Called by aarch64_opcode_lookup. */\n\n");
439 printf ("static int\n");
440 printf ("aarch64_opcode_lookup_1 (uint32_t word)\n");
443 print_decision_tree_1 (2, bittree
);
448 printf ("/* Lookup opcode WORD in the opcode table. N.B. all alias\n");
449 printf (" opcodes are ignored here. */\n\n");
451 printf ("const aarch64_opcode *\n");
452 printf ("aarch64_opcode_lookup (uint32_t word)\n");
454 printf (" return aarch64_opcode_table + aarch64_opcode_lookup_1 (word);\n");
459 print_find_next_opcode_1 (struct bittree
* bittree
)
461 assert (bittree
!= NULL
);
463 /* Leaf node located. */
464 if (bittree
->bits
[0] == NULL
&& bittree
->bits
[1] == NULL
)
466 assert (bittree
->list
!= NULL
);
467 /* Find multiple opcode entries in one leaf node. */
468 if (bittree
->list
->next
!= NULL
)
470 opcode_node
*list
= bittree
->list
;
473 const aarch64_opcode
*curr
= get_aarch64_opcode (list
);
474 const aarch64_opcode
*next
= get_aarch64_opcode (list
->next
);
476 printf (" case %u: ",
477 (unsigned int)(curr
- aarch64_opcode_table
));
478 if (list
->next
!= NULL
)
480 printf ("value = %u; break;\t", real_index (list
->next
->index
));
481 printf ("/* %s --> %s. */\n", curr
->name
, next
->name
);
485 printf ("return NULL;\t\t");
486 printf ("/* %s --> NULL. */\n", curr
->name
);
495 /* Walk down the decoder tree. */
496 print_find_next_opcode_1 (bittree
->bits
[0]);
497 print_find_next_opcode_1 (bittree
->bits
[1]);
500 /* Generate aarch64_find_next_opcode in C code to the standard output. */
503 print_find_next_opcode (struct bittree
* bittree
)
506 printf ("Enter print_find_next_opcode\n");
509 printf ("const aarch64_opcode *\n");
510 printf ("aarch64_find_next_opcode (const aarch64_opcode *opcode)\n");
512 printf (" /* Use the index as the key to locate the next opcode. */\n");
513 printf (" int key = opcode - aarch64_opcode_table;\n");
514 printf (" int value;\n");
515 printf (" switch (key)\n");
518 print_find_next_opcode_1 (bittree
);
520 printf (" default: return NULL;\n");
523 printf (" return aarch64_opcode_table + value;\n");
527 /* Release the dynamic memory resource allocated for the generation of the
531 release_resource_decoder_tree (struct bittree
* bittree
)
533 assert (bittree
!= NULL
);
535 /* Leaf node located. */
536 if (bittree
->bits
[0] == NULL
&& bittree
->bits
[1] == NULL
)
538 assert (bittree
->list
!= NULL
);
539 /* Free opcode_nodes. */
540 opcode_node
*list
= bittree
->list
;
543 opcode_node
*next
= list
->next
;
547 /* Free the tree node. */
552 /* Walk down the decoder tree. */
553 release_resource_decoder_tree (bittree
->bits
[0]);
554 release_resource_decoder_tree (bittree
->bits
[1]);
556 /* Free the tree node. */
560 /* Generate aarch64_find_real_opcode in C code to the standard output.
561 TABLE points to the alias info table, while NUM indicates the number of
562 entries in the table. */
565 print_find_real_opcode (const opcode_node
*table
, int num
)
570 printf ("Enter print_find_real_opcode\n");
573 printf ("const aarch64_opcode *\n");
574 printf ("aarch64_find_real_opcode (const aarch64_opcode *opcode)\n");
576 printf (" /* Use the index as the key to locate the real opcode. */\n");
577 printf (" int key = opcode - aarch64_opcode_table;\n");
578 printf (" int value;\n");
579 printf (" switch (key)\n");
582 for (i
= 0; i
< num
; ++i
)
584 const opcode_node
*real
= table
+ i
;
585 const opcode_node
*alias
= real
->next
;
586 for (; alias
; alias
= alias
->next
)
587 printf (" case %u:\t/* %s */\n", real_index (alias
->index
),
588 get_aarch64_opcode (alias
)->name
);
589 printf (" value = %u;\t/* --> %s. */\n", real_index (real
->index
),
590 get_aarch64_opcode (real
)->name
);
591 printf (" break;\n");
594 printf (" default: return NULL;\n");
597 printf (" return aarch64_opcode_table + value;\n");
601 /* Generate aarch64_find_alias_opcode in C code to the standard output.
602 TABLE points to the alias info table, while NUM indicates the number of
603 entries in the table. */
606 print_find_alias_opcode (const opcode_node
*table
, int num
)
611 printf ("Enter print_find_alias_opcode\n");
614 printf ("const aarch64_opcode *\n");
615 printf ("aarch64_find_alias_opcode (const aarch64_opcode *opcode)\n");
617 printf (" /* Use the index as the key to locate the alias opcode. */\n");
618 printf (" int key = opcode - aarch64_opcode_table;\n");
619 printf (" int value;\n");
620 printf (" switch (key)\n");
623 for (i
= 0; i
< num
; ++i
)
625 const opcode_node
*node
= table
+ i
;
627 printf (" case %u: value = %u; break;", real_index (node
->index
),
628 real_index (node
->next
->index
));
629 printf ("\t/* %s --> %s. */\n", get_aarch64_opcode (node
)->name
,
630 get_aarch64_opcode (node
->next
)->name
);
633 printf (" default: return NULL;\n");
636 printf (" return aarch64_opcode_table + value;\n");
640 /* Generate aarch64_find_next_alias_opcode in C code to the standard output.
641 TABLE points to the alias info table, while NUM indicates the number of
642 entries in the table. */
645 print_find_next_alias_opcode (const opcode_node
*table
, int num
)
650 printf ("Enter print_find_next_alias_opcode\n");
653 printf ("const aarch64_opcode *\n");
654 printf ("aarch64_find_next_alias_opcode (const aarch64_opcode *opcode)\n");
656 printf (" /* Use the index as the key to locate the next opcode. */\n");
657 printf (" int key = opcode - aarch64_opcode_table;\n");
658 printf (" int value;\n");
659 printf (" switch (key)\n");
662 for (i
= 0; i
< num
; ++i
)
664 const opcode_node
*node
= table
+ i
;
666 if (node
->next
->next
== NULL
)
668 while (node
->next
->next
)
670 printf (" case %u: value = %u; break;", real_index (node
->next
->index
),
671 real_index (node
->next
->next
->index
));
672 printf ("\t/* %s --> %s. */\n",
673 get_aarch64_opcode (node
->next
)->name
,
674 get_aarch64_opcode (node
->next
->next
)->name
);
679 printf (" default: return NULL;\n");
682 printf (" return aarch64_opcode_table + value;\n");
686 /* Given OPCODE, establish and return a link list of alias nodes in the
690 find_alias_opcode (const aarch64_opcode
*opcode
)
693 /* Assume maximum of 8 disassemble preference candidates. */
694 const int max_num_aliases
= 8;
695 const aarch64_opcode
*ent
;
696 const aarch64_opcode
*preferred
[max_num_aliases
];
697 opcode_node head
, **next
;
699 assert (opcode_has_alias (opcode
));
702 ent
= aarch64_opcode_table
;
703 while (ent
->name
!= NULL
)
705 /* The mask of an alias opcode must be equal to or a super-set (i.e.
706 more constrained) of that of the aliased opcode; so is the base
708 if (alias_opcode_p (ent
) == TRUE
709 && (ent
->mask
& opcode
->mask
) == opcode
->mask
710 && (opcode
->mask
& ent
->opcode
) == (opcode
->mask
& opcode
->opcode
))
712 assert (i
< max_num_aliases
);
713 preferred
[i
++] = ent
;
715 printf ("found %s for %s.", ent
->name
, opcode
->name
);
723 printf ("un-orderd list: ");
724 for (m
= 0; m
< i
; ++m
)
725 printf ("%s, ", preferred
[m
]->name
);
729 /* There must be at least one alias. */
732 /* Sort preferred array according to the priority (from the lowest to the
737 for (j
= 0; j
< i
- 1; ++j
)
739 for (k
= 0; k
< i
- 1 - j
; ++k
)
741 const aarch64_opcode
*t
;
743 if (opcode_priority (t
) < opcode_priority (preferred
[k
]))
745 preferred
[k
+1] = preferred
[k
];
755 printf ("orderd list: ");
756 for (m
= 0; m
< i
; ++m
)
757 printf ("%s, ", preferred
[m
]->name
);
761 /* Create a link-list of opcode_node with disassemble preference from
767 const aarch64_opcode
*alias
= preferred
[i
];
768 opcode_node
*node
= new_opcode_node ();
771 printf ("add %s.\n", alias
->name
);
773 node
->index
= alias
- aarch64_opcode_table
;
784 /* Create and return alias information.
785 Return the address of the created alias info table; return the number
786 of table entries in *NUM_PTR. */
789 create_alias_info (int *num_ptr
)
793 const aarch64_opcode
*ent
;
795 /* Calculate the total number of opcodes that have alias. */
797 ent
= aarch64_opcode_table
;
798 while (ent
->name
!= NULL
)
800 if (opcode_has_alias (ent
))
802 /* Assert the alias relationship be flat-structured to keep
803 algorithms simple; not allow F_ALIAS and F_HAS_ALIAS both
805 assert (!alias_opcode_p (ent
));
813 /* The array of real opcodes that have alias(es). */
814 ret
= malloc (sizeof (opcode_node
) * num
);
816 /* For each opcode, establish a list of alias nodes in a preferred
818 for (i
= 0, ent
= aarch64_opcode_table
; i
< num
; ++i
, ++ent
)
820 opcode_node
*node
= ret
+ i
;
821 while (ent
->name
!= NULL
&& !opcode_has_alias (ent
))
823 assert (ent
->name
!= NULL
);
824 node
->index
= ent
- aarch64_opcode_table
;
825 node
->next
= find_alias_opcode (ent
);
833 /* Release the dynamic memory resource allocated for the generation of the
834 alias information. */
837 release_resource_alias_info (opcode_node
*alias_info
, int num
)
840 opcode_node
*node
= alias_info
;
842 /* Free opcode_node list. */
843 for (; i
< num
; ++i
, ++node
)
845 opcode_node
*list
= node
->next
;
848 opcode_node
*next
= list
->next
;
851 } while (list
!= NULL
);
854 /* Free opcode_node array. */
858 /* As a debugging utility, print out the result of the table division, although
859 it is not doing much this moment. */
861 print_divide_result (const struct bittree
*bittree ATTRIBUTE_UNUSED
)
863 printf ("max_num_opcodes_at_leaf_node: %d\n", max_num_opcodes_at_leaf_node
);
867 /* Structure to help generate the operand table. */
871 const char *inserter
;
872 const char *extractor
;
877 unsigned processed
: 1;
878 unsigned has_inserter
: 1;
879 unsigned has_extractor
: 1;
882 typedef struct operand operand
;
896 /* Get the operand information in strings. */
898 static operand operands
[] =
900 {"NIL", "0", "0", "", "0", "{0}", "<none>", 0, 0, 0},
901 #define F(...) #__VA_ARGS__
902 #define X(a,b,c,d,e,f,g) \
903 {#a, #b, #c, d, #e, "{"f"}", g, 0, 0, 0},
904 #define Y(a,b,d,e,f,g) \
905 {#a, "ins_"#b, "ext_"#b, d, #e, "{"f"}", g, 0, 0, 0},
907 {"NIL", "0", "0", "", "0", "{0}", "DUMMY", 0, 0, 0},
914 process_operand_table (void)
918 const int num
= sizeof (operands
) / sizeof (operand
);
920 for (i
= 0, opnd
= operands
; i
< num
; ++i
, ++opnd
)
922 opnd
->has_inserter
= opnd
->inserter
[0] != '0';
923 opnd
->has_extractor
= opnd
->extractor
[0] != '0';
927 /* Generate aarch64_operands in C to the standard output. */
930 print_operand_table (void)
934 const int num
= sizeof (operands
) / sizeof (operand
);
937 printf ("Enter print_operand_table\n");
940 printf ("const struct aarch64_operand aarch64_operands[] =\n");
943 for (i
= 0, opnd
= operands
; i
< num
; ++i
, ++opnd
)
947 if (opnd
->flags
[0] != '0')
948 sprintf (flags
, "%s", opnd
->flags
);
949 if (opnd
->has_inserter
)
951 if (flags
[0] != '\0')
952 strcat (flags
, " | ");
953 strcat (flags
, "OPD_F_HAS_INSERTER");
955 if (opnd
->has_extractor
)
957 if (flags
[0] != '\0')
958 strcat (flags
, " | ");
959 strcat (flags
, "OPD_F_HAS_EXTRACTOR");
961 if (flags
[0] == '\0')
966 printf (" {AARCH64_OPND_CLASS_%s, \"%s\", %s, %s, \"%s\"},\n",
967 opnd
->class, opnd
->str
, flags
, opnd
->fields
, opnd
->desc
);
972 /* Generate aarch64_insert_operand in C to the standard output. */
975 print_operand_inserter (void)
979 const int num
= sizeof (operands
) / sizeof (operand
);
982 printf ("Enter print_operand_inserter\n");
985 printf ("const char*\n");
986 printf ("aarch64_insert_operand (const aarch64_operand *self,\n\
987 const aarch64_opnd_info *info,\n\
988 aarch64_insn *code, const aarch64_inst *inst)\n");
990 printf (" /* Use the index as the key. */\n");
991 printf (" int key = self - aarch64_operands;\n");
992 printf (" switch (key)\n");
995 for (i
= 0, opnd
= operands
; i
< num
; ++i
, ++opnd
)
998 for (i
= 0, opnd
= operands
; i
< num
; ++i
, ++opnd
)
1000 if (!opnd
->processed
&& opnd
->has_inserter
)
1003 const int len
= strlen (opnd
->inserter
);
1004 operand
*opnd2
= opnd
+ 1;
1005 printf (" case %u:\n", (unsigned int)(opnd
- operands
));
1006 opnd
->processed
= 1;
1007 for (; j
< num
; ++j
, ++opnd2
)
1009 if (!opnd2
->processed
1010 && opnd2
->has_inserter
1011 && len
== strlen (opnd2
->inserter
)
1012 && strncmp (opnd
->inserter
, opnd2
->inserter
, len
) == 0)
1014 printf (" case %u:\n", (unsigned int)(opnd2
- operands
));
1015 opnd2
->processed
= 1;
1018 printf (" return aarch64_%s (self, info, code, inst);\n",
1023 printf (" default: assert (0); abort ();\n");
1028 /* Generate aarch64_extract_operand in C to the standard output. */
1031 print_operand_extractor (void)
1035 const int num
= sizeof (operands
) / sizeof (operand
);
1038 printf ("Enter print_operand_extractor\n");
1042 printf ("aarch64_extract_operand (const aarch64_operand *self,\n\
1043 aarch64_opnd_info *info,\n\
1044 aarch64_insn code, const aarch64_inst *inst)\n");
1046 printf (" /* Use the index as the key. */\n");
1047 printf (" int key = self - aarch64_operands;\n");
1048 printf (" switch (key)\n");
1051 for (i
= 0, opnd
= operands
; i
< num
; ++i
, ++opnd
)
1052 opnd
->processed
= 0;
1054 for (i
= 0, opnd
= operands
; i
< num
; ++i
, ++opnd
)
1056 if (!opnd
->processed
&& opnd
->has_extractor
)
1059 const int len
= strlen (opnd
->extractor
);
1060 operand
*opnd2
= opnd
+ 1;
1061 printf (" case %u:\n", (unsigned int)(opnd
- operands
));
1062 opnd
->processed
= 1;
1063 for (; j
< num
; ++j
, ++opnd2
)
1065 if (!opnd2
->processed
1066 && opnd2
->has_extractor
1067 && len
== strlen (opnd2
->extractor
)
1068 && strncmp (opnd
->extractor
, opnd2
->extractor
, len
) == 0)
1070 printf (" case %u:\n", (unsigned int)(opnd2
- operands
));
1071 opnd2
->processed
= 1;
1074 printf (" return aarch64_%s (self, info, code, inst);\n",
1079 printf (" default: assert (0); abort ();\n");
1084 /* Table indexed by opcode enumerator stores the index of the corresponding
1085 opcode entry in aarch64_opcode_table. */
1086 static unsigned op_enum_table
[OP_TOTAL_NUM
];
1088 /* Print out the routine which, given the opcode enumerator, returns the
1089 corresponding opcode entry pointer. */
1092 print_get_opcode (void)
1095 const int num
= OP_TOTAL_NUM
;
1096 const aarch64_opcode
*opcode
;
1099 printf ("Enter print_get_opcode\n");
1101 /* Fill in the internal table. */
1102 opcode
= aarch64_opcode_table
;
1103 while (opcode
->name
!= NULL
)
1105 if (opcode
->op
!= OP_NIL
)
1107 /* Assert opcode enumerator be unique, in other words, no shared by
1108 different opcodes. */
1109 if (op_enum_table
[opcode
->op
] != 0)
1111 fprintf (stderr
, "Opcode %u is shared by different %s and %s.\n",
1113 aarch64_opcode_table
[op_enum_table
[opcode
->op
]].name
,
1118 assert (opcode
->op
< OP_TOTAL_NUM
);
1119 op_enum_table
[opcode
->op
] = opcode
- aarch64_opcode_table
;
1124 /* Print the table. */
1126 printf ("/* Indexed by an enum aarch64_op enumerator, the value is the offset of\n\
1127 the corresponding aarch64_opcode entry in the aarch64_opcode_table. */\n\n");
1128 printf ("static const unsigned op_enum_table [] =\n");
1130 for (i
= 0; i
< num
; ++i
)
1131 printf (" %u,\n", op_enum_table
[i
]);
1134 /* Print the function. */
1136 printf ("/* Given the opcode enumerator OP, return the pointer to the corresponding\n");
1137 printf (" opcode entry. */\n");
1139 printf ("const aarch64_opcode *\n");
1140 printf ("aarch64_get_opcode (enum aarch64_op op)\n");
1142 printf (" return aarch64_opcode_table + op_enum_table[op];\n");
1146 /* Print out the content of an opcode table (not in use). */
1147 static void ATTRIBUTE_UNUSED
1148 print_table (struct aarch64_opcode
* table
)
1150 struct aarch64_opcode
*ent
= table
;
1153 printf ("%s\t%08x\t%08x\n", ent
->name
, (unsigned int)ent
->opcode
,
1154 (unsigned int)ent
->mask
);
1155 } while ((++ent
)->name
);
1158 static const char * program_name
= NULL
;
1160 /* Program options. */
1161 struct option long_options
[] =
1163 {"debug", no_argument
, NULL
, 'd'},
1164 {"version", no_argument
, NULL
, 'V'},
1165 {"help", no_argument
, NULL
, 'h'},
1166 {"gen-opc", no_argument
, NULL
, 'c'},
1167 {"gen-asm", no_argument
, NULL
, 'a'},
1168 {"gen-dis", no_argument
, NULL
, 's'},
1169 {0, no_argument
, NULL
, 0}
1173 print_version (void)
1175 printf ("%s: version 1.0\n", program_name
);
1180 usage (FILE * stream
, int status
)
1182 fprintf (stream
, "Usage: %s [-V | --version] [-d | --debug] [--help]\n",
1184 fprintf (stream
, "\t[ [-c | --gen-opc] | [-a | --gen-asm] | [-s | --gen-dis] ]\n");
1189 main (int argc
, char **argv
)
1191 extern int chdir (char *);
1193 int gen_opcode_p
= 0;
1194 int gen_assembler_p
= 0;
1195 int gen_disassembler_p
= 0;
1197 program_name
= *argv
;
1198 xmalloc_set_program_name (program_name
);
1200 while ((c
= getopt_long (argc
, argv
, "vVdhacs", long_options
, 0)) != EOF
)
1218 gen_assembler_p
= 1;
1221 gen_disassembler_p
= 1;
1228 if (argc
== 1 || optind
!= argc
)
1231 if (gen_opcode_p
+ gen_assembler_p
+ gen_disassembler_p
> 1)
1233 printf ("Please specify only one of the following options\n\
1234 [-c | --gen-opc] [-a | --gen-asm] [-s | --gen-dis]\n");
1238 struct bittree
*decoder_tree
;
1240 decoder_tree
= initialize_decoder_tree ();
1242 print_divide_result (decoder_tree
);
1244 printf ("/* This file is automatically generated by aarch64-gen. Do not edit! */\n");
1245 printf ("/* Copyright 2012 Free Software Foundation, Inc.\n\
1246 Contributed by ARM Ltd.\n\
1248 This file is part of the GNU opcodes library.\n\
1250 This library is free software; you can redistribute it and/or modify\n\
1251 it under the terms of the GNU General Public License as published by\n\
1252 the Free Software Foundation; either version 3, or (at your option)\n\
1253 any later version.\n\
1255 It is distributed in the hope that it will be useful, but WITHOUT\n\
1256 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY\n\
1257 or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public\n\
1258 License for more details.\n\
1260 You should have received a copy of the GNU General Public License\n\
1261 along with this program; see the file COPYING3. If not,\n\
1262 see <http://www.gnu.org/licenses/>. */\n");
1265 printf ("#include \"sysdep.h\"\n");
1267 printf ("#include \"aarch64-opc.h\"\n");
1268 if (gen_assembler_p
)
1269 printf ("#include \"aarch64-asm.h\"\n");
1270 if (gen_disassembler_p
)
1271 printf ("#include \"aarch64-dis.h\"\n");
1274 /* Generate opcode entry lookup for the disassembler. */
1275 if (gen_disassembler_p
)
1277 print_decision_tree (decoder_tree
);
1278 print_find_next_opcode (decoder_tree
);
1279 release_resource_decoder_tree (decoder_tree
);
1282 /* Generate alias opcode handling for the assembler or the disassembler. */
1283 if (gen_assembler_p
|| gen_disassembler_p
)
1286 opcode_node
*alias_info
= create_alias_info (&num
);
1288 if (gen_assembler_p
)
1289 print_find_real_opcode (alias_info
, num
);
1291 if (gen_disassembler_p
)
1293 print_find_alias_opcode (alias_info
, num
);
1294 print_find_next_alias_opcode (alias_info
, num
);
1297 release_resource_alias_info (alias_info
, num
);
1300 /* Generate operand table. */
1301 process_operand_table ();
1303 if (gen_assembler_p
)
1304 print_operand_inserter ();
1306 if (gen_disassembler_p
)
1307 print_operand_extractor ();
1310 print_operand_table ();
1312 /* Generate utility to return aarch64_opcode entry given an enumerator. */
1314 print_get_opcode ();