gen-icache.c 19 KB

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