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