source: vendor/binutils/current/opcodes/ia64-opc.c

Last change on this file was 609, checked in by bird, 22 years ago

binutils v2.14 - offical sources.

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