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