]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blame - opcodes/cgen-opc.c
Update year range in copyright notice of binutils files
[thirdparty/binutils-gdb.git] / opcodes / cgen-opc.c
CommitLineData
252b5132
RH
1/* CGEN generic opcode support.
2
250d07de 3 Copyright (C) 1996-2021 Free Software Foundation, Inc.
252b5132 4
9b201bb5 5 This file is part of libopcodes.
252b5132 6
9b201bb5 7 This library is free software; you can redistribute it and/or modify
252b5132 8 it under the terms of the GNU General Public License as published by
9b201bb5 9 the Free Software Foundation; either version 3, or (at your option)
252b5132
RH
10 any later version.
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.
252b5132
RH
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.,
f4321104 19 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA. */
252b5132
RH
20
21#include "sysdep.h"
df7b86aa 22#include "alloca-conf.h"
252b5132
RH
23#include <stdio.h>
24#include "ansidecl.h"
25#include "libiberty.h"
3882b010 26#include "safe-ctype.h"
252b5132
RH
27#include "bfd.h"
28#include "symcat.h"
29#include "opcode/cgen.h"
30
31static unsigned int hash_keyword_name
10e05405 32 (const CGEN_KEYWORD *, const char *, int);
252b5132 33static unsigned int hash_keyword_value
10e05405 34 (const CGEN_KEYWORD *, unsigned int);
252b5132 35static void build_keyword_hash_tables
10e05405 36 (CGEN_KEYWORD *);
252b5132
RH
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
44const CGEN_KEYWORD_ENTRY *
10e05405 45cgen_keyword_lookup_name (CGEN_KEYWORD *kt, const char *name)
252b5132
RH
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
3882b010 66 || (ISALPHA (*p) && (TOLOWER (*p) == TOLOWER (*n)))))
252b5132
RH
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
83const CGEN_KEYWORD_ENTRY *
10e05405 84cgen_keyword_lookup_value (CGEN_KEYWORD *kt, int value)
252b5132
RH
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
105void
10e05405 106cgen_keyword_add (CGEN_KEYWORD *kt, CGEN_KEYWORD_ENTRY *ke)
252b5132
RH
107{
108 unsigned int hash;
3e890047 109 size_t i;
252b5132
RH
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;
3e890047 124
5e91c3b4 125 for (i = 1; i < strlen (ke->name); i++)
3882b010 126 if (! ISALNUM (ke->name[i])
3e890047
GK
127 && ! strchr (kt->nonalpha_chars, ke->name[i]))
128 {
129 size_t idx = strlen (kt->nonalpha_chars);
43e65147 130
3e890047
GK
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 }
252b5132
RH
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
151CGEN_KEYWORD_SEARCH
10e05405 152cgen_keyword_search_init (CGEN_KEYWORD *kt, const char *spec)
252b5132
RH
153{
154 CGEN_KEYWORD_SEARCH search;
155
47b0e7ad 156 /* FIXME: Need to specify format of params. */
252b5132
RH
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
173const CGEN_KEYWORD_ENTRY *
10e05405 174cgen_keyword_search_next (CGEN_KEYWORD_SEARCH *search)
252b5132
RH
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
207static unsigned int
10e05405
MM
208hash_keyword_name (const CGEN_KEYWORD *kt,
209 const char *name,
210 int case_sensitive_p)
252b5132
RH
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)
3882b010 219 hash = (hash * 97) + (unsigned char) TOLOWER (*name);
252b5132
RH
220 return hash % kt->hash_table_size;
221}
222
223/* Return first entry in hash chain for VALUE. */
224
225static unsigned int
10e05405 226hash_keyword_value (const CGEN_KEYWORD *kt, unsigned int value)
252b5132
RH
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
235static void
10e05405 236build_keyword_hash_tables (CGEN_KEYWORD *kt)
252b5132
RH
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\f
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
263const CGEN_HW_ENTRY *
10e05405 264cgen_hw_lookup_by_name (CGEN_CPU_DESC cd, const char *name)
252b5132 265{
510925d3 266 unsigned int i;
252b5132
RH
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
281const CGEN_HW_ENTRY *
10e05405 282cgen_hw_lookup_by_num (CGEN_CPU_DESC cd, unsigned int hwnum)
252b5132 283{
510925d3 284 unsigned int i;
252b5132
RH
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\f
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
301const CGEN_OPERAND *
10e05405 302cgen_operand_lookup_by_name (CGEN_CPU_DESC cd, const char *name)
252b5132 303{
510925d3 304 unsigned int i;
252b5132
RH
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
320const CGEN_OPERAND *
10e05405 321cgen_operand_lookup_by_num (CGEN_CPU_DESC cd, int opnum)
252b5132
RH
322{
323 return cd->operand_table.entries[opnum];
324}
325\f
326/* Instruction support. */
327
328/* Return number of instructions. This includes any added at runtime. */
329
330int
10e05405 331cgen_insn_count (CGEN_CPU_DESC cd)
252b5132
RH
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
345int
10e05405 346cgen_macro_insn_count (CGEN_CPU_DESC cd)
252b5132
RH
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
359CGEN_INSN_INT
e9bffec9
JM
360cgen_get_insn_value (CGEN_CPU_DESC cd, unsigned char *buf, int length,
361 int endian)
252b5132 362{
e9bffec9 363 int big_p = (endian == CGEN_ENDIAN_BIG);
81f6038f
FCE
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
43e65147 373 /* Enforce divisibility. */
81f6038f
FCE
374 if ((length % insn_chunk_bitsize) != 0)
375 abort ();
376
377 for (i = 0; i < length; i += insn_chunk_bitsize) /* NB: i == bits */
378 {
91d6fa6a 379 int bit_index;
81f6038f 380 bfd_vma this_value;
91d6fa6a
NC
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);
81f6038f
FCE
384 value = (value << insn_chunk_bitsize) | this_value;
385 }
386 }
387 else
388 {
e9bffec9 389 value = bfd_get_bits (buf, length, endian == CGEN_ENDIAN_BIG);
81f6038f
FCE
390 }
391
392 return value;
252b5132
RH
393}
394
395/* Cover function to store an insn value properly byteswapped. */
396
397void
10e05405
MM
398cgen_put_insn_value (CGEN_CPU_DESC cd,
399 unsigned char *buf,
400 int length,
e9bffec9
JM
401 CGEN_INSN_INT value,
402 int endian)
252b5132 403{
e9bffec9 404 int big_p = (endian == CGEN_ENDIAN_BIG);
81f6038f
FCE
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
43e65147 413 /* Enforce divisibility. */
81f6038f
FCE
414 if ((length % insn_chunk_bitsize) != 0)
415 abort ();
416
417 for (i = 0; i < length; i += insn_chunk_bitsize) /* NB: i == bits */
418 {
91d6fa6a
NC
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);
81f6038f
FCE
423 value >>= insn_chunk_bitsize;
424 }
425 }
426 else
427 {
428 bfd_put_bits ((bfd_vma) value, buf, length, big_p);
429 }
252b5132
RH
430}
431\f
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
447const CGEN_INSN *
10e05405
MM
448cgen_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)
252b5132 456{
252b5132
RH
457 CGEN_EXTRACT_INFO ex_info;
458 CGEN_EXTRACT_INFO *info;
459
460 if (cd->int_insn_p)
461 {
462 info = NULL;
54064fdb 463 insn_bytes_value = (unsigned char *) xmalloc (cd->max_insn_bitsize / 8);
e9bffec9
JM
464 cgen_put_insn_value (cd, insn_bytes_value, length, insn_int_value,
465 cd->insn_endian);
252b5132
RH
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;
e9bffec9
JM
473 insn_int_value = cgen_get_insn_value (cd, insn_bytes_value, length,
474 cd->insn_endian);
252b5132
RH
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
54064fdb
AM
484 insn_list = cgen_dis_lookup_insn (cd, (char *) insn_bytes_value,
485 insn_int_value);
252b5132
RH
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. */
54064fdb 497 if ((insn_int_value & CGEN_INSN_BASE_MASK (insn))
252b5132
RH
498 == CGEN_INSN_BASE_VALUE (insn))
499 {
500 /* ??? 0 is passed for `pc' */
501 int elength = CGEN_EXTRACT_FN (cd, insn)
54064fdb 502 (cd, insn, info, insn_int_value, fields, (bfd_vma) 0);
252b5132
RH
503 if (elength > 0)
504 {
505 /* sanity check */
506 if (length != 0 && length != elength)
507 abort ();
54064fdb 508 break;
252b5132
RH
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)
54064fdb 528 (cd, insn, info, insn_int_value, fields, (bfd_vma) 0);
252b5132
RH
529 /* Sanity check: must succeed.
530 Could relax this later if it ever proves useful. */
531 if (length == 0)
532 abort ();
252b5132
RH
533 }
534
54064fdb
AM
535 if (cd->int_insn_p)
536 free (insn_bytes_value);
537
538 return insn;
252b5132
RH
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
545void
10e05405
MM
546cgen_get_insn_operands (CGEN_CPU_DESC cd,
547 const CGEN_INSN *insn,
548 const CGEN_FIELDS *fields,
549 int *indices)
252b5132
RH
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
576const CGEN_INSN *
10e05405
MM
577cgen_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)
252b5132
RH
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}
fa7928ca
NC
596
597/* Allow signed overflow of instruction fields. */
598void
10e05405 599cgen_set_signed_overflow_ok (CGEN_CPU_DESC cd)
fa7928ca
NC
600{
601 cd->signed_overflow_ok_p = 1;
602}
603
604/* Generate an error message if a signed field in an instruction overflows. */
605void
10e05405 606cgen_clear_signed_overflow_ok (CGEN_CPU_DESC cd)
fa7928ca
NC
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 ? */
612unsigned int
10e05405 613cgen_signed_overflow_ok_p (CGEN_CPU_DESC cd)
fa7928ca
NC
614{
615 return cd->signed_overflow_ok_p;
616}