* cgen-asm.in (insert_normal): Handle empty fields and 64 bit hosts.
[deliverable/binutils-gdb.git] / opcodes / cgen-opc.c
CommitLineData
9c03036a
DE
1/* CGEN generic opcode support.
2
9a6c492c 3 Copyright (C) 1996, 1997, 1998 Free Software Foundation, Inc.
9c03036a 4
9a6c492c 5 This file is part of the GNU Binutils and GDB, the GNU debugger.
9c03036a 6
9a6c492c
DE
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.
9c03036a 11
9a6c492c
DE
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.
9c03036a 16
9a6c492c
DE
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. */
9c03036a 20
9a6c492c
DE
21#include "sysdep.h"
22#include <ctype.h>
9c03036a 23#include <stdio.h>
9c03036a
DE
24#include "ansidecl.h"
25#include "libiberty.h"
26#include "bfd.h"
9a6c492c 27#include "symcat.h"
9c03036a
DE
28#include "opcode/cgen.h"
29
30/* State variables.
31 These record the state of the currently selected cpu, machine, endian, etc.
32 They are set by cgen_set_cpu. */
33
34/* Current opcode data. */
9a6c492c 35const CGEN_OPCODE_TABLE *cgen_current_opcode_table;
9c03036a
DE
36
37/* Current machine (a la BFD machine number). */
38int cgen_current_mach;
39
40/* Current endian. */
41enum cgen_endian cgen_current_endian = CGEN_ENDIAN_UNKNOWN;
42
9a6c492c
DE
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. */
46
9c03036a 47void
9a6c492c
DE
48cgen_set_cpu (table, mach, endian)
49 const CGEN_OPCODE_TABLE * table;
9c03036a
DE
50 int mach;
51 enum cgen_endian endian;
52{
9a6c492c
DE
53 static int init_once_p;
54
55 cgen_current_opcode_table = table;
9c03036a
DE
56 cgen_current_mach = mach;
57 cgen_current_endian = endian;
58
9a6c492c
DE
59 /* Initialize those things that only need be done once. */
60 if (! init_once_p)
61 {
62 /* Nothing to do currently. */
63 init_once_p = 1;
64 }
65
9c03036a
DE
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
68 us. */
69 /* Reset the hash tables. */
70 cgen_asm_init ();
71 cgen_dis_init ();
9a6c492c 72#endif
9c03036a
DE
73}
74\f
75static unsigned int hash_keyword_name
9a6c492c 76 PARAMS ((const CGEN_KEYWORD *, const char *, int));
9c03036a 77static unsigned int hash_keyword_value
9a6c492c 78 PARAMS ((const CGEN_KEYWORD *, unsigned int));
9c03036a 79static void build_keyword_hash_tables
9a6c492c 80 PARAMS ((CGEN_KEYWORD *));
9c03036a
DE
81
82/* Return number of hash table entries to use for N elements. */
83#define KEYWORD_HASH_SIZE(n) ((n) <= 31 ? 17 : 31)
84
85/* Look up *NAMEP in the keyword table KT.
86 The result is the keyword entry or NULL if not found. */
87
9a6c492c 88const CGEN_KEYWORD_ENTRY *
9c03036a 89cgen_keyword_lookup_name (kt, name)
9a6c492c 90 CGEN_KEYWORD *kt;
9c03036a
DE
91 const char *name;
92{
9a6c492c 93 const CGEN_KEYWORD_ENTRY *ke;
9c03036a
DE
94 const char *p,*n;
95
96 if (kt->name_hash_table == NULL)
97 build_keyword_hash_tables (kt);
98
9a6c492c 99 ke = kt->name_hash_table[hash_keyword_name (kt, name, 0)];
9c03036a
DE
100
101 /* We do case insensitive comparisons.
102 If that ever becomes a problem, add an attribute that denotes
103 "do case sensitive comparisons". */
104
105 while (ke != NULL)
106 {
107 n = name;
108 p = ke->name;
109
110 while (*p
111 && (*p == *n
9a6c492c
DE
112 || (isalpha ((unsigned char) *p)
113 && (tolower ((unsigned char) *p)
114 == tolower ((unsigned char) *n)))))
9c03036a
DE
115 ++n, ++p;
116
117 if (!*p && !*n)
118 return ke;
119
120 ke = ke->next_name;
121 }
122
9a6c492c
DE
123 if (kt->null_entry)
124 return kt->null_entry;
9c03036a
DE
125 return NULL;
126}
127
128/* Look up VALUE in the keyword table KT.
129 The result is the keyword entry or NULL if not found. */
130
9a6c492c 131const CGEN_KEYWORD_ENTRY *
9c03036a 132cgen_keyword_lookup_value (kt, value)
9a6c492c 133 CGEN_KEYWORD *kt;
9c03036a
DE
134 int value;
135{
9a6c492c 136 const CGEN_KEYWORD_ENTRY *ke;
9c03036a
DE
137
138 if (kt->name_hash_table == NULL)
139 build_keyword_hash_tables (kt);
140
141 ke = kt->value_hash_table[hash_keyword_value (kt, value)];
142
143 while (ke != NULL)
144 {
145 if (value == ke->value)
146 return ke;
147 ke = ke->next_value;
148 }
149
150 return NULL;
151}
152
153/* Add an entry to a keyword table. */
154
155void
156cgen_keyword_add (kt, ke)
9a6c492c
DE
157 CGEN_KEYWORD *kt;
158 CGEN_KEYWORD_ENTRY *ke;
9c03036a
DE
159{
160 unsigned int hash;
161
162 if (kt->name_hash_table == NULL)
163 build_keyword_hash_tables (kt);
164
9a6c492c 165 hash = hash_keyword_name (kt, ke->name, 0);
9c03036a
DE
166 ke->next_name = kt->name_hash_table[hash];
167 kt->name_hash_table[hash] = ke;
168
169 hash = hash_keyword_value (kt, ke->value);
170 ke->next_value = kt->value_hash_table[hash];
171 kt->value_hash_table[hash] = ke;
9a6c492c
DE
172
173 if (ke->name[0] == 0)
174 kt->null_entry = ke;
9c03036a
DE
175}
176
177/* FIXME: Need function to return count of keywords. */
178
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
183 deferred].
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. */
186
9a6c492c 187CGEN_KEYWORD_SEARCH
9c03036a 188cgen_keyword_search_init (kt, spec)
9a6c492c 189 CGEN_KEYWORD *kt;
9c03036a
DE
190 const char *spec;
191{
9a6c492c 192 CGEN_KEYWORD_SEARCH search;
9c03036a
DE
193
194 /* FIXME: Need to specify format of PARAMS. */
195 if (spec != NULL)
196 abort ();
197
198 if (kt->name_hash_table == NULL)
199 build_keyword_hash_tables (kt);
200
201 search.table = kt;
202 search.spec = spec;
203 search.current_hash = 0;
204 search.current_entry = NULL;
205 return search;
206}
207
208/* Return the next keyword specified by SEARCH.
209 The result is the next entry or NULL if there are no more. */
210
9a6c492c 211const CGEN_KEYWORD_ENTRY *
9c03036a 212cgen_keyword_search_next (search)
9a6c492c 213 CGEN_KEYWORD_SEARCH *search;
9c03036a 214{
9c03036a
DE
215 /* Has search finished? */
216 if (search->current_hash == search->table->hash_table_size)
217 return NULL;
218
219 /* Search in progress? */
220 if (search->current_entry != NULL
221 /* Anything left on this hash chain? */
222 && search->current_entry->next_name != NULL)
223 {
224 search->current_entry = search->current_entry->next_name;
225 return search->current_entry;
226 }
227
228 /* Move to next hash chain [unless we haven't started yet]. */
229 if (search->current_entry != NULL)
230 ++search->current_hash;
231
232 while (search->current_hash < search->table->hash_table_size)
233 {
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;
238 }
239
240 return NULL;
241}
242
9a6c492c
DE
243/* Return first entry in hash chain for NAME.
244 If CASE_SENSITIVE_P is non-zero, return a case sensitive hash. */
9c03036a
DE
245
246static unsigned int
9a6c492c
DE
247hash_keyword_name (kt, name, case_sensitive_p)
248 const CGEN_KEYWORD *kt;
9c03036a 249 const char *name;
9a6c492c 250 int case_sensitive_p;
9c03036a
DE
251{
252 unsigned int hash;
253
9a6c492c
DE
254 if (case_sensitive_p)
255 for (hash = 0; *name; ++name)
256 hash = (hash * 97) + (unsigned char) *name;
257 else
258 for (hash = 0; *name; ++name)
259 hash = (hash * 97) + (unsigned char) tolower (*name);
9c03036a
DE
260 return hash % kt->hash_table_size;
261}
262
263/* Return first entry in hash chain for VALUE. */
264
265static unsigned int
266hash_keyword_value (kt, value)
9a6c492c
DE
267 const CGEN_KEYWORD *kt;
268 unsigned int value;
9c03036a
DE
269{
270 return value % kt->hash_table_size;
271}
272
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. */
276
277static void
278build_keyword_hash_tables (kt)
9a6c492c 279 CGEN_KEYWORD *kt;
9c03036a
DE
280{
281 int i;
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);
285
286 kt->hash_table_size = size;
9a6c492c
DE
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 *));
9c03036a
DE
293
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]);
298}
299\f
300/* Hardware support. */
301
9a6c492c
DE
302/* Lookup a hardware element by its name. */
303
304const CGEN_HW_ENTRY *
305cgen_hw_lookup_by_name (name)
9c03036a
DE
306 const char *name;
307{
9a6c492c 308 const CGEN_HW_ENTRY * hw = cgen_current_opcode_table->hw_list;
9c03036a
DE
309
310 while (hw != NULL)
311 {
312 if (strcmp (name, hw->name) == 0)
313 return hw;
314 hw = hw->next;
315 }
316
317 return NULL;
318}
9a6c492c
DE
319
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. */
323
324const CGEN_HW_ENTRY *
325cgen_hw_lookup_by_enum (hwnum)
326 int hwnum;
327{
328 const CGEN_HW_ENTRY * hw = cgen_current_opcode_table->hw_list;
329
330 /* ??? This can be speeded up if we first make a guess into
331 the compiled in table. */
332 while (hw != NULL)
333 {
334 if (hwnum == hw->type)
335 return hw;
336 }
337 return NULL;
338}
9c03036a
DE
339\f
340/* Instruction support. */
341
342/* Return number of instructions. This includes any added at runtime. */
343
344int
345cgen_insn_count ()
346{
9a6c492c
DE
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;
349
350 for ( ; insn != NULL; insn = insn->next)
351 ++count;
352
353 return count;
354}
355
356/* Return number of macro-instructions. This includes any added at runtime. */
357
358int
359cgen_macro_insn_count ()
360{
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;
9c03036a
DE
363
364 for ( ; insn != NULL; insn = insn->next)
365 ++count;
366
367 return count;
368}
This page took 0.070502 seconds and 4 git commands to generate.