2 * genmdesc: Generates the machine description
5 * Paolo Molaro (lupus@ximian.com)
7 * (C) 2003 Ximian, Inc.
12 #include <mono/metadata/opcodes.h>
19 char spec [MONO_INST_MAX];
22 static GHashTable *table;
24 #define eat_whitespace(s) while (*(s) && isspace (*(s))) s++;
27 load_file (const char *name) {
35 if (!(f = fopen (name, "r")))
36 g_error ("Cannot open file '%s'", name);
38 comment = g_string_new ("");
40 * The format of the lines are:
42 * opcode: [dest:format] [src1:format] [src2:format] [flags:format] [clob:format]
43 * [cost:num] [res:format] [delay:num] [len:num]
44 * format is a single letter that depends on the field
45 * NOTE: no space between the field name and the ':'
47 * len: maximum instruction length
50 while ((str = fgets (buf, sizeof (buf), f))) {
56 g_string_append (comment, str);
59 p = strchr (str, ':');
61 g_error ("Invalid format at line %d in %s\n", line, name);
64 desc = g_hash_table_lookup (table, str);
66 g_error ("Invalid opcode '%s' at line %d in %s\n", str, line, name);
68 g_error ("Duplicated opcode '%s' at line %d in %s\n", str, line, name);
69 desc->desc = g_strdup (p);
70 desc->comment = g_strdup (comment->str);
71 g_string_truncate (comment, 0);
73 if (strncmp (p, "dest:", 5) == 0) {
74 desc->spec [MONO_INST_DEST] = p [5];
76 } else if (strncmp (p, "src1:", 5) == 0) {
77 desc->spec [MONO_INST_SRC1] = p [5];
79 } else if (strncmp (p, "src2:", 5) == 0) {
80 desc->spec [MONO_INST_SRC2] = p [5];
82 } else if (strncmp (p, "cost:", 5) == 0) {
83 desc->spec [MONO_INST_COST] = p [5];
85 } else if (strncmp (p, "clob:", 5) == 0) {
86 desc->spec [MONO_INST_CLOB] = p [5];
88 } else if (strncmp (p, "res:", 4) == 0) {
89 desc->spec [MONO_INST_RES] = p [4];
91 } else if (strncmp (p, "flags:", 6) == 0) {
92 desc->spec [MONO_INST_FLAGS] = p [6];
94 } else if (strncmp (p, "delay:", 6) == 0) {
95 desc->spec [MONO_INST_DELAY] = p [6];
97 } else if (strncmp (p, "len:", 4) == 0) {
99 desc->spec [MONO_INST_LEN] = strtoul (p, &p, 10);
101 g_error ("Parse error at '%s' at line %d in %s\n", p, line, name);
110 static OpDesc *opcodes = NULL;
117 table = g_hash_table_new (g_str_hash, g_str_equal);
119 opcodes = g_new0 (OpDesc, OP_LAST);
120 for (i = 0; i < MONO_CEE_LAST; ++i) {
123 desc->name = mono_inst_name (i);
124 g_hash_table_insert (table, (char *)desc->name, desc);
126 for (i = OP_LOAD; i < OP_LAST; ++i) {
129 desc->name = mono_inst_name (i);
130 g_hash_table_insert (table, (char *)desc->name, desc);
135 output_char (FILE *f, char c) {
137 fprintf (f, "%c", c);
139 fprintf (f, "\\x%x\" \"", c);
143 build_table (const char *fname, const char *name) {
148 if (!(f = fopen (fname, "w")))
149 g_error ("Cannot open file '%s'", fname);
150 fprintf (f, "/* File automatically generated by genmdesc, don't change */\n\n");
151 fprintf (f, "static const char * const %s [OP_LAST] = {\n", name);
153 for (i = 0; i < MONO_CEE_LAST; ++i) {
156 fprintf (f, "\tNULL,\t/* %s */\n", desc->name);
159 for (j = 0; j < MONO_INST_MAX; ++j)
160 output_char (f, desc->spec [j]);
161 fprintf (f, "\",\t/* %s */\n", desc->name);
164 for (i = MONO_CEE_LAST; i < OP_LOAD; ++i) {
165 fprintf (f, "\tNULL, /* unassigned */\n");
167 for (i = OP_LOAD; i < OP_LAST; ++i) {
170 fprintf (f, "\tNULL,\t/* %s */\n", desc->name);
173 for (j = 0; j < MONO_INST_MAX; ++j)
174 output_char (f, desc->spec [j]);
175 fprintf (f, "\",\t/* %s */\n", desc->name);
178 fprintf (f, "};\n\n");
187 for (i = 0; i < MONO_CEE_LAST; ++i) {
190 g_print ("%s", desc->comment);
192 g_print ("%s:\n", desc->name);
194 g_print ("%s: %s", desc->name, desc->desc);
195 if (!strchr (desc->desc, '\n'))
199 for (i = OP_LOAD; i < OP_LAST; ++i) {
202 g_print ("%s:\n", desc->name);
204 g_print ("%s: %s", desc->name, desc->desc);
205 if (!strchr (desc->desc, '\n'))
212 * TODO: output the table (possibly merged), in the input format
215 main (int argc, char* argv [])
220 /* useful to get a new file when some opcodes are added: looses the comments, though */
221 load_file (argv [1]);
225 load_file (argv [1]);
226 build_table (argv [2], argv [3]);
229 g_print ("Usage: genmdesc arguments\n");
230 g_print ("\tgenmdesc desc Output to stdout the description file.\n");
231 g_print ("\tgenmdesc desc output name Write to output the description in a table named 'name'.\n");