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