xref: /openbsd-src/gnu/usr.bin/binutils-2.17/opcodes/ia64-opc.c (revision 3d8817e467ea46cf4772788d6804dd293abfb01a)
1*3d8817e4Smiod /* ia64-opc.c -- Functions to access the compacted opcode table
2*3d8817e4Smiod    Copyright 1999, 2000, 2001, 2003, 2005 Free Software Foundation, Inc.
3*3d8817e4Smiod    Written by Bob Manson of Cygnus Solutions, <manson@cygnus.com>
4*3d8817e4Smiod 
5*3d8817e4Smiod    This file is part of GDB, GAS, and the GNU binutils.
6*3d8817e4Smiod 
7*3d8817e4Smiod    GDB, GAS, and the GNU binutils are free software; you can redistribute
8*3d8817e4Smiod    them and/or modify them under the terms of the GNU General Public
9*3d8817e4Smiod    License as published by the Free Software Foundation; either version
10*3d8817e4Smiod    2, or (at your option) any later version.
11*3d8817e4Smiod 
12*3d8817e4Smiod    GDB, GAS, and the GNU binutils are distributed in the hope that they
13*3d8817e4Smiod    will be useful, but WITHOUT ANY WARRANTY; without even the implied
14*3d8817e4Smiod    warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
15*3d8817e4Smiod    the GNU General Public License for more details.
16*3d8817e4Smiod 
17*3d8817e4Smiod    You should have received a copy of the GNU General Public License
18*3d8817e4Smiod    along with this file; see the file COPYING.  If not, write to the
19*3d8817e4Smiod    Free Software Foundation, 51 Franklin Street - Fifth Floor, Boston, MA
20*3d8817e4Smiod    02110-1301, USA.  */
21*3d8817e4Smiod 
22*3d8817e4Smiod #include "ansidecl.h"
23*3d8817e4Smiod #include "sysdep.h"
24*3d8817e4Smiod #include "libiberty.h"
25*3d8817e4Smiod #include "ia64-asmtab.h"
26*3d8817e4Smiod #include "ia64-asmtab.c"
27*3d8817e4Smiod 
28*3d8817e4Smiod static void get_opc_prefix (const char **, char *);
29*3d8817e4Smiod static short int find_string_ent (const char *);
30*3d8817e4Smiod static short int find_main_ent (short int);
31*3d8817e4Smiod static short int find_completer (short int, short int, const char *);
32*3d8817e4Smiod static ia64_insn apply_completer (ia64_insn, int);
33*3d8817e4Smiod static int extract_op_bits (int, int, int);
34*3d8817e4Smiod static int extract_op (int, int *, unsigned int *);
35*3d8817e4Smiod static int opcode_verify (ia64_insn, int, enum ia64_insn_type);
36*3d8817e4Smiod static int locate_opcode_ent (ia64_insn, enum ia64_insn_type);
37*3d8817e4Smiod static struct ia64_opcode *make_ia64_opcode
38*3d8817e4Smiod   (ia64_insn, const char *, int, int);
39*3d8817e4Smiod static struct ia64_opcode *ia64_find_matching_opcode
40*3d8817e4Smiod   (const char *, short int);
41*3d8817e4Smiod 
42*3d8817e4Smiod const struct ia64_templ_desc ia64_templ_desc[16] =
43*3d8817e4Smiod   {
44*3d8817e4Smiod     { 0, { IA64_UNIT_M, IA64_UNIT_I, IA64_UNIT_I }, "MII" },	/* 0 */
45*3d8817e4Smiod     { 2, { IA64_UNIT_M, IA64_UNIT_I, IA64_UNIT_I }, "MII" },
46*3d8817e4Smiod     { 0, { IA64_UNIT_M, IA64_UNIT_L, IA64_UNIT_X }, "MLX" },
47*3d8817e4Smiod     { 0, { 0, },				    "-3-" },
48*3d8817e4Smiod     { 0, { IA64_UNIT_M, IA64_UNIT_M, IA64_UNIT_I }, "MMI" },	/* 4 */
49*3d8817e4Smiod     { 1, { IA64_UNIT_M, IA64_UNIT_M, IA64_UNIT_I }, "MMI" },
50*3d8817e4Smiod     { 0, { IA64_UNIT_M, IA64_UNIT_F, IA64_UNIT_I }, "MFI" },
51*3d8817e4Smiod     { 0, { IA64_UNIT_M, IA64_UNIT_M, IA64_UNIT_F }, "MMF" },
52*3d8817e4Smiod     { 0, { IA64_UNIT_M, IA64_UNIT_I, IA64_UNIT_B }, "MIB" },	/* 8 */
53*3d8817e4Smiod     { 0, { IA64_UNIT_M, IA64_UNIT_B, IA64_UNIT_B }, "MBB" },
54*3d8817e4Smiod     { 0, { 0, },				    "-a-" },
55*3d8817e4Smiod     { 0, { IA64_UNIT_B, IA64_UNIT_B, IA64_UNIT_B }, "BBB" },
56*3d8817e4Smiod     { 0, { IA64_UNIT_M, IA64_UNIT_M, IA64_UNIT_B }, "MMB" },	/* c */
57*3d8817e4Smiod     { 0, { 0, },				    "-d-" },
58*3d8817e4Smiod     { 0, { IA64_UNIT_M, IA64_UNIT_F, IA64_UNIT_B }, "MFB" },
59*3d8817e4Smiod     { 0, { 0, },				    "-f-" },
60*3d8817e4Smiod   };
61*3d8817e4Smiod 
62*3d8817e4Smiod 
63*3d8817e4Smiod /* Copy the prefix contained in *PTR (up to a '.' or a NUL) to DEST.
64*3d8817e4Smiod    PTR will be adjusted to point to the start of the next portion
65*3d8817e4Smiod    of the opcode, or at the NUL character. */
66*3d8817e4Smiod 
67*3d8817e4Smiod static void
get_opc_prefix(const char ** ptr,char * dest)68*3d8817e4Smiod get_opc_prefix (const char **ptr, char *dest)
69*3d8817e4Smiod {
70*3d8817e4Smiod   char *c = strchr (*ptr, '.');
71*3d8817e4Smiod   if (c != NULL)
72*3d8817e4Smiod     {
73*3d8817e4Smiod       memcpy (dest, *ptr, c - *ptr);
74*3d8817e4Smiod       dest[c - *ptr] = '\0';
75*3d8817e4Smiod       *ptr = c + 1;
76*3d8817e4Smiod     }
77*3d8817e4Smiod   else
78*3d8817e4Smiod     {
79*3d8817e4Smiod       int l = strlen (*ptr);
80*3d8817e4Smiod       memcpy (dest, *ptr, l);
81*3d8817e4Smiod       dest[l] = '\0';
82*3d8817e4Smiod       *ptr += l;
83*3d8817e4Smiod     }
84*3d8817e4Smiod }
85*3d8817e4Smiod 
86*3d8817e4Smiod /* Find the index of the entry in the string table corresponding to
87*3d8817e4Smiod    STR; return -1 if one does not exist. */
88*3d8817e4Smiod 
89*3d8817e4Smiod static short
find_string_ent(const char * str)90*3d8817e4Smiod find_string_ent (const char *str)
91*3d8817e4Smiod {
92*3d8817e4Smiod   short start = 0;
93*3d8817e4Smiod   short end = sizeof (ia64_strings) / sizeof (const char *);
94*3d8817e4Smiod   short i = (start + end) / 2;
95*3d8817e4Smiod 
96*3d8817e4Smiod   if (strcmp (str, ia64_strings[end - 1]) > 0)
97*3d8817e4Smiod     {
98*3d8817e4Smiod       return -1;
99*3d8817e4Smiod     }
100*3d8817e4Smiod   while (start <= end)
101*3d8817e4Smiod     {
102*3d8817e4Smiod       int c = strcmp (str, ia64_strings[i]);
103*3d8817e4Smiod       if (c < 0)
104*3d8817e4Smiod 	{
105*3d8817e4Smiod 	  end = i - 1;
106*3d8817e4Smiod 	}
107*3d8817e4Smiod       else if (c == 0)
108*3d8817e4Smiod 	{
109*3d8817e4Smiod 	  return i;
110*3d8817e4Smiod 	}
111*3d8817e4Smiod       else
112*3d8817e4Smiod 	{
113*3d8817e4Smiod 	  start = i + 1;
114*3d8817e4Smiod 	}
115*3d8817e4Smiod       i = (start + end) / 2;
116*3d8817e4Smiod     }
117*3d8817e4Smiod   return -1;
118*3d8817e4Smiod }
119*3d8817e4Smiod 
120*3d8817e4Smiod /* Find the opcode in the main opcode table whose name is STRINGINDEX, or
121*3d8817e4Smiod    return -1 if one does not exist. */
122*3d8817e4Smiod 
123*3d8817e4Smiod static short
find_main_ent(short nameindex)124*3d8817e4Smiod find_main_ent (short nameindex)
125*3d8817e4Smiod {
126*3d8817e4Smiod   short start = 0;
127*3d8817e4Smiod   short end = sizeof (main_table) / sizeof (struct ia64_main_table);
128*3d8817e4Smiod   short i = (start + end) / 2;
129*3d8817e4Smiod 
130*3d8817e4Smiod   if (nameindex < main_table[0].name_index
131*3d8817e4Smiod       || nameindex > main_table[end - 1].name_index)
132*3d8817e4Smiod     {
133*3d8817e4Smiod       return -1;
134*3d8817e4Smiod     }
135*3d8817e4Smiod   while (start <= end)
136*3d8817e4Smiod     {
137*3d8817e4Smiod       if (nameindex < main_table[i].name_index)
138*3d8817e4Smiod 	{
139*3d8817e4Smiod 	  end = i - 1;
140*3d8817e4Smiod 	}
141*3d8817e4Smiod       else if (nameindex == main_table[i].name_index)
142*3d8817e4Smiod 	{
143*3d8817e4Smiod 	  while (i > 0 && main_table[i - 1].name_index == nameindex)
144*3d8817e4Smiod 	    {
145*3d8817e4Smiod 	      i--;
146*3d8817e4Smiod 	    }
147*3d8817e4Smiod 	  return i;
148*3d8817e4Smiod 	}
149*3d8817e4Smiod       else
150*3d8817e4Smiod 	{
151*3d8817e4Smiod 	  start = i + 1;
152*3d8817e4Smiod 	}
153*3d8817e4Smiod       i = (start + end) / 2;
154*3d8817e4Smiod     }
155*3d8817e4Smiod   return -1;
156*3d8817e4Smiod }
157*3d8817e4Smiod 
158*3d8817e4Smiod /* Find the index of the entry in the completer table that is part of
159*3d8817e4Smiod    MAIN_ENT (starting from PREV_COMPLETER) that matches NAME, or
160*3d8817e4Smiod    return -1 if one does not exist. */
161*3d8817e4Smiod 
162*3d8817e4Smiod static short
find_completer(short main_ent,short prev_completer,const char * name)163*3d8817e4Smiod find_completer (short main_ent, short prev_completer, const char *name)
164*3d8817e4Smiod {
165*3d8817e4Smiod   short name_index = find_string_ent (name);
166*3d8817e4Smiod 
167*3d8817e4Smiod   if (name_index < 0)
168*3d8817e4Smiod     {
169*3d8817e4Smiod       return -1;
170*3d8817e4Smiod     }
171*3d8817e4Smiod 
172*3d8817e4Smiod   if (prev_completer == -1)
173*3d8817e4Smiod     {
174*3d8817e4Smiod       prev_completer = main_table[main_ent].completers;
175*3d8817e4Smiod     }
176*3d8817e4Smiod   else
177*3d8817e4Smiod     {
178*3d8817e4Smiod       prev_completer = completer_table[prev_completer].subentries;
179*3d8817e4Smiod     }
180*3d8817e4Smiod 
181*3d8817e4Smiod   while (prev_completer != -1)
182*3d8817e4Smiod     {
183*3d8817e4Smiod       if (completer_table[prev_completer].name_index == name_index)
184*3d8817e4Smiod 	{
185*3d8817e4Smiod 	  return prev_completer;
186*3d8817e4Smiod 	}
187*3d8817e4Smiod       prev_completer = completer_table[prev_completer].alternative;
188*3d8817e4Smiod     }
189*3d8817e4Smiod   return -1;
190*3d8817e4Smiod }
191*3d8817e4Smiod 
192*3d8817e4Smiod /* Apply the completer referred to by COMPLETER_INDEX to OPCODE, and
193*3d8817e4Smiod    return the result. */
194*3d8817e4Smiod 
195*3d8817e4Smiod static ia64_insn
apply_completer(ia64_insn opcode,int completer_index)196*3d8817e4Smiod apply_completer (ia64_insn opcode, int completer_index)
197*3d8817e4Smiod {
198*3d8817e4Smiod   ia64_insn mask = completer_table[completer_index].mask;
199*3d8817e4Smiod   ia64_insn bits = completer_table[completer_index].bits;
200*3d8817e4Smiod   int shiftamt = (completer_table[completer_index].offset & 63);
201*3d8817e4Smiod 
202*3d8817e4Smiod   mask = mask << shiftamt;
203*3d8817e4Smiod   bits = bits << shiftamt;
204*3d8817e4Smiod   opcode = (opcode & ~mask) | bits;
205*3d8817e4Smiod   return opcode;
206*3d8817e4Smiod }
207*3d8817e4Smiod 
208*3d8817e4Smiod /* Extract BITS number of bits starting from OP_POINTER + BITOFFSET in
209*3d8817e4Smiod    the dis_table array, and return its value.  (BITOFFSET is numbered
210*3d8817e4Smiod    starting from MSB to LSB, so a BITOFFSET of 0 indicates the MSB of the
211*3d8817e4Smiod    first byte in OP_POINTER.) */
212*3d8817e4Smiod 
213*3d8817e4Smiod static int
extract_op_bits(int op_pointer,int bitoffset,int bits)214*3d8817e4Smiod extract_op_bits (int op_pointer, int bitoffset, int bits)
215*3d8817e4Smiod {
216*3d8817e4Smiod   int res = 0;
217*3d8817e4Smiod 
218*3d8817e4Smiod   op_pointer += (bitoffset / 8);
219*3d8817e4Smiod 
220*3d8817e4Smiod   if (bitoffset % 8)
221*3d8817e4Smiod     {
222*3d8817e4Smiod       unsigned int op = dis_table[op_pointer++];
223*3d8817e4Smiod       int numb = 8 - (bitoffset % 8);
224*3d8817e4Smiod       int mask = (1 << numb) - 1;
225*3d8817e4Smiod       int bata = (bits < numb) ? bits : numb;
226*3d8817e4Smiod       int delta = numb - bata;
227*3d8817e4Smiod 
228*3d8817e4Smiod       res = (res << bata) | ((op & mask) >> delta);
229*3d8817e4Smiod       bitoffset += bata;
230*3d8817e4Smiod       bits -= bata;
231*3d8817e4Smiod     }
232*3d8817e4Smiod   while (bits >= 8)
233*3d8817e4Smiod     {
234*3d8817e4Smiod       res = (res << 8) | (dis_table[op_pointer++] & 255);
235*3d8817e4Smiod       bits -= 8;
236*3d8817e4Smiod     }
237*3d8817e4Smiod   if (bits > 0)
238*3d8817e4Smiod     {
239*3d8817e4Smiod       unsigned int op = (dis_table[op_pointer++] & 255);
240*3d8817e4Smiod       res = (res << bits) | (op >> (8 - bits));
241*3d8817e4Smiod     }
242*3d8817e4Smiod   return res;
243*3d8817e4Smiod }
244*3d8817e4Smiod 
245*3d8817e4Smiod /* Examine the state machine entry at OP_POINTER in the dis_table
246*3d8817e4Smiod    array, and extract its values into OPVAL and OP.  The length of the
247*3d8817e4Smiod    state entry in bits is returned. */
248*3d8817e4Smiod 
249*3d8817e4Smiod static int
extract_op(int op_pointer,int * opval,unsigned int * op)250*3d8817e4Smiod extract_op (int op_pointer, int *opval, unsigned int *op)
251*3d8817e4Smiod {
252*3d8817e4Smiod   int oplen = 5;
253*3d8817e4Smiod 
254*3d8817e4Smiod   *op = dis_table[op_pointer];
255*3d8817e4Smiod 
256*3d8817e4Smiod   if ((*op) & 0x40)
257*3d8817e4Smiod     {
258*3d8817e4Smiod       opval[0] = extract_op_bits (op_pointer, oplen, 5);
259*3d8817e4Smiod       oplen += 5;
260*3d8817e4Smiod     }
261*3d8817e4Smiod   switch ((*op) & 0x30)
262*3d8817e4Smiod     {
263*3d8817e4Smiod     case 0x10:
264*3d8817e4Smiod       {
265*3d8817e4Smiod 	opval[1] = extract_op_bits (op_pointer, oplen, 8);
266*3d8817e4Smiod 	oplen += 8;
267*3d8817e4Smiod 	opval[1] += op_pointer;
268*3d8817e4Smiod 	break;
269*3d8817e4Smiod       }
270*3d8817e4Smiod     case 0x20:
271*3d8817e4Smiod       {
272*3d8817e4Smiod 	opval[1] = extract_op_bits (op_pointer, oplen, 16);
273*3d8817e4Smiod 	if (! (opval[1] & 32768))
274*3d8817e4Smiod 	  {
275*3d8817e4Smiod 	    opval[1] += op_pointer;
276*3d8817e4Smiod 	  }
277*3d8817e4Smiod 	oplen += 16;
278*3d8817e4Smiod 	break;
279*3d8817e4Smiod       }
280*3d8817e4Smiod     case 0x30:
281*3d8817e4Smiod       {
282*3d8817e4Smiod 	oplen--;
283*3d8817e4Smiod 	opval[2] = extract_op_bits (op_pointer, oplen, 12);
284*3d8817e4Smiod 	oplen += 12;
285*3d8817e4Smiod 	opval[2] |= 32768;
286*3d8817e4Smiod 	break;
287*3d8817e4Smiod       }
288*3d8817e4Smiod     }
289*3d8817e4Smiod   if (((*op) & 0x08) && (((*op) & 0x30) != 0x30))
290*3d8817e4Smiod     {
291*3d8817e4Smiod       opval[2] = extract_op_bits (op_pointer, oplen, 16);
292*3d8817e4Smiod       oplen += 16;
293*3d8817e4Smiod       if (! (opval[2] & 32768))
294*3d8817e4Smiod 	{
295*3d8817e4Smiod 	  opval[2] += op_pointer;
296*3d8817e4Smiod 	}
297*3d8817e4Smiod     }
298*3d8817e4Smiod   return oplen;
299*3d8817e4Smiod }
300*3d8817e4Smiod 
301*3d8817e4Smiod /* Returns a non-zero value if the opcode in the main_table list at
302*3d8817e4Smiod    PLACE matches OPCODE and is of type TYPE. */
303*3d8817e4Smiod 
304*3d8817e4Smiod static int
opcode_verify(ia64_insn opcode,int place,enum ia64_insn_type type)305*3d8817e4Smiod opcode_verify (ia64_insn opcode, int place, enum ia64_insn_type type)
306*3d8817e4Smiod {
307*3d8817e4Smiod   if (main_table[place].opcode_type != type)
308*3d8817e4Smiod     {
309*3d8817e4Smiod       return 0;
310*3d8817e4Smiod     }
311*3d8817e4Smiod   if (main_table[place].flags
312*3d8817e4Smiod       & (IA64_OPCODE_F2_EQ_F3 | IA64_OPCODE_LEN_EQ_64MCNT))
313*3d8817e4Smiod     {
314*3d8817e4Smiod       const struct ia64_operand *o1, *o2;
315*3d8817e4Smiod       ia64_insn f2, f3;
316*3d8817e4Smiod 
317*3d8817e4Smiod       if (main_table[place].flags & IA64_OPCODE_F2_EQ_F3)
318*3d8817e4Smiod 	{
319*3d8817e4Smiod 	  o1 = elf64_ia64_operands + IA64_OPND_F2;
320*3d8817e4Smiod 	  o2 = elf64_ia64_operands + IA64_OPND_F3;
321*3d8817e4Smiod 	  (*o1->extract) (o1, opcode, &f2);
322*3d8817e4Smiod 	  (*o2->extract) (o2, opcode, &f3);
323*3d8817e4Smiod 	  if (f2 != f3)
324*3d8817e4Smiod 	    return 0;
325*3d8817e4Smiod 	}
326*3d8817e4Smiod       else
327*3d8817e4Smiod 	{
328*3d8817e4Smiod 	  ia64_insn len, count;
329*3d8817e4Smiod 
330*3d8817e4Smiod 	  /* length must equal 64-count: */
331*3d8817e4Smiod 	  o1 = elf64_ia64_operands + IA64_OPND_LEN6;
332*3d8817e4Smiod 	  o2 = elf64_ia64_operands + main_table[place].operands[2];
333*3d8817e4Smiod 	  (*o1->extract) (o1, opcode, &len);
334*3d8817e4Smiod 	  (*o2->extract) (o2, opcode, &count);
335*3d8817e4Smiod 	  if (len != 64 - count)
336*3d8817e4Smiod 	    return 0;
337*3d8817e4Smiod 	}
338*3d8817e4Smiod     }
339*3d8817e4Smiod   return 1;
340*3d8817e4Smiod }
341*3d8817e4Smiod 
342*3d8817e4Smiod /* Find an instruction entry in the ia64_dis_names array that matches
343*3d8817e4Smiod    opcode OPCODE and is of type TYPE.  Returns either a positive index
344*3d8817e4Smiod    into the array, or a negative value if an entry for OPCODE could
345*3d8817e4Smiod    not be found.  Checks all matches and returns the one with the highest
346*3d8817e4Smiod    priority. */
347*3d8817e4Smiod 
348*3d8817e4Smiod static int
locate_opcode_ent(ia64_insn opcode,enum ia64_insn_type type)349*3d8817e4Smiod locate_opcode_ent (ia64_insn opcode, enum ia64_insn_type type)
350*3d8817e4Smiod {
351*3d8817e4Smiod   int currtest[41];
352*3d8817e4Smiod   int bitpos[41];
353*3d8817e4Smiod   int op_ptr[41];
354*3d8817e4Smiod   int currstatenum = 0;
355*3d8817e4Smiod   short found_disent = -1;
356*3d8817e4Smiod   short found_priority = -1;
357*3d8817e4Smiod 
358*3d8817e4Smiod   currtest[currstatenum] = 0;
359*3d8817e4Smiod   op_ptr[currstatenum] = 0;
360*3d8817e4Smiod   bitpos[currstatenum] = 40;
361*3d8817e4Smiod 
362*3d8817e4Smiod   while (1)
363*3d8817e4Smiod     {
364*3d8817e4Smiod       int op_pointer = op_ptr[currstatenum];
365*3d8817e4Smiod       unsigned int op;
366*3d8817e4Smiod       int currbitnum = bitpos[currstatenum];
367*3d8817e4Smiod       int oplen;
368*3d8817e4Smiod       int opval[3] = {0};
369*3d8817e4Smiod       int next_op;
370*3d8817e4Smiod       int currbit;
371*3d8817e4Smiod 
372*3d8817e4Smiod       oplen = extract_op (op_pointer, opval, &op);
373*3d8817e4Smiod 
374*3d8817e4Smiod       bitpos[currstatenum] = currbitnum;
375*3d8817e4Smiod 
376*3d8817e4Smiod       /* Skip opval[0] bits in the instruction. */
377*3d8817e4Smiod       if (op & 0x40)
378*3d8817e4Smiod 	{
379*3d8817e4Smiod 	  currbitnum -= opval[0];
380*3d8817e4Smiod 	}
381*3d8817e4Smiod 
382*3d8817e4Smiod       /* The value of the current bit being tested. */
383*3d8817e4Smiod       currbit = opcode & (((ia64_insn) 1) << currbitnum) ? 1 : 0;
384*3d8817e4Smiod       next_op = -1;
385*3d8817e4Smiod 
386*3d8817e4Smiod       /* We always perform the tests specified in the current state in
387*3d8817e4Smiod 	 a particular order, falling through to the next test if the
388*3d8817e4Smiod 	 previous one failed. */
389*3d8817e4Smiod       switch (currtest[currstatenum])
390*3d8817e4Smiod 	{
391*3d8817e4Smiod 	case 0:
392*3d8817e4Smiod 	  currtest[currstatenum]++;
393*3d8817e4Smiod 	  if (currbit == 0 && (op & 0x80))
394*3d8817e4Smiod 	    {
395*3d8817e4Smiod 	      /* Check for a zero bit.  If this test solely checks for
396*3d8817e4Smiod 		 a zero bit, we can check for up to 8 consecutive zero
397*3d8817e4Smiod 		 bits (the number to check is specified by the lower 3
398*3d8817e4Smiod 		 bits in the state code.)
399*3d8817e4Smiod 
400*3d8817e4Smiod 		 If the state instruction matches, we go to the very
401*3d8817e4Smiod 		 next state instruction; otherwise, try the next test. */
402*3d8817e4Smiod 
403*3d8817e4Smiod 	      if ((op & 0xf8) == 0x80)
404*3d8817e4Smiod 		{
405*3d8817e4Smiod 		  int count = op & 0x7;
406*3d8817e4Smiod 		  int x;
407*3d8817e4Smiod 
408*3d8817e4Smiod 		  for (x = 0; x <= count; x++)
409*3d8817e4Smiod 		    {
410*3d8817e4Smiod 		      int i =
411*3d8817e4Smiod 			opcode & (((ia64_insn) 1) << (currbitnum - x)) ? 1 : 0;
412*3d8817e4Smiod 		      if (i)
413*3d8817e4Smiod 			{
414*3d8817e4Smiod 			  break;
415*3d8817e4Smiod 			}
416*3d8817e4Smiod 		    }
417*3d8817e4Smiod 		  if (x > count)
418*3d8817e4Smiod 		    {
419*3d8817e4Smiod 		      next_op = op_pointer + ((oplen + 7) / 8);
420*3d8817e4Smiod 		      currbitnum -= count;
421*3d8817e4Smiod 		      break;
422*3d8817e4Smiod 		    }
423*3d8817e4Smiod 		}
424*3d8817e4Smiod 	      else if (! currbit)
425*3d8817e4Smiod 		{
426*3d8817e4Smiod 		  next_op = op_pointer + ((oplen + 7) / 8);
427*3d8817e4Smiod 		  break;
428*3d8817e4Smiod 		}
429*3d8817e4Smiod 	    }
430*3d8817e4Smiod 	  /* FALLTHROUGH */
431*3d8817e4Smiod 	case 1:
432*3d8817e4Smiod 	  /* If the bit in the instruction is one, go to the state
433*3d8817e4Smiod 	     instruction specified by opval[1]. */
434*3d8817e4Smiod 	  currtest[currstatenum]++;
435*3d8817e4Smiod 	  if (currbit && (op & 0x30) != 0 && ((op & 0x30) != 0x30))
436*3d8817e4Smiod 	    {
437*3d8817e4Smiod 	      next_op = opval[1];
438*3d8817e4Smiod 	      break;
439*3d8817e4Smiod 	    }
440*3d8817e4Smiod 	  /* FALLTHROUGH */
441*3d8817e4Smiod 	case 2:
442*3d8817e4Smiod 	  /* Don't care.  Skip the current bit and go to the state
443*3d8817e4Smiod 	     instruction specified by opval[2].
444*3d8817e4Smiod 
445*3d8817e4Smiod 	     An encoding of 0x30 is special; this means that a 12-bit
446*3d8817e4Smiod 	     offset into the ia64_dis_names[] array is specified.  */
447*3d8817e4Smiod 	  currtest[currstatenum]++;
448*3d8817e4Smiod 	  if ((op & 0x08) || ((op & 0x30) == 0x30))
449*3d8817e4Smiod 	    {
450*3d8817e4Smiod 	      next_op = opval[2];
451*3d8817e4Smiod 	      break;
452*3d8817e4Smiod 	    }
453*3d8817e4Smiod 	}
454*3d8817e4Smiod 
455*3d8817e4Smiod       /* If bit 15 is set in the address of the next state, an offset
456*3d8817e4Smiod 	 in the ia64_dis_names array was specified instead.  We then
457*3d8817e4Smiod 	 check to see if an entry in the list of opcodes matches the
458*3d8817e4Smiod 	 opcode we were given; if so, we have succeeded.  */
459*3d8817e4Smiod 
460*3d8817e4Smiod       if ((next_op >= 0) && (next_op & 32768))
461*3d8817e4Smiod 	{
462*3d8817e4Smiod 	  short disent = next_op & 32767;
463*3d8817e4Smiod           short priority = -1;
464*3d8817e4Smiod 
465*3d8817e4Smiod 	  if (next_op > 65535)
466*3d8817e4Smiod 	    {
467*3d8817e4Smiod 	      abort ();
468*3d8817e4Smiod 	    }
469*3d8817e4Smiod 
470*3d8817e4Smiod 	  /* Run through the list of opcodes to check, trying to find
471*3d8817e4Smiod 	     one that matches.  */
472*3d8817e4Smiod 	  while (disent >= 0)
473*3d8817e4Smiod 	    {
474*3d8817e4Smiod 	      int place = ia64_dis_names[disent].insn_index;
475*3d8817e4Smiod 
476*3d8817e4Smiod               priority = ia64_dis_names[disent].priority;
477*3d8817e4Smiod 
478*3d8817e4Smiod 	      if (opcode_verify (opcode, place, type)
479*3d8817e4Smiod                   && priority > found_priority)
480*3d8817e4Smiod 		{
481*3d8817e4Smiod 		  break;
482*3d8817e4Smiod 		}
483*3d8817e4Smiod 	      if (ia64_dis_names[disent].next_flag)
484*3d8817e4Smiod 		{
485*3d8817e4Smiod 		  disent++;
486*3d8817e4Smiod 		}
487*3d8817e4Smiod 	      else
488*3d8817e4Smiod 		{
489*3d8817e4Smiod 		  disent = -1;
490*3d8817e4Smiod 		}
491*3d8817e4Smiod 	    }
492*3d8817e4Smiod 
493*3d8817e4Smiod 	  if (disent >= 0)
494*3d8817e4Smiod 	    {
495*3d8817e4Smiod               found_disent = disent;
496*3d8817e4Smiod               found_priority = priority;
497*3d8817e4Smiod 	    }
498*3d8817e4Smiod           /* Try the next test in this state, regardless of whether a match
499*3d8817e4Smiod              was found. */
500*3d8817e4Smiod           next_op = -2;
501*3d8817e4Smiod 	}
502*3d8817e4Smiod 
503*3d8817e4Smiod       /* next_op == -1 is "back up to the previous state".
504*3d8817e4Smiod 	 next_op == -2 is "stay in this state and try the next test".
505*3d8817e4Smiod 	 Otherwise, transition to the state indicated by next_op. */
506*3d8817e4Smiod 
507*3d8817e4Smiod       if (next_op == -1)
508*3d8817e4Smiod 	{
509*3d8817e4Smiod 	  currstatenum--;
510*3d8817e4Smiod 	  if (currstatenum < 0)
511*3d8817e4Smiod 	    {
512*3d8817e4Smiod               return found_disent;
513*3d8817e4Smiod 	    }
514*3d8817e4Smiod 	}
515*3d8817e4Smiod       else if (next_op >= 0)
516*3d8817e4Smiod 	{
517*3d8817e4Smiod 	  currstatenum++;
518*3d8817e4Smiod 	  bitpos[currstatenum] = currbitnum - 1;
519*3d8817e4Smiod 	  op_ptr[currstatenum] = next_op;
520*3d8817e4Smiod 	  currtest[currstatenum] = 0;
521*3d8817e4Smiod 	}
522*3d8817e4Smiod     }
523*3d8817e4Smiod }
524*3d8817e4Smiod 
525*3d8817e4Smiod /* Construct an ia64_opcode entry based on OPCODE, NAME and PLACE. */
526*3d8817e4Smiod 
527*3d8817e4Smiod static struct ia64_opcode *
make_ia64_opcode(ia64_insn opcode,const char * name,int place,int depind)528*3d8817e4Smiod make_ia64_opcode (ia64_insn opcode, const char *name, int place, int depind)
529*3d8817e4Smiod {
530*3d8817e4Smiod   struct ia64_opcode *res =
531*3d8817e4Smiod     (struct ia64_opcode *) xmalloc (sizeof (struct ia64_opcode));
532*3d8817e4Smiod   res->name = xstrdup (name);
533*3d8817e4Smiod   res->type = main_table[place].opcode_type;
534*3d8817e4Smiod   res->num_outputs = main_table[place].num_outputs;
535*3d8817e4Smiod   res->opcode = opcode;
536*3d8817e4Smiod   res->mask = main_table[place].mask;
537*3d8817e4Smiod   res->operands[0] = main_table[place].operands[0];
538*3d8817e4Smiod   res->operands[1] = main_table[place].operands[1];
539*3d8817e4Smiod   res->operands[2] = main_table[place].operands[2];
540*3d8817e4Smiod   res->operands[3] = main_table[place].operands[3];
541*3d8817e4Smiod   res->operands[4] = main_table[place].operands[4];
542*3d8817e4Smiod   res->flags = main_table[place].flags;
543*3d8817e4Smiod   res->ent_index = place;
544*3d8817e4Smiod   res->dependencies = &op_dependencies[depind];
545*3d8817e4Smiod   return res;
546*3d8817e4Smiod }
547*3d8817e4Smiod 
548*3d8817e4Smiod /* Determine the ia64_opcode entry for the opcode specified by INSN
549*3d8817e4Smiod    and TYPE.  If a valid entry is not found, return NULL. */
550*3d8817e4Smiod struct ia64_opcode *
ia64_dis_opcode(ia64_insn insn,enum ia64_insn_type type)551*3d8817e4Smiod ia64_dis_opcode (ia64_insn insn, enum ia64_insn_type type)
552*3d8817e4Smiod {
553*3d8817e4Smiod   int disent = locate_opcode_ent (insn, type);
554*3d8817e4Smiod 
555*3d8817e4Smiod   if (disent < 0)
556*3d8817e4Smiod     {
557*3d8817e4Smiod       return NULL;
558*3d8817e4Smiod     }
559*3d8817e4Smiod   else
560*3d8817e4Smiod     {
561*3d8817e4Smiod       unsigned int cb = ia64_dis_names[disent].completer_index;
562*3d8817e4Smiod       static char name[128];
563*3d8817e4Smiod       int place = ia64_dis_names[disent].insn_index;
564*3d8817e4Smiod       int ci = main_table[place].completers;
565*3d8817e4Smiod       ia64_insn tinsn = main_table[place].opcode;
566*3d8817e4Smiod 
567*3d8817e4Smiod       strcpy (name, ia64_strings [main_table[place].name_index]);
568*3d8817e4Smiod 
569*3d8817e4Smiod       while (cb)
570*3d8817e4Smiod 	{
571*3d8817e4Smiod 	  if (cb & 1)
572*3d8817e4Smiod 	    {
573*3d8817e4Smiod 	      int cname = completer_table[ci].name_index;
574*3d8817e4Smiod 
575*3d8817e4Smiod 	      tinsn = apply_completer (tinsn, ci);
576*3d8817e4Smiod 
577*3d8817e4Smiod 	      if (ia64_strings[cname][0] != '\0')
578*3d8817e4Smiod 		{
579*3d8817e4Smiod 		  strcat (name, ".");
580*3d8817e4Smiod 		  strcat (name, ia64_strings[cname]);
581*3d8817e4Smiod 		}
582*3d8817e4Smiod 	      if (cb != 1)
583*3d8817e4Smiod 		{
584*3d8817e4Smiod 		  ci = completer_table[ci].subentries;
585*3d8817e4Smiod 		}
586*3d8817e4Smiod 	    }
587*3d8817e4Smiod 	  else
588*3d8817e4Smiod 	    {
589*3d8817e4Smiod 	      ci = completer_table[ci].alternative;
590*3d8817e4Smiod 	    }
591*3d8817e4Smiod 	  if (ci < 0)
592*3d8817e4Smiod 	    {
593*3d8817e4Smiod 	      abort ();
594*3d8817e4Smiod 	    }
595*3d8817e4Smiod 	  cb = cb >> 1;
596*3d8817e4Smiod 	}
597*3d8817e4Smiod       if (tinsn != (insn & main_table[place].mask))
598*3d8817e4Smiod 	{
599*3d8817e4Smiod 	  abort ();
600*3d8817e4Smiod 	}
601*3d8817e4Smiod       return make_ia64_opcode (insn, name, place,
602*3d8817e4Smiod                                completer_table[ci].dependencies);
603*3d8817e4Smiod     }
604*3d8817e4Smiod }
605*3d8817e4Smiod 
606*3d8817e4Smiod /* Search the main_opcode table starting from PLACE for an opcode that
607*3d8817e4Smiod    matches NAME.  Return NULL if one is not found. */
608*3d8817e4Smiod 
609*3d8817e4Smiod static struct ia64_opcode *
ia64_find_matching_opcode(const char * name,short place)610*3d8817e4Smiod ia64_find_matching_opcode (const char *name, short place)
611*3d8817e4Smiod {
612*3d8817e4Smiod   char op[129];
613*3d8817e4Smiod   const char *suffix;
614*3d8817e4Smiod   short name_index;
615*3d8817e4Smiod 
616*3d8817e4Smiod   if (strlen (name) > 128)
617*3d8817e4Smiod     {
618*3d8817e4Smiod       return NULL;
619*3d8817e4Smiod     }
620*3d8817e4Smiod   suffix = name;
621*3d8817e4Smiod   get_opc_prefix (&suffix, op);
622*3d8817e4Smiod   name_index = find_string_ent (op);
623*3d8817e4Smiod   if (name_index < 0)
624*3d8817e4Smiod     {
625*3d8817e4Smiod       return NULL;
626*3d8817e4Smiod     }
627*3d8817e4Smiod 
628*3d8817e4Smiod   while (main_table[place].name_index == name_index)
629*3d8817e4Smiod     {
630*3d8817e4Smiod       const char *curr_suffix = suffix;
631*3d8817e4Smiod       ia64_insn curr_insn = main_table[place].opcode;
632*3d8817e4Smiod       short completer = -1;
633*3d8817e4Smiod 
634*3d8817e4Smiod       do {
635*3d8817e4Smiod 	if (suffix[0] == '\0')
636*3d8817e4Smiod 	  {
637*3d8817e4Smiod 	    completer = find_completer (place, completer, suffix);
638*3d8817e4Smiod 	  }
639*3d8817e4Smiod 	else
640*3d8817e4Smiod 	  {
641*3d8817e4Smiod 	    get_opc_prefix (&curr_suffix, op);
642*3d8817e4Smiod 	    completer = find_completer (place, completer, op);
643*3d8817e4Smiod 	  }
644*3d8817e4Smiod 	if (completer != -1)
645*3d8817e4Smiod 	  {
646*3d8817e4Smiod 	    curr_insn = apply_completer (curr_insn, completer);
647*3d8817e4Smiod 	  }
648*3d8817e4Smiod       } while (completer != -1 && curr_suffix[0] != '\0');
649*3d8817e4Smiod 
650*3d8817e4Smiod       if (completer != -1 && curr_suffix[0] == '\0'
651*3d8817e4Smiod 	  && completer_table[completer].terminal_completer)
652*3d8817e4Smiod 	{
653*3d8817e4Smiod           int depind = completer_table[completer].dependencies;
654*3d8817e4Smiod 	  return make_ia64_opcode (curr_insn, name, place, depind);
655*3d8817e4Smiod 	}
656*3d8817e4Smiod       else
657*3d8817e4Smiod 	{
658*3d8817e4Smiod 	  place++;
659*3d8817e4Smiod 	}
660*3d8817e4Smiod     }
661*3d8817e4Smiod   return NULL;
662*3d8817e4Smiod }
663*3d8817e4Smiod 
664*3d8817e4Smiod /* Find the next opcode after PREV_ENT that matches PREV_ENT, or return NULL
665*3d8817e4Smiod    if one does not exist.
666*3d8817e4Smiod 
667*3d8817e4Smiod    It is the caller's responsibility to invoke ia64_free_opcode () to
668*3d8817e4Smiod    release any resources used by the returned entry. */
669*3d8817e4Smiod 
670*3d8817e4Smiod struct ia64_opcode *
ia64_find_next_opcode(struct ia64_opcode * prev_ent)671*3d8817e4Smiod ia64_find_next_opcode (struct ia64_opcode *prev_ent)
672*3d8817e4Smiod {
673*3d8817e4Smiod   return ia64_find_matching_opcode (prev_ent->name,
674*3d8817e4Smiod 				    prev_ent->ent_index + 1);
675*3d8817e4Smiod }
676*3d8817e4Smiod 
677*3d8817e4Smiod /* Find the first opcode that matches NAME, or return NULL if it does
678*3d8817e4Smiod    not exist.
679*3d8817e4Smiod 
680*3d8817e4Smiod    It is the caller's responsibility to invoke ia64_free_opcode () to
681*3d8817e4Smiod    release any resources used by the returned entry. */
682*3d8817e4Smiod 
683*3d8817e4Smiod struct ia64_opcode *
ia64_find_opcode(const char * name)684*3d8817e4Smiod ia64_find_opcode (const char *name)
685*3d8817e4Smiod {
686*3d8817e4Smiod   char op[129];
687*3d8817e4Smiod   const char *suffix;
688*3d8817e4Smiod   short place;
689*3d8817e4Smiod   short name_index;
690*3d8817e4Smiod 
691*3d8817e4Smiod   if (strlen (name) > 128)
692*3d8817e4Smiod     {
693*3d8817e4Smiod       return NULL;
694*3d8817e4Smiod     }
695*3d8817e4Smiod   suffix = name;
696*3d8817e4Smiod   get_opc_prefix (&suffix, op);
697*3d8817e4Smiod   name_index = find_string_ent (op);
698*3d8817e4Smiod   if (name_index < 0)
699*3d8817e4Smiod     {
700*3d8817e4Smiod       return NULL;
701*3d8817e4Smiod     }
702*3d8817e4Smiod 
703*3d8817e4Smiod   place = find_main_ent (name_index);
704*3d8817e4Smiod 
705*3d8817e4Smiod   if (place < 0)
706*3d8817e4Smiod     {
707*3d8817e4Smiod       return NULL;
708*3d8817e4Smiod     }
709*3d8817e4Smiod   return ia64_find_matching_opcode (name, place);
710*3d8817e4Smiod }
711*3d8817e4Smiod 
712*3d8817e4Smiod /* Free any resources used by ENT. */
713*3d8817e4Smiod void
ia64_free_opcode(struct ia64_opcode * ent)714*3d8817e4Smiod ia64_free_opcode (struct ia64_opcode *ent)
715*3d8817e4Smiod {
716*3d8817e4Smiod   free ((void *)ent->name);
717*3d8817e4Smiod   free (ent);
718*3d8817e4Smiod }
719*3d8817e4Smiod 
720*3d8817e4Smiod const struct ia64_dependency *
ia64_find_dependency(int index)721*3d8817e4Smiod ia64_find_dependency (int index)
722*3d8817e4Smiod {
723*3d8817e4Smiod   index = DEP(index);
724*3d8817e4Smiod 
725*3d8817e4Smiod   if (index < 0
726*3d8817e4Smiod       || index >= (int)(sizeof(dependencies) / sizeof(dependencies[0])))
727*3d8817e4Smiod     return NULL;
728*3d8817e4Smiod 
729*3d8817e4Smiod   return &dependencies[index];
730*3d8817e4Smiod }
731