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