00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026 #include "sysdep.h"
00027 #include <stdio.h>
00028 #include "ansidecl.h"
00029 #include "libiberty.h"
00030 #include "bfd.h"
00031 #include "symcat.h"
00032 #include "opcode/cgen.h"
00033
00034 static CGEN_INSN_LIST * hash_insn_array (CGEN_CPU_DESC, const CGEN_INSN *, int, int, CGEN_INSN_LIST **, CGEN_INSN_LIST *);
00035 static CGEN_INSN_LIST * hash_insn_list (CGEN_CPU_DESC, const CGEN_INSN_LIST *, CGEN_INSN_LIST **, CGEN_INSN_LIST *);
00036 static void build_dis_hash_table (CGEN_CPU_DESC);
00037 static int count_decodable_bits (const CGEN_INSN *);
00038 static void add_insn_to_hash_chain (CGEN_INSN_LIST *,
00039 const CGEN_INSN *,
00040 CGEN_INSN_LIST **,
00041 unsigned int);
00042
00043
00044 static int
00045 count_decodable_bits (const CGEN_INSN *insn)
00046 {
00047 unsigned mask = CGEN_INSN_BASE_MASK (insn);
00048 int bits = 0;
00049 int m;
00050 for (m = 1; m != 0; m <<= 1)
00051 {
00052 if (mask & m)
00053 ++bits;
00054 }
00055 return bits;
00056 }
00057
00058
00059 static void
00060 add_insn_to_hash_chain (CGEN_INSN_LIST *hentbuf,
00061 const CGEN_INSN *insn,
00062 CGEN_INSN_LIST **htable,
00063 unsigned int hash)
00064 {
00065 CGEN_INSN_LIST *current_buf;
00066 CGEN_INSN_LIST *previous_buf;
00067 int insn_decodable_bits;
00068
00069
00070
00071
00072 insn_decodable_bits = count_decodable_bits (insn);
00073 previous_buf = NULL;
00074 for (current_buf = htable[hash]; current_buf != NULL;
00075 current_buf = current_buf->next)
00076 {
00077 int current_decodable_bits = count_decodable_bits (current_buf->insn);
00078 if (insn_decodable_bits >= current_decodable_bits)
00079 break;
00080 previous_buf = current_buf;
00081 }
00082
00083
00084 hentbuf->insn = insn;
00085 hentbuf->next = current_buf;
00086 if (previous_buf == NULL)
00087 htable[hash] = hentbuf;
00088 else
00089 previous_buf->next = hentbuf;
00090 }
00091
00092
00093
00094
00095
00096
00097
00098
00099
00100
00101
00102
00103
00104 static CGEN_INSN_LIST *
00105 hash_insn_array (CGEN_CPU_DESC cd,
00106 const CGEN_INSN * insns,
00107 int count,
00108 int entsize ATTRIBUTE_UNUSED,
00109 CGEN_INSN_LIST ** htable,
00110 CGEN_INSN_LIST * hentbuf)
00111 {
00112 int big_p = CGEN_CPU_ENDIAN (cd) == CGEN_ENDIAN_BIG;
00113 int i;
00114
00115 for (i = count - 1; i >= 0; --i, ++hentbuf)
00116 {
00117 unsigned int hash;
00118 char buf [4];
00119 unsigned long value;
00120 const CGEN_INSN *insn = &insns[i];
00121
00122 if (! (* cd->dis_hash_p) (insn))
00123 continue;
00124
00125
00126
00127
00128 value = CGEN_INSN_BASE_VALUE (insn);
00129 bfd_put_bits ((bfd_vma) value,
00130 buf,
00131 CGEN_INSN_MASK_BITSIZE (insn),
00132 big_p);
00133 hash = (* cd->dis_hash) (buf, value);
00134 add_insn_to_hash_chain (hentbuf, insn, htable, hash);
00135 }
00136
00137 return hentbuf;
00138 }
00139
00140
00141
00142
00143
00144 static CGEN_INSN_LIST *
00145 hash_insn_list (CGEN_CPU_DESC cd,
00146 const CGEN_INSN_LIST *insns,
00147 CGEN_INSN_LIST **htable,
00148 CGEN_INSN_LIST *hentbuf)
00149 {
00150 int big_p = CGEN_CPU_ENDIAN (cd) == CGEN_ENDIAN_BIG;
00151 const CGEN_INSN_LIST *ilist;
00152
00153 for (ilist = insns; ilist != NULL; ilist = ilist->next, ++ hentbuf)
00154 {
00155 unsigned int hash;
00156 char buf[4];
00157 unsigned long value;
00158
00159 if (! (* cd->dis_hash_p) (ilist->insn))
00160 continue;
00161
00162
00163
00164
00165 value = CGEN_INSN_BASE_VALUE (ilist->insn);
00166 bfd_put_bits((bfd_vma) value,
00167 buf,
00168 CGEN_INSN_MASK_BITSIZE (ilist->insn),
00169 big_p);
00170 hash = (* cd->dis_hash) (buf, value);
00171 add_insn_to_hash_chain (hentbuf, ilist->insn, htable, hash);
00172 }
00173
00174 return hentbuf;
00175 }
00176
00177
00178
00179 static void
00180 build_dis_hash_table (CGEN_CPU_DESC cd)
00181 {
00182 int count = cgen_insn_count (cd) + cgen_macro_insn_count (cd);
00183 CGEN_INSN_TABLE *insn_table = & cd->insn_table;
00184 CGEN_INSN_TABLE *macro_insn_table = & cd->macro_insn_table;
00185 unsigned int hash_size = cd->dis_hash_size;
00186 CGEN_INSN_LIST *hash_entry_buf;
00187 CGEN_INSN_LIST **dis_hash_table;
00188 CGEN_INSN_LIST *dis_hash_table_entries;
00189
00190
00191
00192
00193 dis_hash_table = (CGEN_INSN_LIST **)
00194 xmalloc (hash_size * sizeof (CGEN_INSN_LIST *));
00195 memset (dis_hash_table, 0, hash_size * sizeof (CGEN_INSN_LIST *));
00196 dis_hash_table_entries = hash_entry_buf = (CGEN_INSN_LIST *)
00197 xmalloc (count * sizeof (CGEN_INSN_LIST));
00198
00199
00200
00201
00202
00203
00204 hash_entry_buf = hash_insn_array (cd,
00205 insn_table->init_entries + 1,
00206 insn_table->num_init_entries - 1,
00207 insn_table->entry_size,
00208 dis_hash_table, hash_entry_buf);
00209
00210
00211
00212 hash_entry_buf = hash_insn_array (cd, macro_insn_table->init_entries,
00213 macro_insn_table->num_init_entries,
00214 macro_insn_table->entry_size,
00215 dis_hash_table, hash_entry_buf);
00216
00217
00218
00219
00220 hash_entry_buf = hash_insn_list (cd, insn_table->new_entries,
00221 dis_hash_table, hash_entry_buf);
00222
00223
00224
00225 hash_insn_list (cd, macro_insn_table->new_entries,
00226 dis_hash_table, hash_entry_buf);
00227
00228 cd->dis_hash_table = dis_hash_table;
00229 cd->dis_hash_table_entries = dis_hash_table_entries;
00230 }
00231
00232
00233
00234 CGEN_INSN_LIST *
00235 cgen_dis_lookup_insn (CGEN_CPU_DESC cd, const char * buf, CGEN_INSN_INT value)
00236 {
00237 unsigned int hash;
00238
00239 if (cd->dis_hash_table == NULL)
00240 build_dis_hash_table (cd);
00241
00242 hash = (* cd->dis_hash) (buf, value);
00243
00244 return cd->dis_hash_table[hash];
00245 }