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