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