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