Automatic date update in version.in
[binutils-gdb.git] / opcodes / cgen-opc.c
blob298b5f4b2962228608a2321b6f75b4b2e76684ec
1 /* CGEN generic opcode support.
3 Copyright (C) 1996-2024 Free Software Foundation, Inc.
5 This file is part of libopcodes.
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.
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.
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. */
21 #include "sysdep.h"
22 #include <stdio.h>
23 #include "ansidecl.h"
24 #include "libiberty.h"
25 #include "safe-ctype.h"
26 #include "bfd.h"
27 #include "symcat.h"
28 #include "opcode/cgen.h"
30 static unsigned int hash_keyword_name
31 (const CGEN_KEYWORD *, const char *, int);
32 static unsigned int hash_keyword_value
33 (const CGEN_KEYWORD *, unsigned int);
34 static void build_keyword_hash_tables
35 (CGEN_KEYWORD *);
37 /* Return number of hash table entries to use for N elements. */
38 #define KEYWORD_HASH_SIZE(n) ((n) <= 31 ? 17 : 31)
40 /* Look up *NAMEP in the keyword table KT.
41 The result is the keyword entry or NULL if not found. */
43 const CGEN_KEYWORD_ENTRY *
44 cgen_keyword_lookup_name (CGEN_KEYWORD *kt, const char *name)
46 const CGEN_KEYWORD_ENTRY *ke;
47 const char *p,*n;
49 if (kt->name_hash_table == NULL)
50 build_keyword_hash_tables (kt);
52 ke = kt->name_hash_table[hash_keyword_name (kt, name, 0)];
54 /* We do case insensitive comparisons.
55 If that ever becomes a problem, add an attribute that denotes
56 "do case sensitive comparisons". */
58 while (ke != NULL)
60 n = name;
61 p = ke->name;
63 while (*p
64 && (*p == *n
65 || (ISALPHA (*p) && (TOLOWER (*p) == TOLOWER (*n)))))
66 ++n, ++p;
68 if (!*p && !*n)
69 return ke;
71 ke = ke->next_name;
74 if (kt->null_entry)
75 return kt->null_entry;
76 return NULL;
79 /* Look up VALUE in the keyword table KT.
80 The result is the keyword entry or NULL if not found. */
82 const CGEN_KEYWORD_ENTRY *
83 cgen_keyword_lookup_value (CGEN_KEYWORD *kt, int value)
85 const CGEN_KEYWORD_ENTRY *ke;
87 if (kt->name_hash_table == NULL)
88 build_keyword_hash_tables (kt);
90 ke = kt->value_hash_table[hash_keyword_value (kt, value)];
92 while (ke != NULL)
94 if (value == ke->value)
95 return ke;
96 ke = ke->next_value;
99 return NULL;
102 /* Add an entry to a keyword table. */
104 void
105 cgen_keyword_add (CGEN_KEYWORD *kt, CGEN_KEYWORD_ENTRY *ke)
107 unsigned int hash;
108 size_t i;
110 if (kt->name_hash_table == NULL)
111 build_keyword_hash_tables (kt);
113 hash = hash_keyword_name (kt, ke->name, 0);
114 ke->next_name = kt->name_hash_table[hash];
115 kt->name_hash_table[hash] = ke;
117 hash = hash_keyword_value (kt, ke->value);
118 ke->next_value = kt->value_hash_table[hash];
119 kt->value_hash_table[hash] = ke;
121 if (ke->name[0] == 0)
122 kt->null_entry = ke;
124 for (i = 1; i < strlen (ke->name); i++)
125 if (! ISALNUM (ke->name[i])
126 && ! strchr (kt->nonalpha_chars, ke->name[i]))
128 size_t idx = strlen (kt->nonalpha_chars);
130 /* If you hit this limit, please don't just
131 increase the size of the field, instead
132 look for a better algorithm. */
133 if (idx >= sizeof (kt->nonalpha_chars) - 1)
134 abort ();
135 kt->nonalpha_chars[idx] = ke->name[i];
136 kt->nonalpha_chars[idx+1] = 0;
140 /* FIXME: Need function to return count of keywords. */
142 /* Initialize a keyword table search.
143 SPEC is a specification of what to search for.
144 A value of NULL means to find every keyword.
145 Currently NULL is the only acceptable value [further specification
146 deferred].
147 The result is an opaque data item used to record the search status.
148 It is passed to each call to cgen_keyword_search_next. */
150 CGEN_KEYWORD_SEARCH
151 cgen_keyword_search_init (CGEN_KEYWORD *kt, const char *spec)
153 CGEN_KEYWORD_SEARCH search;
155 /* FIXME: Need to specify format of params. */
156 if (spec != NULL)
157 abort ();
159 if (kt->name_hash_table == NULL)
160 build_keyword_hash_tables (kt);
162 search.table = kt;
163 search.spec = spec;
164 search.current_hash = 0;
165 search.current_entry = NULL;
166 return search;
169 /* Return the next keyword specified by SEARCH.
170 The result is the next entry or NULL if there are no more. */
172 const CGEN_KEYWORD_ENTRY *
173 cgen_keyword_search_next (CGEN_KEYWORD_SEARCH *search)
175 /* Has search finished? */
176 if (search->current_hash == search->table->hash_table_size)
177 return NULL;
179 /* Search in progress? */
180 if (search->current_entry != NULL
181 /* Anything left on this hash chain? */
182 && search->current_entry->next_name != NULL)
184 search->current_entry = search->current_entry->next_name;
185 return search->current_entry;
188 /* Move to next hash chain [unless we haven't started yet]. */
189 if (search->current_entry != NULL)
190 ++search->current_hash;
192 while (search->current_hash < search->table->hash_table_size)
194 search->current_entry = search->table->name_hash_table[search->current_hash];
195 if (search->current_entry != NULL)
196 return search->current_entry;
197 ++search->current_hash;
200 return NULL;
203 /* Return first entry in hash chain for NAME.
204 If CASE_SENSITIVE_P is non-zero, return a case sensitive hash. */
206 static unsigned int
207 hash_keyword_name (const CGEN_KEYWORD *kt,
208 const char *name,
209 int case_sensitive_p)
211 unsigned int hash;
213 if (case_sensitive_p)
214 for (hash = 0; *name; ++name)
215 hash = (hash * 97) + (unsigned char) *name;
216 else
217 for (hash = 0; *name; ++name)
218 hash = (hash * 97) + (unsigned char) TOLOWER (*name);
219 return hash % kt->hash_table_size;
222 /* Return first entry in hash chain for VALUE. */
224 static unsigned int
225 hash_keyword_value (const CGEN_KEYWORD *kt, unsigned int value)
227 return value % kt->hash_table_size;
230 /* Build a keyword table's hash tables.
231 We probably needn't build the value hash table for the assembler when
232 we're using the disassembler, but we keep things simple. */
234 static void
235 build_keyword_hash_tables (CGEN_KEYWORD *kt)
237 int i;
238 /* Use the number of compiled in entries as an estimate for the
239 typical sized table [not too many added at runtime]. */
240 unsigned int size = KEYWORD_HASH_SIZE (kt->num_init_entries);
242 kt->hash_table_size = size;
243 kt->name_hash_table = (CGEN_KEYWORD_ENTRY **)
244 xmalloc (size * sizeof (CGEN_KEYWORD_ENTRY *));
245 memset (kt->name_hash_table, 0, size * sizeof (CGEN_KEYWORD_ENTRY *));
246 kt->value_hash_table = (CGEN_KEYWORD_ENTRY **)
247 xmalloc (size * sizeof (CGEN_KEYWORD_ENTRY *));
248 memset (kt->value_hash_table, 0, size * sizeof (CGEN_KEYWORD_ENTRY *));
250 /* The table is scanned backwards as we want keywords appearing earlier to
251 be prefered over later ones. */
252 for (i = kt->num_init_entries - 1; i >= 0; --i)
253 cgen_keyword_add (kt, &kt->init_entries[i]);
256 /* Hardware support. */
258 /* Lookup a hardware element by its name.
259 Returns NULL if NAME is not supported by the currently selected
260 mach/isa. */
262 const CGEN_HW_ENTRY *
263 cgen_hw_lookup_by_name (CGEN_CPU_DESC cd, const char *name)
265 unsigned int i;
266 const CGEN_HW_ENTRY **hw = cd->hw_table.entries;
268 for (i = 0; i < cd->hw_table.num_entries; ++i)
269 if (hw[i] && strcmp (name, hw[i]->name) == 0)
270 return hw[i];
272 return NULL;
275 /* Lookup a hardware element by its number.
276 Hardware elements are enumerated, however it may be possible to add some
277 at runtime, thus HWNUM is not an enum type but rather an int.
278 Returns NULL if HWNUM is not supported by the currently selected mach. */
280 const CGEN_HW_ENTRY *
281 cgen_hw_lookup_by_num (CGEN_CPU_DESC cd, unsigned int hwnum)
283 unsigned int i;
284 const CGEN_HW_ENTRY **hw = cd->hw_table.entries;
286 /* ??? This can be speeded up. */
287 for (i = 0; i < cd->hw_table.num_entries; ++i)
288 if (hw[i] && hwnum == hw[i]->type)
289 return hw[i];
291 return NULL;
294 /* Operand support. */
296 /* Lookup an operand by its name.
297 Returns NULL if NAME is not supported by the currently selected
298 mach/isa. */
300 const CGEN_OPERAND *
301 cgen_operand_lookup_by_name (CGEN_CPU_DESC cd, const char *name)
303 unsigned int i;
304 const CGEN_OPERAND **op = cd->operand_table.entries;
306 for (i = 0; i < cd->operand_table.num_entries; ++i)
307 if (op[i] && strcmp (name, op[i]->name) == 0)
308 return op[i];
310 return NULL;
313 /* Lookup an operand by its number.
314 Operands are enumerated, however it may be possible to add some
315 at runtime, thus OPNUM is not an enum type but rather an int.
316 Returns NULL if OPNUM is not supported by the currently selected
317 mach/isa. */
319 const CGEN_OPERAND *
320 cgen_operand_lookup_by_num (CGEN_CPU_DESC cd, int opnum)
322 return cd->operand_table.entries[opnum];
325 /* Instruction support. */
327 /* Return number of instructions. This includes any added at runtime. */
330 cgen_insn_count (CGEN_CPU_DESC cd)
332 int count = cd->insn_table.num_init_entries;
333 CGEN_INSN_LIST *rt_insns = cd->insn_table.new_entries;
335 for ( ; rt_insns != NULL; rt_insns = rt_insns->next)
336 ++count;
338 return count;
341 /* Return number of macro-instructions.
342 This includes any added at runtime. */
345 cgen_macro_insn_count (CGEN_CPU_DESC cd)
347 int count = cd->macro_insn_table.num_init_entries;
348 CGEN_INSN_LIST *rt_insns = cd->macro_insn_table.new_entries;
350 for ( ; rt_insns != NULL; rt_insns = rt_insns->next)
351 ++count;
353 return count;
356 /* Cover function to read and properly byteswap an insn value. */
358 CGEN_INSN_INT
359 cgen_get_insn_value (CGEN_CPU_DESC cd, unsigned char *buf, int length,
360 int endian)
362 int big_p = (endian == CGEN_ENDIAN_BIG);
363 int insn_chunk_bitsize = cd->insn_chunk_bitsize;
364 CGEN_INSN_INT value = 0;
366 if (insn_chunk_bitsize != 0 && insn_chunk_bitsize < length)
368 /* We need to divide up the incoming value into insn_chunk_bitsize-length
369 segments, and endian-convert them, one at a time. */
370 int i;
372 /* Enforce divisibility. */
373 if ((length % insn_chunk_bitsize) != 0)
374 abort ();
376 for (i = 0; i < length; i += insn_chunk_bitsize) /* NB: i == bits */
378 int bit_index;
379 bfd_vma this_value;
381 bit_index = i; /* NB: not dependent on endianness; opposite of cgen_put_insn_value! */
382 this_value = bfd_get_bits (& buf[bit_index / 8], insn_chunk_bitsize, big_p);
383 value = (value << insn_chunk_bitsize) | this_value;
386 else
388 value = bfd_get_bits (buf, length, endian == CGEN_ENDIAN_BIG);
391 return value;
394 /* Cover function to store an insn value properly byteswapped. */
396 void
397 cgen_put_insn_value (CGEN_CPU_DESC cd,
398 unsigned char *buf,
399 int length,
400 CGEN_INSN_INT value,
401 int endian)
403 int big_p = (endian == CGEN_ENDIAN_BIG);
404 int insn_chunk_bitsize = cd->insn_chunk_bitsize;
406 if (insn_chunk_bitsize != 0 && insn_chunk_bitsize < length)
408 /* We need to divide up the incoming value into insn_chunk_bitsize-length
409 segments, and endian-convert them, one at a time. */
410 int i;
412 /* Enforce divisibility. */
413 if ((length % insn_chunk_bitsize) != 0)
414 abort ();
416 for (i = 0; i < length; i += insn_chunk_bitsize) /* NB: i == bits */
418 int bit_index;
420 bit_index = (length - insn_chunk_bitsize - i); /* NB: not dependent on endianness! */
421 bfd_put_bits ((bfd_vma) value, & buf[bit_index / 8], insn_chunk_bitsize, big_p);
422 value >>= insn_chunk_bitsize;
425 else
427 bfd_put_bits ((bfd_vma) value, buf, length, big_p);
431 /* Look up instruction INSN_*_VALUE and extract its fields.
432 INSN_INT_VALUE is used if CGEN_INT_INSN_P.
433 Otherwise INSN_BYTES_VALUE is used.
434 INSN, if non-null, is the insn table entry.
435 Otherwise INSN_*_VALUE is examined to compute it.
436 LENGTH is the bit length of INSN_*_VALUE if known, otherwise 0.
437 0 is only valid if `insn == NULL && ! CGEN_INT_INSN_P'.
438 If INSN != NULL, LENGTH must be valid.
439 ALIAS_P is non-zero if alias insns are to be included in the search.
441 The result is a pointer to the insn table entry, or NULL if the instruction
442 wasn't recognized. */
444 /* ??? Will need to be revisited for VLIW architectures. */
446 const CGEN_INSN *
447 cgen_lookup_insn (CGEN_CPU_DESC cd,
448 const CGEN_INSN *insn,
449 CGEN_INSN_INT insn_int_value,
450 /* ??? CGEN_INSN_BYTES would be a nice type name to use here. */
451 unsigned char *insn_bytes_value,
452 int length,
453 CGEN_FIELDS *fields,
454 int alias_p)
456 CGEN_EXTRACT_INFO ex_info;
457 CGEN_EXTRACT_INFO *info;
459 if (cd->int_insn_p)
461 info = NULL;
462 insn_bytes_value = (unsigned char *) xmalloc (cd->max_insn_bitsize / 8);
463 cgen_put_insn_value (cd, insn_bytes_value, length, insn_int_value,
464 cd->insn_endian);
466 else
468 info = &ex_info;
469 ex_info.dis_info = NULL;
470 ex_info.insn_bytes = insn_bytes_value;
471 ex_info.valid = -1;
472 insn_int_value = cgen_get_insn_value (cd, insn_bytes_value, length,
473 cd->insn_endian);
476 if (!insn)
478 const CGEN_INSN_LIST *insn_list;
480 /* The instructions are stored in hash lists.
481 Pick the first one and keep trying until we find the right one. */
483 insn_list = cgen_dis_lookup_insn (cd, (char *) insn_bytes_value,
484 insn_int_value);
485 while (insn_list != NULL)
487 insn = insn_list->insn;
489 if (alias_p
490 /* FIXME: Ensure ALIAS attribute always has same index. */
491 || ! CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_ALIAS))
493 /* Basic bit mask must be correct. */
494 /* ??? May wish to allow target to defer this check until the
495 extract handler. */
496 if ((insn_int_value & CGEN_INSN_BASE_MASK (insn))
497 == CGEN_INSN_BASE_VALUE (insn))
499 /* ??? 0 is passed for `pc' */
500 int elength = CGEN_EXTRACT_FN (cd, insn)
501 (cd, insn, info, insn_int_value, fields, (bfd_vma) 0);
502 if (elength > 0)
504 /* sanity check */
505 if (length != 0 && length != elength)
506 abort ();
507 break;
512 insn_list = insn_list->next;
515 else
517 /* Sanity check: can't pass an alias insn if ! alias_p. */
518 if (! alias_p
519 && CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_ALIAS))
520 abort ();
521 /* Sanity check: length must be correct. */
522 if (length != CGEN_INSN_BITSIZE (insn))
523 abort ();
525 /* ??? 0 is passed for `pc' */
526 length = CGEN_EXTRACT_FN (cd, insn)
527 (cd, insn, info, insn_int_value, fields, (bfd_vma) 0);
528 /* Sanity check: must succeed.
529 Could relax this later if it ever proves useful. */
530 if (length == 0)
531 abort ();
534 if (cd->int_insn_p)
535 free (insn_bytes_value);
537 return insn;
540 /* Fill in the operand instances used by INSN whose operands are FIELDS.
541 INDICES is a pointer to a buffer of MAX_OPERAND_INSTANCES ints to be filled
542 in. */
544 void
545 cgen_get_insn_operands (CGEN_CPU_DESC cd,
546 const CGEN_INSN *insn,
547 const CGEN_FIELDS *fields,
548 int *indices)
550 const CGEN_OPINST *opinst;
551 int i;
553 if (insn->opinst == NULL)
554 abort ();
555 for (i = 0, opinst = insn->opinst; opinst->type != CGEN_OPINST_END; ++i, ++opinst)
557 enum cgen_operand_type op_type = opinst->op_type;
558 if (op_type == CGEN_OPERAND_NIL)
559 indices[i] = opinst->index;
560 else
561 indices[i] = (*cd->get_int_operand) (cd, op_type, fields);
565 /* Cover function to cgen_get_insn_operands when either INSN or FIELDS
566 isn't known.
567 The INSN, INSN_*_VALUE, and LENGTH arguments are passed to
568 cgen_lookup_insn unchanged.
569 INSN_INT_VALUE is used if CGEN_INT_INSN_P.
570 Otherwise INSN_BYTES_VALUE is used.
572 The result is the insn table entry or NULL if the instruction wasn't
573 recognized. */
575 const CGEN_INSN *
576 cgen_lookup_get_insn_operands (CGEN_CPU_DESC cd,
577 const CGEN_INSN *insn,
578 CGEN_INSN_INT insn_int_value,
579 /* ??? CGEN_INSN_BYTES would be a nice type name to use here. */
580 unsigned char *insn_bytes_value,
581 int length,
582 int *indices,
583 CGEN_FIELDS *fields)
585 /* Pass non-zero for ALIAS_P only if INSN != NULL.
586 If INSN == NULL, we want a real insn. */
587 insn = cgen_lookup_insn (cd, insn, insn_int_value, insn_bytes_value,
588 length, fields, insn != NULL);
589 if (! insn)
590 return NULL;
592 cgen_get_insn_operands (cd, insn, fields, indices);
593 return insn;
596 /* Allow signed overflow of instruction fields. */
597 void
598 cgen_set_signed_overflow_ok (CGEN_CPU_DESC cd)
600 cd->signed_overflow_ok_p = 1;
603 /* Generate an error message if a signed field in an instruction overflows. */
604 void
605 cgen_clear_signed_overflow_ok (CGEN_CPU_DESC cd)
607 cd->signed_overflow_ok_p = 0;
610 /* Will an error message be generated if a signed field in an instruction overflows ? */
611 unsigned int
612 cgen_signed_overflow_ok_p (CGEN_CPU_DESC cd)
614 return cd->signed_overflow_ok_p;