1 /* This file is part of the program psim. 2 3 Copyright (C) 1994-1997, Andrew Cagney <cagney@highland.com.au> 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 25 #include "filter.h" 26 27 #include "ld-decode.h" 28 #include "ld-cache.h" 29 #include "ld-insn.h" 30 31 #include "igen.h" 32 33 #include "gen-semantics.h" 34 #include "gen-idecode.h" 35 #include "gen-icache.h" 36 37 38 39 static void 40 print_icache_function_header(lf *file, 41 const char *basename, 42 insn_bits *expanded_bits, 43 int is_function_definition) 44 { 45 lf_printf(file, "\n"); 46 lf_print_function_type(file, ICACHE_FUNCTION_TYPE, "EXTERN_ICACHE", " "); 47 print_function_name(file, 48 basename, 49 expanded_bits, 50 function_name_prefix_icache); 51 lf_printf(file, "\n(%s)", ICACHE_FUNCTION_FORMAL); 52 if (!is_function_definition) 53 lf_printf(file, ";"); 54 lf_printf(file, "\n"); 55 } 56 57 58 void 59 print_icache_declaration(insn_table *entry, 60 lf *file, 61 void *data, 62 insn *instruction, 63 int depth) 64 { 65 if (generate_expanded_instructions) { 66 ASSERT(entry->nr_insn == 1); 67 print_icache_function_header(file, 68 entry->insns->file_entry->fields[insn_name], 69 entry->expanded_bits, 70 0/* is not function definition */); 71 } 72 else { 73 print_icache_function_header(file, 74 instruction->file_entry->fields[insn_name], 75 NULL, 76 0/* is not function definition */); 77 } 78 } 79 80 81 82 static void 83 print_icache_extraction(lf *file, 84 insn *instruction, 85 const char *entry_name, 86 const char *entry_type, 87 const char *entry_expression, 88 const char *original_name, 89 const char *file_name, 90 int line_nr, 91 insn_field *cur_field, 92 insn_bits *bits, 93 icache_decl_type what_to_declare, 94 icache_body_type what_to_do, 95 const char *reason) 96 { 97 const char *expression; 98 ASSERT(entry_name != NULL); 99 100 /* Define a storage area for the cache element */ 101 if (what_to_declare == undef_variables) { 102 /* We've finished with the value - destory it */ 103 lf_indent_suppress(file); 104 lf_printf(file, "#undef %s\n", entry_name); 105 return; 106 } 107 else if (what_to_declare == define_variables) { 108 lf_indent_suppress(file); 109 lf_printf(file, "#define %s ", entry_name); 110 } 111 else { 112 if (file_name != NULL) 113 lf_print__external_reference(file, line_nr, file_name); 114 lf_printf(file, "%s const %s UNUSED = ", 115 entry_type == NULL ? "unsigned" : entry_type, 116 entry_name); 117 } 118 119 /* define a value for that storage area as determined by what is in 120 the cache */ 121 if (bits != NULL 122 && strcmp(entry_name, cur_field->val_string) == 0 123 && ((bits->opcode->is_boolean && bits->value == 0) 124 || (!bits->opcode->is_boolean))) { 125 /* The simple field has been made constant (as a result of 126 expanding instructions or similar). Remember that for a 127 boolean field, value is either 0 (implying the required 128 boolean_constant) or nonzero (implying some other value and 129 handled later below) - Define the variable accordingly */ 130 expression = "constant field"; 131 ASSERT(bits->field == cur_field); 132 ASSERT(entry_type == NULL); 133 if (bits->opcode->is_boolean) 134 lf_printf(file, "%d", bits->opcode->boolean_constant); 135 else if (bits->opcode->last < bits->field->last) 136 lf_printf(file, "%d", 137 bits->value << (bits->field->last - bits->opcode->last)); 138 else 139 lf_printf(file, "%d", bits->value); 140 } 141 else if (bits != NULL 142 && original_name != NULL 143 && strncmp(entry_name, 144 original_name, strlen(original_name)) == 0 145 && strncmp(entry_name + strlen(original_name), 146 "_is_", strlen("_is_")) == 0 147 && ((bits->opcode->is_boolean 148 && (atol(entry_name + strlen(original_name) + strlen("_is_")) 149 == bits->opcode->boolean_constant)) 150 || (!bits->opcode->is_boolean))) { 151 expression = "constant compare"; 152 /* An entry, derived from ORIGINAL_NAME, is testing to see of the 153 ORIGINAL_NAME has a specific constant value. That value 154 matching a boolean or constant field */ 155 if (bits->opcode->is_boolean) 156 lf_printf(file, "%d /* %s == %d */", 157 bits->value == 0, 158 original_name, 159 bits->opcode->boolean_constant); 160 else if (bits->opcode->last < bits->field->last) 161 lf_printf(file, "%d /* %s == %d */", 162 (atol(entry_name + strlen(original_name) + strlen("_is_")) 163 == (bits->value << (bits->field->last - bits->opcode->last))), 164 original_name, 165 (bits->value << (bits->field->last - bits->opcode->last))); 166 else 167 lf_printf(file, "%d /* %s == %d */", 168 (atol(entry_name + strlen(original_name) + strlen("_is_")) 169 == bits->value), 170 original_name, 171 bits->value); 172 } 173 else { 174 /* put the field in the local variable, possibly also enter it 175 into the cache */ 176 expression = "extraction"; 177 /* handle the cache */ 178 if ((what_to_do & get_values_from_icache) 179 || (what_to_do & put_values_in_icache)) { 180 lf_printf(file, "cache_entry->crack.%s.%s", 181 instruction->file_entry->fields[insn_form], 182 entry_name); 183 if (what_to_do & put_values_in_icache) /* also put it in the cache? */ 184 lf_printf(file, " = "); 185 } 186 if ((what_to_do & put_values_in_icache) 187 || what_to_do == do_not_use_icache) { 188 if (cur_field != NULL && strcmp(entry_name, cur_field->val_string) == 0) 189 lf_printf(file, "EXTRACTED32(instruction, %d, %d)", 190 i2target(hi_bit_nr, cur_field->first), 191 i2target(hi_bit_nr, cur_field->last)); 192 else if (entry_expression != NULL) 193 lf_printf(file, "%s", entry_expression); 194 else 195 lf_printf(file, "eval_%s", entry_name); 196 } 197 } 198 199 if (!((what_to_declare == define_variables) 200 || (what_to_declare == undef_variables))) 201 lf_printf(file, ";"); 202 if (reason != NULL) 203 lf_printf(file, " /* %s - %s */", reason, expression); 204 lf_printf(file, "\n"); 205 } 206 207 208 void 209 print_icache_body(lf *file, 210 insn *instruction, 211 insn_bits *expanded_bits, 212 cache_table *cache_rules, 213 icache_decl_type what_to_declare, 214 icache_body_type what_to_do) 215 { 216 insn_field *cur_field; 217 218 /* extract instruction fields */ 219 lf_printf(file, "/* extraction: %s ", 220 instruction->file_entry->fields[insn_format]); 221 switch (what_to_declare) { 222 case define_variables: 223 lf_printf(file, "#define"); 224 break; 225 case declare_variables: 226 lf_printf(file, "declare"); 227 break; 228 case undef_variables: 229 lf_printf(file, "#undef"); 230 break; 231 } 232 lf_printf(file, " "); 233 switch (what_to_do) { 234 case get_values_from_icache: 235 lf_printf(file, "get-values-from-icache"); 236 break; 237 case put_values_in_icache: 238 lf_printf(file, "put-values-in-icache"); 239 break; 240 case both_values_and_icache: 241 lf_printf(file, "get-values-from-icache|put-values-in-icache"); 242 break; 243 case do_not_use_icache: 244 lf_printf(file, "do-not-use-icache"); 245 break; 246 } 247 lf_printf(file, " */\n"); 248 249 for (cur_field = instruction->fields->first; 250 cur_field->first < insn_bit_size; 251 cur_field = cur_field->next) { 252 if (cur_field->is_string) { 253 insn_bits *bits; 254 int found_rule = 0; 255 /* find any corresponding value */ 256 for (bits = expanded_bits; 257 bits != NULL; 258 bits = bits->last) { 259 if (bits->field == cur_field) 260 break; 261 } 262 /* try the cache rule table for what to do */ 263 { 264 cache_table *cache_rule; 265 for (cache_rule = cache_rules; 266 cache_rule != NULL; 267 cache_rule = cache_rule->next) { 268 if (strcmp(cur_field->val_string, cache_rule->field_name) == 0) { 269 found_rule = 1; 270 if (cache_rule->type == scratch_value 271 && ((what_to_do & put_values_in_icache) 272 || what_to_do == do_not_use_icache)) 273 print_icache_extraction(file, 274 instruction, 275 cache_rule->derived_name, 276 cache_rule->type_def, 277 cache_rule->expression, 278 cache_rule->field_name, 279 cache_rule->file_entry->file_name, 280 cache_rule->file_entry->line_nr, 281 cur_field, 282 bits, 283 what_to_declare, 284 do_not_use_icache, 285 "icache scratch"); 286 else if (cache_rule->type == compute_value 287 && ((what_to_do & get_values_from_icache) 288 || what_to_do == do_not_use_icache)) 289 print_icache_extraction(file, 290 instruction, 291 cache_rule->derived_name, 292 cache_rule->type_def, 293 cache_rule->expression, 294 cache_rule->field_name, 295 cache_rule->file_entry->file_name, 296 cache_rule->file_entry->line_nr, 297 cur_field, 298 bits, 299 what_to_declare, 300 do_not_use_icache, 301 "semantic compute"); 302 else if (cache_rule->type == cache_value 303 && ((what_to_declare != undef_variables) 304 || !(what_to_do & put_values_in_icache))) 305 print_icache_extraction(file, 306 instruction, 307 cache_rule->derived_name, 308 cache_rule->type_def, 309 cache_rule->expression, 310 cache_rule->field_name, 311 cache_rule->file_entry->file_name, 312 cache_rule->file_entry->line_nr, 313 cur_field, 314 bits, 315 ((what_to_do & put_values_in_icache) 316 ? declare_variables 317 : what_to_declare), 318 what_to_do, 319 "in icache"); 320 } 321 } 322 } 323 /* No rule at all, assume that this is needed in the semantic 324 function (when values are extracted from the icache) and 325 hence must be put into the cache */ 326 if (found_rule == 0 327 && ((what_to_declare != undef_variables) 328 || !(what_to_do & put_values_in_icache))) 329 print_icache_extraction(file, 330 instruction, 331 cur_field->val_string, 332 NULL, NULL, NULL, /* type, exp, orig */ 333 instruction->file_entry->file_name, 334 instruction->file_entry->line_nr, 335 cur_field, 336 bits, 337 ((what_to_do & put_values_in_icache) 338 ? declare_variables 339 : what_to_declare), 340 what_to_do, 341 "default in icache"); 342 /* any thing else ... */ 343 } 344 } 345 346 lf_print__internal_reference(file); 347 348 if ((code & generate_with_insn_in_icache)) { 349 lf_printf(file, "\n"); 350 print_icache_extraction(file, 351 instruction, 352 "insn", 353 "instruction_word", 354 "instruction", 355 NULL, /* origin */ 356 NULL, 0, /* file_name & line_nr */ 357 NULL, NULL, 358 what_to_declare, 359 what_to_do, 360 NULL); 361 } 362 } 363 364 365 366 typedef struct _icache_tree icache_tree; 367 struct _icache_tree { 368 char *name; 369 icache_tree *next; 370 icache_tree *children; 371 }; 372 373 static icache_tree * 374 icache_tree_insert(icache_tree *tree, 375 char *name) 376 { 377 icache_tree *new_tree; 378 /* find it */ 379 icache_tree **ptr_to_cur_tree = &tree->children; 380 icache_tree *cur_tree = *ptr_to_cur_tree; 381 while (cur_tree != NULL 382 && strcmp(cur_tree->name, name) < 0) { 383 ptr_to_cur_tree = &cur_tree->next; 384 cur_tree = *ptr_to_cur_tree; 385 } 386 ASSERT(cur_tree == NULL 387 || strcmp(cur_tree->name, name) >= 0); 388 /* already in the tree */ 389 if (cur_tree != NULL 390 && strcmp(cur_tree->name, name) == 0) 391 return cur_tree; 392 /* missing, insert it */ 393 ASSERT(cur_tree == NULL 394 || strcmp(cur_tree->name, name) > 0); 395 new_tree = ZALLOC(icache_tree); 396 new_tree->name = name; 397 new_tree->next = cur_tree; 398 *ptr_to_cur_tree = new_tree; 399 return new_tree; 400 } 401 402 403 static icache_tree * 404 insn_table_cache_fields(insn_table *table) 405 { 406 icache_tree *tree = ZALLOC(icache_tree); 407 insn *instruction; 408 for (instruction = table->insns; 409 instruction != NULL; 410 instruction = instruction->next) { 411 insn_field *field; 412 icache_tree *form = 413 icache_tree_insert(tree, 414 instruction->file_entry->fields[insn_form]); 415 for (field = instruction->fields->first; 416 field != NULL; 417 field = field->next) { 418 if (field->is_string) 419 icache_tree_insert(form, field->val_string); 420 } 421 } 422 return tree; 423 } 424 425 426 427 extern void 428 print_icache_struct(insn_table *instructions, 429 cache_table *cache_rules, 430 lf *file) 431 { 432 icache_tree *tree = insn_table_cache_fields(instructions); 433 434 lf_printf(file, "\n"); 435 lf_printf(file, "#define WITH_IDECODE_CACHE_SIZE %d\n", 436 (code & generate_with_icache) ? icache_size : 0); 437 lf_printf(file, "\n"); 438 439 /* create an instruction cache if being used */ 440 if ((code & generate_with_icache)) { 441 icache_tree *form; 442 lf_printf(file, "typedef struct _idecode_cache {\n"); 443 lf_printf(file, " unsigned_word address;\n"); 444 lf_printf(file, " void *semantic;\n"); 445 lf_printf(file, " union {\n"); 446 for (form = tree->children; 447 form != NULL; 448 form = form->next) { 449 icache_tree *field; 450 lf_printf(file, " struct {\n"); 451 if (code & generate_with_insn_in_icache) 452 lf_printf(file, " instruction_word insn;\n"); 453 for (field = form->children; 454 field != NULL; 455 field = field->next) { 456 cache_table *cache_rule; 457 int found_rule = 0; 458 for (cache_rule = cache_rules; 459 cache_rule != NULL; 460 cache_rule = cache_rule->next) { 461 if (strcmp(field->name, cache_rule->field_name) == 0) { 462 found_rule = 1; 463 if (cache_rule->derived_name != NULL) 464 lf_printf(file, " %s %s; /* %s */\n", 465 (cache_rule->type_def == NULL 466 ? "unsigned" 467 : cache_rule->type_def), 468 cache_rule->derived_name, 469 cache_rule->field_name); 470 } 471 } 472 if (!found_rule) 473 lf_printf(file, " unsigned %s;\n", field->name); 474 } 475 lf_printf(file, " } %s;\n", form->name); 476 } 477 lf_printf(file, " } crack;\n"); 478 lf_printf(file, "} idecode_cache;\n"); 479 } 480 else { 481 /* alernativly, since no cache, emit a dummy definition for 482 idecode_cache so that code refering to the type can still compile */ 483 lf_printf(file, "typedef void idecode_cache;\n"); 484 } 485 lf_printf(file, "\n"); 486 } 487 488 489 490 static void 491 print_icache_function(lf *file, 492 insn *instruction, 493 insn_bits *expanded_bits, 494 opcode_field *opcodes, 495 cache_table *cache_rules) 496 { 497 int indent; 498 499 /* generate code to enter decoded instruction into the icache */ 500 lf_printf(file, "\n"); 501 lf_print_function_type(file, ICACHE_FUNCTION_TYPE, "EXTERN_ICACHE", "\n"); 502 indent = print_function_name(file, 503 instruction->file_entry->fields[insn_name], 504 expanded_bits, 505 function_name_prefix_icache); 506 lf_indent(file, +indent); 507 lf_printf(file, "(%s)\n", ICACHE_FUNCTION_FORMAL); 508 lf_indent(file, -indent); 509 510 /* function header */ 511 lf_printf(file, "{\n"); 512 lf_indent(file, +2); 513 514 print_my_defines(file, expanded_bits, instruction->file_entry); 515 print_itrace(file, instruction->file_entry, 1/*putting-value-in-cache*/); 516 517 print_idecode_validate(file, instruction, opcodes); 518 519 lf_printf(file, "\n"); 520 lf_printf(file, "{\n"); 521 lf_indent(file, +2); 522 if ((code & generate_with_semantic_icache)) 523 lf_printf(file, "unsigned_word nia;\n"); 524 print_icache_body(file, 525 instruction, 526 expanded_bits, 527 cache_rules, 528 ((code & generate_with_direct_access) 529 ? define_variables 530 : declare_variables), 531 ((code & generate_with_semantic_icache) 532 ? both_values_and_icache 533 : put_values_in_icache)); 534 535 lf_printf(file, "\n"); 536 lf_printf(file, "cache_entry->address = cia;\n"); 537 lf_printf(file, "cache_entry->semantic = "); 538 print_function_name(file, 539 instruction->file_entry->fields[insn_name], 540 expanded_bits, 541 function_name_prefix_semantics); 542 lf_printf(file, ";\n"); 543 lf_printf(file, "\n"); 544 545 if ((code & generate_with_semantic_icache)) { 546 lf_printf(file, "/* semantic routine */\n"); 547 print_semantic_body(file, 548 instruction, 549 expanded_bits, 550 opcodes); 551 lf_printf(file, "return nia;\n"); 552 } 553 554 if (!(code & generate_with_semantic_icache)) { 555 lf_printf(file, "/* return the function proper */\n"); 556 lf_printf(file, "return "); 557 print_function_name(file, 558 instruction->file_entry->fields[insn_name], 559 expanded_bits, 560 function_name_prefix_semantics); 561 lf_printf(file, ";\n"); 562 } 563 564 if ((code & generate_with_direct_access)) 565 print_icache_body(file, 566 instruction, 567 expanded_bits, 568 cache_rules, 569 undef_variables, 570 ((code & generate_with_semantic_icache) 571 ? both_values_and_icache 572 : put_values_in_icache)); 573 574 lf_indent(file, -2); 575 lf_printf(file, "}\n"); 576 lf_indent(file, -2); 577 lf_printf(file, "}\n"); 578 } 579 580 581 void 582 print_icache_definition(insn_table *entry, 583 lf *file, 584 void *data, 585 insn *instruction, 586 int depth) 587 { 588 cache_table *cache_rules = (cache_table*)data; 589 if (generate_expanded_instructions) { 590 ASSERT(entry->nr_insn == 1 591 && entry->opcode == NULL 592 && entry->parent != NULL 593 && entry->parent->opcode != NULL); 594 ASSERT(entry->nr_insn == 1 595 && entry->opcode == NULL 596 && entry->parent != NULL 597 && entry->parent->opcode != NULL 598 && entry->parent->opcode_rule != NULL); 599 print_icache_function(file, 600 entry->insns, 601 entry->expanded_bits, 602 entry->opcode, 603 cache_rules); 604 } 605 else { 606 print_icache_function(file, 607 instruction, 608 NULL, 609 NULL, 610 cache_rules); 611 } 612 } 613 614 615 616 void 617 print_icache_internal_function_declaration(insn_table *table, 618 lf *file, 619 void *data, 620 table_entry *function) 621 { 622 ASSERT((code & generate_with_icache) != 0); 623 if (it_is("internal", function->fields[insn_flags])) { 624 lf_printf(file, "\n"); 625 lf_print_function_type(file, ICACHE_FUNCTION_TYPE, "PSIM_INLINE_ICACHE", 626 "\n"); 627 print_function_name(file, 628 function->fields[insn_name], 629 NULL, 630 function_name_prefix_icache); 631 lf_printf(file, "\n(%s);\n", ICACHE_FUNCTION_FORMAL); 632 } 633 } 634 635 636 void 637 print_icache_internal_function_definition(insn_table *table, 638 lf *file, 639 void *data, 640 table_entry *function) 641 { 642 ASSERT((code & generate_with_icache) != 0); 643 if (it_is("internal", function->fields[insn_flags])) { 644 lf_printf(file, "\n"); 645 lf_print_function_type(file, ICACHE_FUNCTION_TYPE, "PSIM_INLINE_ICACHE", 646 "\n"); 647 print_function_name(file, 648 function->fields[insn_name], 649 NULL, 650 function_name_prefix_icache); 651 lf_printf(file, "\n(%s)\n", ICACHE_FUNCTION_FORMAL); 652 lf_printf(file, "{\n"); 653 lf_indent(file, +2); 654 lf_printf(file, "/* semantic routine */\n"); 655 table_entry_print_cpp_line_nr(file, function); 656 if ((code & generate_with_semantic_icache)) { 657 lf_print__c_code(file, function->annex); 658 lf_printf(file, "error(\"Internal function must longjump\\n\");\n"); 659 lf_printf(file, "return 0;\n"); 660 } 661 else { 662 lf_printf(file, "return "); 663 print_function_name(file, 664 function->fields[insn_name], 665 NULL, 666 function_name_prefix_semantics); 667 lf_printf(file, ";\n"); 668 } 669 670 lf_print__internal_reference(file); 671 lf_indent(file, -2); 672 lf_printf(file, "}\n"); 673 } 674 } 675