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