1/* ia64-opc.c -- Functions to access the compacted opcode table 2 Copyright (C) 1999-2017 Free Software Foundation, Inc. 3 Written by Bob Manson of Cygnus Solutions, <manson@cygnus.com> 4 5 This file is part of the GNU opcodes library. 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 18 along with this file; see the file COPYING. If not, write to the 19 Free Software Foundation, 51 Franklin Street - Fifth Floor, Boston, 20 MA 02110-1301, USA. */ 21 22#include "sysdep.h" 23#include "libiberty.h" 24#include "ia64-asmtab.h" 25#include "ia64-asmtab.c" 26 27static void get_opc_prefix (const char **, char *); 28static short int find_string_ent (const char *); 29static short int find_main_ent (short int); 30static short int find_completer (short int, short int, const char *); 31static ia64_insn apply_completer (ia64_insn, int); 32static int extract_op_bits (int, int, int); 33static int extract_op (int, int *, unsigned int *); 34static int opcode_verify (ia64_insn, int, enum ia64_insn_type); 35static int locate_opcode_ent (ia64_insn, enum ia64_insn_type); 36static struct ia64_opcode *make_ia64_opcode 37 (ia64_insn, const char *, int, int); 38static struct ia64_opcode *ia64_find_matching_opcode 39 (const char *, short int); 40 41const struct ia64_templ_desc ia64_templ_desc[16] = 42 { 43 { 0, { IA64_UNIT_M, IA64_UNIT_I, IA64_UNIT_I }, "MII" }, /* 0 */ 44 { 2, { IA64_UNIT_M, IA64_UNIT_I, IA64_UNIT_I }, "MII" }, 45 { 0, { IA64_UNIT_M, IA64_UNIT_L, IA64_UNIT_X }, "MLX" }, 46 { 0, { 0, }, "-3-" }, 47 { 0, { IA64_UNIT_M, IA64_UNIT_M, IA64_UNIT_I }, "MMI" }, /* 4 */ 48 { 1, { IA64_UNIT_M, IA64_UNIT_M, IA64_UNIT_I }, "MMI" }, 49 { 0, { IA64_UNIT_M, IA64_UNIT_F, IA64_UNIT_I }, "MFI" }, 50 { 0, { IA64_UNIT_M, IA64_UNIT_M, IA64_UNIT_F }, "MMF" }, 51 { 0, { IA64_UNIT_M, IA64_UNIT_I, IA64_UNIT_B }, "MIB" }, /* 8 */ 52 { 0, { IA64_UNIT_M, IA64_UNIT_B, IA64_UNIT_B }, "MBB" }, 53 { 0, { 0, }, "-a-" }, 54 { 0, { IA64_UNIT_B, IA64_UNIT_B, IA64_UNIT_B }, "BBB" }, 55 { 0, { IA64_UNIT_M, IA64_UNIT_M, IA64_UNIT_B }, "MMB" }, /* c */ 56 { 0, { 0, }, "-d-" }, 57 { 0, { IA64_UNIT_M, IA64_UNIT_F, IA64_UNIT_B }, "MFB" }, 58 { 0, { 0, }, "-f-" }, 59 }; 60 61 62/* Copy the prefix contained in *PTR (up to a '.' or a NUL) to DEST. 63 PTR will be adjusted to point to the start of the next portion 64 of the opcode, or at the NUL character. */ 65 66static void 67get_opc_prefix (const char **ptr, char *dest) 68{ 69 char *c = strchr (*ptr, '.'); 70 if (c != NULL) 71 { 72 memcpy (dest, *ptr, c - *ptr); 73 dest[c - *ptr] = '\0'; 74 *ptr = c + 1; 75 } 76 else 77 { 78 int l = strlen (*ptr); 79 memcpy (dest, *ptr, l); 80 dest[l] = '\0'; 81 *ptr += l; 82 } 83} 84 85/* Find the index of the entry in the string table corresponding to 86 STR; return -1 if one does not exist. */ 87 88static short 89find_string_ent (const char *str) 90{ 91 short start = 0; 92 short end = sizeof (ia64_strings) / sizeof (const char *); 93 short i = (start + end) / 2; 94 95 if (strcmp (str, ia64_strings[end - 1]) > 0) 96 { 97 return -1; 98 } 99 while (start <= end) 100 { 101 int c = strcmp (str, ia64_strings[i]); 102 if (c < 0) 103 { 104 end = i - 1; 105 } 106 else if (c == 0) 107 { 108 return i; 109 } 110 else 111 { 112 start = i + 1; 113 } 114 i = (start + end) / 2; 115 } 116 return -1; 117} 118 119/* Find the opcode in the main opcode table whose name is STRINGINDEX, or 120 return -1 if one does not exist. */ 121 122static short 123find_main_ent (short nameindex) 124{ 125 short start = 0; 126 short end = sizeof (main_table) / sizeof (struct ia64_main_table); 127 short i = (start + end) / 2; 128 129 if (nameindex < main_table[0].name_index 130 || nameindex > main_table[end - 1].name_index) 131 { 132 return -1; 133 } 134 while (start <= end) 135 { 136 if (nameindex < main_table[i].name_index) 137 { 138 end = i - 1; 139 } 140 else if (nameindex == main_table[i].name_index) 141 { 142 while (i > 0 && main_table[i - 1].name_index == nameindex) 143 { 144 i--; 145 } 146 return i; 147 } 148 else 149 { 150 start = i + 1; 151 } 152 i = (start + end) / 2; 153 } 154 return -1; 155} 156 157/* Find the index of the entry in the completer table that is part of 158 MAIN_ENT (starting from PREV_COMPLETER) that matches NAME, or 159 return -1 if one does not exist. */ 160 161static short 162find_completer (short main_ent, short prev_completer, const char *name) 163{ 164 short name_index = find_string_ent (name); 165 166 if (name_index < 0) 167 { 168 return -1; 169 } 170 171 if (prev_completer == -1) 172 { 173 prev_completer = main_table[main_ent].completers; 174 } 175 else 176 { 177 prev_completer = completer_table[prev_completer].subentries; 178 } 179 180 while (prev_completer != -1) 181 { 182 if (completer_table[prev_completer].name_index == name_index) 183 { 184 return prev_completer; 185 } 186 prev_completer = completer_table[prev_completer].alternative; 187 } 188 return -1; 189} 190 191/* Apply the completer referred to by COMPLETER_INDEX to OPCODE, and 192 return the result. */ 193 194static ia64_insn 195apply_completer (ia64_insn opcode, int completer_index) 196{ 197 ia64_insn mask = completer_table[completer_index].mask; 198 ia64_insn bits = completer_table[completer_index].bits; 199 int shiftamt = (completer_table[completer_index].offset & 63); 200 201 mask = mask << shiftamt; 202 bits = bits << shiftamt; 203 opcode = (opcode & ~mask) | bits; 204 return opcode; 205} 206 207/* Extract BITS number of bits starting from OP_POINTER + BITOFFSET in 208 the dis_table array, and return its value. (BITOFFSET is numbered 209 starting from MSB to LSB, so a BITOFFSET of 0 indicates the MSB of the 210 first byte in OP_POINTER.) */ 211 212static int 213extract_op_bits (int op_pointer, int bitoffset, int bits) 214{ 215 int res = 0; 216 217 op_pointer += (bitoffset / 8); 218 219 if (bitoffset % 8) 220 { 221 unsigned int op = dis_table[op_pointer++]; 222 int numb = 8 - (bitoffset % 8); 223 int mask = (1 << numb) - 1; 224 int bata = (bits < numb) ? bits : numb; 225 int delta = numb - bata; 226 227 res = (res << bata) | ((op & mask) >> delta); 228 bitoffset += bata; 229 bits -= bata; 230 } 231 while (bits >= 8) 232 { 233 res = (res << 8) | (dis_table[op_pointer++] & 255); 234 bits -= 8; 235 } 236 if (bits > 0) 237 { 238 unsigned int op = (dis_table[op_pointer++] & 255); 239 res = (res << bits) | (op >> (8 - bits)); 240 } 241 return res; 242} 243 244/* Examine the state machine entry at OP_POINTER in the dis_table 245 array, and extract its values into OPVAL and OP. The length of the 246 state entry in bits is returned. */ 247 248static int 249extract_op (int op_pointer, int *opval, unsigned int *op) 250{ 251 int oplen = 5; 252 253 *op = dis_table[op_pointer]; 254 255 if ((*op) & 0x40) 256 { 257 opval[0] = extract_op_bits (op_pointer, oplen, 5); 258 oplen += 5; 259 } 260 switch ((*op) & 0x30) 261 { 262 case 0x10: 263 { 264 opval[1] = extract_op_bits (op_pointer, oplen, 8); 265 oplen += 8; 266 opval[1] += op_pointer; 267 break; 268 } 269 case 0x20: 270 { 271 opval[1] = extract_op_bits (op_pointer, oplen, 16); 272 if (! (opval[1] & 32768)) 273 { 274 opval[1] += op_pointer; 275 } 276 oplen += 16; 277 break; 278 } 279 case 0x30: 280 { 281 oplen--; 282 opval[2] = extract_op_bits (op_pointer, oplen, 12); 283 oplen += 12; 284 opval[2] |= 32768; 285 break; 286 } 287 } 288 if (((*op) & 0x08) && (((*op) & 0x30) != 0x30)) 289 { 290 opval[2] = extract_op_bits (op_pointer, oplen, 16); 291 oplen += 16; 292 if (! (opval[2] & 32768)) 293 { 294 opval[2] += op_pointer; 295 } 296 } 297 return oplen; 298} 299 300/* Returns a non-zero value if the opcode in the main_table list at 301 PLACE matches OPCODE and is of type TYPE. */ 302 303static int 304opcode_verify (ia64_insn opcode, int place, enum ia64_insn_type type) 305{ 306 if (main_table[place].opcode_type != type) 307 { 308 return 0; 309 } 310 if (main_table[place].flags 311 & (IA64_OPCODE_F2_EQ_F3 | IA64_OPCODE_LEN_EQ_64MCNT)) 312 { 313 const struct ia64_operand *o1, *o2; 314 ia64_insn f2, f3; 315 316 if (main_table[place].flags & IA64_OPCODE_F2_EQ_F3) 317 { 318 o1 = elf64_ia64_operands + IA64_OPND_F2; 319 o2 = elf64_ia64_operands + IA64_OPND_F3; 320 (*o1->extract) (o1, opcode, &f2); 321 (*o2->extract) (o2, opcode, &f3); 322 if (f2 != f3) 323 return 0; 324 } 325 else 326 { 327 ia64_insn len, count; 328 329 /* length must equal 64-count: */ 330 o1 = elf64_ia64_operands + IA64_OPND_LEN6; 331 o2 = elf64_ia64_operands + main_table[place].operands[2]; 332 (*o1->extract) (o1, opcode, &len); 333 (*o2->extract) (o2, opcode, &count); 334 if (len != 64 - count) 335 return 0; 336 } 337 } 338 return 1; 339} 340 341/* Find an instruction entry in the ia64_dis_names array that matches 342 opcode OPCODE and is of type TYPE. Returns either a positive index 343 into the array, or a negative value if an entry for OPCODE could 344 not be found. Checks all matches and returns the one with the highest 345 priority. */ 346 347static int 348locate_opcode_ent (ia64_insn opcode, enum ia64_insn_type type) 349{ 350 int currtest[41]; 351 int bitpos[41]; 352 int op_ptr[41]; 353 int currstatenum = 0; 354 short found_disent = -1; 355 short found_priority = -1; 356 357 currtest[currstatenum] = 0; 358 op_ptr[currstatenum] = 0; 359 bitpos[currstatenum] = 40; 360 361 while (1) 362 { 363 int op_pointer = op_ptr[currstatenum]; 364 unsigned int op; 365 int currbitnum = bitpos[currstatenum]; 366 int oplen; 367 int opval[3] = {0}; 368 int next_op; 369 int currbit; 370 371 oplen = extract_op (op_pointer, opval, &op); 372 373 bitpos[currstatenum] = currbitnum; 374 375 /* Skip opval[0] bits in the instruction. */ 376 if (op & 0x40) 377 { 378 currbitnum -= opval[0]; 379 } 380 381 /* The value of the current bit being tested. */ 382 currbit = opcode & (((ia64_insn) 1) << currbitnum) ? 1 : 0; 383 next_op = -1; 384 385 /* We always perform the tests specified in the current state in 386 a particular order, falling through to the next test if the 387 previous one failed. */ 388 switch (currtest[currstatenum]) 389 { 390 case 0: 391 currtest[currstatenum]++; 392 if (currbit == 0 && (op & 0x80)) 393 { 394 /* Check for a zero bit. If this test solely checks for 395 a zero bit, we can check for up to 8 consecutive zero 396 bits (the number to check is specified by the lower 3 397 bits in the state code.) 398 399 If the state instruction matches, we go to the very 400 next state instruction; otherwise, try the next test. */ 401 402 if ((op & 0xf8) == 0x80) 403 { 404 int count = op & 0x7; 405 int x; 406 407 for (x = 0; x <= count; x++) 408 { 409 int i = 410 opcode & (((ia64_insn) 1) << (currbitnum - x)) ? 1 : 0; 411 if (i) 412 { 413 break; 414 } 415 } 416 if (x > count) 417 { 418 next_op = op_pointer + ((oplen + 7) / 8); 419 currbitnum -= count; 420 break; 421 } 422 } 423 else if (! currbit) 424 { 425 next_op = op_pointer + ((oplen + 7) / 8); 426 break; 427 } 428 } 429 /* FALLTHROUGH */ 430 case 1: 431 /* If the bit in the instruction is one, go to the state 432 instruction specified by opval[1]. */ 433 currtest[currstatenum]++; 434 if (currbit && (op & 0x30) != 0 && ((op & 0x30) != 0x30)) 435 { 436 next_op = opval[1]; 437 break; 438 } 439 /* FALLTHROUGH */ 440 case 2: 441 /* Don't care. Skip the current bit and go to the state 442 instruction specified by opval[2]. 443 444 An encoding of 0x30 is special; this means that a 12-bit 445 offset into the ia64_dis_names[] array is specified. */ 446 currtest[currstatenum]++; 447 if ((op & 0x08) || ((op & 0x30) == 0x30)) 448 { 449 next_op = opval[2]; 450 break; 451 } 452 } 453 454 /* If bit 15 is set in the address of the next state, an offset 455 in the ia64_dis_names array was specified instead. We then 456 check to see if an entry in the list of opcodes matches the 457 opcode we were given; if so, we have succeeded. */ 458 459 if ((next_op >= 0) && (next_op & 32768)) 460 { 461 short disent = next_op & 32767; 462 short priority = -1; 463 464 if (next_op > 65535) 465 { 466 abort (); 467 } 468 469 /* Run through the list of opcodes to check, trying to find 470 one that matches. */ 471 while (disent >= 0) 472 { 473 int place = ia64_dis_names[disent].insn_index; 474 475 priority = ia64_dis_names[disent].priority; 476 477 if (opcode_verify (opcode, place, type) 478 && priority > found_priority) 479 { 480 break; 481 } 482 if (ia64_dis_names[disent].next_flag) 483 { 484 disent++; 485 } 486 else 487 { 488 disent = -1; 489 } 490 } 491 492 if (disent >= 0) 493 { 494 found_disent = disent; 495 found_priority = priority; 496 } 497 /* Try the next test in this state, regardless of whether a match 498 was found. */ 499 next_op = -2; 500 } 501 502 /* next_op == -1 is "back up to the previous state". 503 next_op == -2 is "stay in this state and try the next test". 504 Otherwise, transition to the state indicated by next_op. */ 505 506 if (next_op == -1) 507 { 508 currstatenum--; 509 if (currstatenum < 0) 510 { 511 return found_disent; 512 } 513 } 514 else if (next_op >= 0) 515 { 516 currstatenum++; 517 bitpos[currstatenum] = currbitnum - 1; 518 op_ptr[currstatenum] = next_op; 519 currtest[currstatenum] = 0; 520 } 521 } 522} 523 524/* Construct an ia64_opcode entry based on OPCODE, NAME and PLACE. */ 525 526static struct ia64_opcode * 527make_ia64_opcode (ia64_insn opcode, const char *name, int place, int depind) 528{ 529 struct ia64_opcode *res = 530 (struct ia64_opcode *) xmalloc (sizeof (struct ia64_opcode)); 531 res->name = xstrdup (name); 532 res->type = main_table[place].opcode_type; 533 res->num_outputs = main_table[place].num_outputs; 534 res->opcode = opcode; 535 res->mask = main_table[place].mask; 536 res->operands[0] = main_table[place].operands[0]; 537 res->operands[1] = main_table[place].operands[1]; 538 res->operands[2] = main_table[place].operands[2]; 539 res->operands[3] = main_table[place].operands[3]; 540 res->operands[4] = main_table[place].operands[4]; 541 res->flags = main_table[place].flags; 542 res->ent_index = place; 543 res->dependencies = &op_dependencies[depind]; 544 return res; 545} 546 547/* Determine the ia64_opcode entry for the opcode specified by INSN 548 and TYPE. If a valid entry is not found, return NULL. */ 549struct ia64_opcode * 550ia64_dis_opcode (ia64_insn insn, enum ia64_insn_type type) 551{ 552 int disent = locate_opcode_ent (insn, type); 553 554 if (disent < 0) 555 { 556 return NULL; 557 } 558 else 559 { 560 unsigned int cb = ia64_dis_names[disent].completer_index; 561 static char name[128]; 562 int place = ia64_dis_names[disent].insn_index; 563 int ci = main_table[place].completers; 564 ia64_insn tinsn = main_table[place].opcode; 565 566 strcpy (name, ia64_strings [main_table[place].name_index]); 567 568 while (cb) 569 { 570 if (cb & 1) 571 { 572 int cname = completer_table[ci].name_index; 573 574 tinsn = apply_completer (tinsn, ci); 575 576 if (ia64_strings[cname][0] != '\0') 577 { 578 strcat (name, "."); 579 strcat (name, ia64_strings[cname]); 580 } 581 if (cb != 1) 582 { 583 ci = completer_table[ci].subentries; 584 } 585 } 586 else 587 { 588 ci = completer_table[ci].alternative; 589 } 590 if (ci < 0) 591 { 592 abort (); 593 } 594 cb = cb >> 1; 595 } 596 if (tinsn != (insn & main_table[place].mask)) 597 { 598 abort (); 599 } 600 return make_ia64_opcode (insn, name, place, 601 completer_table[ci].dependencies); 602 } 603} 604 605/* Search the main_opcode table starting from PLACE for an opcode that 606 matches NAME. Return NULL if one is not found. */ 607 608static struct ia64_opcode * 609ia64_find_matching_opcode (const char *name, short place) 610{ 611 char op[129]; 612 const char *suffix; 613 short name_index; 614 615 if (strlen (name) > 128) 616 { 617 return NULL; 618 } 619 suffix = name; 620 get_opc_prefix (&suffix, op); 621 name_index = find_string_ent (op); 622 if (name_index < 0) 623 { 624 return NULL; 625 } 626 627 while (main_table[place].name_index == name_index) 628 { 629 const char *curr_suffix = suffix; 630 ia64_insn curr_insn = main_table[place].opcode; 631 short completer = -1; 632 633 do { 634 if (suffix[0] == '\0') 635 { 636 completer = find_completer (place, completer, suffix); 637 } 638 else 639 { 640 get_opc_prefix (&curr_suffix, op); 641 completer = find_completer (place, completer, op); 642 } 643 if (completer != -1) 644 { 645 curr_insn = apply_completer (curr_insn, completer); 646 } 647 } while (completer != -1 && curr_suffix[0] != '\0'); 648 649 if (completer != -1 && curr_suffix[0] == '\0' 650 && completer_table[completer].terminal_completer) 651 { 652 int depind = completer_table[completer].dependencies; 653 return make_ia64_opcode (curr_insn, name, place, depind); 654 } 655 else 656 { 657 place++; 658 } 659 } 660 return NULL; 661} 662 663/* Find the next opcode after PREV_ENT that matches PREV_ENT, or return NULL 664 if one does not exist. 665 666 It is the caller's responsibility to invoke ia64_free_opcode () to 667 release any resources used by the returned entry. */ 668 669struct ia64_opcode * 670ia64_find_next_opcode (struct ia64_opcode *prev_ent) 671{ 672 return ia64_find_matching_opcode (prev_ent->name, 673 prev_ent->ent_index + 1); 674} 675 676/* Find the first opcode that matches NAME, or return NULL if it does 677 not exist. 678 679 It is the caller's responsibility to invoke ia64_free_opcode () to 680 release any resources used by the returned entry. */ 681 682struct ia64_opcode * 683ia64_find_opcode (const char *name) 684{ 685 char op[129]; 686 const char *suffix; 687 short place; 688 short name_index; 689 690 if (strlen (name) > 128) 691 { 692 return NULL; 693 } 694 suffix = name; 695 get_opc_prefix (&suffix, op); 696 name_index = find_string_ent (op); 697 if (name_index < 0) 698 { 699 return NULL; 700 } 701 702 place = find_main_ent (name_index); 703 704 if (place < 0) 705 { 706 return NULL; 707 } 708 return ia64_find_matching_opcode (name, place); 709} 710 711/* Free any resources used by ENT. */ 712void 713ia64_free_opcode (struct ia64_opcode *ent) 714{ 715 free ((void *)ent->name); 716 free (ent); 717} 718 719const struct ia64_dependency * 720ia64_find_dependency (int dep_index) 721{ 722 dep_index = DEP(dep_index); 723 724 if (dep_index < 0 725 || dep_index >= (int) ARRAY_SIZE (dependencies)) 726 return NULL; 727 728 return &dependencies[dep_index]; 729} 730