source: trunk/src/binutils/opcodes/cgen-opc.c@ 887

Last change on this file since 887 was 610, checked in by bird, 22 years ago

This commit was generated by cvs2svn to compensate for changes in r609,
which included commits to RCS files with non-trunk default branches.

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