1 /* ia64-opc.c -- Functions to access the compacted opcode table
2    Copyright (C) 1999-2021 Free Software Foundation, Inc.
3    Written by Bob Manson of Cygnus Solutions, <manson@cygnus.com>
4 
5    This file is part of the GNU opcodes library.
6 
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.
11 
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.
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, 51 Franklin Street - Fifth Floor, Boston,
20    MA 02110-1301, USA.  */
21 
22 #include "sysdep.h"
23 #include "libiberty.h"
24 #include "ia64-asmtab.h"
25 #include "ia64-asmtab.c"
26 
27 static void get_opc_prefix (const char **, char *);
28 static short int find_string_ent (const char *);
29 static short int find_main_ent (short int);
30 static short int find_completer (short int, short int, const char *);
31 static ia64_insn apply_completer (ia64_insn, int);
32 static int extract_op_bits (int, int, int);
33 static int extract_op (int, int *, unsigned int *);
34 static int opcode_verify (ia64_insn, int, enum ia64_insn_type);
35 static int locate_opcode_ent (ia64_insn, enum ia64_insn_type);
36 static struct ia64_opcode *make_ia64_opcode
37   (ia64_insn, const char *, int, int);
38 static struct ia64_opcode *ia64_find_matching_opcode
39   (const char *, short int);
40 
41 const 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 
66 static void
get_opc_prefix(const char ** ptr,char * dest)67 get_opc_prefix (const char **ptr, char *dest)
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 
85 /* Find the index of the entry in the string table corresponding to
86    STR; return -1 if one does not exist. */
87 
88 static short
find_string_ent(const char * str)89 find_string_ent (const char *str)
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 
119 /* Find the opcode in the main opcode table whose name is STRINGINDEX, or
120    return -1 if one does not exist. */
121 
122 static short
find_main_ent(short nameindex)123 find_main_ent (short nameindex)
124 {
125   short start = 0;
126   short end = ARRAY_SIZE (main_table);
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 
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 
161 static short
find_completer(short main_ent,short prev_completer,const char * name)162 find_completer (short main_ent, short prev_completer, const char *name)
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 
191 /* Apply the completer referred to by COMPLETER_INDEX to OPCODE, and
192    return the result. */
193 
194 static ia64_insn
apply_completer(ia64_insn opcode,int completer_index)195 apply_completer (ia64_insn opcode, int completer_index)
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 
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 
212 static int
extract_op_bits(int op_pointer,int bitoffset,int bits)213 extract_op_bits (int op_pointer, int bitoffset, int bits)
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 
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 
248 static int
extract_op(int op_pointer,int * opval,unsigned int * op)249 extract_op (int op_pointer, int *opval, unsigned int *op)
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 
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 
303 static int
opcode_verify(ia64_insn opcode,int place,enum ia64_insn_type type)304 opcode_verify (ia64_insn opcode, int place, enum ia64_insn_type type)
305 {
306   if (main_table[place].opcode_type != type)
307     {
308       return 0;
309     }
310   if (main_table[place].flags
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 
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
344    not be found.  Checks all matches and returns the one with the highest
345    priority. */
346 
347 static int
locate_opcode_ent(ia64_insn opcode,enum ia64_insn_type type)348 locate_opcode_ent (ia64_insn opcode, enum ia64_insn_type type)
349 {
350   int currtest[41];
351   int bitpos[41];
352   int op_ptr[41];
353   int currstatenum = 0;
354   short found_disent = -1;
355   short found_priority = -1;
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;
367       int opval[3] = {0};
368       int next_op;
369       int currbit;
370 
371       oplen = extract_op (op_pointer, opval, &op);
372 
373       bitpos[currstatenum] = currbitnum;
374 
375       /* Skip opval[0] bits in the instruction.  */
376       if (op & 0x40)
377 	{
378 	  currbitnum -= opval[0];
379 	}
380 
381       if (currbitnum < 0)
382 	currbitnum = 0;
383 
384       /* The value of the current bit being tested.  */
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;
465           short priority = -1;
466 
467 	  if (next_op > 65535)
468 	    {
469 	      return -1;
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               priority = ia64_dis_names[disent].priority;
479 
480 	      if (opcode_verify (opcode, place, type)
481                   && priority > found_priority)
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 	    {
497               found_disent = disent;
498               found_priority = priority;
499 	    }
500           /* Try the next test in this state, regardless of whether a match
501              was found. */
502           next_op = -2;
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 	    {
514               return found_disent;
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 
527 /* Construct an ia64_opcode entry based on OPCODE, NAME and PLACE. */
528 
529 static struct ia64_opcode *
make_ia64_opcode(ia64_insn opcode,const char * name,int place,int depind)530 make_ia64_opcode (ia64_insn opcode, const char *name, int place, int depind)
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 
550 /* Determine the ia64_opcode entry for the opcode specified by INSN
551    and TYPE.  If a valid entry is not found, return NULL. */
552 struct ia64_opcode *
ia64_dis_opcode(ia64_insn insn,enum ia64_insn_type type)553 ia64_dis_opcode (ia64_insn insn, enum ia64_insn_type type)
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 	}
603       return make_ia64_opcode (insn, name, place,
604                                completer_table[ci].dependencies);
605     }
606 }
607 
608 /* Search the main_opcode table starting from PLACE for an opcode that
609    matches NAME.  Return NULL if one is not found. */
610 
611 static struct ia64_opcode *
ia64_find_matching_opcode(const char * name,short place)612 ia64_find_matching_opcode (const char *name, short place)
613 {
614   char op[129];
615   const char *suffix;
616   short name_index;
617 
618   if ((unsigned) place >= ARRAY_SIZE (main_table))
619     return NULL;
620 
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 {
640 	if (suffix[0] == '\0')
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 
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 
675 struct ia64_opcode *
ia64_find_next_opcode(struct ia64_opcode * prev_ent)676 ia64_find_next_opcode (struct ia64_opcode *prev_ent)
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 
688 struct ia64_opcode *
ia64_find_opcode(const char * name)689 ia64_find_opcode (const char *name)
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. */
718 void
ia64_free_opcode(struct ia64_opcode * ent)719 ia64_free_opcode (struct ia64_opcode *ent)
720 {
721   free ((void *)ent->name);
722   free (ent);
723 }
724 
725 const struct ia64_dependency *
ia64_find_dependency(int dep_index)726 ia64_find_dependency (int dep_index)
727 {
728   dep_index = DEP(dep_index);
729 
730   if (dep_index < 0
731       || dep_index >= (int) ARRAY_SIZE (dependencies))
732     return NULL;
733 
734   return &dependencies[dep_index];
735 }
736