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