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