1 /* CGEN generic opcode support.
3 Copyright 1996, 1997, 1998, 1999, 2000, 2001
4 Free Software Foundation, Inc.
6 This file is part of the GNU Binutils and GDB, the GNU debugger.
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)
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.
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. */
26 #include "libiberty.h"
29 #include "opcode/cgen.h"
35 static unsigned int hash_keyword_name
36 PARAMS ((const CGEN_KEYWORD
*, const char *, int));
37 static unsigned int hash_keyword_value
38 PARAMS ((const CGEN_KEYWORD
*, unsigned int));
39 static void build_keyword_hash_tables
40 PARAMS ((CGEN_KEYWORD
*));
42 /* Return number of hash table entries to use for N elements. */
43 #define KEYWORD_HASH_SIZE(n) ((n) <= 31 ? 17 : 31)
45 /* Look up *NAMEP in the keyword table KT.
46 The result is the keyword entry or NULL if not found. */
48 const CGEN_KEYWORD_ENTRY
*
49 cgen_keyword_lookup_name (kt
, name
)
53 const CGEN_KEYWORD_ENTRY
*ke
;
56 if (kt
->name_hash_table
== NULL
)
57 build_keyword_hash_tables (kt
);
59 ke
= kt
->name_hash_table
[hash_keyword_name (kt
, name
, 0)];
61 /* We do case insensitive comparisons.
62 If that ever becomes a problem, add an attribute that denotes
63 "do case sensitive comparisons". */
72 || (isalpha ((unsigned char) *p
)
73 && (tolower ((unsigned char) *p
)
74 == tolower ((unsigned char) *n
)))))
84 return kt
->null_entry
;
88 /* Look up VALUE in the keyword table KT.
89 The result is the keyword entry or NULL if not found. */
91 const CGEN_KEYWORD_ENTRY
*
92 cgen_keyword_lookup_value (kt
, value
)
96 const CGEN_KEYWORD_ENTRY
*ke
;
98 if (kt
->name_hash_table
== NULL
)
99 build_keyword_hash_tables (kt
);
101 ke
= kt
->value_hash_table
[hash_keyword_value (kt
, value
)];
105 if (value
== ke
->value
)
113 /* Add an entry to a keyword table. */
116 cgen_keyword_add (kt
, ke
)
118 CGEN_KEYWORD_ENTRY
*ke
;
122 if (kt
->name_hash_table
== NULL
)
123 build_keyword_hash_tables (kt
);
125 hash
= hash_keyword_name (kt
, ke
->name
, 0);
126 ke
->next_name
= kt
->name_hash_table
[hash
];
127 kt
->name_hash_table
[hash
] = ke
;
129 hash
= hash_keyword_value (kt
, ke
->value
);
130 ke
->next_value
= kt
->value_hash_table
[hash
];
131 kt
->value_hash_table
[hash
] = ke
;
133 if (ke
->name
[0] == 0)
137 /* FIXME: Need function to return count of keywords. */
139 /* Initialize a keyword table search.
140 SPEC is a specification of what to search for.
141 A value of NULL means to find every keyword.
142 Currently NULL is the only acceptable value [further specification
144 The result is an opaque data item used to record the search status.
145 It is passed to each call to cgen_keyword_search_next. */
148 cgen_keyword_search_init (kt
, spec
)
152 CGEN_KEYWORD_SEARCH search
;
154 /* FIXME: Need to specify format of PARAMS. */
158 if (kt
->name_hash_table
== NULL
)
159 build_keyword_hash_tables (kt
);
163 search
.current_hash
= 0;
164 search
.current_entry
= NULL
;
168 /* Return the next keyword specified by SEARCH.
169 The result is the next entry or NULL if there are no more. */
171 const CGEN_KEYWORD_ENTRY
*
172 cgen_keyword_search_next (search
)
173 CGEN_KEYWORD_SEARCH
*search
;
175 /* Has search finished? */
176 if (search
->current_hash
== search
->table
->hash_table_size
)
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
;
203 /* Return first entry in hash chain for NAME.
204 If CASE_SENSITIVE_P is non-zero, return a case sensitive hash. */
207 hash_keyword_name (kt
, name
, case_sensitive_p
)
208 const CGEN_KEYWORD
*kt
;
210 int case_sensitive_p
;
214 if (case_sensitive_p
)
215 for (hash
= 0; *name
; ++name
)
216 hash
= (hash
* 97) + (unsigned char) *name
;
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. */
226 hash_keyword_value (kt
, value
)
227 const CGEN_KEYWORD
*kt
;
230 return value
% kt
->hash_table_size
;
233 /* Build a keyword table's hash tables.
234 We probably needn't build the value hash table for the assembler when
235 we're using the disassembler, but we keep things simple. */
238 build_keyword_hash_tables (kt
)
242 /* Use the number of compiled in entries as an estimate for the
243 typical sized table [not too many added at runtime]. */
244 unsigned int size
= KEYWORD_HASH_SIZE (kt
->num_init_entries
);
246 kt
->hash_table_size
= size
;
247 kt
->name_hash_table
= (CGEN_KEYWORD_ENTRY
**)
248 xmalloc (size
* sizeof (CGEN_KEYWORD_ENTRY
*));
249 memset (kt
->name_hash_table
, 0, size
* sizeof (CGEN_KEYWORD_ENTRY
*));
250 kt
->value_hash_table
= (CGEN_KEYWORD_ENTRY
**)
251 xmalloc (size
* sizeof (CGEN_KEYWORD_ENTRY
*));
252 memset (kt
->value_hash_table
, 0, size
* sizeof (CGEN_KEYWORD_ENTRY
*));
254 /* The table is scanned backwards as we want keywords appearing earlier to
255 be prefered over later ones. */
256 for (i
= kt
->num_init_entries
- 1; i
>= 0; --i
)
257 cgen_keyword_add (kt
, &kt
->init_entries
[i
]);
260 /* Hardware support. */
262 /* Lookup a hardware element by its name.
263 Returns NULL if NAME is not supported by the currently selected
266 const CGEN_HW_ENTRY
*
267 cgen_hw_lookup_by_name (cd
, name
)
272 const CGEN_HW_ENTRY
**hw
= cd
->hw_table
.entries
;
274 for (i
= 0; i
< cd
->hw_table
.num_entries
; ++i
)
275 if (hw
[i
] && strcmp (name
, hw
[i
]->name
) == 0)
281 /* Lookup a hardware element by its number.
282 Hardware elements are enumerated, however it may be possible to add some
283 at runtime, thus HWNUM is not an enum type but rather an int.
284 Returns NULL if HWNUM is not supported by the currently selected mach. */
286 const CGEN_HW_ENTRY
*
287 cgen_hw_lookup_by_num (cd
, hwnum
)
292 const CGEN_HW_ENTRY
**hw
= cd
->hw_table
.entries
;
294 /* ??? This can be speeded up. */
295 for (i
= 0; i
< cd
->hw_table
.num_entries
; ++i
)
296 if (hw
[i
] && hwnum
== hw
[i
]->type
)
302 /* Operand support. */
304 /* Lookup an operand by its name.
305 Returns NULL if NAME is not supported by the currently selected
309 cgen_operand_lookup_by_name (cd
, name
)
314 const CGEN_OPERAND
**op
= cd
->operand_table
.entries
;
316 for (i
= 0; i
< cd
->operand_table
.num_entries
; ++i
)
317 if (op
[i
] && strcmp (name
, op
[i
]->name
) == 0)
323 /* Lookup an operand by its number.
324 Operands are enumerated, however it may be possible to add some
325 at runtime, thus OPNUM is not an enum type but rather an int.
326 Returns NULL if OPNUM is not supported by the currently selected
330 cgen_operand_lookup_by_num (cd
, opnum
)
334 return cd
->operand_table
.entries
[opnum
];
337 /* Instruction support. */
339 /* Return number of instructions. This includes any added at runtime. */
345 int count
= cd
->insn_table
.num_init_entries
;
346 CGEN_INSN_LIST
*rt_insns
= cd
->insn_table
.new_entries
;
348 for ( ; rt_insns
!= NULL
; rt_insns
= rt_insns
->next
)
354 /* Return number of macro-instructions.
355 This includes any added at runtime. */
358 cgen_macro_insn_count (cd
)
361 int count
= cd
->macro_insn_table
.num_init_entries
;
362 CGEN_INSN_LIST
*rt_insns
= cd
->macro_insn_table
.new_entries
;
364 for ( ; rt_insns
!= NULL
; rt_insns
= rt_insns
->next
)
370 /* Cover function to read and properly byteswap an insn value. */
373 cgen_get_insn_value (cd
, buf
, length
)
378 return bfd_get_bits (buf
, length
, cd
->insn_endian
== CGEN_ENDIAN_BIG
);
381 /* Cover function to store an insn value properly byteswapped. */
384 cgen_put_insn_value (cd
, buf
, length
, value
)
390 bfd_put_bits ((bfd_vma
) value
, buf
, length
,
391 cd
->insn_endian
== CGEN_ENDIAN_BIG
);
394 /* Look up instruction INSN_*_VALUE and extract its fields.
395 INSN_INT_VALUE is used if CGEN_INT_INSN_P.
396 Otherwise INSN_BYTES_VALUE is used.
397 INSN, if non-null, is the insn table entry.
398 Otherwise INSN_*_VALUE is examined to compute it.
399 LENGTH is the bit length of INSN_*_VALUE if known, otherwise 0.
400 0 is only valid if `insn == NULL && ! CGEN_INT_INSN_P'.
401 If INSN != NULL, LENGTH must be valid.
402 ALIAS_P is non-zero if alias insns are to be included in the search.
404 The result is a pointer to the insn table entry, or NULL if the instruction
405 wasn't recognized. */
407 /* ??? Will need to be revisited for VLIW architectures. */
410 cgen_lookup_insn (cd
, insn
, insn_int_value
, insn_bytes_value
, length
, fields
,
413 const CGEN_INSN
*insn
;
414 CGEN_INSN_INT insn_int_value
;
415 /* ??? CGEN_INSN_BYTES would be a nice type name to use here. */
416 unsigned char *insn_bytes_value
;
422 CGEN_INSN_INT base_insn
;
423 CGEN_EXTRACT_INFO ex_info
;
424 CGEN_EXTRACT_INFO
*info
;
429 buf
= (unsigned char *) alloca (cd
->max_insn_bitsize
/ 8);
430 cgen_put_insn_value (cd
, buf
, length
, insn_int_value
);
431 base_insn
= insn_int_value
;
436 ex_info
.dis_info
= NULL
;
437 ex_info
.insn_bytes
= insn_bytes_value
;
439 buf
= insn_bytes_value
;
440 base_insn
= cgen_get_insn_value (cd
, buf
, length
);
445 const CGEN_INSN_LIST
*insn_list
;
447 /* The instructions are stored in hash lists.
448 Pick the first one and keep trying until we find the right one. */
450 insn_list
= cgen_dis_lookup_insn (cd
, buf
, base_insn
);
451 while (insn_list
!= NULL
)
453 insn
= insn_list
->insn
;
456 /* FIXME: Ensure ALIAS attribute always has same index. */
457 || ! CGEN_INSN_ATTR_VALUE (insn
, CGEN_INSN_ALIAS
))
459 /* Basic bit mask must be correct. */
460 /* ??? May wish to allow target to defer this check until the
462 if ((base_insn
& CGEN_INSN_BASE_MASK (insn
))
463 == CGEN_INSN_BASE_VALUE (insn
))
465 /* ??? 0 is passed for `pc' */
466 int elength
= CGEN_EXTRACT_FN (cd
, insn
)
467 (cd
, insn
, info
, base_insn
, fields
, (bfd_vma
) 0);
471 if (length
!= 0 && length
!= elength
)
478 insn_list
= insn_list
->next
;
483 /* Sanity check: can't pass an alias insn if ! alias_p. */
485 && CGEN_INSN_ATTR_VALUE (insn
, CGEN_INSN_ALIAS
))
487 /* Sanity check: length must be correct. */
488 if (length
!= CGEN_INSN_BITSIZE (insn
))
491 /* ??? 0 is passed for `pc' */
492 length
= CGEN_EXTRACT_FN (cd
, insn
)
493 (cd
, insn
, info
, base_insn
, fields
, (bfd_vma
) 0);
494 /* Sanity check: must succeed.
495 Could relax this later if it ever proves useful. */
504 /* Fill in the operand instances used by INSN whose operands are FIELDS.
505 INDICES is a pointer to a buffer of MAX_OPERAND_INSTANCES ints to be filled
509 cgen_get_insn_operands (cd
, insn
, fields
, indices
)
511 const CGEN_INSN
*insn
;
512 const CGEN_FIELDS
*fields
;
515 const CGEN_OPINST
*opinst
;
518 if (insn
->opinst
== NULL
)
520 for (i
= 0, opinst
= insn
->opinst
; opinst
->type
!= CGEN_OPINST_END
; ++i
, ++opinst
)
522 enum cgen_operand_type op_type
= opinst
->op_type
;
523 if (op_type
== CGEN_OPERAND_NIL
)
524 indices
[i
] = opinst
->index
;
526 indices
[i
] = (*cd
->get_int_operand
) (cd
, op_type
, fields
);
530 /* Cover function to cgen_get_insn_operands when either INSN or FIELDS
532 The INSN, INSN_*_VALUE, and LENGTH arguments are passed to
533 cgen_lookup_insn unchanged.
534 INSN_INT_VALUE is used if CGEN_INT_INSN_P.
535 Otherwise INSN_BYTES_VALUE is used.
537 The result is the insn table entry or NULL if the instruction wasn't
541 cgen_lookup_get_insn_operands (cd
, insn
, insn_int_value
, insn_bytes_value
,
542 length
, indices
, fields
)
544 const CGEN_INSN
*insn
;
545 CGEN_INSN_INT insn_int_value
;
546 /* ??? CGEN_INSN_BYTES would be a nice type name to use here. */
547 unsigned char *insn_bytes_value
;
552 /* Pass non-zero for ALIAS_P only if INSN != NULL.
553 If INSN == NULL, we want a real insn. */
554 insn
= cgen_lookup_insn (cd
, insn
, insn_int_value
, insn_bytes_value
,
555 length
, fields
, insn
!= NULL
);
559 cgen_get_insn_operands (cd
, insn
, fields
, indices
);
563 /* Allow signed overflow of instruction fields. */
565 cgen_set_signed_overflow_ok (cd
)
568 cd
->signed_overflow_ok_p
= 1;
571 /* Generate an error message if a signed field in an instruction overflows. */
573 cgen_clear_signed_overflow_ok (cd
)
576 cd
->signed_overflow_ok_p
= 0;
579 /* Will an error message be generated if a signed field in an instruction overflows ? */
581 cgen_signed_overflow_ok_p (cd
)
584 return cd
->signed_overflow_ok_p
;