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