dgen.c 8.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336
  1. /* This file is part of the program psim.
  2. Copyright (C) 1994-1995, 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 <sys/types.h>
  15. #include <sys/stat.h>
  16. #include <fcntl.h>
  17. #include <getopt.h>
  18. #include <stdio.h>
  19. #include <ctype.h>
  20. #include <stdarg.h>
  21. #include "build-config.h"
  22. #include "misc.h"
  23. #include "lf.h"
  24. #include "table.h"
  25. #ifdef HAVE_UNISTD_H
  26. #include <unistd.h>
  27. #endif
  28. #ifdef HAVE_STDLIB_H
  29. #include <stdlib.h>
  30. #endif
  31. #ifdef HAVE_STRING_H
  32. #include <string.h>
  33. #else
  34. #ifdef HAVE_STRINGS_H
  35. #include <strings.h>
  36. #endif
  37. #endif
  38. /****************************************************************/
  39. int spreg_lookup_table = 1;
  40. enum {
  41. nr_of_sprs = 1024,
  42. };
  43. /****************************************************************/
  44. typedef enum {
  45. spreg_name,
  46. spreg_reg_nr,
  47. spreg_readonly,
  48. spreg_length,
  49. nr_spreg_fields,
  50. } spreg_fields;
  51. typedef struct _spreg_table_entry spreg_table_entry;
  52. struct _spreg_table_entry {
  53. char *name;
  54. int spreg_nr;
  55. int is_readonly;
  56. int length;
  57. table_entry *entry;
  58. spreg_table_entry *next;
  59. };
  60. typedef struct _spreg_table spreg_table;
  61. struct _spreg_table {
  62. spreg_table_entry *sprs;
  63. };
  64. static void
  65. spreg_table_insert(spreg_table *table, table_entry *entry)
  66. {
  67. /* create a new spr entry */
  68. spreg_table_entry *new_spr = ZALLOC(spreg_table_entry);
  69. new_spr->next = NULL;
  70. new_spr->entry = entry;
  71. new_spr->spreg_nr = atoi(entry->fields[spreg_reg_nr]);
  72. new_spr->is_readonly = (entry->fields[spreg_readonly]
  73. ? atoi(entry->fields[spreg_readonly])
  74. : 0);
  75. new_spr->length = atoi(entry->fields[spreg_length]);
  76. new_spr->name = (char*)zalloc(strlen(entry->fields[spreg_name]) + 1);
  77. ASSERT(new_spr->name != NULL);
  78. {
  79. int i;
  80. for (i = 0; entry->fields[spreg_name][i] != '\0'; i++) {
  81. if (isupper(entry->fields[spreg_name][i]))
  82. new_spr->name[i] = tolower(entry->fields[spreg_name][i]);
  83. else
  84. new_spr->name[i] = entry->fields[spreg_name][i];
  85. }
  86. }
  87. /* insert, by spreg_nr order */
  88. {
  89. spreg_table_entry **ptr_to_spreg_entry = &table->sprs;
  90. spreg_table_entry *spreg_entry = *ptr_to_spreg_entry;
  91. while (spreg_entry != NULL && spreg_entry->spreg_nr < new_spr->spreg_nr) {
  92. ptr_to_spreg_entry = &spreg_entry->next;
  93. spreg_entry = *ptr_to_spreg_entry;
  94. }
  95. ASSERT(spreg_entry == NULL || spreg_entry->spreg_nr != new_spr->spreg_nr);
  96. *ptr_to_spreg_entry = new_spr;
  97. new_spr->next = spreg_entry;
  98. }
  99. }
  100. static spreg_table *
  101. spreg_table_load(char *file_name)
  102. {
  103. table *file = table_open(file_name, nr_spreg_fields, 0);
  104. spreg_table *table = ZALLOC(spreg_table);
  105. {
  106. table_entry *entry;
  107. while ((entry = table_entry_read(file)) != NULL) {
  108. spreg_table_insert(table, entry);
  109. }
  110. }
  111. return table;
  112. }
  113. /****************************************************************/
  114. char *spreg_attributes[] = {
  115. "is_valid",
  116. "is_readonly",
  117. "name",
  118. "index",
  119. "length",
  120. 0
  121. };
  122. static void
  123. gen_spreg_h(spreg_table *table, lf *file)
  124. {
  125. spreg_table_entry *entry;
  126. char **attribute;
  127. lf_print__gnu_copyleft(file);
  128. lf_printf(file, "\n");
  129. lf_printf(file, "#ifndef _SPREG_H_\n");
  130. lf_printf(file, "#define _SPREG_H_\n");
  131. lf_printf(file, "\n");
  132. lf_printf(file, "typedef unsigned_word spreg;\n");
  133. lf_printf(file, "\n");
  134. lf_printf(file, "typedef enum {\n");
  135. for (entry = table->sprs;
  136. entry != NULL ;
  137. entry = entry->next) {
  138. lf_printf(file, " spr_%s = %d,\n", entry->name, entry->spreg_nr);
  139. }
  140. lf_printf(file, " nr_of_sprs = %d\n", nr_of_sprs);
  141. lf_printf(file, "} sprs;\n");
  142. lf_printf(file, "\n");
  143. for (attribute = spreg_attributes;
  144. *attribute != NULL;
  145. attribute++) {
  146. if (strcmp(*attribute, "name") == 0) {
  147. lf_print_function_type(file, "const char *", "INLINE_SPREG", " ");
  148. lf_printf(file, "spr_%s(sprs spr);\n", *attribute);
  149. }
  150. else {
  151. lf_print_function_type(file, "int", "INLINE_SPREG", " ");
  152. lf_printf(file, "spr_%s(sprs spr);\n", *attribute);
  153. }
  154. }
  155. lf_printf(file, "\n");
  156. lf_printf(file, "#endif /* _SPREG_H_ */\n");
  157. }
  158. static void
  159. gen_spreg_c(spreg_table *table, lf *file)
  160. {
  161. spreg_table_entry *entry;
  162. char **attribute;
  163. int spreg_nr;
  164. lf_print__gnu_copyleft(file);
  165. lf_printf(file, "\n");
  166. lf_printf(file, "#ifndef _SPREG_C_\n");
  167. lf_printf(file, "#define _SPREG_C_\n");
  168. lf_printf(file, "\n");
  169. lf_printf(file, "#include \"basics.h\"\n");
  170. lf_printf(file, "#include \"spreg.h\"\n");
  171. lf_printf(file, "\n");
  172. lf_printf(file, "typedef struct _spreg_info {\n");
  173. lf_printf(file, " char *name;\n");
  174. lf_printf(file, " int is_valid;\n");
  175. lf_printf(file, " int length;\n");
  176. lf_printf(file, " int is_readonly;\n");
  177. lf_printf(file, " int index;\n");
  178. lf_printf(file, "} spreg_info;\n");
  179. lf_printf(file, "\n");
  180. lf_printf(file, "static spreg_info spr_info[nr_of_sprs+1] = {\n");
  181. entry = table->sprs;
  182. for (spreg_nr = 0; spreg_nr < nr_of_sprs+1; spreg_nr++) {
  183. if (entry == NULL || spreg_nr < entry->spreg_nr)
  184. lf_printf(file, " { 0, 0, 0, 0, %d},\n", spreg_nr);
  185. else {
  186. lf_printf(file, " { \"%s\", %d, %d, %d, spr_%s /*%d*/ },\n",
  187. entry->name, 1, entry->length, entry->is_readonly,
  188. entry->name, entry->spreg_nr);
  189. entry = entry->next;
  190. }
  191. }
  192. lf_printf(file, "};\n");
  193. for (attribute = spreg_attributes;
  194. *attribute != NULL;
  195. attribute++) {
  196. lf_printf(file, "\n");
  197. if (strcmp(*attribute, "name") == 0) {
  198. lf_print_function_type(file, "const char *", "INLINE_SPREG", "\n");
  199. }
  200. else {
  201. lf_print_function_type(file, "int", "INLINE_SPREG", "\n");
  202. }
  203. lf_printf(file, "spr_%s(sprs spr)\n", *attribute);
  204. lf_printf(file, "{\n");
  205. if (spreg_lookup_table
  206. || strcmp(*attribute, "name") == 0
  207. || strcmp(*attribute, "index") == 0)
  208. lf_printf(file, " return spr_info[spr].%s;\n",
  209. *attribute);
  210. else {
  211. spreg_table_entry *entry;
  212. lf_printf(file, " switch (spr) {\n");
  213. for (entry = table->sprs; entry != NULL; entry = entry->next) {
  214. lf_printf(file, " case %d:\n", entry->spreg_nr);
  215. if (strcmp(*attribute, "is_valid") == 0)
  216. lf_printf(file, " return 1;\n");
  217. else if (strcmp(*attribute, "is_readonly") == 0)
  218. lf_printf(file, " return %d;\n", entry->is_readonly);
  219. else if (strcmp(*attribute, "length") == 0)
  220. lf_printf(file, " return %d;\n", entry->length);
  221. else
  222. ASSERT(0);
  223. }
  224. lf_printf(file, " default:\n");
  225. lf_printf(file, " return 0;\n");
  226. lf_printf(file, " }\n");
  227. }
  228. lf_printf(file, "}\n");
  229. }
  230. lf_printf(file, "\n");
  231. lf_printf(file, "#endif /* _SPREG_C_ */\n");
  232. }
  233. /****************************************************************/
  234. int
  235. main(int argc,
  236. char **argv,
  237. char **envp)
  238. {
  239. lf_file_references file_references = lf_include_references;
  240. spreg_table *sprs = NULL;
  241. char *real_file_name = NULL;
  242. int is_header = 0;
  243. int ch;
  244. if (argc <= 1) {
  245. printf("Usage: dgen ...\n");
  246. printf("-s Use switch instead of table\n");
  247. printf("-n <file-name> Use this as cpp line numbering name\n");
  248. printf("-h Output header file\n");
  249. printf("-p <spreg-file> Output spreg.h(P) or spreg.c(p)\n");
  250. printf("-L Suppress cpp line numbering in output files\n");
  251. }
  252. while ((ch = getopt(argc, argv, "hLsn:r:p:")) != -1) {
  253. fprintf(stderr, "\t-%c %s\n", ch, ( optarg ? optarg : ""));
  254. switch(ch) {
  255. case 's':
  256. spreg_lookup_table = 0;
  257. break;
  258. case 'r':
  259. sprs = spreg_table_load(optarg);
  260. break;
  261. case 'n':
  262. real_file_name = strdup(optarg);
  263. break;
  264. case 'L':
  265. file_references = lf_omit_references;
  266. break;
  267. case 'h':
  268. is_header = 1;
  269. break;
  270. case 'p':
  271. {
  272. lf *file = lf_open(optarg, real_file_name, file_references,
  273. (is_header ? lf_is_h : lf_is_c),
  274. argv[0]);
  275. if (is_header)
  276. gen_spreg_h(sprs, file);
  277. else
  278. gen_spreg_c(sprs, file);
  279. lf_close(file);
  280. is_header = 0;
  281. }
  282. real_file_name = NULL;
  283. break;
  284. default:
  285. error("unknown option\n");
  286. }
  287. }
  288. return 0;
  289. }