1/* This file is part of the program psim. 2 3 Copyright 1994, 1995, 1996, 2003 Andrew Cagney 4 5 This program is free software; you can redistribute it and/or modify 6 it under the terms of the GNU General Public License as published by 7 the Free Software Foundation; either version 2 of the License, or 8 (at your option) any later version. 9 10 This program is distributed in the hope that it will be useful, 11 but WITHOUT ANY WARRANTY; without even the implied warranty of 12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 GNU General Public License for more details. 14 15 You should have received a copy of the GNU General Public License 16 along with this program; if not, write to the Free Software 17 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 18 19 */ 20 21 22#include "misc.h" 23#include "lf.h" 24#include "table.h" 25#include "filter.h" 26#include "ld-decode.h" 27#include "ld-cache.h" 28#include "ld-insn.h" 29 30#include "igen.h" 31 32static void 33update_depth(insn_table *entry, 34 lf *file, 35 void *data, 36 insn *instruction, 37 int depth) 38{ 39 int *max_depth = (int*)data; 40 if (*max_depth < depth) 41 *max_depth = depth; 42} 43 44 45int 46insn_table_depth(insn_table *table) 47{ 48 int depth = 0; 49 insn_table_traverse_tree(table, 50 NULL, 51 &depth, 52 1, 53 NULL, /*start*/ 54 update_depth, 55 NULL, /*end*/ 56 NULL); /*padding*/ 57 return depth; 58} 59 60 61static insn_fields * 62parse_insn_format(table_entry *entry, 63 char *format) 64{ 65 char *chp; 66 insn_fields *fields = ZALLOC(insn_fields); 67 68 /* create a leading sentinal */ 69 fields->first = ZALLOC(insn_field); 70 fields->first->first = -1; 71 fields->first->last = -1; 72 fields->first->width = 0; 73 74 /* and a trailing sentinal */ 75 fields->last = ZALLOC(insn_field); 76 fields->last->first = insn_bit_size; 77 fields->last->last = insn_bit_size; 78 fields->last->width = 0; 79 80 /* link them together */ 81 fields->first->next = fields->last; 82 fields->last->prev = fields->first; 83 84 /* now work through the formats */ 85 chp = format; 86 87 while (*chp != '\0') { 88 char *start_pos; 89 char *start_val; 90 int strlen_val; 91 int strlen_pos; 92 insn_field *new_field; 93 94 /* sanity check */ 95 if (!isdigit(*chp)) { 96 error("%s:%d: missing position field at `%s'\n", 97 entry->file_name, entry->line_nr, chp); 98 } 99 100 /* break out the bit position */ 101 start_pos = chp; 102 while (isdigit(*chp)) 103 chp++; 104 strlen_pos = chp - start_pos; 105 if (*chp == '.' && strlen_pos > 0) 106 chp++; 107 else { 108 error("%s:%d: missing field value at %s\n", 109 entry->file_name, entry->line_nr, chp); 110 break; 111 } 112 113 /* break out the value */ 114 start_val = chp; 115 while ((*start_val == '/' && *chp == '/') 116 || (isdigit(*start_val) && isdigit(*chp)) 117 || (isalpha(*start_val) && (isalnum(*chp) || *chp == '_'))) 118 chp++; 119 strlen_val = chp - start_val; 120 if (*chp == ',') 121 chp++; 122 else if (*chp != '\0' || strlen_val == 0) { 123 error("%s:%d: missing field terminator at %s\n", 124 entry->file_name, entry->line_nr, chp); 125 break; 126 } 127 128 /* create a new field and insert it */ 129 new_field = ZALLOC(insn_field); 130 new_field->next = fields->last; 131 new_field->prev = fields->last->prev; 132 new_field->next->prev = new_field; 133 new_field->prev->next = new_field; 134 135 /* the value */ 136 new_field->val_string = (char*)zalloc(strlen_val+1); 137 strncpy(new_field->val_string, start_val, strlen_val); 138 if (isdigit(*new_field->val_string)) { 139 new_field->val_int = a2i(new_field->val_string); 140 new_field->is_int = 1; 141 } 142 else if (new_field->val_string[0] == '/') { 143 new_field->is_slash = 1; 144 } 145 else { 146 new_field->is_string = 1; 147 } 148 149 /* the pos */ 150 new_field->pos_string = (char*)zalloc(strlen_pos+1); 151 strncpy(new_field->pos_string, start_pos, strlen_pos); 152 new_field->first = target_a2i(hi_bit_nr, new_field->pos_string); 153 new_field->last = new_field->next->first - 1; /* guess */ 154 new_field->width = new_field->last - new_field->first + 1; /* guess */ 155 new_field->prev->last = new_field->first-1; /*fix*/ 156 new_field->prev->width = new_field->first - new_field->prev->first; /*fix*/ 157 } 158 159 /* fiddle first/last so that the sentinals `disapear' */ 160 ASSERT(fields->first->last < 0); 161 ASSERT(fields->last->first >= insn_bit_size); 162 fields->first = fields->first->next; 163 fields->last = fields->last->prev; 164 165 /* now go over this again, pointing each bit position at a field 166 record */ 167 { 168 int i; 169 insn_field *field; 170 field = fields->first; 171 for (i = 0; i < insn_bit_size; i++) { 172 while (field->last < i) 173 field = field->next; 174 fields->bits[i] = field; 175 } 176 } 177 178 /* go over each of the fields, and compute a `value' for the insn */ 179 { 180 insn_field *field; 181 fields->value = 0; 182 for (field = fields->first; 183 field->last < insn_bit_size; 184 field = field->next) { 185 fields->value <<= field->width; 186 if (field->is_int) 187 fields->value |= field->val_int; 188 } 189 } 190 return fields; 191} 192 193 194void 195parse_include_entry (table *file, 196 table_entry *file_entry, 197 filter *filters, 198 table_include *includes) 199{ 200 /* parse the include file_entry */ 201 if (file_entry->nr_fields < 4) 202 error ("Incorrect nr fields for include record\n"); 203 /* process it */ 204 if (!is_filtered_out(file_entry->fields[include_flags], filters)) 205 { 206 table_push (file, includes, 207 file_entry->fields[include_path], 208 file_entry->nr_fields, file_entry->nr_fields); 209 } 210} 211 212static void 213model_table_insert(insn_table *table, 214 table_entry *file_entry) 215{ 216 int len; 217 218 /* create a new model */ 219 model *new_model = ZALLOC(model); 220 221 new_model->name = file_entry->fields[model_identifer]; 222 new_model->printable_name = file_entry->fields[model_name]; 223 new_model->insn_default = file_entry->fields[model_default]; 224 225 while (*new_model->insn_default && isspace(*new_model->insn_default)) 226 new_model->insn_default++; 227 228 len = strlen(new_model->insn_default); 229 if (max_model_fields_len < len) 230 max_model_fields_len = len; 231 232 /* append it to the end of the model list */ 233 if (last_model) 234 last_model->next = new_model; 235 else 236 models = new_model; 237 last_model = new_model; 238} 239 240static void 241model_table_insert_specific(insn_table *table, 242 table_entry *file_entry, 243 insn **start_ptr, 244 insn **end_ptr) 245{ 246 insn *ptr = ZALLOC(insn); 247 ptr->file_entry = file_entry; 248 if (*end_ptr) 249 (*end_ptr)->next = ptr; 250 else 251 (*start_ptr) = ptr; 252 (*end_ptr) = ptr; 253} 254 255 256static void 257insn_table_insert_function(insn_table *table, 258 table_entry *file_entry) 259{ 260 /* create a new function */ 261 insn *new_function = ZALLOC(insn); 262 new_function->file_entry = file_entry; 263 264 /* append it to the end of the function list */ 265 if (table->last_function) 266 table->last_function->next = new_function; 267 else 268 table->functions = new_function; 269 table->last_function = new_function; 270} 271 272extern void 273insn_table_insert_insn(insn_table *table, 274 table_entry *file_entry, 275 insn_fields *fields) 276{ 277 insn **ptr_to_cur_insn = &table->insns; 278 insn *cur_insn = *ptr_to_cur_insn; 279 table_model_entry *insn_model_ptr; 280 model *model_ptr; 281 282 /* create a new instruction */ 283 insn *new_insn = ZALLOC(insn); 284 new_insn->file_entry = file_entry; 285 new_insn->fields = fields; 286 287 /* Check out any model information returned to make sure the model 288 is correct. */ 289 for(insn_model_ptr = file_entry->model_first; insn_model_ptr; insn_model_ptr = insn_model_ptr->next) { 290 char *name = insn_model_ptr->fields[insn_model_name]; 291 int len = strlen (insn_model_ptr->fields[insn_model_fields]); 292 293 while (len > 0 && isspace(*insn_model_ptr->fields[insn_model_fields])) { 294 len--; 295 insn_model_ptr->fields[insn_model_fields]++; 296 } 297 298 if (max_model_fields_len < len) 299 max_model_fields_len = len; 300 301 for(model_ptr = models; model_ptr; model_ptr = model_ptr->next) { 302 if (strcmp(name, model_ptr->printable_name) == 0) { 303 304 /* Replace the name field with that of the global model, so that when we 305 want to print it out, we can just compare pointers. */ 306 insn_model_ptr->fields[insn_model_name] = model_ptr->printable_name; 307 break; 308 } 309 } 310 311 if (!model_ptr) 312 error("%s:%d: machine model `%s' was not known about\n", 313 file_entry->file_name, file_entry->line_nr, name); 314 } 315 316 /* insert it according to the order of the fields */ 317 while (cur_insn != NULL 318 && new_insn->fields->value >= cur_insn->fields->value) { 319 ptr_to_cur_insn = &cur_insn->next; 320 cur_insn = *ptr_to_cur_insn; 321 } 322 323 new_insn->next = cur_insn; 324 *ptr_to_cur_insn = new_insn; 325 326 table->nr_insn++; 327} 328 329 330 331insn_table * 332load_insn_table(const char *file_name, 333 decode_table *decode_rules, 334 filter *filters, 335 table_include *includes, 336 cache_table **cache_rules) 337{ 338 table *file = table_open(file_name, nr_insn_table_fields, nr_insn_model_table_fields); 339 insn_table *table = ZALLOC(insn_table); 340 table_entry *file_entry; 341 table->opcode_rule = decode_rules; 342 343 while ((file_entry = table_entry_read(file)) != NULL) { 344 if (it_is("function", file_entry->fields[insn_flags]) 345 || it_is("internal", file_entry->fields[insn_flags])) { 346 insn_table_insert_function(table, file_entry); 347 } 348 else if ((it_is("function", file_entry->fields[insn_form]) 349 || it_is("internal", file_entry->fields[insn_form])) 350 && !is_filtered_out(file_entry->fields[insn_flags], filters)) { 351 /* Ok, this is evil. Need to convert a new style function into 352 an old style function. Construct an old style table and then 353 copy it back. */ 354 char *fields[nr_insn_table_fields]; 355 memset (fields, 0, sizeof fields); 356 fields[insn_flags] = file_entry->fields[insn_form]; 357 fields[function_type] = file_entry->fields[insn_name]; 358 fields[function_name] = file_entry->fields[insn_comment]; 359 fields[function_param] = file_entry->fields[insn_field_6]; 360 memcpy (file_entry->fields, fields, 361 sizeof (fields[0]) * file_entry->nr_fields); 362 insn_table_insert_function(table, file_entry); 363#if 0 364 ":" "..." 365 ":" <filter-flags> 366 ":" <filter-models> 367 ":" <typedef> 368 ":" <name> 369 [ ":" <parameter-list> ] 370 <nl> 371 [ <function-model> ] 372 <code-block> 373#endif 374 } 375 else if (it_is("model", file_entry->fields[insn_flags])) { 376 model_table_insert(table, file_entry); 377 } 378 else if (it_is("model-macro", file_entry->fields[insn_flags])) { 379 model_table_insert_specific(table, file_entry, &model_macros, &last_model_macro); 380 } 381 else if (it_is("model-function", file_entry->fields[insn_flags])) { 382 model_table_insert_specific(table, file_entry, &model_functions, &last_model_function); 383 } 384 else if (it_is("model-internal", file_entry->fields[insn_flags])) { 385 model_table_insert_specific(table, file_entry, &model_internal, &last_model_internal); 386 } 387 else if (it_is("model-static", file_entry->fields[insn_flags])) { 388 model_table_insert_specific(table, file_entry, &model_static, &last_model_static); 389 } 390 else if (it_is("model-data", file_entry->fields[insn_flags])) { 391 model_table_insert_specific(table, file_entry, &model_data, &last_model_data); 392 } 393 else if (it_is("include", file_entry->fields[insn_form]) 394 && !is_filtered_out(file_entry->fields[insn_flags], filters)) { 395 parse_include_entry (file, file_entry, filters, includes); 396 } 397 else if ((it_is("cache", file_entry->fields[insn_form]) 398 || it_is("compute", file_entry->fields[insn_form]) 399 || it_is("scratch", file_entry->fields[insn_form])) 400 && !is_filtered_out(file_entry->fields[insn_flags], filters)) { 401 append_cache_rule (cache_rules, 402 file_entry->fields[insn_form], /* type */ 403 file_entry->fields[cache_name], 404 file_entry->fields[cache_derived_name], 405 file_entry->fields[cache_type_def], 406 file_entry->fields[cache_expression], 407 file_entry); 408 } 409 else { 410 insn_fields *fields; 411 /* skip instructions that aren't relevant to the mode */ 412 if (is_filtered_out(file_entry->fields[insn_flags], filters)) { 413 fprintf(stderr, "Dropping %s - %s\n", 414 file_entry->fields[insn_name], 415 file_entry->fields[insn_flags]); 416 } 417 else { 418 /* create/insert the new instruction */ 419 fields = parse_insn_format(file_entry, 420 file_entry->fields[insn_format]); 421 insn_table_insert_insn(table, file_entry, fields); 422 } 423 } 424 } 425 return table; 426} 427 428 429extern void 430insn_table_traverse_tree(insn_table *table, 431 lf *file, 432 void *data, 433 int depth, 434 leaf_handler *start, 435 insn_handler *leaf, 436 leaf_handler *end, 437 padding_handler *padding) 438{ 439 insn_table *entry; 440 int entry_nr; 441 442 ASSERT(table != NULL 443 && table->opcode != NULL 444 && table->nr_entries > 0 445 && table->entries != 0); 446 447 if (start != NULL && depth >= 0) 448 start(table, file, data, depth); 449 450 for (entry_nr = 0, entry = table->entries; 451 entry_nr < (table->opcode->is_boolean 452 ? 2 453 : (1 << (table->opcode->last - table->opcode->first + 1))); 454 entry_nr ++) { 455 if (entry == NULL 456 || (!table->opcode->is_boolean 457 && entry_nr < entry->opcode_nr)) { 458 if (padding != NULL && depth >= 0) 459 padding(table, file, data, depth, entry_nr); 460 } 461 else { 462 ASSERT(entry != NULL && (entry->opcode_nr == entry_nr 463 || table->opcode->is_boolean)); 464 if (entry->opcode != NULL && depth != 0) { 465 insn_table_traverse_tree(entry, file, data, depth+1, 466 start, leaf, end, padding); 467 } 468 else if (depth >= 0) { 469 if (leaf != NULL) 470 leaf(entry, file, data, entry->insns, depth); 471 } 472 entry = entry->sibling; 473 } 474 } 475 if (end != NULL && depth >= 0) 476 end(table, file, data, depth); 477} 478 479 480extern void 481insn_table_traverse_function(insn_table *table, 482 lf *file, 483 void *data, 484 function_handler *leaf) 485{ 486 insn *function; 487 for (function = table->functions; 488 function != NULL; 489 function = function->next) { 490 leaf(table, file, data, function->file_entry); 491 } 492} 493 494extern void 495insn_table_traverse_insn(insn_table *table, 496 lf *file, 497 void *data, 498 insn_handler *handler) 499{ 500 insn *instruction; 501 for (instruction = table->insns; 502 instruction != NULL; 503 instruction = instruction->next) { 504 handler(table, file, data, instruction, 0); 505 } 506} 507 508 509/****************************************************************/ 510 511typedef enum { 512 field_constant_int = 1, 513 field_constant_slash = 2, 514 field_constant_string = 3 515} constant_field_types; 516 517 518static int 519insn_field_is_constant(insn_field *field, 520 decode_table *rule) 521{ 522 /* field is an integer */ 523 if (field->is_int) 524 return field_constant_int; 525 /* field is `/' and treating that as a constant */ 526 if (field->is_slash && rule->force_slash) 527 return field_constant_slash; 528 /* field, though variable is on the list */ 529 if (field->is_string && rule->force_expansion != NULL) { 530 char *forced_fields = rule->force_expansion; 531 while (*forced_fields != '\0') { 532 int field_len; 533 char *end = strchr(forced_fields, ','); 534 if (end == NULL) 535 field_len = strlen(forced_fields); 536 else 537 field_len = end-forced_fields; 538 if (strncmp(forced_fields, field->val_string, field_len) == 0 539 && field->val_string[field_len] == '\0') 540 return field_constant_string; 541 forced_fields += field_len; 542 if (*forced_fields == ',') 543 forced_fields++; 544 } 545 } 546 return 0; 547} 548 549 550static opcode_field * 551insn_table_find_opcode_field(insn *insns, 552 decode_table *rule, 553 int string_only) 554{ 555 opcode_field *curr_opcode = ZALLOC(opcode_field); 556 insn *entry; 557 ASSERT(rule); 558 559 curr_opcode->first = insn_bit_size; 560 curr_opcode->last = -1; 561 for (entry = insns; entry != NULL; entry = entry->next) { 562 insn_fields *fields = entry->fields; 563 opcode_field new_opcode; 564 565 /* find a start point for the opcode field */ 566 new_opcode.first = rule->first; 567 while (new_opcode.first <= rule->last 568 && (!string_only 569 || insn_field_is_constant(fields->bits[new_opcode.first], 570 rule) != field_constant_string) 571 && (string_only 572 || !insn_field_is_constant(fields->bits[new_opcode.first], 573 rule))) 574 new_opcode.first = fields->bits[new_opcode.first]->last + 1; 575 ASSERT(new_opcode.first > rule->last 576 || (string_only 577 && insn_field_is_constant(fields->bits[new_opcode.first], 578 rule) == field_constant_string) 579 || (!string_only 580 && insn_field_is_constant(fields->bits[new_opcode.first], 581 rule))); 582 583 /* find the end point for the opcode field */ 584 new_opcode.last = rule->last; 585 while (new_opcode.last >= rule->first 586 && (!string_only 587 || insn_field_is_constant(fields->bits[new_opcode.last], 588 rule) != field_constant_string) 589 && (string_only 590 || !insn_field_is_constant(fields->bits[new_opcode.last], 591 rule))) 592 new_opcode.last = fields->bits[new_opcode.last]->first - 1; 593 ASSERT(new_opcode.last < rule->first 594 || (string_only 595 && insn_field_is_constant(fields->bits[new_opcode.last], 596 rule) == field_constant_string) 597 || (!string_only 598 && insn_field_is_constant(fields->bits[new_opcode.last], 599 rule))); 600 601 /* now see if our current opcode needs expanding */ 602 if (new_opcode.first <= rule->last 603 && curr_opcode->first > new_opcode.first) 604 curr_opcode->first = new_opcode.first; 605 if (new_opcode.last >= rule->first 606 && curr_opcode->last < new_opcode.last) 607 curr_opcode->last = new_opcode.last; 608 609 } 610 611 /* was any thing interesting found? */ 612 if (curr_opcode->first > rule->last) { 613 ASSERT(curr_opcode->last < rule->first); 614 return NULL; 615 } 616 ASSERT(curr_opcode->last >= rule->first); 617 ASSERT(curr_opcode->first <= rule->last); 618 619 /* if something was found, check it includes the forced field range */ 620 if (!string_only 621 && curr_opcode->first > rule->force_first) { 622 curr_opcode->first = rule->force_first; 623 } 624 if (!string_only 625 && curr_opcode->last < rule->force_last) { 626 curr_opcode->last = rule->force_last; 627 } 628 /* handle special case elminating any need to do shift after mask */ 629 if (string_only 630 && rule->force_last == insn_bit_size-1) { 631 curr_opcode->last = insn_bit_size-1; 632 } 633 634 /* handle any special cases */ 635 switch (rule->type) { 636 case normal_decode_rule: 637 /* let the above apply */ 638 break; 639 case expand_forced_rule: 640 /* expand a limited nr of bits, ignoring the rest */ 641 curr_opcode->first = rule->force_first; 642 curr_opcode->last = rule->force_last; 643 break; 644 case boolean_rule: 645 curr_opcode->is_boolean = 1; 646 curr_opcode->boolean_constant = rule->special_constant; 647 break; 648 default: 649 error("Something is going wrong\n"); 650 } 651 652 return curr_opcode; 653} 654 655 656static void 657insn_table_insert_expanded(insn_table *table, 658 insn *old_insn, 659 int new_opcode_nr, 660 insn_bits *new_bits) 661{ 662 insn_table **ptr_to_cur_entry = &table->entries; 663 insn_table *cur_entry = *ptr_to_cur_entry; 664 665 /* find the new table for this entry */ 666 while (cur_entry != NULL 667 && cur_entry->opcode_nr < new_opcode_nr) { 668 ptr_to_cur_entry = &cur_entry->sibling; 669 cur_entry = *ptr_to_cur_entry; 670 } 671 672 if (cur_entry == NULL || cur_entry->opcode_nr != new_opcode_nr) { 673 insn_table *new_entry = ZALLOC(insn_table); 674 new_entry->opcode_nr = new_opcode_nr; 675 new_entry->expanded_bits = new_bits; 676 new_entry->opcode_rule = table->opcode_rule->next; 677 new_entry->sibling = cur_entry; 678 new_entry->parent = table; 679 *ptr_to_cur_entry = new_entry; 680 cur_entry = new_entry; 681 table->nr_entries++; 682 } 683 /* ASSERT new_bits == cur_entry bits */ 684 ASSERT(cur_entry != NULL && cur_entry->opcode_nr == new_opcode_nr); 685 insn_table_insert_insn(cur_entry, 686 old_insn->file_entry, 687 old_insn->fields); 688} 689 690static void 691insn_table_expand_opcode(insn_table *table, 692 insn *instruction, 693 int field_nr, 694 int opcode_nr, 695 insn_bits *bits) 696{ 697 698 if (field_nr > table->opcode->last) { 699 insn_table_insert_expanded(table, instruction, opcode_nr, bits); 700 } 701 else { 702 insn_field *field = instruction->fields->bits[field_nr]; 703 if (field->is_int || field->is_slash) { 704 ASSERT(field->first >= table->opcode->first 705 && field->last <= table->opcode->last); 706 insn_table_expand_opcode(table, instruction, field->last+1, 707 ((opcode_nr << field->width) + field->val_int), 708 bits); 709 } 710 else { 711 int val; 712 int last_pos = ((field->last < table->opcode->last) 713 ? field->last : table->opcode->last); 714 int first_pos = ((field->first > table->opcode->first) 715 ? field->first : table->opcode->first); 716 int width = last_pos - first_pos + 1; 717 int last_val = (table->opcode->is_boolean 718 ? 2 : (1 << width)); 719 for (val = 0; val < last_val; val++) { 720 insn_bits *new_bits = ZALLOC(insn_bits); 721 new_bits->field = field; 722 new_bits->value = val; 723 new_bits->last = bits; 724 new_bits->opcode = table->opcode; 725 insn_table_expand_opcode(table, instruction, last_pos+1, 726 ((opcode_nr << width) | val), 727 new_bits); 728 } 729 } 730 } 731} 732 733static void 734insn_table_insert_expanding(insn_table *table, 735 insn *entry) 736{ 737 insn_table_expand_opcode(table, 738 entry, 739 table->opcode->first, 740 0, 741 table->expanded_bits); 742} 743 744 745extern void 746insn_table_expand_insns(insn_table *table) 747{ 748 749 ASSERT(table->nr_insn >= 1); 750 751 /* determine a valid opcode */ 752 while (table->opcode_rule) { 753 /* specials only for single instructions */ 754 if ((table->nr_insn > 1 755 && table->opcode_rule->special_mask == 0 756 && table->opcode_rule->type == normal_decode_rule) 757 || (table->nr_insn == 1 758 && table->opcode_rule->special_mask != 0 759 && ((table->insns->fields->value 760 & table->opcode_rule->special_mask) 761 == table->opcode_rule->special_value)) 762 || (generate_expanded_instructions 763 && table->opcode_rule->special_mask == 0 764 && table->opcode_rule->type == normal_decode_rule)) 765 table->opcode = 766 insn_table_find_opcode_field(table->insns, 767 table->opcode_rule, 768 table->nr_insn == 1/*string*/ 769 ); 770 if (table->opcode != NULL) 771 break; 772 table->opcode_rule = table->opcode_rule->next; 773 } 774 775 /* did we find anything */ 776 if (table->opcode == NULL) { 777 return; 778 } 779 ASSERT(table->opcode != NULL); 780 781 /* back link what we found to its parent */ 782 if (table->parent != NULL) { 783 ASSERT(table->parent->opcode != NULL); 784 table->opcode->parent = table->parent->opcode; 785 } 786 787 /* expand the raw instructions according to the opcode */ 788 { 789 insn *entry; 790 for (entry = table->insns; entry != NULL; entry = entry->next) { 791 insn_table_insert_expanding(table, entry); 792 } 793 } 794 795 /* and do the same for the sub entries */ 796 { 797 insn_table *entry; 798 for (entry = table->entries; entry != NULL; entry = entry->sibling) { 799 insn_table_expand_insns(entry); 800 } 801 } 802} 803 804 805 806 807#ifdef MAIN 808 809static void 810dump_insn_field(insn_field *field, 811 int indent) 812{ 813 814 printf("(insn_field*)0x%x\n", (unsigned)field); 815 816 dumpf(indent, "(first %d)\n", field->first); 817 818 dumpf(indent, "(last %d)\n", field->last); 819 820 dumpf(indent, "(width %d)\n", field->width); 821 822 if (field->is_int) 823 dumpf(indent, "(is_int %d)\n", field->val_int); 824 825 if (field->is_slash) 826 dumpf(indent, "(is_slash)\n"); 827 828 if (field->is_string) 829 dumpf(indent, "(is_string `%s')\n", field->val_string); 830 831 dumpf(indent, "(next 0x%x)\n", field->next); 832 833 dumpf(indent, "(prev 0x%x)\n", field->prev); 834 835 836} 837 838static void 839dump_insn_fields(insn_fields *fields, 840 int indent) 841{ 842 int i; 843 844 printf("(insn_fields*)%p\n", fields); 845 846 dumpf(indent, "(first 0x%x)\n", fields->first); 847 dumpf(indent, "(last 0x%x)\n", fields->last); 848 849 dumpf(indent, "(value 0x%x)\n", fields->value); 850 851 for (i = 0; i < insn_bit_size; i++) { 852 dumpf(indent, "(bits[%d] ", i, fields->bits[i]); 853 dump_insn_field(fields->bits[i], indent+1); 854 dumpf(indent, " )\n"); 855 } 856 857} 858 859 860static void 861dump_opcode_field(opcode_field *field, int indent, int levels) 862{ 863 printf("(opcode_field*)%p\n", field); 864 if (levels && field != NULL) { 865 dumpf(indent, "(first %d)\n", field->first); 866 dumpf(indent, "(last %d)\n", field->last); 867 dumpf(indent, "(is_boolean %d)\n", field->is_boolean); 868 dumpf(indent, "(parent "); 869 dump_opcode_field(field->parent, indent, levels-1); 870 } 871} 872 873 874static void 875dump_insn_bits(insn_bits *bits, int indent, int levels) 876{ 877 printf("(insn_bits*)%p\n", bits); 878 879 if (levels && bits != NULL) { 880 dumpf(indent, "(value %d)\n", bits->value); 881 dumpf(indent, "(opcode "); 882 dump_opcode_field(bits->opcode, indent+1, 0); 883 dumpf(indent, " )\n"); 884 dumpf(indent, "(field "); 885 dump_insn_field(bits->field, indent+1); 886 dumpf(indent, " )\n"); 887 dumpf(indent, "(last "); 888 dump_insn_bits(bits->last, indent+1, levels-1); 889 } 890} 891 892 893 894static void 895dump_insn(insn *entry, int indent, int levels) 896{ 897 printf("(insn*)%p\n", entry); 898 899 if (levels && entry != NULL) { 900 901 dumpf(indent, "(file_entry "); 902 dump_table_entry(entry->file_entry, indent+1); 903 dumpf(indent, " )\n"); 904 905 dumpf(indent, "(fields "); 906 dump_insn_fields(entry->fields, indent+1); 907 dumpf(indent, " )\n"); 908 909 dumpf(indent, "(next "); 910 dump_insn(entry->next, indent+1, levels-1); 911 dumpf(indent, " )\n"); 912 913 } 914 915} 916 917 918static void 919dump_insn_table(insn_table *table, 920 int indent, int levels) 921{ 922 923 printf("(insn_table*)%p\n", table); 924 925 if (levels && table != NULL) { 926 927 dumpf(indent, "(opcode_nr %d)\n", table->opcode_nr); 928 929 dumpf(indent, "(expanded_bits "); 930 dump_insn_bits(table->expanded_bits, indent+1, -1); 931 dumpf(indent, " )\n"); 932 933 dumpf(indent, "(int nr_insn %d)\n", table->nr_insn); 934 935 dumpf(indent, "(insns "); 936 dump_insn(table->insns, indent+1, table->nr_insn); 937 dumpf(indent, " )\n"); 938 939 dumpf(indent, "(opcode_rule "); 940 dump_decode_rule(table->opcode_rule, indent+1); 941 dumpf(indent, " )\n"); 942 943 dumpf(indent, "(opcode "); 944 dump_opcode_field(table->opcode, indent+1, 1); 945 dumpf(indent, " )\n"); 946 947 dumpf(indent, "(nr_entries %d)\n", table->entries); 948 dumpf(indent, "(entries "); 949 dump_insn_table(table->entries, indent+1, table->nr_entries); 950 dumpf(indent, " )\n"); 951 952 dumpf(indent, "(sibling ", table->sibling); 953 dump_insn_table(table->sibling, indent+1, levels-1); 954 dumpf(indent, " )\n"); 955 956 dumpf(indent, "(parent ", table->parent); 957 dump_insn_table(table->parent, indent+1, 0); 958 dumpf(indent, " )\n"); 959 960 } 961} 962 963int insn_bit_size = max_insn_bit_size; 964int hi_bit_nr; 965int generate_expanded_instructions; 966 967int 968main(int argc, char **argv) 969{ 970 filter *filters = NULL; 971 decode_table *decode_rules = NULL; 972 insn_table *instructions = NULL; 973 cache_table *cache_rules = NULL; 974 975 if (argc != 5) 976 error("Usage: insn <filter> <hi-bit-nr> <decode-table> <insn-table>\n"); 977 978 filters = new_filter(argv[1], filters); 979 hi_bit_nr = a2i(argv[2]); 980 ASSERT(hi_bit_nr < insn_bit_size); 981 decode_rules = load_decode_table(argv[3], hi_bit_nr); 982 instructions = load_insn_table(argv[4], decode_rules, filters, NULL, 983 &cache_rules); 984 insn_table_expand_insns(instructions); 985 986 dump_insn_table(instructions, 0, -1); 987 return 0; 988} 989 990#endif 991