00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026 #include "ansidecl.h"
00027 #include "libiberty.h"
00028 #include "sysdep.h"
00029 #include "ia64-asmtab.h"
00030 #include "ia64-asmtab.c"
00031
00032 static void get_opc_prefix (const char **, char *);
00033 static short int find_string_ent (const char *);
00034 static short int find_main_ent (short int);
00035 static short int find_completer (short int, short int, const char *);
00036 static ia64_insn apply_completer (ia64_insn, int);
00037 static int extract_op_bits (int, int, int);
00038 static int extract_op (int, int *, unsigned int *);
00039 static int opcode_verify (ia64_insn, int, enum ia64_insn_type);
00040 static int locate_opcode_ent (ia64_insn, enum ia64_insn_type);
00041 static struct ia64_opcode *make_ia64_opcode
00042 (ia64_insn, const char *, int, int);
00043 static struct ia64_opcode *ia64_find_matching_opcode
00044 (const char *, short int);
00045
00046 const struct ia64_templ_desc ia64_templ_desc[16] =
00047 {
00048 { 0, { IA64_UNIT_M, IA64_UNIT_I, IA64_UNIT_I }, "MII" },
00049 { 2, { IA64_UNIT_M, IA64_UNIT_I, IA64_UNIT_I }, "MII" },
00050 { 0, { IA64_UNIT_M, IA64_UNIT_L, IA64_UNIT_X }, "MLX" },
00051 { 0, { 0, }, "-3-" },
00052 { 0, { IA64_UNIT_M, IA64_UNIT_M, IA64_UNIT_I }, "MMI" },
00053 { 1, { IA64_UNIT_M, IA64_UNIT_M, IA64_UNIT_I }, "MMI" },
00054 { 0, { IA64_UNIT_M, IA64_UNIT_F, IA64_UNIT_I }, "MFI" },
00055 { 0, { IA64_UNIT_M, IA64_UNIT_M, IA64_UNIT_F }, "MMF" },
00056 { 0, { IA64_UNIT_M, IA64_UNIT_I, IA64_UNIT_B }, "MIB" },
00057 { 0, { IA64_UNIT_M, IA64_UNIT_B, IA64_UNIT_B }, "MBB" },
00058 { 0, { 0, }, "-a-" },
00059 { 0, { IA64_UNIT_B, IA64_UNIT_B, IA64_UNIT_B }, "BBB" },
00060 { 0, { IA64_UNIT_M, IA64_UNIT_M, IA64_UNIT_B }, "MMB" },
00061 { 0, { 0, }, "-d-" },
00062 { 0, { IA64_UNIT_M, IA64_UNIT_F, IA64_UNIT_B }, "MFB" },
00063 { 0, { 0, }, "-f-" },
00064 };
00065
00066
00067
00068
00069
00070
00071 static void
00072 get_opc_prefix (const char **ptr, char *dest)
00073 {
00074 char *c = strchr (*ptr, '.');
00075 if (c != NULL)
00076 {
00077 memcpy (dest, *ptr, c - *ptr);
00078 dest[c - *ptr] = '\0';
00079 *ptr = c + 1;
00080 }
00081 else
00082 {
00083 int l = strlen (*ptr);
00084 memcpy (dest, *ptr, l);
00085 dest[l] = '\0';
00086 *ptr += l;
00087 }
00088 }
00089
00090
00091
00092
00093 static short
00094 find_string_ent (const char *str)
00095 {
00096 short start = 0;
00097 short end = sizeof (ia64_strings) / sizeof (const char *);
00098 short i = (start + end) / 2;
00099
00100 if (strcmp (str, ia64_strings[end - 1]) > 0)
00101 {
00102 return -1;
00103 }
00104 while (start <= end)
00105 {
00106 int c = strcmp (str, ia64_strings[i]);
00107 if (c < 0)
00108 {
00109 end = i - 1;
00110 }
00111 else if (c == 0)
00112 {
00113 return i;
00114 }
00115 else
00116 {
00117 start = i + 1;
00118 }
00119 i = (start + end) / 2;
00120 }
00121 return -1;
00122 }
00123
00124
00125
00126
00127 static short
00128 find_main_ent (short nameindex)
00129 {
00130 short start = 0;
00131 short end = sizeof (main_table) / sizeof (struct ia64_main_table);
00132 short i = (start + end) / 2;
00133
00134 if (nameindex < main_table[0].name_index
00135 || nameindex > main_table[end - 1].name_index)
00136 {
00137 return -1;
00138 }
00139 while (start <= end)
00140 {
00141 if (nameindex < main_table[i].name_index)
00142 {
00143 end = i - 1;
00144 }
00145 else if (nameindex == main_table[i].name_index)
00146 {
00147 while (i > 0 && main_table[i - 1].name_index == nameindex)
00148 {
00149 i--;
00150 }
00151 return i;
00152 }
00153 else
00154 {
00155 start = i + 1;
00156 }
00157 i = (start + end) / 2;
00158 }
00159 return -1;
00160 }
00161
00162
00163
00164
00165
00166 static short
00167 find_completer (short main_ent, short prev_completer, const char *name)
00168 {
00169 short name_index = find_string_ent (name);
00170
00171 if (name_index < 0)
00172 {
00173 return -1;
00174 }
00175
00176 if (prev_completer == -1)
00177 {
00178 prev_completer = main_table[main_ent].completers;
00179 }
00180 else
00181 {
00182 prev_completer = completer_table[prev_completer].subentries;
00183 }
00184
00185 while (prev_completer != -1)
00186 {
00187 if (completer_table[prev_completer].name_index == name_index)
00188 {
00189 return prev_completer;
00190 }
00191 prev_completer = completer_table[prev_completer].alternative;
00192 }
00193 return -1;
00194 }
00195
00196
00197
00198
00199 static ia64_insn
00200 apply_completer (ia64_insn opcode, int completer_index)
00201 {
00202 ia64_insn mask = completer_table[completer_index].mask;
00203 ia64_insn bits = completer_table[completer_index].bits;
00204 int shiftamt = (completer_table[completer_index].offset & 63);
00205
00206 mask = mask << shiftamt;
00207 bits = bits << shiftamt;
00208 opcode = (opcode & ~mask) | bits;
00209 return opcode;
00210 }
00211
00212
00213
00214
00215
00216
00217 static int
00218 extract_op_bits (int op_pointer, int bitoffset, int bits)
00219 {
00220 int res = 0;
00221
00222 op_pointer += (bitoffset / 8);
00223
00224 if (bitoffset % 8)
00225 {
00226 unsigned int op = dis_table[op_pointer++];
00227 int numb = 8 - (bitoffset % 8);
00228 int mask = (1 << numb) - 1;
00229 int bata = (bits < numb) ? bits : numb;
00230 int delta = numb - bata;
00231
00232 res = (res << bata) | ((op & mask) >> delta);
00233 bitoffset += bata;
00234 bits -= bata;
00235 }
00236 while (bits >= 8)
00237 {
00238 res = (res << 8) | (dis_table[op_pointer++] & 255);
00239 bits -= 8;
00240 }
00241 if (bits > 0)
00242 {
00243 unsigned int op = (dis_table[op_pointer++] & 255);
00244 res = (res << bits) | (op >> (8 - bits));
00245 }
00246 return res;
00247 }
00248
00249
00250
00251
00252
00253 static int
00254 extract_op (int op_pointer, int *opval, unsigned int *op)
00255 {
00256 int oplen = 5;
00257
00258 *op = dis_table[op_pointer];
00259
00260 if ((*op) & 0x40)
00261 {
00262 opval[0] = extract_op_bits (op_pointer, oplen, 5);
00263 oplen += 5;
00264 }
00265 switch ((*op) & 0x30)
00266 {
00267 case 0x10:
00268 {
00269 opval[1] = extract_op_bits (op_pointer, oplen, 8);
00270 oplen += 8;
00271 opval[1] += op_pointer;
00272 break;
00273 }
00274 case 0x20:
00275 {
00276 opval[1] = extract_op_bits (op_pointer, oplen, 16);
00277 if (! (opval[1] & 32768))
00278 {
00279 opval[1] += op_pointer;
00280 }
00281 oplen += 16;
00282 break;
00283 }
00284 case 0x30:
00285 {
00286 oplen--;
00287 opval[2] = extract_op_bits (op_pointer, oplen, 12);
00288 oplen += 12;
00289 opval[2] |= 32768;
00290 break;
00291 }
00292 }
00293 if (((*op) & 0x08) && (((*op) & 0x30) != 0x30))
00294 {
00295 opval[2] = extract_op_bits (op_pointer, oplen, 16);
00296 oplen += 16;
00297 if (! (opval[2] & 32768))
00298 {
00299 opval[2] += op_pointer;
00300 }
00301 }
00302 return oplen;
00303 }
00304
00305
00306
00307
00308 static int
00309 opcode_verify (ia64_insn opcode, int place, enum ia64_insn_type type)
00310 {
00311 if (main_table[place].opcode_type != type)
00312 {
00313 return 0;
00314 }
00315 if (main_table[place].flags
00316 & (IA64_OPCODE_F2_EQ_F3 | IA64_OPCODE_LEN_EQ_64MCNT))
00317 {
00318 const struct ia64_operand *o1, *o2;
00319 ia64_insn f2, f3;
00320
00321 if (main_table[place].flags & IA64_OPCODE_F2_EQ_F3)
00322 {
00323 o1 = elf64_ia64_operands + IA64_OPND_F2;
00324 o2 = elf64_ia64_operands + IA64_OPND_F3;
00325 (*o1->extract) (o1, opcode, &f2);
00326 (*o2->extract) (o2, opcode, &f3);
00327 if (f2 != f3)
00328 return 0;
00329 }
00330 else
00331 {
00332 ia64_insn len, count;
00333
00334
00335 o1 = elf64_ia64_operands + IA64_OPND_LEN6;
00336 o2 = elf64_ia64_operands + main_table[place].operands[2];
00337 (*o1->extract) (o1, opcode, &len);
00338 (*o2->extract) (o2, opcode, &count);
00339 if (len != 64 - count)
00340 return 0;
00341 }
00342 }
00343 return 1;
00344 }
00345
00346
00347
00348
00349
00350
00351
00352 static int
00353 locate_opcode_ent (ia64_insn opcode, enum ia64_insn_type type)
00354 {
00355 int currtest[41];
00356 int bitpos[41];
00357 int op_ptr[41];
00358 int currstatenum = 0;
00359 short found_disent = -1;
00360 short found_priority = -1;
00361
00362 currtest[currstatenum] = 0;
00363 op_ptr[currstatenum] = 0;
00364 bitpos[currstatenum] = 40;
00365
00366 while (1)
00367 {
00368 int op_pointer = op_ptr[currstatenum];
00369 unsigned int op;
00370 int currbitnum = bitpos[currstatenum];
00371 int oplen;
00372 int opval[3] = {0};
00373 int next_op;
00374 int currbit;
00375
00376 oplen = extract_op (op_pointer, opval, &op);
00377
00378 bitpos[currstatenum] = currbitnum;
00379
00380
00381 if (op & 0x40)
00382 {
00383 currbitnum -= opval[0];
00384 }
00385
00386
00387 currbit = opcode & (((ia64_insn) 1) << currbitnum) ? 1 : 0;
00388 next_op = -1;
00389
00390
00391
00392
00393 switch (currtest[currstatenum])
00394 {
00395 case 0:
00396 currtest[currstatenum]++;
00397 if (currbit == 0 && (op & 0x80))
00398 {
00399
00400
00401
00402
00403
00404
00405
00406
00407 if ((op & 0xf8) == 0x80)
00408 {
00409 int count = op & 0x7;
00410 int x;
00411
00412 for (x = 0; x <= count; x++)
00413 {
00414 int i =
00415 opcode & (((ia64_insn) 1) << (currbitnum - x)) ? 1 : 0;
00416 if (i)
00417 {
00418 break;
00419 }
00420 }
00421 if (x > count)
00422 {
00423 next_op = op_pointer + ((oplen + 7) / 8);
00424 currbitnum -= count;
00425 break;
00426 }
00427 }
00428 else if (! currbit)
00429 {
00430 next_op = op_pointer + ((oplen + 7) / 8);
00431 break;
00432 }
00433 }
00434
00435 case 1:
00436
00437
00438 currtest[currstatenum]++;
00439 if (currbit && (op & 0x30) != 0 && ((op & 0x30) != 0x30))
00440 {
00441 next_op = opval[1];
00442 break;
00443 }
00444
00445 case 2:
00446
00447
00448
00449
00450
00451 currtest[currstatenum]++;
00452 if ((op & 0x08) || ((op & 0x30) == 0x30))
00453 {
00454 next_op = opval[2];
00455 break;
00456 }
00457 }
00458
00459
00460
00461
00462
00463
00464 if ((next_op >= 0) && (next_op & 32768))
00465 {
00466 short disent = next_op & 32767;
00467 short priority = -1;
00468
00469 if (next_op > 65535)
00470 {
00471 abort ();
00472 }
00473
00474
00475
00476 while (disent >= 0)
00477 {
00478 int place = ia64_dis_names[disent].insn_index;
00479
00480 priority = ia64_dis_names[disent].priority;
00481
00482 if (opcode_verify (opcode, place, type)
00483 && priority > found_priority)
00484 {
00485 break;
00486 }
00487 if (ia64_dis_names[disent].next_flag)
00488 {
00489 disent++;
00490 }
00491 else
00492 {
00493 disent = -1;
00494 }
00495 }
00496
00497 if (disent >= 0)
00498 {
00499 found_disent = disent;
00500 found_priority = priority;
00501 }
00502
00503
00504 next_op = -2;
00505 }
00506
00507
00508
00509
00510
00511 if (next_op == -1)
00512 {
00513 currstatenum--;
00514 if (currstatenum < 0)
00515 {
00516 return found_disent;
00517 }
00518 }
00519 else if (next_op >= 0)
00520 {
00521 currstatenum++;
00522 bitpos[currstatenum] = currbitnum - 1;
00523 op_ptr[currstatenum] = next_op;
00524 currtest[currstatenum] = 0;
00525 }
00526 }
00527 }
00528
00529
00530
00531 static struct ia64_opcode *
00532 make_ia64_opcode (ia64_insn opcode, const char *name, int place, int depind)
00533 {
00534 struct ia64_opcode *res =
00535 (struct ia64_opcode *) xmalloc (sizeof (struct ia64_opcode));
00536 res->name = xstrdup (name);
00537 res->type = main_table[place].opcode_type;
00538 res->num_outputs = main_table[place].num_outputs;
00539 res->opcode = opcode;
00540 res->mask = main_table[place].mask;
00541 res->operands[0] = main_table[place].operands[0];
00542 res->operands[1] = main_table[place].operands[1];
00543 res->operands[2] = main_table[place].operands[2];
00544 res->operands[3] = main_table[place].operands[3];
00545 res->operands[4] = main_table[place].operands[4];
00546 res->flags = main_table[place].flags;
00547 res->ent_index = place;
00548 res->dependencies = &op_dependencies[depind];
00549 return res;
00550 }
00551
00552
00553
00554 struct ia64_opcode *
00555 ia64_dis_opcode (ia64_insn insn, enum ia64_insn_type type)
00556 {
00557 int disent = locate_opcode_ent (insn, type);
00558
00559 if (disent < 0)
00560 {
00561 return NULL;
00562 }
00563 else
00564 {
00565 unsigned int cb = ia64_dis_names[disent].completer_index;
00566 static char name[128];
00567 int place = ia64_dis_names[disent].insn_index;
00568 int ci = main_table[place].completers;
00569 ia64_insn tinsn = main_table[place].opcode;
00570
00571 strcpy (name, ia64_strings [main_table[place].name_index]);
00572
00573 while (cb)
00574 {
00575 if (cb & 1)
00576 {
00577 int cname = completer_table[ci].name_index;
00578
00579 tinsn = apply_completer (tinsn, ci);
00580
00581 if (ia64_strings[cname][0] != '\0')
00582 {
00583 strcat (name, ".");
00584 strcat (name, ia64_strings[cname]);
00585 }
00586 if (cb != 1)
00587 {
00588 ci = completer_table[ci].subentries;
00589 }
00590 }
00591 else
00592 {
00593 ci = completer_table[ci].alternative;
00594 }
00595 if (ci < 0)
00596 {
00597 abort ();
00598 }
00599 cb = cb >> 1;
00600 }
00601 if (tinsn != (insn & main_table[place].mask))
00602 {
00603 abort ();
00604 }
00605 return make_ia64_opcode (insn, name, place,
00606 completer_table[ci].dependencies);
00607 }
00608 }
00609
00610
00611
00612
00613 static struct ia64_opcode *
00614 ia64_find_matching_opcode (const char *name, short place)
00615 {
00616 char op[129];
00617 const char *suffix;
00618 short name_index;
00619
00620 if (strlen (name) > 128)
00621 {
00622 return NULL;
00623 }
00624 suffix = name;
00625 get_opc_prefix (&suffix, op);
00626 name_index = find_string_ent (op);
00627 if (name_index < 0)
00628 {
00629 return NULL;
00630 }
00631
00632 while (main_table[place].name_index == name_index)
00633 {
00634 const char *curr_suffix = suffix;
00635 ia64_insn curr_insn = main_table[place].opcode;
00636 short completer = -1;
00637
00638 do {
00639 if (suffix[0] == '\0')
00640 {
00641 completer = find_completer (place, completer, suffix);
00642 }
00643 else
00644 {
00645 get_opc_prefix (&curr_suffix, op);
00646 completer = find_completer (place, completer, op);
00647 }
00648 if (completer != -1)
00649 {
00650 curr_insn = apply_completer (curr_insn, completer);
00651 }
00652 } while (completer != -1 && curr_suffix[0] != '\0');
00653
00654 if (completer != -1 && curr_suffix[0] == '\0'
00655 && completer_table[completer].terminal_completer)
00656 {
00657 int depind = completer_table[completer].dependencies;
00658 return make_ia64_opcode (curr_insn, name, place, depind);
00659 }
00660 else
00661 {
00662 place++;
00663 }
00664 }
00665 return NULL;
00666 }
00667
00668
00669
00670
00671
00672
00673
00674 struct ia64_opcode *
00675 ia64_find_next_opcode (struct ia64_opcode *prev_ent)
00676 {
00677 return ia64_find_matching_opcode (prev_ent->name,
00678 prev_ent->ent_index + 1);
00679 }
00680
00681
00682
00683
00684
00685
00686
00687 struct ia64_opcode *
00688 ia64_find_opcode (const char *name)
00689 {
00690 char op[129];
00691 const char *suffix;
00692 short place;
00693 short name_index;
00694
00695 if (strlen (name) > 128)
00696 {
00697 return NULL;
00698 }
00699 suffix = name;
00700 get_opc_prefix (&suffix, op);
00701 name_index = find_string_ent (op);
00702 if (name_index < 0)
00703 {
00704 return NULL;
00705 }
00706
00707 place = find_main_ent (name_index);
00708
00709 if (place < 0)
00710 {
00711 return NULL;
00712 }
00713 return ia64_find_matching_opcode (name, place);
00714 }
00715
00716
00717 void
00718 ia64_free_opcode (struct ia64_opcode *ent)
00719 {
00720 free ((void *)ent->name);
00721 free (ent);
00722 }
00723
00724 const struct ia64_dependency *
00725 ia64_find_dependency (int index)
00726 {
00727 index = DEP(index);
00728
00729 if (index < 0
00730 || index >= (int)(sizeof(dependencies) / sizeof(dependencies[0])))
00731 return NULL;
00732
00733 return &dependencies[index];
00734 }