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