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