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