1 /* CGEN generic opcode support.
2 
3    Copyright (C) 1996-2020 Free Software Foundation, Inc.
4 
5    This file is part of libopcodes.
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 along
18    with this program; if not, write to the Free Software Foundation, Inc.,
19    51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.  */
20 
21 #include "sysdep.h"
22 #include "alloca-conf.h"
23 #include <stdio.h>
24 #include "ansidecl.h"
25 #include "libiberty.h"
26 #include "safe-ctype.h"
27 #include "bfd.h"
28 #include "symcat.h"
29 #include "opcode/cgen.h"
30 
31 static unsigned int hash_keyword_name
32   (const CGEN_KEYWORD *, const char *, int);
33 static unsigned int hash_keyword_value
34   (const CGEN_KEYWORD *, unsigned int);
35 static void build_keyword_hash_tables
36   (CGEN_KEYWORD *);
37 
38 /* Return number of hash table entries to use for N elements.  */
39 #define KEYWORD_HASH_SIZE(n) ((n) <= 31 ? 17 : 31)
40 
41 /* Look up *NAMEP in the keyword table KT.
42    The result is the keyword entry or NULL if not found.  */
43 
44 const CGEN_KEYWORD_ENTRY *
cgen_keyword_lookup_name(CGEN_KEYWORD * kt,const char * name)45 cgen_keyword_lookup_name (CGEN_KEYWORD *kt, const char *name)
46 {
47   const CGEN_KEYWORD_ENTRY *ke;
48   const char *p,*n;
49 
50   if (kt->name_hash_table == NULL)
51     build_keyword_hash_tables (kt);
52 
53   ke = kt->name_hash_table[hash_keyword_name (kt, name, 0)];
54 
55   /* We do case insensitive comparisons.
56      If that ever becomes a problem, add an attribute that denotes
57      "do case sensitive comparisons".  */
58 
59   while (ke != NULL)
60     {
61       n = name;
62       p = ke->name;
63 
64       while (*p
65 	     && (*p == *n
66 		 || (ISALPHA (*p) && (TOLOWER (*p) == TOLOWER (*n)))))
67 	++n, ++p;
68 
69       if (!*p && !*n)
70 	return ke;
71 
72       ke = ke->next_name;
73     }
74 
75   if (kt->null_entry)
76     return kt->null_entry;
77   return NULL;
78 }
79 
80 /* Look up VALUE in the keyword table KT.
81    The result is the keyword entry or NULL if not found.  */
82 
83 const CGEN_KEYWORD_ENTRY *
cgen_keyword_lookup_value(CGEN_KEYWORD * kt,int value)84 cgen_keyword_lookup_value (CGEN_KEYWORD *kt, int value)
85 {
86   const CGEN_KEYWORD_ENTRY *ke;
87 
88   if (kt->name_hash_table == NULL)
89     build_keyword_hash_tables (kt);
90 
91   ke = kt->value_hash_table[hash_keyword_value (kt, value)];
92 
93   while (ke != NULL)
94     {
95       if (value == ke->value)
96 	return ke;
97       ke = ke->next_value;
98     }
99 
100   return NULL;
101 }
102 
103 /* Add an entry to a keyword table.  */
104 
105 void
cgen_keyword_add(CGEN_KEYWORD * kt,CGEN_KEYWORD_ENTRY * ke)106 cgen_keyword_add (CGEN_KEYWORD *kt, CGEN_KEYWORD_ENTRY *ke)
107 {
108   unsigned int hash;
109   size_t i;
110 
111   if (kt->name_hash_table == NULL)
112     build_keyword_hash_tables (kt);
113 
114   hash = hash_keyword_name (kt, ke->name, 0);
115   ke->next_name = kt->name_hash_table[hash];
116   kt->name_hash_table[hash] = ke;
117 
118   hash = hash_keyword_value (kt, ke->value);
119   ke->next_value = kt->value_hash_table[hash];
120   kt->value_hash_table[hash] = ke;
121 
122   if (ke->name[0] == 0)
123     kt->null_entry = ke;
124 
125   for (i = 1; i < strlen (ke->name); i++)
126     if (! ISALNUM (ke->name[i])
127 	&& ! strchr (kt->nonalpha_chars, ke->name[i]))
128       {
129 	size_t idx = strlen (kt->nonalpha_chars);
130 
131 	/* If you hit this limit, please don't just
132 	   increase the size of the field, instead
133 	   look for a better algorithm.  */
134 	if (idx >= sizeof (kt->nonalpha_chars) - 1)
135 	  abort ();
136 	kt->nonalpha_chars[idx] = ke->name[i];
137 	kt->nonalpha_chars[idx+1] = 0;
138       }
139 }
140 
141 /* FIXME: Need function to return count of keywords.  */
142 
143 /* Initialize a keyword table search.
144    SPEC is a specification of what to search for.
145    A value of NULL means to find every keyword.
146    Currently NULL is the only acceptable value [further specification
147    deferred].
148    The result is an opaque data item used to record the search status.
149    It is passed to each call to cgen_keyword_search_next.  */
150 
151 CGEN_KEYWORD_SEARCH
cgen_keyword_search_init(CGEN_KEYWORD * kt,const char * spec)152 cgen_keyword_search_init (CGEN_KEYWORD *kt, const char *spec)
153 {
154   CGEN_KEYWORD_SEARCH search;
155 
156   /* FIXME: Need to specify format of params.  */
157   if (spec != NULL)
158     abort ();
159 
160   if (kt->name_hash_table == NULL)
161     build_keyword_hash_tables (kt);
162 
163   search.table = kt;
164   search.spec = spec;
165   search.current_hash = 0;
166   search.current_entry = NULL;
167   return search;
168 }
169 
170 /* Return the next keyword specified by SEARCH.
171    The result is the next entry or NULL if there are no more.  */
172 
173 const CGEN_KEYWORD_ENTRY *
cgen_keyword_search_next(CGEN_KEYWORD_SEARCH * search)174 cgen_keyword_search_next (CGEN_KEYWORD_SEARCH *search)
175 {
176   /* Has search finished?  */
177   if (search->current_hash == search->table->hash_table_size)
178     return NULL;
179 
180   /* Search in progress?  */
181   if (search->current_entry != NULL
182       /* Anything left on this hash chain?  */
183       && search->current_entry->next_name != NULL)
184     {
185       search->current_entry = search->current_entry->next_name;
186       return search->current_entry;
187     }
188 
189   /* Move to next hash chain [unless we haven't started yet].  */
190   if (search->current_entry != NULL)
191     ++search->current_hash;
192 
193   while (search->current_hash < search->table->hash_table_size)
194     {
195       search->current_entry = search->table->name_hash_table[search->current_hash];
196       if (search->current_entry != NULL)
197 	return search->current_entry;
198       ++search->current_hash;
199     }
200 
201   return NULL;
202 }
203 
204 /* Return first entry in hash chain for NAME.
205    If CASE_SENSITIVE_P is non-zero, return a case sensitive hash.  */
206 
207 static unsigned int
hash_keyword_name(const CGEN_KEYWORD * kt,const char * name,int case_sensitive_p)208 hash_keyword_name (const CGEN_KEYWORD *kt,
209 		   const char *name,
210 		   int case_sensitive_p)
211 {
212   unsigned int hash;
213 
214   if (case_sensitive_p)
215     for (hash = 0; *name; ++name)
216       hash = (hash * 97) + (unsigned char) *name;
217   else
218     for (hash = 0; *name; ++name)
219       hash = (hash * 97) + (unsigned char) TOLOWER (*name);
220   return hash % kt->hash_table_size;
221 }
222 
223 /* Return first entry in hash chain for VALUE.  */
224 
225 static unsigned int
hash_keyword_value(const CGEN_KEYWORD * kt,unsigned int value)226 hash_keyword_value (const CGEN_KEYWORD *kt, unsigned int value)
227 {
228   return value % kt->hash_table_size;
229 }
230 
231 /* Build a keyword table's hash tables.
232    We probably needn't build the value hash table for the assembler when
233    we're using the disassembler, but we keep things simple.  */
234 
235 static void
build_keyword_hash_tables(CGEN_KEYWORD * kt)236 build_keyword_hash_tables (CGEN_KEYWORD *kt)
237 {
238   int i;
239   /* Use the number of compiled in entries as an estimate for the
240      typical sized table [not too many added at runtime].  */
241   unsigned int size = KEYWORD_HASH_SIZE (kt->num_init_entries);
242 
243   kt->hash_table_size = size;
244   kt->name_hash_table = (CGEN_KEYWORD_ENTRY **)
245     xmalloc (size * sizeof (CGEN_KEYWORD_ENTRY *));
246   memset (kt->name_hash_table, 0, size * sizeof (CGEN_KEYWORD_ENTRY *));
247   kt->value_hash_table = (CGEN_KEYWORD_ENTRY **)
248     xmalloc (size * sizeof (CGEN_KEYWORD_ENTRY *));
249   memset (kt->value_hash_table, 0, size * sizeof (CGEN_KEYWORD_ENTRY *));
250 
251   /* The table is scanned backwards as we want keywords appearing earlier to
252      be prefered over later ones.  */
253   for (i = kt->num_init_entries - 1; i >= 0; --i)
254     cgen_keyword_add (kt, &kt->init_entries[i]);
255 }
256 
257 /* Hardware support.  */
258 
259 /* Lookup a hardware element by its name.
260    Returns NULL if NAME is not supported by the currently selected
261    mach/isa.  */
262 
263 const CGEN_HW_ENTRY *
cgen_hw_lookup_by_name(CGEN_CPU_DESC cd,const char * name)264 cgen_hw_lookup_by_name (CGEN_CPU_DESC cd, const char *name)
265 {
266   unsigned int i;
267   const CGEN_HW_ENTRY **hw = cd->hw_table.entries;
268 
269   for (i = 0; i < cd->hw_table.num_entries; ++i)
270     if (hw[i] && strcmp (name, hw[i]->name) == 0)
271       return hw[i];
272 
273   return NULL;
274 }
275 
276 /* Lookup a hardware element by its number.
277    Hardware elements are enumerated, however it may be possible to add some
278    at runtime, thus HWNUM is not an enum type but rather an int.
279    Returns NULL if HWNUM is not supported by the currently selected mach.  */
280 
281 const CGEN_HW_ENTRY *
cgen_hw_lookup_by_num(CGEN_CPU_DESC cd,unsigned int hwnum)282 cgen_hw_lookup_by_num (CGEN_CPU_DESC cd, unsigned int hwnum)
283 {
284   unsigned int i;
285   const CGEN_HW_ENTRY **hw = cd->hw_table.entries;
286 
287   /* ??? This can be speeded up.  */
288   for (i = 0; i < cd->hw_table.num_entries; ++i)
289     if (hw[i] && hwnum == hw[i]->type)
290       return hw[i];
291 
292   return NULL;
293 }
294 
295 /* Operand support.  */
296 
297 /* Lookup an operand by its name.
298    Returns NULL if NAME is not supported by the currently selected
299    mach/isa.  */
300 
301 const CGEN_OPERAND *
cgen_operand_lookup_by_name(CGEN_CPU_DESC cd,const char * name)302 cgen_operand_lookup_by_name (CGEN_CPU_DESC cd, const char *name)
303 {
304   unsigned int i;
305   const CGEN_OPERAND **op = cd->operand_table.entries;
306 
307   for (i = 0; i < cd->operand_table.num_entries; ++i)
308     if (op[i] && strcmp (name, op[i]->name) == 0)
309       return op[i];
310 
311   return NULL;
312 }
313 
314 /* Lookup an operand by its number.
315    Operands are enumerated, however it may be possible to add some
316    at runtime, thus OPNUM is not an enum type but rather an int.
317    Returns NULL if OPNUM is not supported by the currently selected
318    mach/isa.  */
319 
320 const CGEN_OPERAND *
cgen_operand_lookup_by_num(CGEN_CPU_DESC cd,int opnum)321 cgen_operand_lookup_by_num (CGEN_CPU_DESC cd, int opnum)
322 {
323   return cd->operand_table.entries[opnum];
324 }
325 
326 /* Instruction support.  */
327 
328 /* Return number of instructions.  This includes any added at runtime.  */
329 
330 int
cgen_insn_count(CGEN_CPU_DESC cd)331 cgen_insn_count (CGEN_CPU_DESC cd)
332 {
333   int count = cd->insn_table.num_init_entries;
334   CGEN_INSN_LIST *rt_insns = cd->insn_table.new_entries;
335 
336   for ( ; rt_insns != NULL; rt_insns = rt_insns->next)
337     ++count;
338 
339   return count;
340 }
341 
342 /* Return number of macro-instructions.
343    This includes any added at runtime.  */
344 
345 int
cgen_macro_insn_count(CGEN_CPU_DESC cd)346 cgen_macro_insn_count (CGEN_CPU_DESC cd)
347 {
348   int count = cd->macro_insn_table.num_init_entries;
349   CGEN_INSN_LIST *rt_insns = cd->macro_insn_table.new_entries;
350 
351   for ( ; rt_insns != NULL; rt_insns = rt_insns->next)
352     ++count;
353 
354   return count;
355 }
356 
357 /* Cover function to read and properly byteswap an insn value.  */
358 
359 CGEN_INSN_INT
cgen_get_insn_value(CGEN_CPU_DESC cd,unsigned char * buf,int length,int endian)360 cgen_get_insn_value (CGEN_CPU_DESC cd, unsigned char *buf, int length,
361                      int endian)
362 {
363   int big_p = (endian == CGEN_ENDIAN_BIG);
364   int insn_chunk_bitsize = cd->insn_chunk_bitsize;
365   CGEN_INSN_INT value = 0;
366 
367   if (insn_chunk_bitsize != 0 && insn_chunk_bitsize < length)
368     {
369       /* We need to divide up the incoming value into insn_chunk_bitsize-length
370 	 segments, and endian-convert them, one at a time. */
371       int i;
372 
373       /* Enforce divisibility. */
374       if ((length % insn_chunk_bitsize) != 0)
375 	abort ();
376 
377       for (i = 0; i < length; i += insn_chunk_bitsize) /* NB: i == bits */
378 	{
379 	  int bit_index;
380 	  bfd_vma this_value;
381 
382 	  bit_index = i; /* NB: not dependent on endianness; opposite of cgen_put_insn_value! */
383 	  this_value = bfd_get_bits (& buf[bit_index / 8], insn_chunk_bitsize, big_p);
384 	  value = (value << insn_chunk_bitsize) | this_value;
385 	}
386     }
387   else
388     {
389       value = bfd_get_bits (buf, length, endian == CGEN_ENDIAN_BIG);
390     }
391 
392   return value;
393 }
394 
395 /* Cover function to store an insn value properly byteswapped.  */
396 
397 void
cgen_put_insn_value(CGEN_CPU_DESC cd,unsigned char * buf,int length,CGEN_INSN_INT value,int endian)398 cgen_put_insn_value (CGEN_CPU_DESC cd,
399 		     unsigned char *buf,
400 		     int length,
401 		     CGEN_INSN_INT value,
402                      int endian)
403 {
404   int big_p = (endian == CGEN_ENDIAN_BIG);
405   int insn_chunk_bitsize = cd->insn_chunk_bitsize;
406 
407   if (insn_chunk_bitsize != 0 && insn_chunk_bitsize < length)
408     {
409       /* We need to divide up the incoming value into insn_chunk_bitsize-length
410 	 segments, and endian-convert them, one at a time. */
411       int i;
412 
413       /* Enforce divisibility. */
414       if ((length % insn_chunk_bitsize) != 0)
415 	abort ();
416 
417       for (i = 0; i < length; i += insn_chunk_bitsize) /* NB: i == bits */
418 	{
419 	  int bit_index;
420 
421 	  bit_index = (length - insn_chunk_bitsize - i); /* NB: not dependent on endianness! */
422 	  bfd_put_bits ((bfd_vma) value, & buf[bit_index / 8], insn_chunk_bitsize, big_p);
423 	  value >>= insn_chunk_bitsize;
424 	}
425     }
426   else
427     {
428       bfd_put_bits ((bfd_vma) value, buf, length, big_p);
429     }
430 }
431 
432 /* Look up instruction INSN_*_VALUE and extract its fields.
433    INSN_INT_VALUE is used if CGEN_INT_INSN_P.
434    Otherwise INSN_BYTES_VALUE is used.
435    INSN, if non-null, is the insn table entry.
436    Otherwise INSN_*_VALUE is examined to compute it.
437    LENGTH is the bit length of INSN_*_VALUE if known, otherwise 0.
438    0 is only valid if `insn == NULL && ! CGEN_INT_INSN_P'.
439    If INSN != NULL, LENGTH must be valid.
440    ALIAS_P is non-zero if alias insns are to be included in the search.
441 
442    The result is a pointer to the insn table entry, or NULL if the instruction
443    wasn't recognized.  */
444 
445 /* ??? Will need to be revisited for VLIW architectures.  */
446 
447 const CGEN_INSN *
cgen_lookup_insn(CGEN_CPU_DESC cd,const CGEN_INSN * insn,CGEN_INSN_INT insn_int_value,unsigned char * insn_bytes_value,int length,CGEN_FIELDS * fields,int alias_p)448 cgen_lookup_insn (CGEN_CPU_DESC cd,
449 		  const CGEN_INSN *insn,
450 		  CGEN_INSN_INT insn_int_value,
451 		  /* ??? CGEN_INSN_BYTES would be a nice type name to use here.  */
452 		  unsigned char *insn_bytes_value,
453 		  int length,
454 		  CGEN_FIELDS *fields,
455 		  int alias_p)
456 {
457   CGEN_EXTRACT_INFO ex_info;
458   CGEN_EXTRACT_INFO *info;
459 
460   if (cd->int_insn_p)
461     {
462       info = NULL;
463       insn_bytes_value = (unsigned char *) xmalloc (cd->max_insn_bitsize / 8);
464       cgen_put_insn_value (cd, insn_bytes_value, length, insn_int_value,
465                            cd->insn_endian);
466     }
467   else
468     {
469       info = &ex_info;
470       ex_info.dis_info = NULL;
471       ex_info.insn_bytes = insn_bytes_value;
472       ex_info.valid = -1;
473       insn_int_value = cgen_get_insn_value (cd, insn_bytes_value, length,
474                                             cd->insn_endian);
475     }
476 
477   if (!insn)
478     {
479       const CGEN_INSN_LIST *insn_list;
480 
481       /* The instructions are stored in hash lists.
482 	 Pick the first one and keep trying until we find the right one.  */
483 
484       insn_list = cgen_dis_lookup_insn (cd, (char *) insn_bytes_value,
485 					insn_int_value);
486       while (insn_list != NULL)
487 	{
488 	  insn = insn_list->insn;
489 
490 	  if (alias_p
491 	      /* FIXME: Ensure ALIAS attribute always has same index.  */
492 	      || ! CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_ALIAS))
493 	    {
494 	      /* Basic bit mask must be correct.  */
495 	      /* ??? May wish to allow target to defer this check until the
496 		 extract handler.  */
497 	      if ((insn_int_value & CGEN_INSN_BASE_MASK (insn))
498 		  == CGEN_INSN_BASE_VALUE (insn))
499 		{
500 		  /* ??? 0 is passed for `pc' */
501 		  int elength = CGEN_EXTRACT_FN (cd, insn)
502 		    (cd, insn, info, insn_int_value, fields, (bfd_vma) 0);
503 		  if (elength > 0)
504 		    {
505 		      /* sanity check */
506 		      if (length != 0 && length != elength)
507 			abort ();
508 		      break;
509 		    }
510 		}
511 	    }
512 
513 	  insn_list = insn_list->next;
514 	}
515     }
516   else
517     {
518       /* Sanity check: can't pass an alias insn if ! alias_p.  */
519       if (! alias_p
520 	  && CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_ALIAS))
521 	abort ();
522       /* Sanity check: length must be correct.  */
523       if (length != CGEN_INSN_BITSIZE (insn))
524 	abort ();
525 
526       /* ??? 0 is passed for `pc' */
527       length = CGEN_EXTRACT_FN (cd, insn)
528 	(cd, insn, info, insn_int_value, fields, (bfd_vma) 0);
529       /* Sanity check: must succeed.
530 	 Could relax this later if it ever proves useful.  */
531       if (length == 0)
532 	abort ();
533     }
534 
535   if (cd->int_insn_p)
536     free (insn_bytes_value);
537 
538   return insn;
539 }
540 
541 /* Fill in the operand instances used by INSN whose operands are FIELDS.
542    INDICES is a pointer to a buffer of MAX_OPERAND_INSTANCES ints to be filled
543    in.  */
544 
545 void
cgen_get_insn_operands(CGEN_CPU_DESC cd,const CGEN_INSN * insn,const CGEN_FIELDS * fields,int * indices)546 cgen_get_insn_operands (CGEN_CPU_DESC cd,
547 			const CGEN_INSN *insn,
548 			const CGEN_FIELDS *fields,
549 			int *indices)
550 {
551   const CGEN_OPINST *opinst;
552   int i;
553 
554   if (insn->opinst == NULL)
555     abort ();
556   for (i = 0, opinst = insn->opinst; opinst->type != CGEN_OPINST_END; ++i, ++opinst)
557     {
558       enum cgen_operand_type op_type = opinst->op_type;
559       if (op_type == CGEN_OPERAND_NIL)
560 	indices[i] = opinst->index;
561       else
562 	indices[i] = (*cd->get_int_operand) (cd, op_type, fields);
563     }
564 }
565 
566 /* Cover function to cgen_get_insn_operands when either INSN or FIELDS
567    isn't known.
568    The INSN, INSN_*_VALUE, and LENGTH arguments are passed to
569    cgen_lookup_insn unchanged.
570    INSN_INT_VALUE is used if CGEN_INT_INSN_P.
571    Otherwise INSN_BYTES_VALUE is used.
572 
573    The result is the insn table entry or NULL if the instruction wasn't
574    recognized.  */
575 
576 const CGEN_INSN *
cgen_lookup_get_insn_operands(CGEN_CPU_DESC cd,const CGEN_INSN * insn,CGEN_INSN_INT insn_int_value,unsigned char * insn_bytes_value,int length,int * indices,CGEN_FIELDS * fields)577 cgen_lookup_get_insn_operands (CGEN_CPU_DESC cd,
578 			       const CGEN_INSN *insn,
579 			       CGEN_INSN_INT insn_int_value,
580 			       /* ??? CGEN_INSN_BYTES would be a nice type name to use here.  */
581 			       unsigned char *insn_bytes_value,
582 			       int length,
583 			       int *indices,
584 			       CGEN_FIELDS *fields)
585 {
586   /* Pass non-zero for ALIAS_P only if INSN != NULL.
587      If INSN == NULL, we want a real insn.  */
588   insn = cgen_lookup_insn (cd, insn, insn_int_value, insn_bytes_value,
589 			   length, fields, insn != NULL);
590   if (! insn)
591     return NULL;
592 
593   cgen_get_insn_operands (cd, insn, fields, indices);
594   return insn;
595 }
596 
597 /* Allow signed overflow of instruction fields.  */
598 void
cgen_set_signed_overflow_ok(CGEN_CPU_DESC cd)599 cgen_set_signed_overflow_ok (CGEN_CPU_DESC cd)
600 {
601   cd->signed_overflow_ok_p = 1;
602 }
603 
604 /* Generate an error message if a signed field in an instruction overflows.  */
605 void
cgen_clear_signed_overflow_ok(CGEN_CPU_DESC cd)606 cgen_clear_signed_overflow_ok (CGEN_CPU_DESC cd)
607 {
608   cd->signed_overflow_ok_p = 0;
609 }
610 
611 /* Will an error message be generated if a signed field in an instruction overflows ? */
612 unsigned int
cgen_signed_overflow_ok_p(CGEN_CPU_DESC cd)613 cgen_signed_overflow_ok_p (CGEN_CPU_DESC cd)
614 {
615   return cd->signed_overflow_ok_p;
616 }
617