Fix typos in ChangeLogs; fix dates in copyright notices
[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 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. Checks all matches and returns the one with the highest
350 priority. */
351
352 static int
353 locate_opcode_ent (opcode, type)
354 ia64_insn opcode;
355 enum ia64_insn_type type;
356 {
357 int currtest[41];
358 int bitpos[41];
359 int op_ptr[41];
360 int currstatenum = 0;
361 short found_disent = -1;
362 short found_priority = -1;
363
364 currtest[currstatenum] = 0;
365 op_ptr[currstatenum] = 0;
366 bitpos[currstatenum] = 40;
367
368 while (1)
369 {
370 int op_pointer = op_ptr[currstatenum];
371 unsigned int op;
372 int currbitnum = bitpos[currstatenum];
373 int oplen;
374 int opval[3];
375 int next_op;
376 int currbit;
377
378 oplen = extract_op (op_pointer, opval, &op);
379
380 bitpos[currstatenum] = currbitnum;
381
382 /* Skip opval[0] bits in the instruction. */
383 if (op & 0x40)
384 {
385 currbitnum -= opval[0];
386 }
387
388 /* The value of the current bit being tested. */
389 currbit = opcode & (((ia64_insn) 1) << currbitnum) ? 1 : 0;
390 next_op = -1;
391
392 /* We always perform the tests specified in the current state in
393 a particular order, falling through to the next test if the
394 previous one failed. */
395 switch (currtest[currstatenum])
396 {
397 case 0:
398 currtest[currstatenum]++;
399 if (currbit == 0 && (op & 0x80))
400 {
401 /* Check for a zero bit. If this test solely checks for
402 a zero bit, we can check for up to 8 consecutive zero
403 bits (the number to check is specified by the lower 3
404 bits in the state code.)
405
406 If the state instruction matches, we go to the very
407 next state instruction; otherwise, try the next test. */
408
409 if ((op & 0xf8) == 0x80)
410 {
411 int count = op & 0x7;
412 int x;
413
414 for (x = 0; x <= count; x++)
415 {
416 int i =
417 opcode & (((ia64_insn) 1) << (currbitnum - x)) ? 1 : 0;
418 if (i)
419 {
420 break;
421 }
422 }
423 if (x > count)
424 {
425 next_op = op_pointer + ((oplen + 7) / 8);
426 currbitnum -= count;
427 break;
428 }
429 }
430 else if (! currbit)
431 {
432 next_op = op_pointer + ((oplen + 7) / 8);
433 break;
434 }
435 }
436 /* FALLTHROUGH */
437 case 1:
438 /* If the bit in the instruction is one, go to the state
439 instruction specified by opval[1]. */
440 currtest[currstatenum]++;
441 if (currbit && (op & 0x30) != 0 && ((op & 0x30) != 0x30))
442 {
443 next_op = opval[1];
444 break;
445 }
446 /* FALLTHROUGH */
447 case 2:
448 /* Don't care. Skip the current bit and go to the state
449 instruction specified by opval[2].
450
451 An encoding of 0x30 is special; this means that a 12-bit
452 offset into the ia64_dis_names[] array is specified. */
453 currtest[currstatenum]++;
454 if ((op & 0x08) || ((op & 0x30) == 0x30))
455 {
456 next_op = opval[2];
457 break;
458 }
459 }
460
461 /* If bit 15 is set in the address of the next state, an offset
462 in the ia64_dis_names array was specified instead. We then
463 check to see if an entry in the list of opcodes matches the
464 opcode we were given; if so, we have succeeded. */
465
466 if ((next_op >= 0) && (next_op & 32768))
467 {
468 short disent = next_op & 32767;
469 short priority = -1;
470
471 if (next_op > 65535)
472 {
473 abort ();
474 }
475
476 /* Run through the list of opcodes to check, trying to find
477 one that matches. */
478 while (disent >= 0)
479 {
480 int place = ia64_dis_names[disent].insn_index;
481
482 priority = ia64_dis_names[disent].priority;
483
484 if (opcode_verify (opcode, place, type)
485 && priority > found_priority)
486 {
487 break;
488 }
489 if (ia64_dis_names[disent].next_flag)
490 {
491 disent++;
492 }
493 else
494 {
495 disent = -1;
496 }
497 }
498
499 if (disent >= 0)
500 {
501 found_disent = disent;
502 found_priority = priority;
503 }
504 /* Try the next test in this state, regardless of whether a match
505 was found. */
506 next_op = -2;
507 }
508
509 /* next_op == -1 is "back up to the previous state".
510 next_op == -2 is "stay in this state and try the next test".
511 Otherwise, transition to the state indicated by next_op. */
512
513 if (next_op == -1)
514 {
515 currstatenum--;
516 if (currstatenum < 0)
517 {
518 return found_disent;
519 }
520 }
521 else if (next_op >= 0)
522 {
523 currstatenum++;
524 bitpos[currstatenum] = currbitnum - 1;
525 op_ptr[currstatenum] = next_op;
526 currtest[currstatenum] = 0;
527 }
528 }
529 }
530 \f
531 /* Construct an ia64_opcode entry based on OPCODE, NAME and PLACE. */
532
533 static struct ia64_opcode *
534 make_ia64_opcode (opcode, name, place, depind)
535 ia64_insn opcode;
536 const char *name;
537 int place;
538 int depind;
539 {
540 struct ia64_opcode *res =
541 (struct ia64_opcode *) xmalloc (sizeof (struct ia64_opcode));
542 res->name = xstrdup (name);
543 res->type = main_table[place].opcode_type;
544 res->num_outputs = main_table[place].num_outputs;
545 res->opcode = opcode;
546 res->mask = main_table[place].mask;
547 res->operands[0] = main_table[place].operands[0];
548 res->operands[1] = main_table[place].operands[1];
549 res->operands[2] = main_table[place].operands[2];
550 res->operands[3] = main_table[place].operands[3];
551 res->operands[4] = main_table[place].operands[4];
552 res->flags = main_table[place].flags;
553 res->ent_index = place;
554 res->dependencies = &op_dependencies[depind];
555 return res;
556 }
557 \f
558 /* Determine the ia64_opcode entry for the opcode specified by INSN
559 and TYPE. If a valid entry is not found, return NULL. */
560 struct ia64_opcode *
561 ia64_dis_opcode (insn, type)
562 ia64_insn insn;
563 enum ia64_insn_type type;
564 {
565 int disent = locate_opcode_ent (insn, type);
566
567 if (disent < 0)
568 {
569 return NULL;
570 }
571 else
572 {
573 unsigned int cb = ia64_dis_names[disent].completer_index;
574 static char name[128];
575 int place = ia64_dis_names[disent].insn_index;
576 int ci = main_table[place].completers;
577 ia64_insn tinsn = main_table[place].opcode;
578
579 strcpy (name, ia64_strings [main_table[place].name_index]);
580
581 while (cb)
582 {
583 if (cb & 1)
584 {
585 int cname = completer_table[ci].name_index;
586
587 tinsn = apply_completer (tinsn, ci);
588
589 if (ia64_strings[cname][0] != '\0')
590 {
591 strcat (name, ".");
592 strcat (name, ia64_strings[cname]);
593 }
594 if (cb != 1)
595 {
596 ci = completer_table[ci].subentries;
597 }
598 }
599 else
600 {
601 ci = completer_table[ci].alternative;
602 }
603 if (ci < 0)
604 {
605 abort ();
606 }
607 cb = cb >> 1;
608 }
609 if (tinsn != (insn & main_table[place].mask))
610 {
611 abort ();
612 }
613 return make_ia64_opcode (insn, name, place,
614 completer_table[ci].dependencies);
615 }
616 }
617 \f
618 /* Search the main_opcode table starting from PLACE for an opcode that
619 matches NAME. Return NULL if one is not found. */
620
621 static struct ia64_opcode *
622 ia64_find_matching_opcode (name, place)
623 const char *name;
624 short place;
625 {
626 char op[129];
627 const char *suffix;
628 short name_index;
629
630 if (strlen (name) > 128)
631 {
632 return NULL;
633 }
634 suffix = name;
635 get_opc_prefix (&suffix, op);
636 name_index = find_string_ent (op);
637 if (name_index < 0)
638 {
639 return NULL;
640 }
641
642 while (main_table[place].name_index == name_index)
643 {
644 const char *curr_suffix = suffix;
645 ia64_insn curr_insn = main_table[place].opcode;
646 short completer = -1;
647
648 do {
649 if (suffix[0] == '\0')
650 {
651 completer = find_completer (place, completer, suffix);
652 }
653 else
654 {
655 get_opc_prefix (&curr_suffix, op);
656 completer = find_completer (place, completer, op);
657 }
658 if (completer != -1)
659 {
660 curr_insn = apply_completer (curr_insn, completer);
661 }
662 } while (completer != -1 && curr_suffix[0] != '\0');
663
664 if (completer != -1 && curr_suffix[0] == '\0'
665 && completer_table[completer].terminal_completer)
666 {
667 int depind = completer_table[completer].dependencies;
668 return make_ia64_opcode (curr_insn, name, place, depind);
669 }
670 else
671 {
672 place++;
673 }
674 }
675 return NULL;
676 }
677 \f
678 /* Find the next opcode after PREV_ENT that matches PREV_ENT, or return NULL
679 if one does not exist.
680
681 It is the caller's responsibility to invoke ia64_free_opcode () to
682 release any resources used by the returned entry. */
683
684 struct ia64_opcode *
685 ia64_find_next_opcode (prev_ent)
686 struct ia64_opcode *prev_ent;
687 {
688 return ia64_find_matching_opcode (prev_ent->name,
689 prev_ent->ent_index + 1);
690 }
691
692 /* Find the first opcode that matches NAME, or return NULL if it does
693 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_opcode (name)
700 const char *name;
701 {
702 char op[129];
703 const char *suffix;
704 short place;
705 short name_index;
706
707 if (strlen (name) > 128)
708 {
709 return NULL;
710 }
711 suffix = name;
712 get_opc_prefix (&suffix, op);
713 name_index = find_string_ent (op);
714 if (name_index < 0)
715 {
716 return NULL;
717 }
718
719 place = find_main_ent (name_index);
720
721 if (place < 0)
722 {
723 return NULL;
724 }
725 return ia64_find_matching_opcode (name, place);
726 }
727
728 /* Free any resources used by ENT. */
729 void
730 ia64_free_opcode (ent)
731 struct ia64_opcode *ent;
732 {
733 free ((void *)ent->name);
734 free (ent);
735 }
736
737 const struct ia64_dependency *
738 ia64_find_dependency (index)
739 int index;
740 {
741 index = DEP(index);
742
743 if (index < 0
744 || index >= (int)(sizeof(dependencies) / sizeof(dependencies[0])))
745 return NULL;
746
747 return &dependencies[index];
748 }
This page took 0.047877 seconds and 5 git commands to generate.