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