1/* This file is part of the program psim. 2 3 Copyright 1994, 1995, 1996, 1997, 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#include <getopt.h> 21#include <stdlib.h> 22 23#include "misc.h" 24#include "lf.h" 25#include "table.h" 26#include "build-config.h" 27 28#include "filter.h" 29 30#include "ld-cache.h" 31#include "ld-decode.h" 32#include "ld-insn.h" 33 34#include "igen.h" 35 36#include "gen-model.h" 37#include "gen-icache.h" 38#include "gen-itable.h" 39#include "gen-idecode.h" 40#include "gen-semantics.h" 41#include "gen-support.h" 42 43int hi_bit_nr; 44int insn_bit_size = max_insn_bit_size; 45 46igen_code code = generate_calls; 47 48int generate_expanded_instructions; 49int icache_size = 1024; 50int generate_smp; 51 52/****************************************************************/ 53 54static int 55print_insn_bits(lf *file, insn_bits *bits) 56{ 57 int nr = 0; 58 if (bits == NULL) 59 return nr; 60 nr += print_insn_bits(file, bits->last); 61 nr += lf_putchr(file, '_'); 62 nr += lf_putstr(file, bits->field->val_string); 63 if (bits->opcode->is_boolean && bits->value == 0) 64 nr += lf_putint(file, bits->opcode->boolean_constant); 65 else if (!bits->opcode->is_boolean) { 66 if (bits->opcode->last < bits->field->last) 67 nr += lf_putint(file, bits->value << (bits->field->last - bits->opcode->last)); 68 else 69 nr += lf_putint(file, bits->value); 70 } 71 return nr; 72} 73 74extern int 75print_function_name(lf *file, 76 const char *basename, 77 insn_bits *expanded_bits, 78 lf_function_name_prefixes prefix) 79{ 80 int nr = 0; 81 /* the prefix */ 82 switch (prefix) { 83 case function_name_prefix_semantics: 84 nr += lf_putstr(file, "semantic_"); 85 break; 86 case function_name_prefix_idecode: 87 nr += lf_printf(file, "idecode_"); 88 break; 89 case function_name_prefix_itable: 90 nr += lf_putstr(file, "itable_"); 91 break; 92 case function_name_prefix_icache: 93 nr += lf_putstr(file, "icache_"); 94 break; 95 default: 96 break; 97 } 98 99 /* the function name */ 100 { 101 const char *pos; 102 for (pos = basename; 103 *pos != '\0'; 104 pos++) { 105 switch (*pos) { 106 case '/': 107 case '-': 108 case '(': 109 case ')': 110 break; 111 case ' ': 112 nr += lf_putchr(file, '_'); 113 break; 114 default: 115 nr += lf_putchr(file, *pos); 116 break; 117 } 118 } 119 } 120 121 /* the suffix */ 122 if (generate_expanded_instructions) 123 nr += print_insn_bits(file, expanded_bits); 124 125 return nr; 126} 127 128 129void 130print_my_defines(lf *file, 131 insn_bits *expanded_bits, 132 table_entry *file_entry) 133{ 134 /* #define MY_INDEX xxxxx */ 135 lf_indent_suppress(file); 136 lf_printf(file, "#undef MY_INDEX\n"); 137 lf_indent_suppress(file); 138 lf_printf(file, "#define MY_INDEX "); 139 print_function_name(file, 140 file_entry->fields[insn_name], 141 NULL, 142 function_name_prefix_itable); 143 lf_printf(file, "\n"); 144 /* #define MY_PREFIX xxxxxx */ 145 lf_indent_suppress(file); 146 lf_printf(file, "#undef MY_PREFIX\n"); 147 lf_indent_suppress(file); 148 lf_printf(file, "#define MY_PREFIX "); 149 print_function_name(file, 150 file_entry->fields[insn_name], 151 expanded_bits, 152 function_name_prefix_none); 153 lf_printf(file, "\n"); 154} 155 156 157void 158print_itrace(lf *file, 159 table_entry *file_entry, 160 int idecode) 161{ 162 lf_print__external_reference(file, file_entry->line_nr, file_entry->file_name); 163 lf_printf(file, "ITRACE(trace_%s, (\"%s %s\\n\"));\n", 164 (idecode ? "idecode" : "semantics"), 165 (idecode ? "idecode" : "semantics"), 166 file_entry->fields[insn_name]); 167 lf_print__internal_reference(file); 168} 169 170 171/****************************************************************/ 172 173 174static void 175gen_semantics_h(insn_table *table, 176 lf *file, 177 igen_code generate) 178{ 179 lf_printf(file, "typedef %s idecode_semantic\n(%s);\n", 180 SEMANTIC_FUNCTION_TYPE, 181 SEMANTIC_FUNCTION_FORMAL); 182 lf_printf(file, "\n"); 183 if ((code & generate_calls)) { 184 lf_printf(file, "extern int option_mpc860c0;\n"); 185 lf_printf(file, "#define MPC860C0_PAGE_SIZE 0x1000\n"); 186 lf_printf(file, "\n"); 187 lf_printf(file, "PSIM_EXTERN_SEMANTICS(void)\n"); 188 lf_printf(file, "semantic_init(device* root);\n"); 189 lf_printf(file, "\n"); 190 if (generate_expanded_instructions) 191 insn_table_traverse_tree(table, 192 file, NULL, 193 1, 194 NULL, /* start */ 195 print_semantic_declaration, /* leaf */ 196 NULL, /* end */ 197 NULL); /* padding */ 198 else 199 insn_table_traverse_insn(table, 200 file, NULL, 201 print_semantic_declaration); 202 203 } 204 else { 205 lf_print__this_file_is_empty(file); 206 } 207} 208 209 210static void 211gen_semantics_c(insn_table *table, 212 cache_table *cache_rules, 213 lf *file, 214 igen_code generate) 215{ 216 if ((code & generate_calls)) { 217 lf_printf(file, "\n"); 218 lf_printf(file, "#include \"cpu.h\"\n"); 219 lf_printf(file, "#include \"idecode.h\"\n"); 220 lf_printf(file, "#include \"semantics.h\"\n"); 221 lf_printf(file, "#include \"tree.h\"\n"); 222 lf_printf(file, "#ifdef HAVE_COMMON_FPU\n"); 223 lf_printf(file, "#include \"sim-inline.h\"\n"); 224 lf_printf(file, "#include \"sim-fpu.h\"\n"); 225 lf_printf(file, "#endif\n"); 226 lf_printf(file, "#include \"support.h\"\n"); 227 lf_printf(file, "\n"); 228 lf_printf(file, "int option_mpc860c0 = 0;\n"); 229 lf_printf(file, "\n"); 230 lf_printf(file, "PSIM_EXTERN_SEMANTICS(void)\n"); 231 lf_printf(file, "semantic_init(device* root)\n"); 232 lf_printf(file, "{\n"); 233 lf_printf(file, " option_mpc860c0 = 0;\n"); 234 lf_printf(file, " if (tree_find_property(root, \"/options/mpc860c0\"))\n"); 235 lf_printf(file, " option_mpc860c0 = tree_find_integer_property(root, \"/options/mpc860c0\");\n"); 236 lf_printf(file, " option_mpc860c0 *= 4; /* convert word count to byte count */\n"); 237 lf_printf(file, "}\n"); 238 lf_printf(file, "\n"); 239 if (generate_expanded_instructions) 240 insn_table_traverse_tree(table, 241 file, cache_rules, 242 1, 243 NULL, /* start */ 244 print_semantic_definition, /* leaf */ 245 NULL, /* end */ 246 NULL); /* padding */ 247 else 248 insn_table_traverse_insn(table, 249 file, cache_rules, 250 print_semantic_definition); 251 252 } 253 else { 254 lf_print__this_file_is_empty(file); 255 } 256} 257 258 259/****************************************************************/ 260 261 262static void 263gen_icache_h(insn_table *table, 264 lf *file, 265 igen_code generate) 266{ 267 lf_printf(file, "typedef %s idecode_icache\n(%s);\n", 268 ICACHE_FUNCTION_TYPE, 269 ICACHE_FUNCTION_FORMAL); 270 lf_printf(file, "\n"); 271 if ((code & generate_calls) 272 && (code & generate_with_icache)) { 273 insn_table_traverse_function(table, 274 file, NULL, 275 print_icache_internal_function_declaration); 276 if (generate_expanded_instructions) 277 insn_table_traverse_tree(table, 278 file, NULL, 279 1, 280 NULL, /* start */ 281 print_icache_declaration, /* leaf */ 282 NULL, /* end */ 283 NULL); /* padding */ 284 else 285 insn_table_traverse_insn(table, 286 file, NULL, 287 print_icache_declaration); 288 289 } 290 else { 291 lf_print__this_file_is_empty(file); 292 } 293} 294 295static void 296gen_icache_c(insn_table *table, 297 cache_table *cache_rules, 298 lf *file, 299 igen_code generate) 300{ 301 /* output `internal' invalid/floating-point unavailable functions 302 where needed */ 303 if ((code & generate_calls) 304 && (code & generate_with_icache)) { 305 lf_printf(file, "\n"); 306 lf_printf(file, "#include \"cpu.h\"\n"); 307 lf_printf(file, "#include \"idecode.h\"\n"); 308 lf_printf(file, "#include \"semantics.h\"\n"); 309 lf_printf(file, "#include \"icache.h\"\n"); 310 lf_printf(file, "#ifdef HAVE_COMMON_FPU\n"); 311 lf_printf(file, "#include \"sim-inline.h\"\n"); 312 lf_printf(file, "#include \"sim-fpu.h\"\n"); 313 lf_printf(file, "#endif\n"); 314 lf_printf(file, "#include \"support.h\"\n"); 315 lf_printf(file, "\n"); 316 insn_table_traverse_function(table, 317 file, NULL, 318 print_icache_internal_function_definition); 319 lf_printf(file, "\n"); 320 if (generate_expanded_instructions) 321 insn_table_traverse_tree(table, 322 file, cache_rules, 323 1, 324 NULL, /* start */ 325 print_icache_definition, /* leaf */ 326 NULL, /* end */ 327 NULL); /* padding */ 328 else 329 insn_table_traverse_insn(table, 330 file, cache_rules, 331 print_icache_definition); 332 333 } 334 else { 335 lf_print__this_file_is_empty(file); 336 } 337} 338 339 340/****************************************************************/ 341 342 343int 344main(int argc, 345 char **argv, 346 char **envp) 347{ 348 cache_table *cache_rules = NULL; 349 lf_file_references file_references = lf_include_references; 350 decode_table *decode_rules = NULL; 351 filter *filters = NULL; 352 insn_table *instructions = NULL; 353 table_include *includes = NULL; 354 static const struct option longopts[] = { { 0 } }; 355 char *real_file_name = NULL; 356 int is_header = 0; 357 int ch; 358 359 if (argc == 1) { 360 printf("Usage:\n"); 361 printf(" igen <config-opts> ... <input-opts>... <output-opts>...\n"); 362 printf("Config options:\n"); 363 printf(" -F <filter-out-flag> eg -F 64 to skip 64bit instructions\n"); 364 printf(" -E Expand (duplicate) semantic functions\n"); 365 printf(" -I <icache-size> Generate cracking cache version\n"); 366 printf(" -C Include semantics in cache functions\n"); 367 printf(" -S Include insn (instruction) in icache\n"); 368 printf(" -R Use defines to reference cache vars\n"); 369 printf(" -L Supress line numbering in output files\n"); 370 printf(" -B <bit-size> Set the number of bits in an instruction\n"); 371 printf(" -H <high-bit> Set the nr of the high (msb bit)\n"); 372 printf(" -N <nr-cpus> Specify the max number of cpus the simulation will support\n"); 373 printf(" -J Use jumps instead of function calls\n"); 374 printf(" -T <mechanism> Override the mechanism used to decode an instruction\n"); 375 printf(" using <mechanism> instead of what was specified in the\n"); 376 printf(" decode-rules input file\n"); 377 printf("\n"); 378 printf("Input options (ucase version also dumps loaded table):\n"); 379 printf(" -o <decode-rules>\n"); 380 printf(" -k <cache-rules>\n"); 381 printf(" -i <instruction-table>\n"); 382 printf("\n"); 383 printf("Output options:\n"); 384 printf(" -n <real-name> Specify the real name of for the next output file\n"); 385 printf(" -h Generate header file\n"); 386 printf(" -c <output-file> output icache\n"); 387 printf(" -d <output-file> output idecode\n"); 388 printf(" -m <output-file> output model\n"); 389 printf(" -s <output-file> output schematic\n"); 390 printf(" -t <output-file> output itable\n"); 391 printf(" -f <output-file> output support functions\n"); 392 } 393 394 while ( 395 (ch = getopt_long (argc, argv, "F:EI:RSLJT:CB:H:N:o:k:i:n:hc:d:m:s:t:f:", 396 longopts, NULL)) 397 != -1) 398 { 399#if 0 /* For debugging. */ 400 fprintf(stderr, "\t-%c %s\n", ch, (optarg ? optarg : "")); 401#endif 402 switch(ch) { 403 case 'C': 404 code |= generate_with_icache; 405 code |= generate_with_semantic_icache; 406 break; 407 case 'S': 408 code |= generate_with_icache; 409 code |= generate_with_insn_in_icache; 410 break; 411 case 'L': 412 file_references = lf_omit_references; 413 break; 414 case 'E': 415 generate_expanded_instructions = 1; 416 break; 417 case 'G': 418 { 419 int enable_p; 420 char *argp; 421 if (strncmp (optarg, "no-", strlen ("no-")) == 0) 422 { 423 argp = optarg + strlen ("no-"); 424 enable_p = 0; 425 } 426 else if (strncmp (optarg, "!", strlen ("!")) == 0) 427 { 428 argp = optarg + strlen ("no-"); 429 enable_p = 0; 430 } 431 else 432 { 433 argp = optarg; 434 enable_p = 1; 435 } 436 if (strncmp (argp, "gen-icache", strlen ("gen-icache")) == 0) 437 { 438 switch (argp[strlen ("gen-icache")]) 439 { 440 case '=': 441 icache_size = atoi (argp + strlen ("gen-icache") + 1); 442 code |= generate_with_icache; 443 break; 444 case '\0': 445 code |= generate_with_icache; 446 break; 447 default: 448 error ("Expecting -Ggen-icache or -Ggen-icache=<N>\n"); 449 } 450 } 451 } 452 case 'I': 453 { 454 table_include **dir = &includes; 455 while ((*dir) != NULL) 456 dir = &(*dir)->next; 457 (*dir) = ZALLOC (table_include); 458 (*dir)->dir = strdup (optarg); 459 } 460 break; 461 case 'N': 462 generate_smp = a2i(optarg); 463 break; 464 case 'R': 465 code |= generate_with_direct_access; 466 break; 467 case 'B': 468 insn_bit_size = a2i(optarg); 469 ASSERT(insn_bit_size > 0 && insn_bit_size <= max_insn_bit_size 470 && (hi_bit_nr == insn_bit_size-1 || hi_bit_nr == 0)); 471 break; 472 case 'H': 473 hi_bit_nr = a2i(optarg); 474 ASSERT(hi_bit_nr == insn_bit_size-1 || hi_bit_nr == 0); 475 break; 476 case 'F': 477 filters = new_filter(optarg, filters); 478 break; 479 case 'J': 480 code &= ~generate_calls; 481 code |= generate_jumps; 482 break; 483 case 'T': 484 force_decode_gen_type(optarg); 485 break; 486 case 'i': 487 if (decode_rules == NULL) { 488 fprintf(stderr, "Must specify decode tables\n"); 489 exit (1); 490 } 491 instructions = load_insn_table(optarg, decode_rules, filters, includes, 492 &cache_rules); 493 fprintf(stderr, "\texpanding ...\n"); 494 insn_table_expand_insns(instructions); 495 break; 496 case 'o': 497 decode_rules = load_decode_table(optarg, hi_bit_nr); 498 break; 499 case 'k': 500 cache_rules = load_cache_table(optarg, hi_bit_nr); 501 break; 502 case 'n': 503 real_file_name = strdup(optarg); 504 break; 505 case 'h': 506 is_header = 1; 507 break; 508 case 's': 509 case 'd': 510 case 'm': 511 case 't': 512 case 'f': 513 case 'c': 514 { 515 lf *file = lf_open(optarg, real_file_name, file_references, 516 (is_header ? lf_is_h : lf_is_c), 517 argv[0]); 518 lf_print__file_start(file); 519 ASSERT(instructions != NULL); 520 switch (ch) { 521 case 's': 522 if(is_header) 523 gen_semantics_h(instructions, file, code); 524 else 525 gen_semantics_c(instructions, cache_rules, file, code); 526 break; 527 case 'd': 528 if (is_header) 529 gen_idecode_h(file, instructions, cache_rules); 530 else 531 gen_idecode_c(file, instructions, cache_rules); 532 break; 533 case 'm': 534 if (is_header) 535 gen_model_h(instructions, file); 536 else 537 gen_model_c(instructions, file); 538 break; 539 case 't': 540 if (is_header) 541 gen_itable_h(instructions, file); 542 else 543 gen_itable_c(instructions, file); 544 break; 545 case 'f': 546 if (is_header) 547 gen_support_h(instructions, file); 548 else 549 gen_support_c(instructions, file); 550 break; 551 case 'c': 552 if (is_header) 553 gen_icache_h(instructions, file, code); 554 else 555 gen_icache_c(instructions, cache_rules, file, code); 556 break; 557 } 558 lf_print__file_finish(file); 559 lf_close(file); 560 is_header = 0; 561 } 562 real_file_name = NULL; 563 break; 564 default: 565 error("unknown option\n"); 566 } 567 } 568 return 0; 569} 570