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