xref: /openbsd-src/gnu/usr.bin/binutils/opcodes/ia64-opc.c (revision cf2f2c5620d6d9a4fd01930983c4b9a1f76d7aa3)
15f210c2aSfgsch /* ia64-opc.c -- Functions to access the compacted opcode table
2*cf2f2c56Smiod    Copyright 1999, 2000, 2003 Free Software Foundation, Inc.
35f210c2aSfgsch    Written by Bob Manson of Cygnus Solutions, <manson@cygnus.com>
45f210c2aSfgsch 
55f210c2aSfgsch    This file is part of GDB, GAS, and the GNU binutils.
65f210c2aSfgsch 
75f210c2aSfgsch    GDB, GAS, and the GNU binutils are free software; you can redistribute
85f210c2aSfgsch    them and/or modify them under the terms of the GNU General Public
95f210c2aSfgsch    License as published by the Free Software Foundation; either version
105f210c2aSfgsch    2, or (at your option) any later version.
115f210c2aSfgsch 
125f210c2aSfgsch    GDB, GAS, and the GNU binutils are distributed in the hope that they
135f210c2aSfgsch    will be useful, but WITHOUT ANY WARRANTY; without even the implied
145f210c2aSfgsch    warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
155f210c2aSfgsch    the GNU General Public License for more details.
165f210c2aSfgsch 
175f210c2aSfgsch    You should have received a copy of the GNU General Public License
185f210c2aSfgsch    along with this file; see the file COPYING.  If not, write to the
195f210c2aSfgsch    Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
205f210c2aSfgsch    02111-1307, USA.  */
215f210c2aSfgsch 
225f210c2aSfgsch #include "ansidecl.h"
235f210c2aSfgsch #include "libiberty.h"
245f210c2aSfgsch #include "sysdep.h"
255f210c2aSfgsch #include "ia64-asmtab.h"
265f210c2aSfgsch #include "ia64-asmtab.c"
275f210c2aSfgsch 
28*cf2f2c56Smiod static void get_opc_prefix (const char **, char *);
29*cf2f2c56Smiod static short int find_string_ent (const char *);
30*cf2f2c56Smiod static short int find_main_ent (short int);
31*cf2f2c56Smiod static short int find_completer (short int, short int, const char *);
32*cf2f2c56Smiod static ia64_insn apply_completer (ia64_insn, int);
33*cf2f2c56Smiod static int extract_op_bits (int, int, int);
34*cf2f2c56Smiod static int extract_op (int, int *, unsigned int *);
35*cf2f2c56Smiod static int opcode_verify (ia64_insn, int, enum ia64_insn_type);
36*cf2f2c56Smiod static int locate_opcode_ent (ia64_insn, enum ia64_insn_type);
37d2201f2fSdrahn static struct ia64_opcode *make_ia64_opcode
38*cf2f2c56Smiod   (ia64_insn, const char *, int, int);
39d2201f2fSdrahn static struct ia64_opcode *ia64_find_matching_opcode
40*cf2f2c56Smiod   (const char *, short int);
41d2201f2fSdrahn 
425f210c2aSfgsch const struct ia64_templ_desc ia64_templ_desc[16] =
435f210c2aSfgsch   {
445f210c2aSfgsch     { 0, { IA64_UNIT_M, IA64_UNIT_I, IA64_UNIT_I }, "MII" },	/* 0 */
455f210c2aSfgsch     { 2, { IA64_UNIT_M, IA64_UNIT_I, IA64_UNIT_I }, "MII" },
465f210c2aSfgsch     { 0, { IA64_UNIT_M, IA64_UNIT_L, IA64_UNIT_X }, "MLX" },
475f210c2aSfgsch     { 0, { 0, },				    "-3-" },
485f210c2aSfgsch     { 0, { IA64_UNIT_M, IA64_UNIT_M, IA64_UNIT_I }, "MMI" },	/* 4 */
495f210c2aSfgsch     { 1, { IA64_UNIT_M, IA64_UNIT_M, IA64_UNIT_I }, "MMI" },
505f210c2aSfgsch     { 0, { IA64_UNIT_M, IA64_UNIT_F, IA64_UNIT_I }, "MFI" },
515f210c2aSfgsch     { 0, { IA64_UNIT_M, IA64_UNIT_M, IA64_UNIT_F }, "MMF" },
525f210c2aSfgsch     { 0, { IA64_UNIT_M, IA64_UNIT_I, IA64_UNIT_B }, "MIB" },	/* 8 */
535f210c2aSfgsch     { 0, { IA64_UNIT_M, IA64_UNIT_B, IA64_UNIT_B }, "MBB" },
545f210c2aSfgsch     { 0, { 0, },				    "-a-" },
555f210c2aSfgsch     { 0, { IA64_UNIT_B, IA64_UNIT_B, IA64_UNIT_B }, "BBB" },
565f210c2aSfgsch     { 0, { IA64_UNIT_M, IA64_UNIT_M, IA64_UNIT_B }, "MMB" },	/* c */
575f210c2aSfgsch     { 0, { 0, },				    "-d-" },
585f210c2aSfgsch     { 0, { IA64_UNIT_M, IA64_UNIT_F, IA64_UNIT_B }, "MFB" },
595f210c2aSfgsch     { 0, { 0, },				    "-f-" },
605f210c2aSfgsch   };
615f210c2aSfgsch 
625f210c2aSfgsch 
635f210c2aSfgsch /* Copy the prefix contained in *PTR (up to a '.' or a NUL) to DEST.
645f210c2aSfgsch    PTR will be adjusted to point to the start of the next portion
655f210c2aSfgsch    of the opcode, or at the NUL character. */
665f210c2aSfgsch 
675f210c2aSfgsch static void
get_opc_prefix(const char ** ptr,char * dest)68*cf2f2c56Smiod get_opc_prefix (const char **ptr, char *dest)
695f210c2aSfgsch {
705f210c2aSfgsch   char *c = strchr (*ptr, '.');
715f210c2aSfgsch   if (c != NULL)
725f210c2aSfgsch     {
735f210c2aSfgsch       memcpy (dest, *ptr, c - *ptr);
745f210c2aSfgsch       dest[c - *ptr] = '\0';
755f210c2aSfgsch       *ptr = c + 1;
765f210c2aSfgsch     }
775f210c2aSfgsch   else
785f210c2aSfgsch     {
795f210c2aSfgsch       int l = strlen (*ptr);
805f210c2aSfgsch       memcpy (dest, *ptr, l);
815f210c2aSfgsch       dest[l] = '\0';
825f210c2aSfgsch       *ptr += l;
835f210c2aSfgsch     }
845f210c2aSfgsch }
855f210c2aSfgsch 
865f210c2aSfgsch /* Find the index of the entry in the string table corresponding to
875f210c2aSfgsch    STR; return -1 if one does not exist. */
885f210c2aSfgsch 
895f210c2aSfgsch static short
find_string_ent(const char * str)90*cf2f2c56Smiod find_string_ent (const char *str)
915f210c2aSfgsch {
925f210c2aSfgsch   short start = 0;
935f210c2aSfgsch   short end = sizeof (ia64_strings) / sizeof (const char *);
945f210c2aSfgsch   short i = (start + end) / 2;
955f210c2aSfgsch 
965f210c2aSfgsch   if (strcmp (str, ia64_strings[end - 1]) > 0)
975f210c2aSfgsch     {
985f210c2aSfgsch       return -1;
995f210c2aSfgsch     }
1005f210c2aSfgsch   while (start <= end)
1015f210c2aSfgsch     {
1025f210c2aSfgsch       int c = strcmp (str, ia64_strings[i]);
1035f210c2aSfgsch       if (c < 0)
1045f210c2aSfgsch 	{
1055f210c2aSfgsch 	  end = i - 1;
1065f210c2aSfgsch 	}
1075f210c2aSfgsch       else if (c == 0)
1085f210c2aSfgsch 	{
1095f210c2aSfgsch 	  return i;
1105f210c2aSfgsch 	}
1115f210c2aSfgsch       else
1125f210c2aSfgsch 	{
1135f210c2aSfgsch 	  start = i + 1;
1145f210c2aSfgsch 	}
1155f210c2aSfgsch       i = (start + end) / 2;
1165f210c2aSfgsch     }
1175f210c2aSfgsch   return -1;
1185f210c2aSfgsch }
1195f210c2aSfgsch 
1205f210c2aSfgsch /* Find the opcode in the main opcode table whose name is STRINGINDEX, or
1215f210c2aSfgsch    return -1 if one does not exist. */
1225f210c2aSfgsch 
1235f210c2aSfgsch static short
find_main_ent(short nameindex)124*cf2f2c56Smiod find_main_ent (short nameindex)
1255f210c2aSfgsch {
1265f210c2aSfgsch   short start = 0;
1275f210c2aSfgsch   short end = sizeof (main_table) / sizeof (struct ia64_main_table);
1285f210c2aSfgsch   short i = (start + end) / 2;
1295f210c2aSfgsch 
1305f210c2aSfgsch   if (nameindex < main_table[0].name_index
1315f210c2aSfgsch       || nameindex > main_table[end - 1].name_index)
1325f210c2aSfgsch     {
1335f210c2aSfgsch       return -1;
1345f210c2aSfgsch     }
1355f210c2aSfgsch   while (start <= end)
1365f210c2aSfgsch     {
1375f210c2aSfgsch       if (nameindex < main_table[i].name_index)
1385f210c2aSfgsch 	{
1395f210c2aSfgsch 	  end = i - 1;
1405f210c2aSfgsch 	}
1415f210c2aSfgsch       else if (nameindex == main_table[i].name_index)
1425f210c2aSfgsch 	{
1435f210c2aSfgsch 	  while (i > 0 && main_table[i - 1].name_index == nameindex)
1445f210c2aSfgsch 	    {
1455f210c2aSfgsch 	      i--;
1465f210c2aSfgsch 	    }
1475f210c2aSfgsch 	  return i;
1485f210c2aSfgsch 	}
1495f210c2aSfgsch       else
1505f210c2aSfgsch 	{
1515f210c2aSfgsch 	  start = i + 1;
1525f210c2aSfgsch 	}
1535f210c2aSfgsch       i = (start + end) / 2;
1545f210c2aSfgsch     }
1555f210c2aSfgsch   return -1;
1565f210c2aSfgsch }
1575f210c2aSfgsch 
1585f210c2aSfgsch /* Find the index of the entry in the completer table that is part of
1595f210c2aSfgsch    MAIN_ENT (starting from PREV_COMPLETER) that matches NAME, or
1605f210c2aSfgsch    return -1 if one does not exist. */
1615f210c2aSfgsch 
1625f210c2aSfgsch static short
find_completer(short main_ent,short prev_completer,const char * name)163*cf2f2c56Smiod find_completer (short main_ent, short prev_completer, const char *name)
1645f210c2aSfgsch {
1655f210c2aSfgsch   short name_index = find_string_ent (name);
1665f210c2aSfgsch 
1675f210c2aSfgsch   if (name_index < 0)
1685f210c2aSfgsch     {
1695f210c2aSfgsch       return -1;
1705f210c2aSfgsch     }
1715f210c2aSfgsch 
1725f210c2aSfgsch   if (prev_completer == -1)
1735f210c2aSfgsch     {
1745f210c2aSfgsch       prev_completer = main_table[main_ent].completers;
1755f210c2aSfgsch     }
1765f210c2aSfgsch   else
1775f210c2aSfgsch     {
1785f210c2aSfgsch       prev_completer = completer_table[prev_completer].subentries;
1795f210c2aSfgsch     }
1805f210c2aSfgsch 
1815f210c2aSfgsch   while (prev_completer != -1)
1825f210c2aSfgsch     {
1835f210c2aSfgsch       if (completer_table[prev_completer].name_index == name_index)
1845f210c2aSfgsch 	{
1855f210c2aSfgsch 	  return prev_completer;
1865f210c2aSfgsch 	}
1875f210c2aSfgsch       prev_completer = completer_table[prev_completer].alternative;
1885f210c2aSfgsch     }
1895f210c2aSfgsch   return -1;
1905f210c2aSfgsch }
1915f210c2aSfgsch 
1925f210c2aSfgsch /* Apply the completer referred to by COMPLETER_INDEX to OPCODE, and
1935f210c2aSfgsch    return the result. */
1945f210c2aSfgsch 
1955f210c2aSfgsch static ia64_insn
apply_completer(ia64_insn opcode,int completer_index)196*cf2f2c56Smiod apply_completer (ia64_insn opcode, int completer_index)
1975f210c2aSfgsch {
1985f210c2aSfgsch   ia64_insn mask = completer_table[completer_index].mask;
1995f210c2aSfgsch   ia64_insn bits = completer_table[completer_index].bits;
2005f210c2aSfgsch   int shiftamt = (completer_table[completer_index].offset & 63);
2015f210c2aSfgsch 
2025f210c2aSfgsch   mask = mask << shiftamt;
2035f210c2aSfgsch   bits = bits << shiftamt;
2045f210c2aSfgsch   opcode = (opcode & ~mask) | bits;
2055f210c2aSfgsch   return opcode;
2065f210c2aSfgsch }
2075f210c2aSfgsch 
2085f210c2aSfgsch /* Extract BITS number of bits starting from OP_POINTER + BITOFFSET in
2095f210c2aSfgsch    the dis_table array, and return its value.  (BITOFFSET is numbered
2105f210c2aSfgsch    starting from MSB to LSB, so a BITOFFSET of 0 indicates the MSB of the
2115f210c2aSfgsch    first byte in OP_POINTER.) */
2125f210c2aSfgsch 
2135f210c2aSfgsch static int
extract_op_bits(int op_pointer,int bitoffset,int bits)214*cf2f2c56Smiod extract_op_bits (int op_pointer, int bitoffset, int bits)
2155f210c2aSfgsch {
2165f210c2aSfgsch   int res = 0;
2175f210c2aSfgsch 
2185f210c2aSfgsch   op_pointer += (bitoffset / 8);
2195f210c2aSfgsch 
2205f210c2aSfgsch   if (bitoffset % 8)
2215f210c2aSfgsch     {
2225f210c2aSfgsch       unsigned int op = dis_table[op_pointer++];
2235f210c2aSfgsch       int numb = 8 - (bitoffset % 8);
2245f210c2aSfgsch       int mask = (1 << numb) - 1;
2255f210c2aSfgsch       int bata = (bits < numb) ? bits : numb;
2265f210c2aSfgsch       int delta = numb - bata;
2275f210c2aSfgsch 
2285f210c2aSfgsch       res = (res << bata) | ((op & mask) >> delta);
2295f210c2aSfgsch       bitoffset += bata;
2305f210c2aSfgsch       bits -= bata;
2315f210c2aSfgsch     }
2325f210c2aSfgsch   while (bits >= 8)
2335f210c2aSfgsch     {
2345f210c2aSfgsch       res = (res << 8) | (dis_table[op_pointer++] & 255);
2355f210c2aSfgsch       bits -= 8;
2365f210c2aSfgsch     }
2375f210c2aSfgsch   if (bits > 0)
2385f210c2aSfgsch     {
2395f210c2aSfgsch       unsigned int op = (dis_table[op_pointer++] & 255);
2405f210c2aSfgsch       res = (res << bits) | (op >> (8 - bits));
2415f210c2aSfgsch     }
2425f210c2aSfgsch   return res;
2435f210c2aSfgsch }
2445f210c2aSfgsch 
2455f210c2aSfgsch /* Examine the state machine entry at OP_POINTER in the dis_table
2465f210c2aSfgsch    array, and extract its values into OPVAL and OP.  The length of the
2475f210c2aSfgsch    state entry in bits is returned. */
2485f210c2aSfgsch 
2495f210c2aSfgsch static int
extract_op(int op_pointer,int * opval,unsigned int * op)250*cf2f2c56Smiod extract_op (int op_pointer, int *opval, unsigned int *op)
2515f210c2aSfgsch {
2525f210c2aSfgsch   int oplen = 5;
2535f210c2aSfgsch 
2545f210c2aSfgsch   *op = dis_table[op_pointer];
2555f210c2aSfgsch 
2565f210c2aSfgsch   if ((*op) & 0x40)
2575f210c2aSfgsch     {
2585f210c2aSfgsch       opval[0] = extract_op_bits (op_pointer, oplen, 5);
2595f210c2aSfgsch       oplen += 5;
2605f210c2aSfgsch     }
2615f210c2aSfgsch   switch ((*op) & 0x30)
2625f210c2aSfgsch     {
2635f210c2aSfgsch     case 0x10:
2645f210c2aSfgsch       {
2655f210c2aSfgsch 	opval[1] = extract_op_bits (op_pointer, oplen, 8);
2665f210c2aSfgsch 	oplen += 8;
2675f210c2aSfgsch 	opval[1] += op_pointer;
2685f210c2aSfgsch 	break;
2695f210c2aSfgsch       }
2705f210c2aSfgsch     case 0x20:
2715f210c2aSfgsch       {
2725f210c2aSfgsch 	opval[1] = extract_op_bits (op_pointer, oplen, 16);
2735f210c2aSfgsch 	if (! (opval[1] & 32768))
2745f210c2aSfgsch 	  {
2755f210c2aSfgsch 	    opval[1] += op_pointer;
2765f210c2aSfgsch 	  }
2775f210c2aSfgsch 	oplen += 16;
2785f210c2aSfgsch 	break;
2795f210c2aSfgsch       }
2805f210c2aSfgsch     case 0x30:
2815f210c2aSfgsch       {
2825f210c2aSfgsch 	oplen--;
2835f210c2aSfgsch 	opval[2] = extract_op_bits (op_pointer, oplen, 12);
2845f210c2aSfgsch 	oplen += 12;
2855f210c2aSfgsch 	opval[2] |= 32768;
2865f210c2aSfgsch 	break;
2875f210c2aSfgsch       }
2885f210c2aSfgsch     }
2895f210c2aSfgsch   if (((*op) & 0x08) && (((*op) & 0x30) != 0x30))
2905f210c2aSfgsch     {
2915f210c2aSfgsch       opval[2] = extract_op_bits (op_pointer, oplen, 16);
2925f210c2aSfgsch       oplen += 16;
2935f210c2aSfgsch       if (! (opval[2] & 32768))
2945f210c2aSfgsch 	{
2955f210c2aSfgsch 	  opval[2] += op_pointer;
2965f210c2aSfgsch 	}
2975f210c2aSfgsch     }
2985f210c2aSfgsch   return oplen;
2995f210c2aSfgsch }
3005f210c2aSfgsch 
3015f210c2aSfgsch /* Returns a non-zero value if the opcode in the main_table list at
3025f210c2aSfgsch    PLACE matches OPCODE and is of type TYPE. */
3035f210c2aSfgsch 
3045f210c2aSfgsch static int
opcode_verify(ia64_insn opcode,int place,enum ia64_insn_type type)305*cf2f2c56Smiod opcode_verify (ia64_insn opcode, int place, enum ia64_insn_type type)
3065f210c2aSfgsch {
3075f210c2aSfgsch   if (main_table[place].opcode_type != type)
3085f210c2aSfgsch     {
3095f210c2aSfgsch       return 0;
3105f210c2aSfgsch     }
3115f210c2aSfgsch   if (main_table[place].flags
3125f210c2aSfgsch       & (IA64_OPCODE_F2_EQ_F3 | IA64_OPCODE_LEN_EQ_64MCNT))
3135f210c2aSfgsch     {
3145f210c2aSfgsch       const struct ia64_operand *o1, *o2;
3155f210c2aSfgsch       ia64_insn f2, f3;
3165f210c2aSfgsch 
3175f210c2aSfgsch       if (main_table[place].flags & IA64_OPCODE_F2_EQ_F3)
3185f210c2aSfgsch 	{
3195f210c2aSfgsch 	  o1 = elf64_ia64_operands + IA64_OPND_F2;
3205f210c2aSfgsch 	  o2 = elf64_ia64_operands + IA64_OPND_F3;
3215f210c2aSfgsch 	  (*o1->extract) (o1, opcode, &f2);
3225f210c2aSfgsch 	  (*o2->extract) (o2, opcode, &f3);
3235f210c2aSfgsch 	  if (f2 != f3)
3245f210c2aSfgsch 	    return 0;
3255f210c2aSfgsch 	}
3265f210c2aSfgsch       else
3275f210c2aSfgsch 	{
3285f210c2aSfgsch 	  ia64_insn len, count;
3295f210c2aSfgsch 
3305f210c2aSfgsch 	  /* length must equal 64-count: */
3315f210c2aSfgsch 	  o1 = elf64_ia64_operands + IA64_OPND_LEN6;
3325f210c2aSfgsch 	  o2 = elf64_ia64_operands + main_table[place].operands[2];
3335f210c2aSfgsch 	  (*o1->extract) (o1, opcode, &len);
3345f210c2aSfgsch 	  (*o2->extract) (o2, opcode, &count);
3355f210c2aSfgsch 	  if (len != 64 - count)
3365f210c2aSfgsch 	    return 0;
3375f210c2aSfgsch 	}
3385f210c2aSfgsch     }
3395f210c2aSfgsch   return 1;
3405f210c2aSfgsch }
3415f210c2aSfgsch 
3425f210c2aSfgsch /* Find an instruction entry in the ia64_dis_names array that matches
3435f210c2aSfgsch    opcode OPCODE and is of type TYPE.  Returns either a positive index
3445f210c2aSfgsch    into the array, or a negative value if an entry for OPCODE could
3455f210c2aSfgsch    not be found.  Checks all matches and returns the one with the highest
3465f210c2aSfgsch    priority. */
3475f210c2aSfgsch 
3485f210c2aSfgsch static int
locate_opcode_ent(ia64_insn opcode,enum ia64_insn_type type)349*cf2f2c56Smiod locate_opcode_ent (ia64_insn opcode, enum ia64_insn_type type)
3505f210c2aSfgsch {
3515f210c2aSfgsch   int currtest[41];
3525f210c2aSfgsch   int bitpos[41];
3535f210c2aSfgsch   int op_ptr[41];
3545f210c2aSfgsch   int currstatenum = 0;
3555f210c2aSfgsch   short found_disent = -1;
3565f210c2aSfgsch   short found_priority = -1;
3575f210c2aSfgsch 
3585f210c2aSfgsch   currtest[currstatenum] = 0;
3595f210c2aSfgsch   op_ptr[currstatenum] = 0;
3605f210c2aSfgsch   bitpos[currstatenum] = 40;
3615f210c2aSfgsch 
3625f210c2aSfgsch   while (1)
3635f210c2aSfgsch     {
3645f210c2aSfgsch       int op_pointer = op_ptr[currstatenum];
3655f210c2aSfgsch       unsigned int op;
3665f210c2aSfgsch       int currbitnum = bitpos[currstatenum];
3675f210c2aSfgsch       int oplen;
3685f210c2aSfgsch       int opval[3];
3695f210c2aSfgsch       int next_op;
3705f210c2aSfgsch       int currbit;
3715f210c2aSfgsch 
3725f210c2aSfgsch       oplen = extract_op (op_pointer, opval, &op);
3735f210c2aSfgsch 
3745f210c2aSfgsch       bitpos[currstatenum] = currbitnum;
3755f210c2aSfgsch 
3765f210c2aSfgsch       /* Skip opval[0] bits in the instruction. */
3775f210c2aSfgsch       if (op & 0x40)
3785f210c2aSfgsch 	{
3795f210c2aSfgsch 	  currbitnum -= opval[0];
3805f210c2aSfgsch 	}
3815f210c2aSfgsch 
3825f210c2aSfgsch       /* The value of the current bit being tested. */
3835f210c2aSfgsch       currbit = opcode & (((ia64_insn) 1) << currbitnum) ? 1 : 0;
3845f210c2aSfgsch       next_op = -1;
3855f210c2aSfgsch 
3865f210c2aSfgsch       /* We always perform the tests specified in the current state in
3875f210c2aSfgsch 	 a particular order, falling through to the next test if the
3885f210c2aSfgsch 	 previous one failed. */
3895f210c2aSfgsch       switch (currtest[currstatenum])
3905f210c2aSfgsch 	{
3915f210c2aSfgsch 	case 0:
3925f210c2aSfgsch 	  currtest[currstatenum]++;
3935f210c2aSfgsch 	  if (currbit == 0 && (op & 0x80))
3945f210c2aSfgsch 	    {
3955f210c2aSfgsch 	      /* Check for a zero bit.  If this test solely checks for
3965f210c2aSfgsch 		 a zero bit, we can check for up to 8 consecutive zero
3975f210c2aSfgsch 		 bits (the number to check is specified by the lower 3
3985f210c2aSfgsch 		 bits in the state code.)
3995f210c2aSfgsch 
4005f210c2aSfgsch 		 If the state instruction matches, we go to the very
4015f210c2aSfgsch 		 next state instruction; otherwise, try the next test. */
4025f210c2aSfgsch 
4035f210c2aSfgsch 	      if ((op & 0xf8) == 0x80)
4045f210c2aSfgsch 		{
4055f210c2aSfgsch 		  int count = op & 0x7;
4065f210c2aSfgsch 		  int x;
4075f210c2aSfgsch 
4085f210c2aSfgsch 		  for (x = 0; x <= count; x++)
4095f210c2aSfgsch 		    {
4105f210c2aSfgsch 		      int i =
4115f210c2aSfgsch 			opcode & (((ia64_insn) 1) << (currbitnum - x)) ? 1 : 0;
4125f210c2aSfgsch 		      if (i)
4135f210c2aSfgsch 			{
4145f210c2aSfgsch 			  break;
4155f210c2aSfgsch 			}
4165f210c2aSfgsch 		    }
4175f210c2aSfgsch 		  if (x > count)
4185f210c2aSfgsch 		    {
4195f210c2aSfgsch 		      next_op = op_pointer + ((oplen + 7) / 8);
4205f210c2aSfgsch 		      currbitnum -= count;
4215f210c2aSfgsch 		      break;
4225f210c2aSfgsch 		    }
4235f210c2aSfgsch 		}
4245f210c2aSfgsch 	      else if (! currbit)
4255f210c2aSfgsch 		{
4265f210c2aSfgsch 		  next_op = op_pointer + ((oplen + 7) / 8);
4275f210c2aSfgsch 		  break;
4285f210c2aSfgsch 		}
4295f210c2aSfgsch 	    }
4305f210c2aSfgsch 	  /* FALLTHROUGH */
4315f210c2aSfgsch 	case 1:
4325f210c2aSfgsch 	  /* If the bit in the instruction is one, go to the state
4335f210c2aSfgsch 	     instruction specified by opval[1]. */
4345f210c2aSfgsch 	  currtest[currstatenum]++;
4355f210c2aSfgsch 	  if (currbit && (op & 0x30) != 0 && ((op & 0x30) != 0x30))
4365f210c2aSfgsch 	    {
4375f210c2aSfgsch 	      next_op = opval[1];
4385f210c2aSfgsch 	      break;
4395f210c2aSfgsch 	    }
4405f210c2aSfgsch 	  /* FALLTHROUGH */
4415f210c2aSfgsch 	case 2:
4425f210c2aSfgsch 	  /* Don't care.  Skip the current bit and go to the state
4435f210c2aSfgsch 	     instruction specified by opval[2].
4445f210c2aSfgsch 
4455f210c2aSfgsch 	     An encoding of 0x30 is special; this means that a 12-bit
4465f210c2aSfgsch 	     offset into the ia64_dis_names[] array is specified.  */
4475f210c2aSfgsch 	  currtest[currstatenum]++;
4485f210c2aSfgsch 	  if ((op & 0x08) || ((op & 0x30) == 0x30))
4495f210c2aSfgsch 	    {
4505f210c2aSfgsch 	      next_op = opval[2];
4515f210c2aSfgsch 	      break;
4525f210c2aSfgsch 	    }
4535f210c2aSfgsch 	}
4545f210c2aSfgsch 
4555f210c2aSfgsch       /* If bit 15 is set in the address of the next state, an offset
4565f210c2aSfgsch 	 in the ia64_dis_names array was specified instead.  We then
4575f210c2aSfgsch 	 check to see if an entry in the list of opcodes matches the
4585f210c2aSfgsch 	 opcode we were given; if so, we have succeeded.  */
4595f210c2aSfgsch 
4605f210c2aSfgsch       if ((next_op >= 0) && (next_op & 32768))
4615f210c2aSfgsch 	{
4625f210c2aSfgsch 	  short disent = next_op & 32767;
4635f210c2aSfgsch           short priority = -1;
4645f210c2aSfgsch 
4655f210c2aSfgsch 	  if (next_op > 65535)
4665f210c2aSfgsch 	    {
4675f210c2aSfgsch 	      abort ();
4685f210c2aSfgsch 	    }
4695f210c2aSfgsch 
4705f210c2aSfgsch 	  /* Run through the list of opcodes to check, trying to find
4715f210c2aSfgsch 	     one that matches.  */
4725f210c2aSfgsch 	  while (disent >= 0)
4735f210c2aSfgsch 	    {
4745f210c2aSfgsch 	      int place = ia64_dis_names[disent].insn_index;
4755f210c2aSfgsch 
4765f210c2aSfgsch               priority = ia64_dis_names[disent].priority;
4775f210c2aSfgsch 
4785f210c2aSfgsch 	      if (opcode_verify (opcode, place, type)
4795f210c2aSfgsch                   && priority > found_priority)
4805f210c2aSfgsch 		{
4815f210c2aSfgsch 		  break;
4825f210c2aSfgsch 		}
4835f210c2aSfgsch 	      if (ia64_dis_names[disent].next_flag)
4845f210c2aSfgsch 		{
4855f210c2aSfgsch 		  disent++;
4865f210c2aSfgsch 		}
4875f210c2aSfgsch 	      else
4885f210c2aSfgsch 		{
4895f210c2aSfgsch 		  disent = -1;
4905f210c2aSfgsch 		}
4915f210c2aSfgsch 	    }
4925f210c2aSfgsch 
4935f210c2aSfgsch 	  if (disent >= 0)
4945f210c2aSfgsch 	    {
4955f210c2aSfgsch               found_disent = disent;
4965f210c2aSfgsch               found_priority = priority;
4975f210c2aSfgsch 	    }
4985f210c2aSfgsch           /* Try the next test in this state, regardless of whether a match
4995f210c2aSfgsch              was found. */
5005f210c2aSfgsch           next_op = -2;
5015f210c2aSfgsch 	}
5025f210c2aSfgsch 
5035f210c2aSfgsch       /* next_op == -1 is "back up to the previous state".
5045f210c2aSfgsch 	 next_op == -2 is "stay in this state and try the next test".
5055f210c2aSfgsch 	 Otherwise, transition to the state indicated by next_op. */
5065f210c2aSfgsch 
5075f210c2aSfgsch       if (next_op == -1)
5085f210c2aSfgsch 	{
5095f210c2aSfgsch 	  currstatenum--;
5105f210c2aSfgsch 	  if (currstatenum < 0)
5115f210c2aSfgsch 	    {
5125f210c2aSfgsch               return found_disent;
5135f210c2aSfgsch 	    }
5145f210c2aSfgsch 	}
5155f210c2aSfgsch       else if (next_op >= 0)
5165f210c2aSfgsch 	{
5175f210c2aSfgsch 	  currstatenum++;
5185f210c2aSfgsch 	  bitpos[currstatenum] = currbitnum - 1;
5195f210c2aSfgsch 	  op_ptr[currstatenum] = next_op;
5205f210c2aSfgsch 	  currtest[currstatenum] = 0;
5215f210c2aSfgsch 	}
5225f210c2aSfgsch     }
5235f210c2aSfgsch }
5245f210c2aSfgsch 
5255f210c2aSfgsch /* Construct an ia64_opcode entry based on OPCODE, NAME and PLACE. */
5265f210c2aSfgsch 
5275f210c2aSfgsch static struct ia64_opcode *
make_ia64_opcode(ia64_insn opcode,const char * name,int place,int depind)528*cf2f2c56Smiod make_ia64_opcode (ia64_insn opcode, const char *name, int place, int depind)
5295f210c2aSfgsch {
5305f210c2aSfgsch   struct ia64_opcode *res =
5315f210c2aSfgsch     (struct ia64_opcode *) xmalloc (sizeof (struct ia64_opcode));
5325f210c2aSfgsch   res->name = xstrdup (name);
5335f210c2aSfgsch   res->type = main_table[place].opcode_type;
5345f210c2aSfgsch   res->num_outputs = main_table[place].num_outputs;
5355f210c2aSfgsch   res->opcode = opcode;
5365f210c2aSfgsch   res->mask = main_table[place].mask;
5375f210c2aSfgsch   res->operands[0] = main_table[place].operands[0];
5385f210c2aSfgsch   res->operands[1] = main_table[place].operands[1];
5395f210c2aSfgsch   res->operands[2] = main_table[place].operands[2];
5405f210c2aSfgsch   res->operands[3] = main_table[place].operands[3];
5415f210c2aSfgsch   res->operands[4] = main_table[place].operands[4];
5425f210c2aSfgsch   res->flags = main_table[place].flags;
5435f210c2aSfgsch   res->ent_index = place;
5445f210c2aSfgsch   res->dependencies = &op_dependencies[depind];
5455f210c2aSfgsch   return res;
5465f210c2aSfgsch }
5475f210c2aSfgsch 
5485f210c2aSfgsch /* Determine the ia64_opcode entry for the opcode specified by INSN
5495f210c2aSfgsch    and TYPE.  If a valid entry is not found, return NULL. */
5505f210c2aSfgsch struct ia64_opcode *
ia64_dis_opcode(ia64_insn insn,enum ia64_insn_type type)551*cf2f2c56Smiod ia64_dis_opcode (ia64_insn insn, enum ia64_insn_type type)
5525f210c2aSfgsch {
5535f210c2aSfgsch   int disent = locate_opcode_ent (insn, type);
5545f210c2aSfgsch 
5555f210c2aSfgsch   if (disent < 0)
5565f210c2aSfgsch     {
5575f210c2aSfgsch       return NULL;
5585f210c2aSfgsch     }
5595f210c2aSfgsch   else
5605f210c2aSfgsch     {
5615f210c2aSfgsch       unsigned int cb = ia64_dis_names[disent].completer_index;
5625f210c2aSfgsch       static char name[128];
5635f210c2aSfgsch       int place = ia64_dis_names[disent].insn_index;
5645f210c2aSfgsch       int ci = main_table[place].completers;
5655f210c2aSfgsch       ia64_insn tinsn = main_table[place].opcode;
5665f210c2aSfgsch 
5675f210c2aSfgsch       strcpy (name, ia64_strings [main_table[place].name_index]);
5685f210c2aSfgsch 
5695f210c2aSfgsch       while (cb)
5705f210c2aSfgsch 	{
5715f210c2aSfgsch 	  if (cb & 1)
5725f210c2aSfgsch 	    {
5735f210c2aSfgsch 	      int cname = completer_table[ci].name_index;
5745f210c2aSfgsch 
5755f210c2aSfgsch 	      tinsn = apply_completer (tinsn, ci);
5765f210c2aSfgsch 
5775f210c2aSfgsch 	      if (ia64_strings[cname][0] != '\0')
5785f210c2aSfgsch 		{
5795f210c2aSfgsch 		  strcat (name, ".");
5805f210c2aSfgsch 		  strcat (name, ia64_strings[cname]);
5815f210c2aSfgsch 		}
5825f210c2aSfgsch 	      if (cb != 1)
5835f210c2aSfgsch 		{
5845f210c2aSfgsch 		  ci = completer_table[ci].subentries;
5855f210c2aSfgsch 		}
5865f210c2aSfgsch 	    }
5875f210c2aSfgsch 	  else
5885f210c2aSfgsch 	    {
5895f210c2aSfgsch 	      ci = completer_table[ci].alternative;
5905f210c2aSfgsch 	    }
5915f210c2aSfgsch 	  if (ci < 0)
5925f210c2aSfgsch 	    {
5935f210c2aSfgsch 	      abort ();
5945f210c2aSfgsch 	    }
5955f210c2aSfgsch 	  cb = cb >> 1;
5965f210c2aSfgsch 	}
5975f210c2aSfgsch       if (tinsn != (insn & main_table[place].mask))
5985f210c2aSfgsch 	{
5995f210c2aSfgsch 	  abort ();
6005f210c2aSfgsch 	}
6015f210c2aSfgsch       return make_ia64_opcode (insn, name, place,
6025f210c2aSfgsch                                completer_table[ci].dependencies);
6035f210c2aSfgsch     }
6045f210c2aSfgsch }
6055f210c2aSfgsch 
6065f210c2aSfgsch /* Search the main_opcode table starting from PLACE for an opcode that
6075f210c2aSfgsch    matches NAME.  Return NULL if one is not found. */
6085f210c2aSfgsch 
6095f210c2aSfgsch static struct ia64_opcode *
ia64_find_matching_opcode(const char * name,short place)610*cf2f2c56Smiod ia64_find_matching_opcode (const char *name, short place)
6115f210c2aSfgsch {
6125f210c2aSfgsch   char op[129];
6135f210c2aSfgsch   const char *suffix;
6145f210c2aSfgsch   short name_index;
6155f210c2aSfgsch 
6165f210c2aSfgsch   if (strlen (name) > 128)
6175f210c2aSfgsch     {
6185f210c2aSfgsch       return NULL;
6195f210c2aSfgsch     }
6205f210c2aSfgsch   suffix = name;
6215f210c2aSfgsch   get_opc_prefix (&suffix, op);
6225f210c2aSfgsch   name_index = find_string_ent (op);
6235f210c2aSfgsch   if (name_index < 0)
6245f210c2aSfgsch     {
6255f210c2aSfgsch       return NULL;
6265f210c2aSfgsch     }
6275f210c2aSfgsch 
6285f210c2aSfgsch   while (main_table[place].name_index == name_index)
6295f210c2aSfgsch     {
6305f210c2aSfgsch       const char *curr_suffix = suffix;
6315f210c2aSfgsch       ia64_insn curr_insn = main_table[place].opcode;
6325f210c2aSfgsch       short completer = -1;
6335f210c2aSfgsch 
6345f210c2aSfgsch       do {
6355f210c2aSfgsch 	if (suffix[0] == '\0')
6365f210c2aSfgsch 	  {
6375f210c2aSfgsch 	    completer = find_completer (place, completer, suffix);
6385f210c2aSfgsch 	  }
6395f210c2aSfgsch 	else
6405f210c2aSfgsch 	  {
6415f210c2aSfgsch 	    get_opc_prefix (&curr_suffix, op);
6425f210c2aSfgsch 	    completer = find_completer (place, completer, op);
6435f210c2aSfgsch 	  }
6445f210c2aSfgsch 	if (completer != -1)
6455f210c2aSfgsch 	  {
6465f210c2aSfgsch 	    curr_insn = apply_completer (curr_insn, completer);
6475f210c2aSfgsch 	  }
6485f210c2aSfgsch       } while (completer != -1 && curr_suffix[0] != '\0');
6495f210c2aSfgsch 
6505f210c2aSfgsch       if (completer != -1 && curr_suffix[0] == '\0'
6515f210c2aSfgsch 	  && completer_table[completer].terminal_completer)
6525f210c2aSfgsch 	{
6535f210c2aSfgsch           int depind = completer_table[completer].dependencies;
6545f210c2aSfgsch 	  return make_ia64_opcode (curr_insn, name, place, depind);
6555f210c2aSfgsch 	}
6565f210c2aSfgsch       else
6575f210c2aSfgsch 	{
6585f210c2aSfgsch 	  place++;
6595f210c2aSfgsch 	}
6605f210c2aSfgsch     }
6615f210c2aSfgsch   return NULL;
6625f210c2aSfgsch }
6635f210c2aSfgsch 
6645f210c2aSfgsch /* Find the next opcode after PREV_ENT that matches PREV_ENT, or return NULL
6655f210c2aSfgsch    if one does not exist.
6665f210c2aSfgsch 
6675f210c2aSfgsch    It is the caller's responsibility to invoke ia64_free_opcode () to
6685f210c2aSfgsch    release any resources used by the returned entry. */
6695f210c2aSfgsch 
6705f210c2aSfgsch struct ia64_opcode *
ia64_find_next_opcode(struct ia64_opcode * prev_ent)671*cf2f2c56Smiod ia64_find_next_opcode (struct ia64_opcode *prev_ent)
6725f210c2aSfgsch {
6735f210c2aSfgsch   return ia64_find_matching_opcode (prev_ent->name,
6745f210c2aSfgsch 				    prev_ent->ent_index + 1);
6755f210c2aSfgsch }
6765f210c2aSfgsch 
6775f210c2aSfgsch /* Find the first opcode that matches NAME, or return NULL if it does
6785f210c2aSfgsch    not exist.
6795f210c2aSfgsch 
6805f210c2aSfgsch    It is the caller's responsibility to invoke ia64_free_opcode () to
6815f210c2aSfgsch    release any resources used by the returned entry. */
6825f210c2aSfgsch 
6835f210c2aSfgsch struct ia64_opcode *
ia64_find_opcode(const char * name)684*cf2f2c56Smiod ia64_find_opcode (const char *name)
6855f210c2aSfgsch {
6865f210c2aSfgsch   char op[129];
6875f210c2aSfgsch   const char *suffix;
6885f210c2aSfgsch   short place;
6895f210c2aSfgsch   short name_index;
6905f210c2aSfgsch 
6915f210c2aSfgsch   if (strlen (name) > 128)
6925f210c2aSfgsch     {
6935f210c2aSfgsch       return NULL;
6945f210c2aSfgsch     }
6955f210c2aSfgsch   suffix = name;
6965f210c2aSfgsch   get_opc_prefix (&suffix, op);
6975f210c2aSfgsch   name_index = find_string_ent (op);
6985f210c2aSfgsch   if (name_index < 0)
6995f210c2aSfgsch     {
7005f210c2aSfgsch       return NULL;
7015f210c2aSfgsch     }
7025f210c2aSfgsch 
7035f210c2aSfgsch   place = find_main_ent (name_index);
7045f210c2aSfgsch 
7055f210c2aSfgsch   if (place < 0)
7065f210c2aSfgsch     {
7075f210c2aSfgsch       return NULL;
7085f210c2aSfgsch     }
7095f210c2aSfgsch   return ia64_find_matching_opcode (name, place);
7105f210c2aSfgsch }
7115f210c2aSfgsch 
7125f210c2aSfgsch /* Free any resources used by ENT. */
7135f210c2aSfgsch void
ia64_free_opcode(struct ia64_opcode * ent)714*cf2f2c56Smiod ia64_free_opcode (struct ia64_opcode *ent)
7155f210c2aSfgsch {
7165f210c2aSfgsch   free ((void *)ent->name);
7175f210c2aSfgsch   free (ent);
7185f210c2aSfgsch }
7195f210c2aSfgsch 
7205f210c2aSfgsch const struct ia64_dependency *
ia64_find_dependency(int index)721*cf2f2c56Smiod ia64_find_dependency (int index)
7225f210c2aSfgsch {
7235f210c2aSfgsch   index = DEP(index);
7245f210c2aSfgsch 
7255f210c2aSfgsch   if (index < 0
7265f210c2aSfgsch       || index >= (int)(sizeof(dependencies) / sizeof(dependencies[0])))
7275f210c2aSfgsch     return NULL;
7285f210c2aSfgsch 
7295f210c2aSfgsch   return &dependencies[index];
7305f210c2aSfgsch }
731