Re-add support for lbarx, lharx, stbcx. and sthcx. insns back to the E6500 cpu.
[binutils-gdb.git] / opcodes / cgen-opc.c
blob543ce32397b9c784f881ccdaf5393260b3dfdd77
1 /* CGEN generic opcode support.
3 Copyright (C) 1996-2016 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 "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"
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 *);
38 /* Return number of hash table entries to use for N elements. */
39 #define KEYWORD_HASH_SIZE(n) ((n) <= 31 ? 17 : 31)
41 /* Look up *NAMEP in the keyword table KT.
42 The result is the keyword entry or NULL if not found. */
44 const CGEN_KEYWORD_ENTRY *
45 cgen_keyword_lookup_name (CGEN_KEYWORD *kt, const char *name)
47 const CGEN_KEYWORD_ENTRY *ke;
48 const char *p,*n;
50 if (kt->name_hash_table == NULL)
51 build_keyword_hash_tables (kt);
53 ke = kt->name_hash_table[hash_keyword_name (kt, name, 0)];
55 /* We do case insensitive comparisons.
56 If that ever becomes a problem, add an attribute that denotes
57 "do case sensitive comparisons". */
59 while (ke != NULL)
61 n = name;
62 p = ke->name;
64 while (*p
65 && (*p == *n
66 || (ISALPHA (*p) && (TOLOWER (*p) == TOLOWER (*n)))))
67 ++n, ++p;
69 if (!*p && !*n)
70 return ke;
72 ke = ke->next_name;
75 if (kt->null_entry)
76 return kt->null_entry;
77 return NULL;
80 /* Look up VALUE in the keyword table KT.
81 The result is the keyword entry or NULL if not found. */
83 const CGEN_KEYWORD_ENTRY *
84 cgen_keyword_lookup_value (CGEN_KEYWORD *kt, int value)
86 const CGEN_KEYWORD_ENTRY *ke;
88 if (kt->name_hash_table == NULL)
89 build_keyword_hash_tables (kt);
91 ke = kt->value_hash_table[hash_keyword_value (kt, value)];
93 while (ke != NULL)
95 if (value == ke->value)
96 return ke;
97 ke = ke->next_value;
100 return NULL;
103 /* Add an entry to a keyword table. */
105 void
106 cgen_keyword_add (CGEN_KEYWORD *kt, CGEN_KEYWORD_ENTRY *ke)
108 unsigned int hash;
109 size_t i;
111 if (kt->name_hash_table == NULL)
112 build_keyword_hash_tables (kt);
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;
118 hash = hash_keyword_value (kt, ke->value);
119 ke->next_value = kt->value_hash_table[hash];
120 kt->value_hash_table[hash] = ke;
122 if (ke->name[0] == 0)
123 kt->null_entry = ke;
125 for (i = 1; i < strlen (ke->name); i++)
126 if (! ISALNUM (ke->name[i])
127 && ! strchr (kt->nonalpha_chars, ke->name[i]))
129 size_t idx = strlen (kt->nonalpha_chars);
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;
141 /* FIXME: Need function to return count of keywords. */
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. */
151 CGEN_KEYWORD_SEARCH
152 cgen_keyword_search_init (CGEN_KEYWORD *kt, const char *spec)
154 CGEN_KEYWORD_SEARCH search;
156 /* FIXME: Need to specify format of params. */
157 if (spec != NULL)
158 abort ();
160 if (kt->name_hash_table == NULL)
161 build_keyword_hash_tables (kt);
163 search.table = kt;
164 search.spec = spec;
165 search.current_hash = 0;
166 search.current_entry = NULL;
167 return search;
170 /* Return the next keyword specified by SEARCH.
171 The result is the next entry or NULL if there are no more. */
173 const CGEN_KEYWORD_ENTRY *
174 cgen_keyword_search_next (CGEN_KEYWORD_SEARCH *search)
176 /* Has search finished? */
177 if (search->current_hash == search->table->hash_table_size)
178 return NULL;
180 /* Search in progress? */
181 if (search->current_entry != NULL
182 /* Anything left on this hash chain? */
183 && search->current_entry->next_name != NULL)
185 search->current_entry = search->current_entry->next_name;
186 return search->current_entry;
189 /* Move to next hash chain [unless we haven't started yet]. */
190 if (search->current_entry != NULL)
191 ++search->current_hash;
193 while (search->current_hash < search->table->hash_table_size)
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;
201 return NULL;
204 /* Return first entry in hash chain for NAME.
205 If CASE_SENSITIVE_P is non-zero, return a case sensitive hash. */
207 static unsigned int
208 hash_keyword_name (const CGEN_KEYWORD *kt,
209 const char *name,
210 int case_sensitive_p)
212 unsigned int hash;
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;
223 /* Return first entry in hash chain for VALUE. */
225 static unsigned int
226 hash_keyword_value (const CGEN_KEYWORD *kt, unsigned int value)
228 return value % kt->hash_table_size;
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. */
235 static void
236 build_keyword_hash_tables (CGEN_KEYWORD *kt)
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);
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 *));
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]);
257 /* Hardware support. */
259 /* Lookup a hardware element by its name.
260 Returns NULL if NAME is not supported by the currently selected
261 mach/isa. */
263 const CGEN_HW_ENTRY *
264 cgen_hw_lookup_by_name (CGEN_CPU_DESC cd, const char *name)
266 unsigned int i;
267 const CGEN_HW_ENTRY **hw = cd->hw_table.entries;
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];
273 return NULL;
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. */
281 const CGEN_HW_ENTRY *
282 cgen_hw_lookup_by_num (CGEN_CPU_DESC cd, unsigned int hwnum)
284 unsigned int i;
285 const CGEN_HW_ENTRY **hw = cd->hw_table.entries;
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];
292 return NULL;
295 /* Operand support. */
297 /* Lookup an operand by its name.
298 Returns NULL if NAME is not supported by the currently selected
299 mach/isa. */
301 const CGEN_OPERAND *
302 cgen_operand_lookup_by_name (CGEN_CPU_DESC cd, const char *name)
304 unsigned int i;
305 const CGEN_OPERAND **op = cd->operand_table.entries;
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];
311 return NULL;
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. */
320 const CGEN_OPERAND *
321 cgen_operand_lookup_by_num (CGEN_CPU_DESC cd, int opnum)
323 return cd->operand_table.entries[opnum];
326 /* Instruction support. */
328 /* Return number of instructions. This includes any added at runtime. */
331 cgen_insn_count (CGEN_CPU_DESC cd)
333 int count = cd->insn_table.num_init_entries;
334 CGEN_INSN_LIST *rt_insns = cd->insn_table.new_entries;
336 for ( ; rt_insns != NULL; rt_insns = rt_insns->next)
337 ++count;
339 return count;
342 /* Return number of macro-instructions.
343 This includes any added at runtime. */
346 cgen_macro_insn_count (CGEN_CPU_DESC cd)
348 int count = cd->macro_insn_table.num_init_entries;
349 CGEN_INSN_LIST *rt_insns = cd->macro_insn_table.new_entries;
351 for ( ; rt_insns != NULL; rt_insns = rt_insns->next)
352 ++count;
354 return count;
357 /* Cover function to read and properly byteswap an insn value. */
359 CGEN_INSN_INT
360 cgen_get_insn_value (CGEN_CPU_DESC cd, unsigned char *buf, int length)
362 int big_p = (cd->insn_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, cd->insn_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)
402 int big_p = (cd->insn_endian == CGEN_ENDIAN_BIG);
403 int insn_chunk_bitsize = cd->insn_chunk_bitsize;
405 if (insn_chunk_bitsize != 0 && insn_chunk_bitsize < length)
407 /* We need to divide up the incoming value into insn_chunk_bitsize-length
408 segments, and endian-convert them, one at a time. */
409 int i;
411 /* Enforce divisibility. */
412 if ((length % insn_chunk_bitsize) != 0)
413 abort ();
415 for (i = 0; i < length; i += insn_chunk_bitsize) /* NB: i == bits */
417 int bit_index;
419 bit_index = (length - insn_chunk_bitsize - i); /* NB: not dependent on endianness! */
420 bfd_put_bits ((bfd_vma) value, & buf[bit_index / 8], insn_chunk_bitsize, big_p);
421 value >>= insn_chunk_bitsize;
424 else
426 bfd_put_bits ((bfd_vma) value, buf, length, big_p);
430 /* Look up instruction INSN_*_VALUE and extract its fields.
431 INSN_INT_VALUE is used if CGEN_INT_INSN_P.
432 Otherwise INSN_BYTES_VALUE is used.
433 INSN, if non-null, is the insn table entry.
434 Otherwise INSN_*_VALUE is examined to compute it.
435 LENGTH is the bit length of INSN_*_VALUE if known, otherwise 0.
436 0 is only valid if `insn == NULL && ! CGEN_INT_INSN_P'.
437 If INSN != NULL, LENGTH must be valid.
438 ALIAS_P is non-zero if alias insns are to be included in the search.
440 The result is a pointer to the insn table entry, or NULL if the instruction
441 wasn't recognized. */
443 /* ??? Will need to be revisited for VLIW architectures. */
445 const CGEN_INSN *
446 cgen_lookup_insn (CGEN_CPU_DESC cd,
447 const CGEN_INSN *insn,
448 CGEN_INSN_INT insn_int_value,
449 /* ??? CGEN_INSN_BYTES would be a nice type name to use here. */
450 unsigned char *insn_bytes_value,
451 int length,
452 CGEN_FIELDS *fields,
453 int alias_p)
455 unsigned char *buf;
456 CGEN_INSN_INT base_insn;
457 CGEN_EXTRACT_INFO ex_info;
458 CGEN_EXTRACT_INFO *info;
460 if (cd->int_insn_p)
462 info = NULL;
463 buf = (unsigned char *) xmalloc (cd->max_insn_bitsize / 8);
464 cgen_put_insn_value (cd, buf, length, insn_int_value);
465 base_insn = insn_int_value;
466 free (buf);
468 else
470 info = &ex_info;
471 ex_info.dis_info = NULL;
472 ex_info.insn_bytes = insn_bytes_value;
473 ex_info.valid = -1;
474 buf = insn_bytes_value;
475 base_insn = cgen_get_insn_value (cd, buf, length);
478 if (!insn)
480 const CGEN_INSN_LIST *insn_list;
482 /* The instructions are stored in hash lists.
483 Pick the first one and keep trying until we find the right one. */
485 insn_list = cgen_dis_lookup_insn (cd, (char *) buf, base_insn);
486 while (insn_list != NULL)
488 insn = insn_list->insn;
490 if (alias_p
491 /* FIXME: Ensure ALIAS attribute always has same index. */
492 || ! CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_ALIAS))
494 /* Basic bit mask must be correct. */
495 /* ??? May wish to allow target to defer this check until the
496 extract handler. */
497 if ((base_insn & CGEN_INSN_BASE_MASK (insn))
498 == CGEN_INSN_BASE_VALUE (insn))
500 /* ??? 0 is passed for `pc' */
501 int elength = CGEN_EXTRACT_FN (cd, insn)
502 (cd, insn, info, base_insn, fields, (bfd_vma) 0);
503 if (elength > 0)
505 /* sanity check */
506 if (length != 0 && length != elength)
507 abort ();
508 return insn;
513 insn_list = insn_list->next;
516 else
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 ();
526 /* ??? 0 is passed for `pc' */
527 length = CGEN_EXTRACT_FN (cd, insn)
528 (cd, insn, info, base_insn, 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 return insn;
536 return NULL;
539 /* Fill in the operand instances used by INSN whose operands are FIELDS.
540 INDICES is a pointer to a buffer of MAX_OPERAND_INSTANCES ints to be filled
541 in. */
543 void
544 cgen_get_insn_operands (CGEN_CPU_DESC cd,
545 const CGEN_INSN *insn,
546 const CGEN_FIELDS *fields,
547 int *indices)
549 const CGEN_OPINST *opinst;
550 int i;
552 if (insn->opinst == NULL)
553 abort ();
554 for (i = 0, opinst = insn->opinst; opinst->type != CGEN_OPINST_END; ++i, ++opinst)
556 enum cgen_operand_type op_type = opinst->op_type;
557 if (op_type == CGEN_OPERAND_NIL)
558 indices[i] = opinst->index;
559 else
560 indices[i] = (*cd->get_int_operand) (cd, op_type, fields);
564 /* Cover function to cgen_get_insn_operands when either INSN or FIELDS
565 isn't known.
566 The INSN, INSN_*_VALUE, and LENGTH arguments are passed to
567 cgen_lookup_insn unchanged.
568 INSN_INT_VALUE is used if CGEN_INT_INSN_P.
569 Otherwise INSN_BYTES_VALUE is used.
571 The result is the insn table entry or NULL if the instruction wasn't
572 recognized. */
574 const CGEN_INSN *
575 cgen_lookup_get_insn_operands (CGEN_CPU_DESC cd,
576 const CGEN_INSN *insn,
577 CGEN_INSN_INT insn_int_value,
578 /* ??? CGEN_INSN_BYTES would be a nice type name to use here. */
579 unsigned char *insn_bytes_value,
580 int length,
581 int *indices,
582 CGEN_FIELDS *fields)
584 /* Pass non-zero for ALIAS_P only if INSN != NULL.
585 If INSN == NULL, we want a real insn. */
586 insn = cgen_lookup_insn (cd, insn, insn_int_value, insn_bytes_value,
587 length, fields, insn != NULL);
588 if (! insn)
589 return NULL;
591 cgen_get_insn_operands (cd, insn, fields, indices);
592 return insn;
595 /* Allow signed overflow of instruction fields. */
596 void
597 cgen_set_signed_overflow_ok (CGEN_CPU_DESC cd)
599 cd->signed_overflow_ok_p = 1;
602 /* Generate an error message if a signed field in an instruction overflows. */
603 void
604 cgen_clear_signed_overflow_ok (CGEN_CPU_DESC cd)
606 cd->signed_overflow_ok_p = 0;
609 /* Will an error message be generated if a signed field in an instruction overflows ? */
610 unsigned int
611 cgen_signed_overflow_ok_p (CGEN_CPU_DESC cd)
613 return cd->signed_overflow_ok_p;