source: binutils/trunk/opcodes/ia64-opc.c@ 1973

Last change on this file since 1973 was 1973, checked in by Silvan Scherrer, 8 years ago

binutils: update trunk to version 2.27

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