diff options
Diffstat (limited to 'contrib/binutils/opcodes/cgen-opc.c')
-rw-r--r-- | contrib/binutils/opcodes/cgen-opc.c | 128 |
1 files changed, 77 insertions, 51 deletions
diff --git a/contrib/binutils/opcodes/cgen-opc.c b/contrib/binutils/opcodes/cgen-opc.c index f9c67c8..a9d937b 100644 --- a/contrib/binutils/opcodes/cgen-opc.c +++ b/contrib/binutils/opcodes/cgen-opc.c @@ -1,28 +1,30 @@ /* CGEN generic opcode support. -Copyright (C) 1996, 1997 Free Software Foundation, Inc. + Copyright (C) 1996, 1997, 1998 Free Software Foundation, Inc. -This file is part of the GNU Binutils and GDB, the GNU debugger. + This file is part of the GNU Binutils and GDB, the GNU debugger. -This program is free software; you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation; either version 2, or (at your option) -any later version. + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2, or (at your option) + any later version. -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. -You should have received a copy of the GNU General Public License along -with this program; if not, write to the Free Software Foundation, Inc., -59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "sysdep.h" +#include <ctype.h> #include <stdio.h> #include "ansidecl.h" #include "libiberty.h" #include "bfd.h" +#include "symcat.h" #include "opcode/cgen.h" /* State variables. @@ -38,31 +40,44 @@ int cgen_current_mach; /* Current endian. */ enum cgen_endian cgen_current_endian = CGEN_ENDIAN_UNKNOWN; +/* FIXME: To support multiple architectures, we need to return a handle + to the state set up by this function, and pass the handle back to the + other functions. Later. */ + void cgen_set_cpu (data, mach, endian) CGEN_OPCODE_DATA *data; int mach; enum cgen_endian endian; { + static int init_once_p; + cgen_current_opcode_data = data; cgen_current_mach = mach; cgen_current_endian = endian; + /* Initialize those things that only need be done once. */ + if (! init_once_p) + { + /* Nothing to do currently. */ + init_once_p = 1; + } + #if 0 /* This isn't done here because it would put assembler support in the disassembler, etc. The caller is required to call these after calling us. */ /* Reset the hash tables. */ cgen_asm_init (); cgen_dis_init (); -#endif +#endif } static unsigned int hash_keyword_name - PARAMS ((const struct cgen_keyword *, const char *)); + PARAMS ((const CGEN_KEYWORD *, const char *, int)); static unsigned int hash_keyword_value - PARAMS ((const struct cgen_keyword *, int)); + PARAMS ((const CGEN_KEYWORD *, unsigned int)); static void build_keyword_hash_tables - PARAMS ((struct cgen_keyword *)); + PARAMS ((CGEN_KEYWORD *)); /* Return number of hash table entries to use for N elements. */ #define KEYWORD_HASH_SIZE(n) ((n) <= 31 ? 17 : 31) @@ -70,18 +85,18 @@ static void build_keyword_hash_tables /* Look up *NAMEP in the keyword table KT. The result is the keyword entry or NULL if not found. */ -const struct cgen_keyword_entry * +const CGEN_KEYWORD_ENTRY * cgen_keyword_lookup_name (kt, name) - struct cgen_keyword *kt; + CGEN_KEYWORD *kt; const char *name; { - const struct cgen_keyword_entry *ke; + const CGEN_KEYWORD_ENTRY *ke; const char *p,*n; if (kt->name_hash_table == NULL) build_keyword_hash_tables (kt); - ke = kt->name_hash_table[hash_keyword_name (kt, name)]; + ke = kt->name_hash_table[hash_keyword_name (kt, name, 0)]; /* We do case insensitive comparisons. If that ever becomes a problem, add an attribute that denotes @@ -94,7 +109,9 @@ cgen_keyword_lookup_name (kt, name) while (*p && (*p == *n - || (isalpha (*p) && tolower (*p) == tolower (*n)))) + || (isalpha ((unsigned char) *p) + && (tolower ((unsigned char) *p) + == tolower ((unsigned char) *n))))) ++n, ++p; if (!*p && !*n) @@ -103,18 +120,20 @@ cgen_keyword_lookup_name (kt, name) ke = ke->next_name; } + if (kt->null_entry) + return kt->null_entry; return NULL; } /* Look up VALUE in the keyword table KT. The result is the keyword entry or NULL if not found. */ -const struct cgen_keyword_entry * +const CGEN_KEYWORD_ENTRY * cgen_keyword_lookup_value (kt, value) - struct cgen_keyword *kt; + CGEN_KEYWORD *kt; int value; { - const struct cgen_keyword_entry *ke; + const CGEN_KEYWORD_ENTRY *ke; if (kt->name_hash_table == NULL) build_keyword_hash_tables (kt); @@ -135,21 +154,24 @@ cgen_keyword_lookup_value (kt, value) void cgen_keyword_add (kt, ke) - struct cgen_keyword *kt; - struct cgen_keyword_entry *ke; + CGEN_KEYWORD *kt; + CGEN_KEYWORD_ENTRY *ke; { unsigned int hash; if (kt->name_hash_table == NULL) build_keyword_hash_tables (kt); - hash = hash_keyword_name (kt, ke->name); + hash = hash_keyword_name (kt, ke->name, 0); ke->next_name = kt->name_hash_table[hash]; kt->name_hash_table[hash] = ke; hash = hash_keyword_value (kt, ke->value); ke->next_value = kt->value_hash_table[hash]; kt->value_hash_table[hash] = ke; + + if (ke->name[0] == 0) + kt->null_entry = ke; } /* FIXME: Need function to return count of keywords. */ @@ -162,12 +184,12 @@ cgen_keyword_add (kt, ke) The result is an opaque data item used to record the search status. It is passed to each call to cgen_keyword_search_next. */ -struct cgen_keyword_search +CGEN_KEYWORD_SEARCH cgen_keyword_search_init (kt, spec) - struct cgen_keyword *kt; + CGEN_KEYWORD *kt; const char *spec; { - struct cgen_keyword_search search; + CGEN_KEYWORD_SEARCH search; /* FIXME: Need to specify format of PARAMS. */ if (spec != NULL) @@ -186,12 +208,10 @@ cgen_keyword_search_init (kt, spec) /* Return the next keyword specified by SEARCH. The result is the next entry or NULL if there are no more. */ -const struct cgen_keyword_entry * +const CGEN_KEYWORD_ENTRY * cgen_keyword_search_next (search) - struct cgen_keyword_search *search; + CGEN_KEYWORD_SEARCH *search; { - const struct cgen_keyword_entry *ke; - /* Has search finished? */ if (search->current_hash == search->table->hash_table_size) return NULL; @@ -220,17 +240,23 @@ cgen_keyword_search_next (search) return NULL; } -/* Return first entry in hash chain for NAME. */ +/* Return first entry in hash chain for NAME. + If CASE_SENSITIVE_P is non-zero, return a case sensitive hash. */ static unsigned int -hash_keyword_name (kt, name) - const struct cgen_keyword *kt; +hash_keyword_name (kt, name, case_sensitive_p) + const CGEN_KEYWORD *kt; const char *name; + int case_sensitive_p; { unsigned int hash; - for (hash = 0; *name; ++name) - hash = (hash * 97) + (unsigned char) *name; + if (case_sensitive_p) + for (hash = 0; *name; ++name) + hash = (hash * 97) + (unsigned char) *name; + else + for (hash = 0; *name; ++name) + hash = (hash * 97) + (unsigned char) tolower (*name); return hash % kt->hash_table_size; } @@ -238,8 +264,8 @@ hash_keyword_name (kt, name) static unsigned int hash_keyword_value (kt, value) - const struct cgen_keyword *kt; - int value; + const CGEN_KEYWORD *kt; + unsigned int value; { return value % kt->hash_table_size; } @@ -250,7 +276,7 @@ hash_keyword_value (kt, value) static void build_keyword_hash_tables (kt) - struct cgen_keyword *kt; + CGEN_KEYWORD *kt; { int i; /* Use the number of compiled in entries as an estimate for the @@ -258,12 +284,12 @@ build_keyword_hash_tables (kt) unsigned int size = KEYWORD_HASH_SIZE (kt->num_init_entries); kt->hash_table_size = size; - kt->name_hash_table = (struct cgen_keyword_entry **) - xmalloc (size * sizeof (struct cgen_keyword_entry *)); - memset (kt->name_hash_table, 0, size * sizeof (struct cgen_keyword_entry *)); - kt->value_hash_table = (struct cgen_keyword_entry **) - xmalloc (size * sizeof (struct cgen_keyword_entry *)); - memset (kt->value_hash_table, 0, size * sizeof (struct cgen_keyword_entry *)); + kt->name_hash_table = (CGEN_KEYWORD_ENTRY **) + xmalloc (size * sizeof (CGEN_KEYWORD_ENTRY *)); + memset (kt->name_hash_table, 0, size * sizeof (CGEN_KEYWORD_ENTRY *)); + kt->value_hash_table = (CGEN_KEYWORD_ENTRY **) + xmalloc (size * sizeof (CGEN_KEYWORD_ENTRY *)); + memset (kt->value_hash_table, 0, size * sizeof (CGEN_KEYWORD_ENTRY *)); /* The table is scanned backwards as we want keywords appearing earlier to be prefered over later ones. */ @@ -273,11 +299,11 @@ build_keyword_hash_tables (kt) /* Hardware support. */ -CGEN_HW_ENTRY * +const CGEN_HW_ENTRY * cgen_hw_lookup (name) const char *name; { - CGEN_HW_ENTRY *hw = cgen_current_opcode_data->hw_list; + const CGEN_HW_ENTRY *hw = cgen_current_opcode_data->hw_list; while (hw != NULL) { |