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