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