igen.c 15 KB

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