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