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 "safe-ctype.h"
00031 #include "bfd.h"
00032 #include "symcat.h"
00033 #include "opcode/cgen.h"
00034
00035 #ifdef HAVE_ALLOCA_H
00036 #include <alloca.h>
00037 #endif
00038
00039 static unsigned int hash_keyword_name
00040 (const CGEN_KEYWORD *, const char *, int);
00041 static unsigned int hash_keyword_value
00042 (const CGEN_KEYWORD *, unsigned int);
00043 static void build_keyword_hash_tables
00044 (CGEN_KEYWORD *);
00045
00046
00047 #define KEYWORD_HASH_SIZE(n) ((n) <= 31 ? 17 : 31)
00048
00049
00050
00051
00052 const CGEN_KEYWORD_ENTRY *
00053 cgen_keyword_lookup_name (CGEN_KEYWORD *kt, const char *name)
00054 {
00055 const CGEN_KEYWORD_ENTRY *ke;
00056 const char *p,*n;
00057
00058 if (kt->name_hash_table == NULL)
00059 build_keyword_hash_tables (kt);
00060
00061 ke = kt->name_hash_table[hash_keyword_name (kt, name, 0)];
00062
00063
00064
00065
00066
00067 while (ke != NULL)
00068 {
00069 n = name;
00070 p = ke->name;
00071
00072 while (*p
00073 && (*p == *n
00074 || (ISALPHA (*p) && (TOLOWER (*p) == TOLOWER (*n)))))
00075 ++n, ++p;
00076
00077 if (!*p && !*n)
00078 return ke;
00079
00080 ke = ke->next_name;
00081 }
00082
00083 if (kt->null_entry)
00084 return kt->null_entry;
00085 return NULL;
00086 }
00087
00088
00089
00090
00091 const CGEN_KEYWORD_ENTRY *
00092 cgen_keyword_lookup_value (CGEN_KEYWORD *kt, int value)
00093 {
00094 const CGEN_KEYWORD_ENTRY *ke;
00095
00096 if (kt->name_hash_table == NULL)
00097 build_keyword_hash_tables (kt);
00098
00099 ke = kt->value_hash_table[hash_keyword_value (kt, value)];
00100
00101 while (ke != NULL)
00102 {
00103 if (value == ke->value)
00104 return ke;
00105 ke = ke->next_value;
00106 }
00107
00108 return NULL;
00109 }
00110
00111
00112
00113 void
00114 cgen_keyword_add (CGEN_KEYWORD *kt, CGEN_KEYWORD_ENTRY *ke)
00115 {
00116 unsigned int hash;
00117 size_t i;
00118
00119 if (kt->name_hash_table == NULL)
00120 build_keyword_hash_tables (kt);
00121
00122 hash = hash_keyword_name (kt, ke->name, 0);
00123 ke->next_name = kt->name_hash_table[hash];
00124 kt->name_hash_table[hash] = ke;
00125
00126 hash = hash_keyword_value (kt, ke->value);
00127 ke->next_value = kt->value_hash_table[hash];
00128 kt->value_hash_table[hash] = ke;
00129
00130 if (ke->name[0] == 0)
00131 kt->null_entry = ke;
00132
00133 for (i = 1; i < strlen (ke->name); i++)
00134 if (! ISALNUM (ke->name[i])
00135 && ! strchr (kt->nonalpha_chars, ke->name[i]))
00136 {
00137 size_t idx = strlen (kt->nonalpha_chars);
00138
00139
00140
00141
00142 if (idx >= sizeof (kt->nonalpha_chars) - 1)
00143 abort ();
00144 kt->nonalpha_chars[idx] = ke->name[i];
00145 kt->nonalpha_chars[idx+1] = 0;
00146 }
00147 }
00148
00149
00150
00151
00152
00153
00154
00155
00156
00157
00158
00159 CGEN_KEYWORD_SEARCH
00160 cgen_keyword_search_init (CGEN_KEYWORD *kt, const char *spec)
00161 {
00162 CGEN_KEYWORD_SEARCH search;
00163
00164
00165 if (spec != NULL)
00166 abort ();
00167
00168 if (kt->name_hash_table == NULL)
00169 build_keyword_hash_tables (kt);
00170
00171 search.table = kt;
00172 search.spec = spec;
00173 search.current_hash = 0;
00174 search.current_entry = NULL;
00175 return search;
00176 }
00177
00178
00179
00180
00181 const CGEN_KEYWORD_ENTRY *
00182 cgen_keyword_search_next (CGEN_KEYWORD_SEARCH *search)
00183 {
00184
00185 if (search->current_hash == search->table->hash_table_size)
00186 return NULL;
00187
00188
00189 if (search->current_entry != NULL
00190
00191 && search->current_entry->next_name != NULL)
00192 {
00193 search->current_entry = search->current_entry->next_name;
00194 return search->current_entry;
00195 }
00196
00197
00198 if (search->current_entry != NULL)
00199 ++search->current_hash;
00200
00201 while (search->current_hash < search->table->hash_table_size)
00202 {
00203 search->current_entry = search->table->name_hash_table[search->current_hash];
00204 if (search->current_entry != NULL)
00205 return search->current_entry;
00206 ++search->current_hash;
00207 }
00208
00209 return NULL;
00210 }
00211
00212
00213
00214
00215 static unsigned int
00216 hash_keyword_name (const CGEN_KEYWORD *kt,
00217 const char *name,
00218 int case_sensitive_p)
00219 {
00220 unsigned int hash;
00221
00222 if (case_sensitive_p)
00223 for (hash = 0; *name; ++name)
00224 hash = (hash * 97) + (unsigned char) *name;
00225 else
00226 for (hash = 0; *name; ++name)
00227 hash = (hash * 97) + (unsigned char) TOLOWER (*name);
00228 return hash % kt->hash_table_size;
00229 }
00230
00231
00232
00233 static unsigned int
00234 hash_keyword_value (const CGEN_KEYWORD *kt, unsigned int value)
00235 {
00236 return value % kt->hash_table_size;
00237 }
00238
00239
00240
00241
00242
00243 static void
00244 build_keyword_hash_tables (CGEN_KEYWORD *kt)
00245 {
00246 int i;
00247
00248
00249 unsigned int size = KEYWORD_HASH_SIZE (kt->num_init_entries);
00250
00251 kt->hash_table_size = size;
00252 kt->name_hash_table = (CGEN_KEYWORD_ENTRY **)
00253 xmalloc (size * sizeof (CGEN_KEYWORD_ENTRY *));
00254 memset (kt->name_hash_table, 0, size * sizeof (CGEN_KEYWORD_ENTRY *));
00255 kt->value_hash_table = (CGEN_KEYWORD_ENTRY **)
00256 xmalloc (size * sizeof (CGEN_KEYWORD_ENTRY *));
00257 memset (kt->value_hash_table, 0, size * sizeof (CGEN_KEYWORD_ENTRY *));
00258
00259
00260
00261 for (i = kt->num_init_entries - 1; i >= 0; --i)
00262 cgen_keyword_add (kt, &kt->init_entries[i]);
00263 }
00264
00265
00266
00267
00268
00269
00270
00271 const CGEN_HW_ENTRY *
00272 cgen_hw_lookup_by_name (CGEN_CPU_DESC cd, const char *name)
00273 {
00274 unsigned int i;
00275 const CGEN_HW_ENTRY **hw = cd->hw_table.entries;
00276
00277 for (i = 0; i < cd->hw_table.num_entries; ++i)
00278 if (hw[i] && strcmp (name, hw[i]->name) == 0)
00279 return hw[i];
00280
00281 return NULL;
00282 }
00283
00284
00285
00286
00287
00288
00289 const CGEN_HW_ENTRY *
00290 cgen_hw_lookup_by_num (CGEN_CPU_DESC cd, unsigned int hwnum)
00291 {
00292 unsigned int i;
00293 const CGEN_HW_ENTRY **hw = cd->hw_table.entries;
00294
00295
00296 for (i = 0; i < cd->hw_table.num_entries; ++i)
00297 if (hw[i] && hwnum == hw[i]->type)
00298 return hw[i];
00299
00300 return NULL;
00301 }
00302
00303
00304
00305
00306
00307
00308
00309 const CGEN_OPERAND *
00310 cgen_operand_lookup_by_name (CGEN_CPU_DESC cd, const char *name)
00311 {
00312 unsigned int i;
00313 const CGEN_OPERAND **op = cd->operand_table.entries;
00314
00315 for (i = 0; i < cd->operand_table.num_entries; ++i)
00316 if (op[i] && strcmp (name, op[i]->name) == 0)
00317 return op[i];
00318
00319 return NULL;
00320 }
00321
00322
00323
00324
00325
00326
00327
00328 const CGEN_OPERAND *
00329 cgen_operand_lookup_by_num (CGEN_CPU_DESC cd, int opnum)
00330 {
00331 return cd->operand_table.entries[opnum];
00332 }
00333
00334
00335
00336
00337
00338 int
00339 cgen_insn_count (CGEN_CPU_DESC cd)
00340 {
00341 int count = cd->insn_table.num_init_entries;
00342 CGEN_INSN_LIST *rt_insns = cd->insn_table.new_entries;
00343
00344 for ( ; rt_insns != NULL; rt_insns = rt_insns->next)
00345 ++count;
00346
00347 return count;
00348 }
00349
00350
00351
00352
00353 int
00354 cgen_macro_insn_count (CGEN_CPU_DESC cd)
00355 {
00356 int count = cd->macro_insn_table.num_init_entries;
00357 CGEN_INSN_LIST *rt_insns = cd->macro_insn_table.new_entries;
00358
00359 for ( ; rt_insns != NULL; rt_insns = rt_insns->next)
00360 ++count;
00361
00362 return count;
00363 }
00364
00365
00366
00367 CGEN_INSN_INT
00368 cgen_get_insn_value (CGEN_CPU_DESC cd, unsigned char *buf, int length)
00369 {
00370 int big_p = (cd->insn_endian == CGEN_ENDIAN_BIG);
00371 int insn_chunk_bitsize = cd->insn_chunk_bitsize;
00372 CGEN_INSN_INT value = 0;
00373
00374 if (insn_chunk_bitsize != 0 && insn_chunk_bitsize < length)
00375 {
00376
00377
00378 int i;
00379
00380
00381 if ((length % insn_chunk_bitsize) != 0)
00382 abort ();
00383
00384 for (i = 0; i < length; i += insn_chunk_bitsize)
00385 {
00386 int index;
00387 bfd_vma this_value;
00388 index = i;
00389 this_value = bfd_get_bits (& buf[index / 8], insn_chunk_bitsize, big_p);
00390 value = (value << insn_chunk_bitsize) | this_value;
00391 }
00392 }
00393 else
00394 {
00395 value = bfd_get_bits (buf, length, cd->insn_endian == CGEN_ENDIAN_BIG);
00396 }
00397
00398 return value;
00399 }
00400
00401
00402
00403 void
00404 cgen_put_insn_value (CGEN_CPU_DESC cd,
00405 unsigned char *buf,
00406 int length,
00407 CGEN_INSN_INT value)
00408 {
00409 int big_p = (cd->insn_endian == CGEN_ENDIAN_BIG);
00410 int insn_chunk_bitsize = cd->insn_chunk_bitsize;
00411
00412 if (insn_chunk_bitsize != 0 && insn_chunk_bitsize < length)
00413 {
00414
00415
00416 int i;
00417
00418
00419 if ((length % insn_chunk_bitsize) != 0)
00420 abort ();
00421
00422 for (i = 0; i < length; i += insn_chunk_bitsize)
00423 {
00424 int index;
00425 index = (length - insn_chunk_bitsize - i);
00426 bfd_put_bits ((bfd_vma) value, & buf[index / 8], insn_chunk_bitsize, big_p);
00427 value >>= insn_chunk_bitsize;
00428 }
00429 }
00430 else
00431 {
00432 bfd_put_bits ((bfd_vma) value, buf, length, big_p);
00433 }
00434 }
00435
00436
00437
00438
00439
00440
00441
00442
00443
00444
00445
00446
00447
00448
00449
00450
00451 const CGEN_INSN *
00452 cgen_lookup_insn (CGEN_CPU_DESC cd,
00453 const CGEN_INSN *insn,
00454 CGEN_INSN_INT insn_int_value,
00455
00456 unsigned char *insn_bytes_value,
00457 int length,
00458 CGEN_FIELDS *fields,
00459 int alias_p)
00460 {
00461 unsigned char *buf;
00462 CGEN_INSN_INT base_insn;
00463 CGEN_EXTRACT_INFO ex_info;
00464 CGEN_EXTRACT_INFO *info;
00465
00466 if (cd->int_insn_p)
00467 {
00468 info = NULL;
00469 buf = (unsigned char *) alloca (cd->max_insn_bitsize / 8);
00470 cgen_put_insn_value (cd, buf, length, insn_int_value);
00471 base_insn = insn_int_value;
00472 }
00473 else
00474 {
00475 info = &ex_info;
00476 ex_info.dis_info = NULL;
00477 ex_info.insn_bytes = insn_bytes_value;
00478 ex_info.valid = -1;
00479 buf = insn_bytes_value;
00480 base_insn = cgen_get_insn_value (cd, buf, length);
00481 }
00482
00483 if (!insn)
00484 {
00485 const CGEN_INSN_LIST *insn_list;
00486
00487
00488
00489
00490 insn_list = cgen_dis_lookup_insn (cd, (char *) buf, base_insn);
00491 while (insn_list != NULL)
00492 {
00493 insn = insn_list->insn;
00494
00495 if (alias_p
00496
00497 || ! CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_ALIAS))
00498 {
00499
00500
00501
00502 if ((base_insn & CGEN_INSN_BASE_MASK (insn))
00503 == CGEN_INSN_BASE_VALUE (insn))
00504 {
00505
00506 int elength = CGEN_EXTRACT_FN (cd, insn)
00507 (cd, insn, info, base_insn, fields, (bfd_vma) 0);
00508 if (elength > 0)
00509 {
00510
00511 if (length != 0 && length != elength)
00512 abort ();
00513 return insn;
00514 }
00515 }
00516 }
00517
00518 insn_list = insn_list->next;
00519 }
00520 }
00521 else
00522 {
00523
00524 if (! alias_p
00525 && CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_ALIAS))
00526 abort ();
00527
00528 if (length != CGEN_INSN_BITSIZE (insn))
00529 abort ();
00530
00531
00532 length = CGEN_EXTRACT_FN (cd, insn)
00533 (cd, insn, info, base_insn, fields, (bfd_vma) 0);
00534
00535
00536 if (length == 0)
00537 abort ();
00538 return insn;
00539 }
00540
00541 return NULL;
00542 }
00543
00544
00545
00546
00547
00548 void
00549 cgen_get_insn_operands (CGEN_CPU_DESC cd,
00550 const CGEN_INSN *insn,
00551 const CGEN_FIELDS *fields,
00552 int *indices)
00553 {
00554 const CGEN_OPINST *opinst;
00555 int i;
00556
00557 if (insn->opinst == NULL)
00558 abort ();
00559 for (i = 0, opinst = insn->opinst; opinst->type != CGEN_OPINST_END; ++i, ++opinst)
00560 {
00561 enum cgen_operand_type op_type = opinst->op_type;
00562 if (op_type == CGEN_OPERAND_NIL)
00563 indices[i] = opinst->index;
00564 else
00565 indices[i] = (*cd->get_int_operand) (cd, op_type, fields);
00566 }
00567 }
00568
00569
00570
00571
00572
00573
00574
00575
00576
00577
00578
00579 const CGEN_INSN *
00580 cgen_lookup_get_insn_operands (CGEN_CPU_DESC cd,
00581 const CGEN_INSN *insn,
00582 CGEN_INSN_INT insn_int_value,
00583
00584 unsigned char *insn_bytes_value,
00585 int length,
00586 int *indices,
00587 CGEN_FIELDS *fields)
00588 {
00589
00590
00591 insn = cgen_lookup_insn (cd, insn, insn_int_value, insn_bytes_value,
00592 length, fields, insn != NULL);
00593 if (! insn)
00594 return NULL;
00595
00596 cgen_get_insn_operands (cd, insn, fields, indices);
00597 return insn;
00598 }
00599
00600
00601 void
00602 cgen_set_signed_overflow_ok (CGEN_CPU_DESC cd)
00603 {
00604 cd->signed_overflow_ok_p = 1;
00605 }
00606
00607
00608 void
00609 cgen_clear_signed_overflow_ok (CGEN_CPU_DESC cd)
00610 {
00611 cd->signed_overflow_ok_p = 0;
00612 }
00613
00614
00615 unsigned int
00616 cgen_signed_overflow_ok_p (CGEN_CPU_DESC cd)
00617 {
00618 return cd->signed_overflow_ok_p;
00619 }