184865Sobrien/* ia64-opc.c -- Functions to access the compacted opcode table 2218822Sdim Copyright 1999, 2000, 2001, 2003, 2005 Free Software Foundation, Inc. 384865Sobrien Written by Bob Manson of Cygnus Solutions, <manson@cygnus.com> 484865Sobrien 584865Sobrien This file is part of GDB, GAS, and the GNU binutils. 684865Sobrien 784865Sobrien GDB, GAS, and the GNU binutils are free software; you can redistribute 884865Sobrien them and/or modify them under the terms of the GNU General Public 984865Sobrien License as published by the Free Software Foundation; either version 1084865Sobrien 2, or (at your option) any later version. 1184865Sobrien 1284865Sobrien GDB, GAS, and the GNU binutils are distributed in the hope that they 1384865Sobrien will be useful, but WITHOUT ANY WARRANTY; without even the implied 1484865Sobrien warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See 1584865Sobrien the GNU General Public License for more details. 1684865Sobrien 1784865Sobrien You should have received a copy of the GNU General Public License 1884865Sobrien along with this file; see the file COPYING. If not, write to the 19218822Sdim Free Software Foundation, 51 Franklin Street - Fifth Floor, Boston, MA 20218822Sdim 02110-1301, USA. */ 2184865Sobrien 2284865Sobrien#include "ansidecl.h" 23218822Sdim#include "sysdep.h" 2484865Sobrien#include "libiberty.h" 2584865Sobrien#include "ia64-asmtab.h" 2684865Sobrien#include "ia64-asmtab.c" 2784865Sobrien 28130561Sobrienstatic void get_opc_prefix (const char **, char *); 29130561Sobrienstatic short int find_string_ent (const char *); 30130561Sobrienstatic short int find_main_ent (short int); 31130561Sobrienstatic short int find_completer (short int, short int, const char *); 32130561Sobrienstatic ia64_insn apply_completer (ia64_insn, int); 33130561Sobrienstatic int extract_op_bits (int, int, int); 34130561Sobrienstatic int extract_op (int, int *, unsigned int *); 35130561Sobrienstatic int opcode_verify (ia64_insn, int, enum ia64_insn_type); 36130561Sobrienstatic int locate_opcode_ent (ia64_insn, enum ia64_insn_type); 3789857Sobrienstatic struct ia64_opcode *make_ia64_opcode 38130561Sobrien (ia64_insn, const char *, int, int); 3989857Sobrienstatic struct ia64_opcode *ia64_find_matching_opcode 40130561Sobrien (const char *, short int); 4189857Sobrien 4284865Sobrienconst struct ia64_templ_desc ia64_templ_desc[16] = 4384865Sobrien { 4484865Sobrien { 0, { IA64_UNIT_M, IA64_UNIT_I, IA64_UNIT_I }, "MII" }, /* 0 */ 4584865Sobrien { 2, { IA64_UNIT_M, IA64_UNIT_I, IA64_UNIT_I }, "MII" }, 4684865Sobrien { 0, { IA64_UNIT_M, IA64_UNIT_L, IA64_UNIT_X }, "MLX" }, 4784865Sobrien { 0, { 0, }, "-3-" }, 4884865Sobrien { 0, { IA64_UNIT_M, IA64_UNIT_M, IA64_UNIT_I }, "MMI" }, /* 4 */ 4984865Sobrien { 1, { IA64_UNIT_M, IA64_UNIT_M, IA64_UNIT_I }, "MMI" }, 5084865Sobrien { 0, { IA64_UNIT_M, IA64_UNIT_F, IA64_UNIT_I }, "MFI" }, 5184865Sobrien { 0, { IA64_UNIT_M, IA64_UNIT_M, IA64_UNIT_F }, "MMF" }, 5284865Sobrien { 0, { IA64_UNIT_M, IA64_UNIT_I, IA64_UNIT_B }, "MIB" }, /* 8 */ 5384865Sobrien { 0, { IA64_UNIT_M, IA64_UNIT_B, IA64_UNIT_B }, "MBB" }, 5484865Sobrien { 0, { 0, }, "-a-" }, 5584865Sobrien { 0, { IA64_UNIT_B, IA64_UNIT_B, IA64_UNIT_B }, "BBB" }, 5684865Sobrien { 0, { IA64_UNIT_M, IA64_UNIT_M, IA64_UNIT_B }, "MMB" }, /* c */ 5784865Sobrien { 0, { 0, }, "-d-" }, 5884865Sobrien { 0, { IA64_UNIT_M, IA64_UNIT_F, IA64_UNIT_B }, "MFB" }, 5984865Sobrien { 0, { 0, }, "-f-" }, 6084865Sobrien }; 6184865Sobrien 6284865Sobrien 6384865Sobrien/* Copy the prefix contained in *PTR (up to a '.' or a NUL) to DEST. 6484865Sobrien PTR will be adjusted to point to the start of the next portion 6584865Sobrien of the opcode, or at the NUL character. */ 6684865Sobrien 6784865Sobrienstatic void 68130561Sobrienget_opc_prefix (const char **ptr, char *dest) 6984865Sobrien{ 7084865Sobrien char *c = strchr (*ptr, '.'); 7184865Sobrien if (c != NULL) 7284865Sobrien { 7384865Sobrien memcpy (dest, *ptr, c - *ptr); 7484865Sobrien dest[c - *ptr] = '\0'; 7584865Sobrien *ptr = c + 1; 7684865Sobrien } 7784865Sobrien else 7884865Sobrien { 7984865Sobrien int l = strlen (*ptr); 8084865Sobrien memcpy (dest, *ptr, l); 8184865Sobrien dest[l] = '\0'; 8284865Sobrien *ptr += l; 8384865Sobrien } 8484865Sobrien} 8584865Sobrien 8684865Sobrien/* Find the index of the entry in the string table corresponding to 8784865Sobrien STR; return -1 if one does not exist. */ 8884865Sobrien 8984865Sobrienstatic short 90130561Sobrienfind_string_ent (const char *str) 9184865Sobrien{ 9284865Sobrien short start = 0; 9384865Sobrien short end = sizeof (ia64_strings) / sizeof (const char *); 9484865Sobrien short i = (start + end) / 2; 9584865Sobrien 9684865Sobrien if (strcmp (str, ia64_strings[end - 1]) > 0) 9784865Sobrien { 9884865Sobrien return -1; 9984865Sobrien } 10084865Sobrien while (start <= end) 10184865Sobrien { 10284865Sobrien int c = strcmp (str, ia64_strings[i]); 10384865Sobrien if (c < 0) 10484865Sobrien { 10584865Sobrien end = i - 1; 10684865Sobrien } 10784865Sobrien else if (c == 0) 10884865Sobrien { 10984865Sobrien return i; 11084865Sobrien } 11184865Sobrien else 11284865Sobrien { 11384865Sobrien start = i + 1; 11484865Sobrien } 11584865Sobrien i = (start + end) / 2; 11684865Sobrien } 11784865Sobrien return -1; 11884865Sobrien} 11984865Sobrien 12084865Sobrien/* Find the opcode in the main opcode table whose name is STRINGINDEX, or 12184865Sobrien return -1 if one does not exist. */ 12284865Sobrien 12384865Sobrienstatic short 124130561Sobrienfind_main_ent (short nameindex) 12584865Sobrien{ 12684865Sobrien short start = 0; 12784865Sobrien short end = sizeof (main_table) / sizeof (struct ia64_main_table); 12884865Sobrien short i = (start + end) / 2; 12984865Sobrien 13084865Sobrien if (nameindex < main_table[0].name_index 13184865Sobrien || nameindex > main_table[end - 1].name_index) 13284865Sobrien { 13384865Sobrien return -1; 13484865Sobrien } 13584865Sobrien while (start <= end) 13684865Sobrien { 13784865Sobrien if (nameindex < main_table[i].name_index) 13884865Sobrien { 13984865Sobrien end = i - 1; 14084865Sobrien } 14184865Sobrien else if (nameindex == main_table[i].name_index) 14284865Sobrien { 14384865Sobrien while (i > 0 && main_table[i - 1].name_index == nameindex) 14484865Sobrien { 14584865Sobrien i--; 14684865Sobrien } 14784865Sobrien return i; 14884865Sobrien } 14984865Sobrien else 15084865Sobrien { 15184865Sobrien start = i + 1; 15284865Sobrien } 15384865Sobrien i = (start + end) / 2; 15484865Sobrien } 15584865Sobrien return -1; 15684865Sobrien} 15784865Sobrien 15884865Sobrien/* Find the index of the entry in the completer table that is part of 15984865Sobrien MAIN_ENT (starting from PREV_COMPLETER) that matches NAME, or 16084865Sobrien return -1 if one does not exist. */ 16184865Sobrien 16289857Sobrienstatic short 163130561Sobrienfind_completer (short main_ent, short prev_completer, const char *name) 16484865Sobrien{ 16584865Sobrien short name_index = find_string_ent (name); 16684865Sobrien 16784865Sobrien if (name_index < 0) 16884865Sobrien { 16984865Sobrien return -1; 17084865Sobrien } 17184865Sobrien 17284865Sobrien if (prev_completer == -1) 17384865Sobrien { 17484865Sobrien prev_completer = main_table[main_ent].completers; 17584865Sobrien } 17684865Sobrien else 17784865Sobrien { 17884865Sobrien prev_completer = completer_table[prev_completer].subentries; 17984865Sobrien } 18084865Sobrien 18184865Sobrien while (prev_completer != -1) 18284865Sobrien { 18384865Sobrien if (completer_table[prev_completer].name_index == name_index) 18484865Sobrien { 18584865Sobrien return prev_completer; 18684865Sobrien } 18784865Sobrien prev_completer = completer_table[prev_completer].alternative; 18884865Sobrien } 18984865Sobrien return -1; 19084865Sobrien} 19184865Sobrien 19284865Sobrien/* Apply the completer referred to by COMPLETER_INDEX to OPCODE, and 19384865Sobrien return the result. */ 19484865Sobrien 19584865Sobrienstatic ia64_insn 196130561Sobrienapply_completer (ia64_insn opcode, int completer_index) 19784865Sobrien{ 19884865Sobrien ia64_insn mask = completer_table[completer_index].mask; 19984865Sobrien ia64_insn bits = completer_table[completer_index].bits; 20084865Sobrien int shiftamt = (completer_table[completer_index].offset & 63); 20184865Sobrien 20284865Sobrien mask = mask << shiftamt; 20384865Sobrien bits = bits << shiftamt; 20484865Sobrien opcode = (opcode & ~mask) | bits; 20584865Sobrien return opcode; 20684865Sobrien} 20784865Sobrien 20884865Sobrien/* Extract BITS number of bits starting from OP_POINTER + BITOFFSET in 20984865Sobrien the dis_table array, and return its value. (BITOFFSET is numbered 21084865Sobrien starting from MSB to LSB, so a BITOFFSET of 0 indicates the MSB of the 21184865Sobrien first byte in OP_POINTER.) */ 21284865Sobrien 21384865Sobrienstatic int 214130561Sobrienextract_op_bits (int op_pointer, int bitoffset, int bits) 21584865Sobrien{ 21684865Sobrien int res = 0; 21784865Sobrien 21884865Sobrien op_pointer += (bitoffset / 8); 21984865Sobrien 22084865Sobrien if (bitoffset % 8) 22184865Sobrien { 22284865Sobrien unsigned int op = dis_table[op_pointer++]; 22384865Sobrien int numb = 8 - (bitoffset % 8); 22484865Sobrien int mask = (1 << numb) - 1; 22584865Sobrien int bata = (bits < numb) ? bits : numb; 22684865Sobrien int delta = numb - bata; 22784865Sobrien 22884865Sobrien res = (res << bata) | ((op & mask) >> delta); 22984865Sobrien bitoffset += bata; 23084865Sobrien bits -= bata; 23184865Sobrien } 23284865Sobrien while (bits >= 8) 23384865Sobrien { 23484865Sobrien res = (res << 8) | (dis_table[op_pointer++] & 255); 23584865Sobrien bits -= 8; 23684865Sobrien } 23784865Sobrien if (bits > 0) 23884865Sobrien { 23984865Sobrien unsigned int op = (dis_table[op_pointer++] & 255); 24084865Sobrien res = (res << bits) | (op >> (8 - bits)); 24184865Sobrien } 24284865Sobrien return res; 24384865Sobrien} 24484865Sobrien 24584865Sobrien/* Examine the state machine entry at OP_POINTER in the dis_table 24684865Sobrien array, and extract its values into OPVAL and OP. The length of the 24784865Sobrien state entry in bits is returned. */ 24884865Sobrien 24984865Sobrienstatic int 250130561Sobrienextract_op (int op_pointer, int *opval, unsigned int *op) 25184865Sobrien{ 25284865Sobrien int oplen = 5; 25384865Sobrien 25484865Sobrien *op = dis_table[op_pointer]; 25584865Sobrien 25684865Sobrien if ((*op) & 0x40) 25784865Sobrien { 25884865Sobrien opval[0] = extract_op_bits (op_pointer, oplen, 5); 25984865Sobrien oplen += 5; 26084865Sobrien } 26184865Sobrien switch ((*op) & 0x30) 26284865Sobrien { 26384865Sobrien case 0x10: 26484865Sobrien { 26584865Sobrien opval[1] = extract_op_bits (op_pointer, oplen, 8); 26684865Sobrien oplen += 8; 26784865Sobrien opval[1] += op_pointer; 26884865Sobrien break; 26984865Sobrien } 27084865Sobrien case 0x20: 27184865Sobrien { 27284865Sobrien opval[1] = extract_op_bits (op_pointer, oplen, 16); 27384865Sobrien if (! (opval[1] & 32768)) 27484865Sobrien { 27584865Sobrien opval[1] += op_pointer; 27684865Sobrien } 27784865Sobrien oplen += 16; 27884865Sobrien break; 27984865Sobrien } 28084865Sobrien case 0x30: 28184865Sobrien { 28284865Sobrien oplen--; 28384865Sobrien opval[2] = extract_op_bits (op_pointer, oplen, 12); 28484865Sobrien oplen += 12; 28584865Sobrien opval[2] |= 32768; 28684865Sobrien break; 28784865Sobrien } 28884865Sobrien } 28984865Sobrien if (((*op) & 0x08) && (((*op) & 0x30) != 0x30)) 29084865Sobrien { 29184865Sobrien opval[2] = extract_op_bits (op_pointer, oplen, 16); 29284865Sobrien oplen += 16; 29384865Sobrien if (! (opval[2] & 32768)) 29484865Sobrien { 29584865Sobrien opval[2] += op_pointer; 29684865Sobrien } 29784865Sobrien } 29884865Sobrien return oplen; 29984865Sobrien} 30084865Sobrien 30184865Sobrien/* Returns a non-zero value if the opcode in the main_table list at 30284865Sobrien PLACE matches OPCODE and is of type TYPE. */ 30384865Sobrien 30484865Sobrienstatic int 305130561Sobrienopcode_verify (ia64_insn opcode, int place, enum ia64_insn_type type) 30684865Sobrien{ 30784865Sobrien if (main_table[place].opcode_type != type) 30884865Sobrien { 30984865Sobrien return 0; 31084865Sobrien } 31189857Sobrien if (main_table[place].flags 31284865Sobrien & (IA64_OPCODE_F2_EQ_F3 | IA64_OPCODE_LEN_EQ_64MCNT)) 31384865Sobrien { 31484865Sobrien const struct ia64_operand *o1, *o2; 31584865Sobrien ia64_insn f2, f3; 31684865Sobrien 31784865Sobrien if (main_table[place].flags & IA64_OPCODE_F2_EQ_F3) 31884865Sobrien { 31984865Sobrien o1 = elf64_ia64_operands + IA64_OPND_F2; 32084865Sobrien o2 = elf64_ia64_operands + IA64_OPND_F3; 32184865Sobrien (*o1->extract) (o1, opcode, &f2); 32284865Sobrien (*o2->extract) (o2, opcode, &f3); 32384865Sobrien if (f2 != f3) 32484865Sobrien return 0; 32584865Sobrien } 32684865Sobrien else 32784865Sobrien { 32884865Sobrien ia64_insn len, count; 32984865Sobrien 33084865Sobrien /* length must equal 64-count: */ 33184865Sobrien o1 = elf64_ia64_operands + IA64_OPND_LEN6; 33284865Sobrien o2 = elf64_ia64_operands + main_table[place].operands[2]; 33384865Sobrien (*o1->extract) (o1, opcode, &len); 33484865Sobrien (*o2->extract) (o2, opcode, &count); 33584865Sobrien if (len != 64 - count) 33684865Sobrien return 0; 33784865Sobrien } 33884865Sobrien } 33984865Sobrien return 1; 34084865Sobrien} 34184865Sobrien 34284865Sobrien/* Find an instruction entry in the ia64_dis_names array that matches 34384865Sobrien opcode OPCODE and is of type TYPE. Returns either a positive index 34484865Sobrien into the array, or a negative value if an entry for OPCODE could 34584865Sobrien not be found. Checks all matches and returns the one with the highest 34684865Sobrien priority. */ 34784865Sobrien 34884865Sobrienstatic int 349130561Sobrienlocate_opcode_ent (ia64_insn opcode, enum ia64_insn_type type) 35084865Sobrien{ 35184865Sobrien int currtest[41]; 35284865Sobrien int bitpos[41]; 35384865Sobrien int op_ptr[41]; 35484865Sobrien int currstatenum = 0; 35584865Sobrien short found_disent = -1; 35684865Sobrien short found_priority = -1; 35784865Sobrien 35884865Sobrien currtest[currstatenum] = 0; 35984865Sobrien op_ptr[currstatenum] = 0; 36084865Sobrien bitpos[currstatenum] = 40; 36184865Sobrien 36284865Sobrien while (1) 36384865Sobrien { 36484865Sobrien int op_pointer = op_ptr[currstatenum]; 36584865Sobrien unsigned int op; 36684865Sobrien int currbitnum = bitpos[currstatenum]; 36784865Sobrien int oplen; 368218822Sdim int opval[3] = {0}; 36984865Sobrien int next_op; 37084865Sobrien int currbit; 37184865Sobrien 37284865Sobrien oplen = extract_op (op_pointer, opval, &op); 37384865Sobrien 37484865Sobrien bitpos[currstatenum] = currbitnum; 37584865Sobrien 37684865Sobrien /* Skip opval[0] bits in the instruction. */ 37784865Sobrien if (op & 0x40) 37884865Sobrien { 37984865Sobrien currbitnum -= opval[0]; 38084865Sobrien } 38184865Sobrien 38284865Sobrien /* The value of the current bit being tested. */ 38384865Sobrien currbit = opcode & (((ia64_insn) 1) << currbitnum) ? 1 : 0; 38484865Sobrien next_op = -1; 38584865Sobrien 38684865Sobrien /* We always perform the tests specified in the current state in 38784865Sobrien a particular order, falling through to the next test if the 38884865Sobrien previous one failed. */ 38984865Sobrien switch (currtest[currstatenum]) 39084865Sobrien { 39184865Sobrien case 0: 39284865Sobrien currtest[currstatenum]++; 39384865Sobrien if (currbit == 0 && (op & 0x80)) 39484865Sobrien { 39584865Sobrien /* Check for a zero bit. If this test solely checks for 39684865Sobrien a zero bit, we can check for up to 8 consecutive zero 39784865Sobrien bits (the number to check is specified by the lower 3 39884865Sobrien bits in the state code.) 39984865Sobrien 40084865Sobrien If the state instruction matches, we go to the very 40184865Sobrien next state instruction; otherwise, try the next test. */ 40284865Sobrien 40384865Sobrien if ((op & 0xf8) == 0x80) 40484865Sobrien { 40584865Sobrien int count = op & 0x7; 40684865Sobrien int x; 40784865Sobrien 40884865Sobrien for (x = 0; x <= count; x++) 40984865Sobrien { 41084865Sobrien int i = 41184865Sobrien opcode & (((ia64_insn) 1) << (currbitnum - x)) ? 1 : 0; 41284865Sobrien if (i) 41384865Sobrien { 41484865Sobrien break; 41584865Sobrien } 41684865Sobrien } 41784865Sobrien if (x > count) 41884865Sobrien { 41984865Sobrien next_op = op_pointer + ((oplen + 7) / 8); 42084865Sobrien currbitnum -= count; 42184865Sobrien break; 42284865Sobrien } 42384865Sobrien } 42484865Sobrien else if (! currbit) 42584865Sobrien { 42684865Sobrien next_op = op_pointer + ((oplen + 7) / 8); 42784865Sobrien break; 42884865Sobrien } 42984865Sobrien } 43084865Sobrien /* FALLTHROUGH */ 43184865Sobrien case 1: 43284865Sobrien /* If the bit in the instruction is one, go to the state 43384865Sobrien instruction specified by opval[1]. */ 43484865Sobrien currtest[currstatenum]++; 43584865Sobrien if (currbit && (op & 0x30) != 0 && ((op & 0x30) != 0x30)) 43684865Sobrien { 43784865Sobrien next_op = opval[1]; 43884865Sobrien break; 43984865Sobrien } 44084865Sobrien /* FALLTHROUGH */ 44184865Sobrien case 2: 44284865Sobrien /* Don't care. Skip the current bit and go to the state 44384865Sobrien instruction specified by opval[2]. 44484865Sobrien 44584865Sobrien An encoding of 0x30 is special; this means that a 12-bit 44684865Sobrien offset into the ia64_dis_names[] array is specified. */ 44784865Sobrien currtest[currstatenum]++; 44884865Sobrien if ((op & 0x08) || ((op & 0x30) == 0x30)) 44984865Sobrien { 45084865Sobrien next_op = opval[2]; 45184865Sobrien break; 45284865Sobrien } 45384865Sobrien } 45484865Sobrien 45584865Sobrien /* If bit 15 is set in the address of the next state, an offset 45684865Sobrien in the ia64_dis_names array was specified instead. We then 45784865Sobrien check to see if an entry in the list of opcodes matches the 45884865Sobrien opcode we were given; if so, we have succeeded. */ 45984865Sobrien 46084865Sobrien if ((next_op >= 0) && (next_op & 32768)) 46184865Sobrien { 46284865Sobrien short disent = next_op & 32767; 46384865Sobrien short priority = -1; 46484865Sobrien 46584865Sobrien if (next_op > 65535) 46684865Sobrien { 46784865Sobrien abort (); 46884865Sobrien } 46984865Sobrien 47084865Sobrien /* Run through the list of opcodes to check, trying to find 47184865Sobrien one that matches. */ 47284865Sobrien while (disent >= 0) 47384865Sobrien { 47484865Sobrien int place = ia64_dis_names[disent].insn_index; 47584865Sobrien 47684865Sobrien priority = ia64_dis_names[disent].priority; 47784865Sobrien 47889857Sobrien if (opcode_verify (opcode, place, type) 47984865Sobrien && priority > found_priority) 48084865Sobrien { 48184865Sobrien break; 48284865Sobrien } 48384865Sobrien if (ia64_dis_names[disent].next_flag) 48484865Sobrien { 48584865Sobrien disent++; 48684865Sobrien } 48784865Sobrien else 48884865Sobrien { 48984865Sobrien disent = -1; 49084865Sobrien } 49184865Sobrien } 49284865Sobrien 49384865Sobrien if (disent >= 0) 49484865Sobrien { 49584865Sobrien found_disent = disent; 49684865Sobrien found_priority = priority; 49784865Sobrien } 49884865Sobrien /* Try the next test in this state, regardless of whether a match 49984865Sobrien was found. */ 50084865Sobrien next_op = -2; 50184865Sobrien } 50284865Sobrien 50384865Sobrien /* next_op == -1 is "back up to the previous state". 50484865Sobrien next_op == -2 is "stay in this state and try the next test". 50584865Sobrien Otherwise, transition to the state indicated by next_op. */ 50684865Sobrien 50784865Sobrien if (next_op == -1) 50884865Sobrien { 50984865Sobrien currstatenum--; 51084865Sobrien if (currstatenum < 0) 51184865Sobrien { 51284865Sobrien return found_disent; 51384865Sobrien } 51484865Sobrien } 51584865Sobrien else if (next_op >= 0) 51684865Sobrien { 51784865Sobrien currstatenum++; 51884865Sobrien bitpos[currstatenum] = currbitnum - 1; 51984865Sobrien op_ptr[currstatenum] = next_op; 52084865Sobrien currtest[currstatenum] = 0; 52184865Sobrien } 52284865Sobrien } 52384865Sobrien} 52484865Sobrien 52584865Sobrien/* Construct an ia64_opcode entry based on OPCODE, NAME and PLACE. */ 52684865Sobrien 52784865Sobrienstatic struct ia64_opcode * 528130561Sobrienmake_ia64_opcode (ia64_insn opcode, const char *name, int place, int depind) 52984865Sobrien{ 53084865Sobrien struct ia64_opcode *res = 53184865Sobrien (struct ia64_opcode *) xmalloc (sizeof (struct ia64_opcode)); 53284865Sobrien res->name = xstrdup (name); 53384865Sobrien res->type = main_table[place].opcode_type; 53484865Sobrien res->num_outputs = main_table[place].num_outputs; 53584865Sobrien res->opcode = opcode; 53684865Sobrien res->mask = main_table[place].mask; 53784865Sobrien res->operands[0] = main_table[place].operands[0]; 53884865Sobrien res->operands[1] = main_table[place].operands[1]; 53984865Sobrien res->operands[2] = main_table[place].operands[2]; 54084865Sobrien res->operands[3] = main_table[place].operands[3]; 54184865Sobrien res->operands[4] = main_table[place].operands[4]; 54284865Sobrien res->flags = main_table[place].flags; 54384865Sobrien res->ent_index = place; 54484865Sobrien res->dependencies = &op_dependencies[depind]; 54584865Sobrien return res; 54684865Sobrien} 54784865Sobrien 54884865Sobrien/* Determine the ia64_opcode entry for the opcode specified by INSN 54984865Sobrien and TYPE. If a valid entry is not found, return NULL. */ 55084865Sobrienstruct ia64_opcode * 551130561Sobrienia64_dis_opcode (ia64_insn insn, enum ia64_insn_type type) 55284865Sobrien{ 55384865Sobrien int disent = locate_opcode_ent (insn, type); 55484865Sobrien 55584865Sobrien if (disent < 0) 55684865Sobrien { 55784865Sobrien return NULL; 55884865Sobrien } 55984865Sobrien else 56084865Sobrien { 56184865Sobrien unsigned int cb = ia64_dis_names[disent].completer_index; 56284865Sobrien static char name[128]; 56384865Sobrien int place = ia64_dis_names[disent].insn_index; 56484865Sobrien int ci = main_table[place].completers; 56584865Sobrien ia64_insn tinsn = main_table[place].opcode; 56684865Sobrien 56784865Sobrien strcpy (name, ia64_strings [main_table[place].name_index]); 56884865Sobrien 56984865Sobrien while (cb) 57084865Sobrien { 57184865Sobrien if (cb & 1) 57284865Sobrien { 57384865Sobrien int cname = completer_table[ci].name_index; 57484865Sobrien 57584865Sobrien tinsn = apply_completer (tinsn, ci); 57684865Sobrien 57784865Sobrien if (ia64_strings[cname][0] != '\0') 57884865Sobrien { 57984865Sobrien strcat (name, "."); 58084865Sobrien strcat (name, ia64_strings[cname]); 58184865Sobrien } 58284865Sobrien if (cb != 1) 58384865Sobrien { 58484865Sobrien ci = completer_table[ci].subentries; 58584865Sobrien } 58684865Sobrien } 58784865Sobrien else 58884865Sobrien { 58984865Sobrien ci = completer_table[ci].alternative; 59084865Sobrien } 59184865Sobrien if (ci < 0) 59284865Sobrien { 59384865Sobrien abort (); 59484865Sobrien } 59584865Sobrien cb = cb >> 1; 59684865Sobrien } 59784865Sobrien if (tinsn != (insn & main_table[place].mask)) 59884865Sobrien { 59984865Sobrien abort (); 60084865Sobrien } 60189857Sobrien return make_ia64_opcode (insn, name, place, 60284865Sobrien completer_table[ci].dependencies); 60384865Sobrien } 60484865Sobrien} 60584865Sobrien 60684865Sobrien/* Search the main_opcode table starting from PLACE for an opcode that 60784865Sobrien matches NAME. Return NULL if one is not found. */ 60884865Sobrien 60984865Sobrienstatic struct ia64_opcode * 610130561Sobrienia64_find_matching_opcode (const char *name, short place) 61184865Sobrien{ 61284865Sobrien char op[129]; 61384865Sobrien const char *suffix; 61484865Sobrien short name_index; 61584865Sobrien 61684865Sobrien if (strlen (name) > 128) 61784865Sobrien { 61884865Sobrien return NULL; 61984865Sobrien } 62084865Sobrien suffix = name; 62184865Sobrien get_opc_prefix (&suffix, op); 62284865Sobrien name_index = find_string_ent (op); 62384865Sobrien if (name_index < 0) 62484865Sobrien { 62584865Sobrien return NULL; 62684865Sobrien } 62784865Sobrien 62884865Sobrien while (main_table[place].name_index == name_index) 62984865Sobrien { 63084865Sobrien const char *curr_suffix = suffix; 63184865Sobrien ia64_insn curr_insn = main_table[place].opcode; 63284865Sobrien short completer = -1; 63384865Sobrien 63484865Sobrien do { 63589857Sobrien if (suffix[0] == '\0') 63684865Sobrien { 63784865Sobrien completer = find_completer (place, completer, suffix); 63884865Sobrien } 63984865Sobrien else 64084865Sobrien { 64184865Sobrien get_opc_prefix (&curr_suffix, op); 64284865Sobrien completer = find_completer (place, completer, op); 64384865Sobrien } 64484865Sobrien if (completer != -1) 64584865Sobrien { 64684865Sobrien curr_insn = apply_completer (curr_insn, completer); 64784865Sobrien } 64884865Sobrien } while (completer != -1 && curr_suffix[0] != '\0'); 64984865Sobrien 65084865Sobrien if (completer != -1 && curr_suffix[0] == '\0' 65184865Sobrien && completer_table[completer].terminal_completer) 65284865Sobrien { 65384865Sobrien int depind = completer_table[completer].dependencies; 65484865Sobrien return make_ia64_opcode (curr_insn, name, place, depind); 65584865Sobrien } 65684865Sobrien else 65784865Sobrien { 65884865Sobrien place++; 65984865Sobrien } 66084865Sobrien } 66184865Sobrien return NULL; 66284865Sobrien} 66384865Sobrien 66484865Sobrien/* Find the next opcode after PREV_ENT that matches PREV_ENT, or return NULL 66584865Sobrien if one does not exist. 66684865Sobrien 66784865Sobrien It is the caller's responsibility to invoke ia64_free_opcode () to 66884865Sobrien release any resources used by the returned entry. */ 66984865Sobrien 67084865Sobrienstruct ia64_opcode * 671130561Sobrienia64_find_next_opcode (struct ia64_opcode *prev_ent) 67284865Sobrien{ 67384865Sobrien return ia64_find_matching_opcode (prev_ent->name, 67484865Sobrien prev_ent->ent_index + 1); 67584865Sobrien} 67684865Sobrien 67784865Sobrien/* Find the first opcode that matches NAME, or return NULL if it does 67884865Sobrien not exist. 67984865Sobrien 68084865Sobrien It is the caller's responsibility to invoke ia64_free_opcode () to 68184865Sobrien release any resources used by the returned entry. */ 68284865Sobrien 68384865Sobrienstruct ia64_opcode * 684130561Sobrienia64_find_opcode (const char *name) 68584865Sobrien{ 68684865Sobrien char op[129]; 68784865Sobrien const char *suffix; 68884865Sobrien short place; 68984865Sobrien short name_index; 69084865Sobrien 69184865Sobrien if (strlen (name) > 128) 69284865Sobrien { 69384865Sobrien return NULL; 69484865Sobrien } 69584865Sobrien suffix = name; 69684865Sobrien get_opc_prefix (&suffix, op); 69784865Sobrien name_index = find_string_ent (op); 69884865Sobrien if (name_index < 0) 69984865Sobrien { 70084865Sobrien return NULL; 70184865Sobrien } 70284865Sobrien 70384865Sobrien place = find_main_ent (name_index); 70484865Sobrien 70584865Sobrien if (place < 0) 70684865Sobrien { 70784865Sobrien return NULL; 70884865Sobrien } 70984865Sobrien return ia64_find_matching_opcode (name, place); 71084865Sobrien} 71184865Sobrien 71284865Sobrien/* Free any resources used by ENT. */ 71384865Sobrienvoid 714130561Sobrienia64_free_opcode (struct ia64_opcode *ent) 71584865Sobrien{ 71684865Sobrien free ((void *)ent->name); 71784865Sobrien free (ent); 71884865Sobrien} 71984865Sobrien 72084865Sobrienconst struct ia64_dependency * 721130561Sobrienia64_find_dependency (int index) 72284865Sobrien{ 72384865Sobrien index = DEP(index); 72484865Sobrien 72584865Sobrien if (index < 0 72684865Sobrien || index >= (int)(sizeof(dependencies) / sizeof(dependencies[0]))) 72784865Sobrien return NULL; 72884865Sobrien 72984865Sobrien return &dependencies[index]; 73084865Sobrien} 731