1 /* CGEN generic opcode support. 2 3 Copyright (C) 1996-2022 Free Software Foundation, Inc. 4 5 This file is part of libopcodes. 6 7 This library is free software; you can redistribute it and/or modify 8 it under the terms of the GNU General Public License as published by 9 the Free Software Foundation; either version 3, or (at your option) 10 any later version. 11 12 It is distributed in the hope that it will be useful, but WITHOUT 13 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY 14 or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public 15 License for more details. 16 17 You should have received a copy of the GNU General Public License along 18 with this program; if not, write to the Free Software Foundation, Inc., 19 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA. */ 20 21 #include "sysdep.h" 22 #include <stdio.h> 23 #include "ansidecl.h" 24 #include "libiberty.h" 25 #include "safe-ctype.h" 26 #include "bfd.h" 27 #include "symcat.h" 28 #include "opcode/cgen.h" 29 30 static unsigned int hash_keyword_name 31 (const CGEN_KEYWORD *, const char *, int); 32 static unsigned int hash_keyword_value 33 (const CGEN_KEYWORD *, unsigned int); 34 static void build_keyword_hash_tables 35 (CGEN_KEYWORD *); 36 37 /* Return number of hash table entries to use for N elements. */ 38 #define KEYWORD_HASH_SIZE(n) ((n) <= 31 ? 17 : 31) 39 40 /* Look up *NAMEP in the keyword table KT. 41 The result is the keyword entry or NULL if not found. */ 42 43 const CGEN_KEYWORD_ENTRY * 44 cgen_keyword_lookup_name (CGEN_KEYWORD *kt, const char *name) 45 { 46 const CGEN_KEYWORD_ENTRY *ke; 47 const char *p,*n; 48 49 if (kt->name_hash_table == NULL) 50 build_keyword_hash_tables (kt); 51 52 ke = kt->name_hash_table[hash_keyword_name (kt, name, 0)]; 53 54 /* We do case insensitive comparisons. 55 If that ever becomes a problem, add an attribute that denotes 56 "do case sensitive comparisons". */ 57 58 while (ke != NULL) 59 { 60 n = name; 61 p = ke->name; 62 63 while (*p 64 && (*p == *n 65 || (ISALPHA (*p) && (TOLOWER (*p) == TOLOWER (*n))))) 66 ++n, ++p; 67 68 if (!*p && !*n) 69 return ke; 70 71 ke = ke->next_name; 72 } 73 74 if (kt->null_entry) 75 return kt->null_entry; 76 return NULL; 77 } 78 79 /* Look up VALUE in the keyword table KT. 80 The result is the keyword entry or NULL if not found. */ 81 82 const CGEN_KEYWORD_ENTRY * 83 cgen_keyword_lookup_value (CGEN_KEYWORD *kt, int value) 84 { 85 const CGEN_KEYWORD_ENTRY *ke; 86 87 if (kt->name_hash_table == NULL) 88 build_keyword_hash_tables (kt); 89 90 ke = kt->value_hash_table[hash_keyword_value (kt, value)]; 91 92 while (ke != NULL) 93 { 94 if (value == ke->value) 95 return ke; 96 ke = ke->next_value; 97 } 98 99 return NULL; 100 } 101 102 /* Add an entry to a keyword table. */ 103 104 void 105 cgen_keyword_add (CGEN_KEYWORD *kt, CGEN_KEYWORD_ENTRY *ke) 106 { 107 unsigned int hash; 108 size_t i; 109 110 if (kt->name_hash_table == NULL) 111 build_keyword_hash_tables (kt); 112 113 hash = hash_keyword_name (kt, ke->name, 0); 114 ke->next_name = kt->name_hash_table[hash]; 115 kt->name_hash_table[hash] = ke; 116 117 hash = hash_keyword_value (kt, ke->value); 118 ke->next_value = kt->value_hash_table[hash]; 119 kt->value_hash_table[hash] = ke; 120 121 if (ke->name[0] == 0) 122 kt->null_entry = ke; 123 124 for (i = 1; i < strlen (ke->name); i++) 125 if (! ISALNUM (ke->name[i]) 126 && ! strchr (kt->nonalpha_chars, ke->name[i])) 127 { 128 size_t idx = strlen (kt->nonalpha_chars); 129 130 /* If you hit this limit, please don't just 131 increase the size of the field, instead 132 look for a better algorithm. */ 133 if (idx >= sizeof (kt->nonalpha_chars) - 1) 134 abort (); 135 kt->nonalpha_chars[idx] = ke->name[i]; 136 kt->nonalpha_chars[idx+1] = 0; 137 } 138 } 139 140 /* FIXME: Need function to return count of keywords. */ 141 142 /* Initialize a keyword table search. 143 SPEC is a specification of what to search for. 144 A value of NULL means to find every keyword. 145 Currently NULL is the only acceptable value [further specification 146 deferred]. 147 The result is an opaque data item used to record the search status. 148 It is passed to each call to cgen_keyword_search_next. */ 149 150 CGEN_KEYWORD_SEARCH 151 cgen_keyword_search_init (CGEN_KEYWORD *kt, const char *spec) 152 { 153 CGEN_KEYWORD_SEARCH search; 154 155 /* FIXME: Need to specify format of params. */ 156 if (spec != NULL) 157 abort (); 158 159 if (kt->name_hash_table == NULL) 160 build_keyword_hash_tables (kt); 161 162 search.table = kt; 163 search.spec = spec; 164 search.current_hash = 0; 165 search.current_entry = NULL; 166 return search; 167 } 168 169 /* Return the next keyword specified by SEARCH. 170 The result is the next entry or NULL if there are no more. */ 171 172 const CGEN_KEYWORD_ENTRY * 173 cgen_keyword_search_next (CGEN_KEYWORD_SEARCH *search) 174 { 175 /* Has search finished? */ 176 if (search->current_hash == search->table->hash_table_size) 177 return NULL; 178 179 /* Search in progress? */ 180 if (search->current_entry != NULL 181 /* Anything left on this hash chain? */ 182 && search->current_entry->next_name != NULL) 183 { 184 search->current_entry = search->current_entry->next_name; 185 return search->current_entry; 186 } 187 188 /* Move to next hash chain [unless we haven't started yet]. */ 189 if (search->current_entry != NULL) 190 ++search->current_hash; 191 192 while (search->current_hash < search->table->hash_table_size) 193 { 194 search->current_entry = search->table->name_hash_table[search->current_hash]; 195 if (search->current_entry != NULL) 196 return search->current_entry; 197 ++search->current_hash; 198 } 199 200 return NULL; 201 } 202 203 /* Return first entry in hash chain for NAME. 204 If CASE_SENSITIVE_P is non-zero, return a case sensitive hash. */ 205 206 static unsigned int 207 hash_keyword_name (const CGEN_KEYWORD *kt, 208 const char *name, 209 int case_sensitive_p) 210 { 211 unsigned int hash; 212 213 if (case_sensitive_p) 214 for (hash = 0; *name; ++name) 215 hash = (hash * 97) + (unsigned char) *name; 216 else 217 for (hash = 0; *name; ++name) 218 hash = (hash * 97) + (unsigned char) TOLOWER (*name); 219 return hash % kt->hash_table_size; 220 } 221 222 /* Return first entry in hash chain for VALUE. */ 223 224 static unsigned int 225 hash_keyword_value (const CGEN_KEYWORD *kt, unsigned int value) 226 { 227 return value % kt->hash_table_size; 228 } 229 230 /* Build a keyword table's hash tables. 231 We probably needn't build the value hash table for the assembler when 232 we're using the disassembler, but we keep things simple. */ 233 234 static void 235 build_keyword_hash_tables (CGEN_KEYWORD *kt) 236 { 237 int i; 238 /* Use the number of compiled in entries as an estimate for the 239 typical sized table [not too many added at runtime]. */ 240 unsigned int size = KEYWORD_HASH_SIZE (kt->num_init_entries); 241 242 kt->hash_table_size = size; 243 kt->name_hash_table = (CGEN_KEYWORD_ENTRY **) 244 xmalloc (size * sizeof (CGEN_KEYWORD_ENTRY *)); 245 memset (kt->name_hash_table, 0, size * sizeof (CGEN_KEYWORD_ENTRY *)); 246 kt->value_hash_table = (CGEN_KEYWORD_ENTRY **) 247 xmalloc (size * sizeof (CGEN_KEYWORD_ENTRY *)); 248 memset (kt->value_hash_table, 0, size * sizeof (CGEN_KEYWORD_ENTRY *)); 249 250 /* The table is scanned backwards as we want keywords appearing earlier to 251 be prefered over later ones. */ 252 for (i = kt->num_init_entries - 1; i >= 0; --i) 253 cgen_keyword_add (kt, &kt->init_entries[i]); 254 } 255 256 /* Hardware support. */ 257 258 /* Lookup a hardware element by its name. 259 Returns NULL if NAME is not supported by the currently selected 260 mach/isa. */ 261 262 const CGEN_HW_ENTRY * 263 cgen_hw_lookup_by_name (CGEN_CPU_DESC cd, const char *name) 264 { 265 unsigned int i; 266 const CGEN_HW_ENTRY **hw = cd->hw_table.entries; 267 268 for (i = 0; i < cd->hw_table.num_entries; ++i) 269 if (hw[i] && strcmp (name, hw[i]->name) == 0) 270 return hw[i]; 271 272 return NULL; 273 } 274 275 /* Lookup a hardware element by its number. 276 Hardware elements are enumerated, however it may be possible to add some 277 at runtime, thus HWNUM is not an enum type but rather an int. 278 Returns NULL if HWNUM is not supported by the currently selected mach. */ 279 280 const CGEN_HW_ENTRY * 281 cgen_hw_lookup_by_num (CGEN_CPU_DESC cd, unsigned int hwnum) 282 { 283 unsigned int i; 284 const CGEN_HW_ENTRY **hw = cd->hw_table.entries; 285 286 /* ??? This can be speeded up. */ 287 for (i = 0; i < cd->hw_table.num_entries; ++i) 288 if (hw[i] && hwnum == hw[i]->type) 289 return hw[i]; 290 291 return NULL; 292 } 293 294 /* Operand support. */ 295 296 /* Lookup an operand by its name. 297 Returns NULL if NAME is not supported by the currently selected 298 mach/isa. */ 299 300 const CGEN_OPERAND * 301 cgen_operand_lookup_by_name (CGEN_CPU_DESC cd, const char *name) 302 { 303 unsigned int i; 304 const CGEN_OPERAND **op = cd->operand_table.entries; 305 306 for (i = 0; i < cd->operand_table.num_entries; ++i) 307 if (op[i] && strcmp (name, op[i]->name) == 0) 308 return op[i]; 309 310 return NULL; 311 } 312 313 /* Lookup an operand by its number. 314 Operands are enumerated, however it may be possible to add some 315 at runtime, thus OPNUM is not an enum type but rather an int. 316 Returns NULL if OPNUM is not supported by the currently selected 317 mach/isa. */ 318 319 const CGEN_OPERAND * 320 cgen_operand_lookup_by_num (CGEN_CPU_DESC cd, int opnum) 321 { 322 return cd->operand_table.entries[opnum]; 323 } 324 325 /* Instruction support. */ 326 327 /* Return number of instructions. This includes any added at runtime. */ 328 329 int 330 cgen_insn_count (CGEN_CPU_DESC cd) 331 { 332 int count = cd->insn_table.num_init_entries; 333 CGEN_INSN_LIST *rt_insns = cd->insn_table.new_entries; 334 335 for ( ; rt_insns != NULL; rt_insns = rt_insns->next) 336 ++count; 337 338 return count; 339 } 340 341 /* Return number of macro-instructions. 342 This includes any added at runtime. */ 343 344 int 345 cgen_macro_insn_count (CGEN_CPU_DESC cd) 346 { 347 int count = cd->macro_insn_table.num_init_entries; 348 CGEN_INSN_LIST *rt_insns = cd->macro_insn_table.new_entries; 349 350 for ( ; rt_insns != NULL; rt_insns = rt_insns->next) 351 ++count; 352 353 return count; 354 } 355 356 /* Cover function to read and properly byteswap an insn value. */ 357 358 CGEN_INSN_INT 359 cgen_get_insn_value (CGEN_CPU_DESC cd, unsigned char *buf, int length, 360 int endian) 361 { 362 int big_p = (endian == CGEN_ENDIAN_BIG); 363 int insn_chunk_bitsize = cd->insn_chunk_bitsize; 364 CGEN_INSN_INT value = 0; 365 366 if (insn_chunk_bitsize != 0 && insn_chunk_bitsize < length) 367 { 368 /* We need to divide up the incoming value into insn_chunk_bitsize-length 369 segments, and endian-convert them, one at a time. */ 370 int i; 371 372 /* Enforce divisibility. */ 373 if ((length % insn_chunk_bitsize) != 0) 374 abort (); 375 376 for (i = 0; i < length; i += insn_chunk_bitsize) /* NB: i == bits */ 377 { 378 int bit_index; 379 bfd_vma this_value; 380 381 bit_index = i; /* NB: not dependent on endianness; opposite of cgen_put_insn_value! */ 382 this_value = bfd_get_bits (& buf[bit_index / 8], insn_chunk_bitsize, big_p); 383 value = (value << insn_chunk_bitsize) | this_value; 384 } 385 } 386 else 387 { 388 value = bfd_get_bits (buf, length, endian == CGEN_ENDIAN_BIG); 389 } 390 391 return value; 392 } 393 394 /* Cover function to store an insn value properly byteswapped. */ 395 396 void 397 cgen_put_insn_value (CGEN_CPU_DESC cd, 398 unsigned char *buf, 399 int length, 400 CGEN_INSN_INT value, 401 int endian) 402 { 403 int big_p = (endian == CGEN_ENDIAN_BIG); 404 int insn_chunk_bitsize = cd->insn_chunk_bitsize; 405 406 if (insn_chunk_bitsize != 0 && insn_chunk_bitsize < length) 407 { 408 /* We need to divide up the incoming value into insn_chunk_bitsize-length 409 segments, and endian-convert them, one at a time. */ 410 int i; 411 412 /* Enforce divisibility. */ 413 if ((length % insn_chunk_bitsize) != 0) 414 abort (); 415 416 for (i = 0; i < length; i += insn_chunk_bitsize) /* NB: i == bits */ 417 { 418 int bit_index; 419 420 bit_index = (length - insn_chunk_bitsize - i); /* NB: not dependent on endianness! */ 421 bfd_put_bits ((bfd_vma) value, & buf[bit_index / 8], insn_chunk_bitsize, big_p); 422 value >>= insn_chunk_bitsize; 423 } 424 } 425 else 426 { 427 bfd_put_bits ((bfd_vma) value, buf, length, big_p); 428 } 429 } 430 431 /* Look up instruction INSN_*_VALUE and extract its fields. 432 INSN_INT_VALUE is used if CGEN_INT_INSN_P. 433 Otherwise INSN_BYTES_VALUE is used. 434 INSN, if non-null, is the insn table entry. 435 Otherwise INSN_*_VALUE is examined to compute it. 436 LENGTH is the bit length of INSN_*_VALUE if known, otherwise 0. 437 0 is only valid if `insn == NULL && ! CGEN_INT_INSN_P'. 438 If INSN != NULL, LENGTH must be valid. 439 ALIAS_P is non-zero if alias insns are to be included in the search. 440 441 The result is a pointer to the insn table entry, or NULL if the instruction 442 wasn't recognized. */ 443 444 /* ??? Will need to be revisited for VLIW architectures. */ 445 446 const CGEN_INSN * 447 cgen_lookup_insn (CGEN_CPU_DESC cd, 448 const CGEN_INSN *insn, 449 CGEN_INSN_INT insn_int_value, 450 /* ??? CGEN_INSN_BYTES would be a nice type name to use here. */ 451 unsigned char *insn_bytes_value, 452 int length, 453 CGEN_FIELDS *fields, 454 int alias_p) 455 { 456 CGEN_EXTRACT_INFO ex_info; 457 CGEN_EXTRACT_INFO *info; 458 459 if (cd->int_insn_p) 460 { 461 info = NULL; 462 insn_bytes_value = (unsigned char *) xmalloc (cd->max_insn_bitsize / 8); 463 cgen_put_insn_value (cd, insn_bytes_value, length, insn_int_value, 464 cd->insn_endian); 465 } 466 else 467 { 468 info = &ex_info; 469 ex_info.dis_info = NULL; 470 ex_info.insn_bytes = insn_bytes_value; 471 ex_info.valid = -1; 472 insn_int_value = cgen_get_insn_value (cd, insn_bytes_value, length, 473 cd->insn_endian); 474 } 475 476 if (!insn) 477 { 478 const CGEN_INSN_LIST *insn_list; 479 480 /* The instructions are stored in hash lists. 481 Pick the first one and keep trying until we find the right one. */ 482 483 insn_list = cgen_dis_lookup_insn (cd, (char *) insn_bytes_value, 484 insn_int_value); 485 while (insn_list != NULL) 486 { 487 insn = insn_list->insn; 488 489 if (alias_p 490 /* FIXME: Ensure ALIAS attribute always has same index. */ 491 || ! CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_ALIAS)) 492 { 493 /* Basic bit mask must be correct. */ 494 /* ??? May wish to allow target to defer this check until the 495 extract handler. */ 496 if ((insn_int_value & CGEN_INSN_BASE_MASK (insn)) 497 == CGEN_INSN_BASE_VALUE (insn)) 498 { 499 /* ??? 0 is passed for `pc' */ 500 int elength = CGEN_EXTRACT_FN (cd, insn) 501 (cd, insn, info, insn_int_value, fields, (bfd_vma) 0); 502 if (elength > 0) 503 { 504 /* sanity check */ 505 if (length != 0 && length != elength) 506 abort (); 507 break; 508 } 509 } 510 } 511 512 insn_list = insn_list->next; 513 } 514 } 515 else 516 { 517 /* Sanity check: can't pass an alias insn if ! alias_p. */ 518 if (! alias_p 519 && CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_ALIAS)) 520 abort (); 521 /* Sanity check: length must be correct. */ 522 if (length != CGEN_INSN_BITSIZE (insn)) 523 abort (); 524 525 /* ??? 0 is passed for `pc' */ 526 length = CGEN_EXTRACT_FN (cd, insn) 527 (cd, insn, info, insn_int_value, fields, (bfd_vma) 0); 528 /* Sanity check: must succeed. 529 Could relax this later if it ever proves useful. */ 530 if (length == 0) 531 abort (); 532 } 533 534 if (cd->int_insn_p) 535 free (insn_bytes_value); 536 537 return insn; 538 } 539 540 /* Fill in the operand instances used by INSN whose operands are FIELDS. 541 INDICES is a pointer to a buffer of MAX_OPERAND_INSTANCES ints to be filled 542 in. */ 543 544 void 545 cgen_get_insn_operands (CGEN_CPU_DESC cd, 546 const CGEN_INSN *insn, 547 const CGEN_FIELDS *fields, 548 int *indices) 549 { 550 const CGEN_OPINST *opinst; 551 int i; 552 553 if (insn->opinst == NULL) 554 abort (); 555 for (i = 0, opinst = insn->opinst; opinst->type != CGEN_OPINST_END; ++i, ++opinst) 556 { 557 enum cgen_operand_type op_type = opinst->op_type; 558 if (op_type == CGEN_OPERAND_NIL) 559 indices[i] = opinst->index; 560 else 561 indices[i] = (*cd->get_int_operand) (cd, op_type, fields); 562 } 563 } 564 565 /* Cover function to cgen_get_insn_operands when either INSN or FIELDS 566 isn't known. 567 The INSN, INSN_*_VALUE, and LENGTH arguments are passed to 568 cgen_lookup_insn unchanged. 569 INSN_INT_VALUE is used if CGEN_INT_INSN_P. 570 Otherwise INSN_BYTES_VALUE is used. 571 572 The result is the insn table entry or NULL if the instruction wasn't 573 recognized. */ 574 575 const CGEN_INSN * 576 cgen_lookup_get_insn_operands (CGEN_CPU_DESC cd, 577 const CGEN_INSN *insn, 578 CGEN_INSN_INT insn_int_value, 579 /* ??? CGEN_INSN_BYTES would be a nice type name to use here. */ 580 unsigned char *insn_bytes_value, 581 int length, 582 int *indices, 583 CGEN_FIELDS *fields) 584 { 585 /* Pass non-zero for ALIAS_P only if INSN != NULL. 586 If INSN == NULL, we want a real insn. */ 587 insn = cgen_lookup_insn (cd, insn, insn_int_value, insn_bytes_value, 588 length, fields, insn != NULL); 589 if (! insn) 590 return NULL; 591 592 cgen_get_insn_operands (cd, insn, fields, indices); 593 return insn; 594 } 595 596 /* Allow signed overflow of instruction fields. */ 597 void 598 cgen_set_signed_overflow_ok (CGEN_CPU_DESC cd) 599 { 600 cd->signed_overflow_ok_p = 1; 601 } 602 603 /* Generate an error message if a signed field in an instruction overflows. */ 604 void 605 cgen_clear_signed_overflow_ok (CGEN_CPU_DESC cd) 606 { 607 cd->signed_overflow_ok_p = 0; 608 } 609 610 /* Will an error message be generated if a signed field in an instruction overflows ? */ 611 unsigned int 612 cgen_signed_overflow_ok_p (CGEN_CPU_DESC cd) 613 { 614 return cd->signed_overflow_ok_p; 615 } 616