1 /* CGEN generic opcode support.
3 Copyright (C) 1996, 1997, 1998 Free Software Foundation, Inc.
5 This file is part of the GNU Binutils and GDB, the GNU debugger.
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)
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.
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. */
25 #include "libiberty.h"
28 #include "opcode/cgen.h"
31 These record the state of the currently selected cpu, machine, endian, etc.
32 They are set by cgen_set_cpu. */
34 /* Current opcode data. */
35 const CGEN_OPCODE_TABLE
*cgen_current_opcode_table
;
37 /* Current machine (a la BFD machine number). */
38 int cgen_current_mach
;
41 enum cgen_endian cgen_current_endian
= CGEN_ENDIAN_UNKNOWN
;
43 /* FIXME: To support multiple architectures, we need to return a handle
44 to the state set up by this function, and pass the handle back to the
45 other functions. Later. */
48 cgen_set_cpu (table
, mach
, endian
)
49 const CGEN_OPCODE_TABLE
* table
;
51 enum cgen_endian endian
;
53 static int init_once_p
;
55 cgen_current_opcode_table
= table
;
56 cgen_current_mach
= mach
;
57 cgen_current_endian
= endian
;
59 /* Initialize those things that only need be done once. */
62 /* Nothing to do currently. */
66 #if 0 /* This isn't done here because it would put assembler support in the
67 disassembler, etc. The caller is required to call these after calling
69 /* Reset the hash tables. */
75 static unsigned int hash_keyword_name
76 PARAMS ((const CGEN_KEYWORD
*, const char *, int));
77 static unsigned int hash_keyword_value
78 PARAMS ((const CGEN_KEYWORD
*, unsigned int));
79 static void build_keyword_hash_tables
80 PARAMS ((CGEN_KEYWORD
*));
82 /* Return number of hash table entries to use for N elements. */
83 #define KEYWORD_HASH_SIZE(n) ((n) <= 31 ? 17 : 31)
85 /* Look up *NAMEP in the keyword table KT.
86 The result is the keyword entry or NULL if not found. */
88 const CGEN_KEYWORD_ENTRY
*
89 cgen_keyword_lookup_name (kt
, name
)
93 const CGEN_KEYWORD_ENTRY
*ke
;
96 if (kt
->name_hash_table
== NULL
)
97 build_keyword_hash_tables (kt
);
99 ke
= kt
->name_hash_table
[hash_keyword_name (kt
, name
, 0)];
101 /* We do case insensitive comparisons.
102 If that ever becomes a problem, add an attribute that denotes
103 "do case sensitive comparisons". */
112 || (isalpha ((unsigned char) *p
)
113 && (tolower ((unsigned char) *p
)
114 == tolower ((unsigned char) *n
)))))
124 return kt
->null_entry
;
128 /* Look up VALUE in the keyword table KT.
129 The result is the keyword entry or NULL if not found. */
131 const CGEN_KEYWORD_ENTRY
*
132 cgen_keyword_lookup_value (kt
, value
)
136 const CGEN_KEYWORD_ENTRY
*ke
;
138 if (kt
->name_hash_table
== NULL
)
139 build_keyword_hash_tables (kt
);
141 ke
= kt
->value_hash_table
[hash_keyword_value (kt
, value
)];
145 if (value
== ke
->value
)
153 /* Add an entry to a keyword table. */
156 cgen_keyword_add (kt
, ke
)
158 CGEN_KEYWORD_ENTRY
*ke
;
162 if (kt
->name_hash_table
== NULL
)
163 build_keyword_hash_tables (kt
);
165 hash
= hash_keyword_name (kt
, ke
->name
, 0);
166 ke
->next_name
= kt
->name_hash_table
[hash
];
167 kt
->name_hash_table
[hash
] = ke
;
169 hash
= hash_keyword_value (kt
, ke
->value
);
170 ke
->next_value
= kt
->value_hash_table
[hash
];
171 kt
->value_hash_table
[hash
] = ke
;
173 if (ke
->name
[0] == 0)
177 /* FIXME: Need function to return count of keywords. */
179 /* Initialize a keyword table search.
180 SPEC is a specification of what to search for.
181 A value of NULL means to find every keyword.
182 Currently NULL is the only acceptable value [further specification
184 The result is an opaque data item used to record the search status.
185 It is passed to each call to cgen_keyword_search_next. */
188 cgen_keyword_search_init (kt
, spec
)
192 CGEN_KEYWORD_SEARCH search
;
194 /* FIXME: Need to specify format of PARAMS. */
198 if (kt
->name_hash_table
== NULL
)
199 build_keyword_hash_tables (kt
);
203 search
.current_hash
= 0;
204 search
.current_entry
= NULL
;
208 /* Return the next keyword specified by SEARCH.
209 The result is the next entry or NULL if there are no more. */
211 const CGEN_KEYWORD_ENTRY
*
212 cgen_keyword_search_next (search
)
213 CGEN_KEYWORD_SEARCH
*search
;
215 /* Has search finished? */
216 if (search
->current_hash
== search
->table
->hash_table_size
)
219 /* Search in progress? */
220 if (search
->current_entry
!= NULL
221 /* Anything left on this hash chain? */
222 && search
->current_entry
->next_name
!= NULL
)
224 search
->current_entry
= search
->current_entry
->next_name
;
225 return search
->current_entry
;
228 /* Move to next hash chain [unless we haven't started yet]. */
229 if (search
->current_entry
!= NULL
)
230 ++search
->current_hash
;
232 while (search
->current_hash
< search
->table
->hash_table_size
)
234 search
->current_entry
= search
->table
->name_hash_table
[search
->current_hash
];
235 if (search
->current_entry
!= NULL
)
236 return search
->current_entry
;
237 ++search
->current_hash
;
243 /* Return first entry in hash chain for NAME.
244 If CASE_SENSITIVE_P is non-zero, return a case sensitive hash. */
247 hash_keyword_name (kt
, name
, case_sensitive_p
)
248 const CGEN_KEYWORD
*kt
;
250 int case_sensitive_p
;
254 if (case_sensitive_p
)
255 for (hash
= 0; *name
; ++name
)
256 hash
= (hash
* 97) + (unsigned char) *name
;
258 for (hash
= 0; *name
; ++name
)
259 hash
= (hash
* 97) + (unsigned char) tolower (*name
);
260 return hash
% kt
->hash_table_size
;
263 /* Return first entry in hash chain for VALUE. */
266 hash_keyword_value (kt
, value
)
267 const CGEN_KEYWORD
*kt
;
270 return value
% kt
->hash_table_size
;
273 /* Build a keyword table's hash tables.
274 We probably needn't build the value hash table for the assembler when
275 we're using the disassembler, but we keep things simple. */
278 build_keyword_hash_tables (kt
)
282 /* Use the number of compiled in entries as an estimate for the
283 typical sized table [not too many added at runtime]. */
284 unsigned int size
= KEYWORD_HASH_SIZE (kt
->num_init_entries
);
286 kt
->hash_table_size
= size
;
287 kt
->name_hash_table
= (CGEN_KEYWORD_ENTRY
**)
288 xmalloc (size
* sizeof (CGEN_KEYWORD_ENTRY
*));
289 memset (kt
->name_hash_table
, 0, size
* sizeof (CGEN_KEYWORD_ENTRY
*));
290 kt
->value_hash_table
= (CGEN_KEYWORD_ENTRY
**)
291 xmalloc (size
* sizeof (CGEN_KEYWORD_ENTRY
*));
292 memset (kt
->value_hash_table
, 0, size
* sizeof (CGEN_KEYWORD_ENTRY
*));
294 /* The table is scanned backwards as we want keywords appearing earlier to
295 be prefered over later ones. */
296 for (i
= kt
->num_init_entries
- 1; i
>= 0; --i
)
297 cgen_keyword_add (kt
, &kt
->init_entries
[i
]);
300 /* Hardware support. */
302 /* Lookup a hardware element by its name. */
304 const CGEN_HW_ENTRY
*
305 cgen_hw_lookup_by_name (name
)
308 const CGEN_HW_ENTRY
* hw
= cgen_current_opcode_table
->hw_list
;
312 if (strcmp (name
, hw
->name
) == 0)
320 /* Lookup a hardware element by its enum.
321 Hardware elements are enumerated, however it may be possible to add some
322 at runtime, thus HWNUM is not an enum type but rather an int. */
324 const CGEN_HW_ENTRY
*
325 cgen_hw_lookup_by_enum (hwnum
)
328 const CGEN_HW_ENTRY
* hw
= cgen_current_opcode_table
->hw_list
;
330 /* ??? This can be speeded up if we first make a guess into
331 the compiled in table. */
334 if (hwnum
== hw
->type
)
340 /* Instruction support. */
342 /* Return number of instructions. This includes any added at runtime. */
347 int count
= cgen_current_opcode_table
->insn_table
->num_init_entries
;
348 CGEN_INSN_LIST
* insn
= cgen_current_opcode_table
->insn_table
->new_entries
;
350 for ( ; insn
!= NULL
; insn
= insn
->next
)
356 /* Return number of macro-instructions. This includes any added at runtime. */
359 cgen_macro_insn_count ()
361 int count
= cgen_current_opcode_table
->macro_insn_table
->num_init_entries
;
362 CGEN_INSN_LIST
* insn
= cgen_current_opcode_table
->macro_insn_table
->new_entries
;
364 for ( ; insn
!= NULL
; insn
= insn
->next
)