Commit | Line | Data |
---|---|---|
c906108c SS |
1 | /* This file is part of the program psim. |
2 | ||
3 | Copyright (C) 1994-1995, Andrew Cagney <cagney@highland.com.au> | |
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 | #include "misc.h" | |
23 | #include "lf.h" | |
24 | #include "table.h" | |
25 | ||
26 | #include "filter.h" | |
27 | ||
28 | #include "ld-decode.h" | |
29 | #include "ld-insn.h" | |
30 | ||
31 | #include "gen-model.h" | |
32 | ||
33 | #ifndef NULL | |
34 | #define NULL 0 | |
35 | #endif | |
36 | ||
37 | ||
38 | static void | |
39 | model_c_or_h_data(insn_table *table, | |
40 | lf *file, | |
41 | table_entry *data) | |
42 | { | |
43 | if (data->annex) { | |
44 | table_entry_print_cpp_line_nr(file, data); | |
45 | lf_print__c_code(file, data->annex); | |
46 | lf_print__internal_reference(file); | |
47 | lf_printf(file, "\n"); | |
48 | } | |
49 | } | |
50 | ||
51 | static void | |
52 | model_c_or_h_function(insn_table *entry, | |
53 | lf *file, | |
54 | table_entry *function, | |
55 | char *prefix) | |
56 | { | |
57 | if (function->fields[function_type] == NULL | |
58 | || function->fields[function_type][0] == '\0') { | |
59 | error("Model function type not specified for %s", function->fields[function_name]); | |
60 | } | |
61 | lf_printf(file, "\n"); | |
62 | lf_print_function_type(file, function->fields[function_type], prefix, " "); | |
63 | lf_printf(file, "%s\n(%s);\n", | |
64 | function->fields[function_name], | |
65 | function->fields[function_param]); | |
66 | lf_printf(file, "\n"); | |
67 | } | |
68 | ||
69 | void | |
70 | gen_model_h(insn_table *table, lf *file) | |
71 | { | |
72 | insn *insn_ptr; | |
73 | model *model_ptr; | |
74 | insn *macro; | |
75 | char *name; | |
76 | int model_create_p = 0; | |
77 | int model_init_p = 0; | |
78 | int model_halt_p = 0; | |
79 | int model_mon_info_p = 0; | |
80 | int model_mon_info_free_p = 0; | |
81 | ||
82 | for(macro = model_macros; macro; macro = macro->next) { | |
83 | model_c_or_h_data(table, file, macro->file_entry); | |
84 | } | |
85 | ||
86 | lf_printf(file, "typedef enum _model_enum {\n"); | |
87 | lf_printf(file, " MODEL_NONE,\n"); | |
88 | for (model_ptr = models; model_ptr; model_ptr = model_ptr->next) { | |
89 | lf_printf(file, " MODEL_%s,\n", model_ptr->name); | |
90 | } | |
91 | lf_printf(file, " nr_models\n"); | |
92 | lf_printf(file, "} model_enum;\n"); | |
93 | lf_printf(file, "\n"); | |
94 | ||
95 | lf_printf(file, "#define DEFAULT_MODEL MODEL_%s\n", (models) ? models->name : "NONE"); | |
96 | lf_printf(file, "\n"); | |
97 | ||
98 | lf_printf(file, "typedef struct _model_data model_data;\n"); | |
99 | lf_printf(file, "typedef struct _model_time model_time;\n"); | |
100 | lf_printf(file, "\n"); | |
101 | ||
102 | lf_printf(file, "extern model_enum current_model;\n"); | |
103 | lf_printf(file, "extern const char *model_name[ (int)nr_models ];\n"); | |
104 | lf_printf(file, "extern const char *const *const model_func_unit_name[ (int)nr_models ];\n"); | |
105 | lf_printf(file, "extern const model_time *const model_time_mapping[ (int)nr_models ];\n"); | |
106 | lf_printf(file, "\n"); | |
107 | ||
108 | for(insn_ptr = model_functions; insn_ptr; insn_ptr = insn_ptr->next) { | |
109 | model_c_or_h_function(table, file, insn_ptr->file_entry, "INLINE_MODEL"); | |
110 | name = insn_ptr->file_entry->fields[function_name]; | |
111 | if (strcmp (name, "model_create") == 0) | |
112 | model_create_p = 1; | |
113 | else if (strcmp (name, "model_init") == 0) | |
114 | model_init_p = 1; | |
115 | else if (strcmp (name, "model_halt") == 0) | |
116 | model_halt_p = 1; | |
117 | else if (strcmp (name, "model_mon_info") == 0) | |
118 | model_mon_info_p = 1; | |
119 | else if (strcmp (name, "model_mon_info_free") == 0) | |
120 | model_mon_info_free_p = 1; | |
121 | } | |
122 | ||
123 | if (!model_create_p) { | |
124 | lf_print_function_type(file, "model_data *", "INLINE_MODEL", " "); | |
125 | lf_printf(file, "model_create\n"); | |
126 | lf_printf(file, "(cpu *processor);\n"); | |
127 | lf_printf(file, "\n"); | |
128 | } | |
129 | ||
130 | if (!model_init_p) { | |
131 | lf_print_function_type(file, "void", "INLINE_MODEL", " "); | |
132 | lf_printf(file, "model_init\n"); | |
133 | lf_printf(file, "(model_data *model_ptr);\n"); | |
134 | lf_printf(file, "\n"); | |
135 | } | |
136 | ||
137 | if (!model_halt_p) { | |
138 | lf_print_function_type(file, "void", "INLINE_MODEL", " "); | |
139 | lf_printf(file, "model_halt\n"); | |
140 | lf_printf(file, "(model_data *model_ptr);\n"); | |
141 | lf_printf(file, "\n"); | |
142 | } | |
143 | ||
144 | if (!model_mon_info_p) { | |
145 | lf_print_function_type(file, "model_print *", "INLINE_MODEL", " "); | |
146 | lf_printf(file, "model_mon_info\n"); | |
147 | lf_printf(file, "(model_data *model_ptr);\n"); | |
148 | lf_printf(file, "\n"); | |
149 | } | |
150 | ||
151 | if (!model_mon_info_free_p) { | |
152 | lf_print_function_type(file, "void", "INLINE_MODEL", " "); | |
153 | lf_printf(file, "model_mon_info_free\n"); | |
154 | lf_printf(file, "(model_data *model_ptr,\n"); | |
155 | lf_printf(file, " model_print *info_ptr);\n"); | |
156 | lf_printf(file, "\n"); | |
157 | } | |
158 | ||
159 | lf_print_function_type(file, "void", "INLINE_MODEL", " "); | |
160 | lf_printf(file, "model_set\n"); | |
161 | lf_printf(file, "(const char *name);\n"); | |
162 | } | |
163 | ||
164 | /****************************************************************/ | |
165 | ||
166 | typedef struct _model_c_passed_data model_c_passed_data; | |
167 | struct _model_c_passed_data { | |
168 | lf *file; | |
169 | model *model_ptr; | |
170 | }; | |
171 | ||
172 | static void | |
173 | model_c_insn(insn_table *entry, | |
174 | lf *phony_file, | |
175 | void *data, | |
176 | insn *instruction, | |
177 | int depth) | |
178 | { | |
179 | model_c_passed_data *data_ptr = (model_c_passed_data *)data; | |
180 | lf *file = data_ptr->file; | |
181 | char *current_name = data_ptr->model_ptr->printable_name; | |
182 | table_model_entry *model_ptr = instruction->file_entry->model_first; | |
183 | ||
184 | while (model_ptr) { | |
185 | if (model_ptr->fields[insn_model_name] == current_name) { | |
186 | lf_printf(file, " { %-*s }, /* %s */\n", | |
187 | max_model_fields_len, | |
188 | model_ptr->fields[insn_model_fields], | |
189 | instruction->file_entry->fields[insn_name]); | |
190 | return; | |
191 | } | |
192 | ||
193 | model_ptr = model_ptr->next; | |
194 | } | |
195 | ||
196 | lf_printf(file, " { %-*s }, /* %s */\n", | |
197 | max_model_fields_len, | |
198 | data_ptr->model_ptr->insn_default, | |
199 | instruction->file_entry->fields[insn_name]); | |
200 | } | |
201 | ||
202 | static void | |
203 | model_c_function(insn_table *table, | |
204 | lf *file, | |
205 | table_entry *function, | |
206 | const char *prefix) | |
207 | { | |
208 | if (function->fields[function_type] == NULL | |
209 | || function->fields[function_type][0] == '\0') { | |
210 | error("Model function return type not specified for %s", function->fields[function_name]); | |
211 | } | |
212 | else { | |
213 | lf_printf(file, "\n"); | |
214 | lf_print_function_type(file, function->fields[function_type], prefix, "\n"); | |
215 | lf_printf(file, "%s(%s)\n", | |
216 | function->fields[function_name], | |
217 | function->fields[function_param]); | |
218 | } | |
219 | table_entry_print_cpp_line_nr(file, function); | |
220 | lf_printf(file, "{\n"); | |
221 | if (function->annex) { | |
222 | lf_indent(file, +2); | |
223 | lf_print__c_code(file, function->annex); | |
224 | lf_indent(file, -2); | |
225 | } | |
226 | lf_printf(file, "}\n"); | |
227 | lf_print__internal_reference(file); | |
228 | lf_printf(file, "\n"); | |
229 | } | |
230 | ||
231 | void | |
232 | gen_model_c(insn_table *table, lf *file) | |
233 | { | |
234 | insn *insn_ptr; | |
235 | model *model_ptr; | |
236 | char *name; | |
237 | int model_create_p = 0; | |
238 | int model_init_p = 0; | |
239 | int model_halt_p = 0; | |
240 | int model_mon_info_p = 0; | |
241 | int model_mon_info_free_p = 0; | |
242 | ||
243 | lf_printf(file, "\n"); | |
244 | lf_printf(file, "#include \"cpu.h\"\n"); | |
245 | lf_printf(file, "#include \"mon.h\"\n"); | |
246 | lf_printf(file, "\n"); | |
247 | lf_printf(file, "#ifdef HAVE_STDLIB_H\n"); | |
248 | lf_printf(file, "#include <stdlib.h>\n"); | |
249 | lf_printf(file, "#endif\n"); | |
250 | lf_printf(file, "\n"); | |
251 | ||
252 | for(insn_ptr = model_data; insn_ptr; insn_ptr = insn_ptr->next) { | |
253 | model_c_or_h_data(table, file, insn_ptr->file_entry); | |
254 | } | |
255 | ||
256 | for(insn_ptr = model_static; insn_ptr; insn_ptr = insn_ptr->next) { | |
257 | model_c_or_h_function(table, file, insn_ptr->file_entry, "/*h*/STATIC"); | |
258 | } | |
259 | ||
260 | for(insn_ptr = model_internal; insn_ptr; insn_ptr = insn_ptr->next) { | |
261 | model_c_or_h_function(table, file, insn_ptr->file_entry, "STATIC_INLINE_MODEL"); | |
262 | } | |
263 | ||
264 | for(insn_ptr = model_static; insn_ptr; insn_ptr = insn_ptr->next) { | |
265 | model_c_function(table, file, insn_ptr->file_entry, "/*c*/STATIC"); | |
266 | } | |
267 | ||
268 | for(insn_ptr = model_internal; insn_ptr; insn_ptr = insn_ptr->next) { | |
269 | model_c_function(table, file, insn_ptr->file_entry, "STATIC_INLINE_MODEL"); | |
270 | } | |
271 | ||
272 | for(insn_ptr = model_functions; insn_ptr; insn_ptr = insn_ptr->next) { | |
273 | model_c_function(table, file, insn_ptr->file_entry, "INLINE_MODEL"); | |
274 | name = insn_ptr->file_entry->fields[function_name]; | |
275 | if (strcmp (name, "model_create") == 0) | |
276 | model_create_p = 1; | |
277 | else if (strcmp (name, "model_init") == 0) | |
278 | model_init_p = 1; | |
279 | else if (strcmp (name, "model_halt") == 0) | |
280 | model_halt_p = 1; | |
281 | else if (strcmp (name, "model_mon_info") == 0) | |
282 | model_mon_info_p = 1; | |
283 | else if (strcmp (name, "model_mon_info_free") == 0) | |
284 | model_mon_info_free_p = 1; | |
285 | } | |
286 | ||
287 | if (!model_create_p) { | |
288 | lf_print_function_type(file, "model_data *", "INLINE_MODEL", "\n"); | |
289 | lf_printf(file, "model_create(cpu *processor)\n"); | |
290 | lf_printf(file, "{\n"); | |
291 | lf_printf(file, " return (model_data *)0;\n"); | |
292 | lf_printf(file, "}\n"); | |
293 | lf_printf(file, "\n"); | |
294 | } | |
295 | ||
296 | if (!model_init_p) { | |
297 | lf_print_function_type(file, "void", "INLINE_MODEL", "\n"); | |
298 | lf_printf(file, "model_init(model_data *model_ptr)\n"); | |
299 | lf_printf(file, "{\n"); | |
300 | lf_printf(file, "}\n"); | |
301 | lf_printf(file, "\n"); | |
302 | } | |
303 | ||
304 | if (!model_halt_p) { | |
305 | lf_print_function_type(file, "void", "INLINE_MODEL", "\n"); | |
306 | lf_printf(file, "model_halt(model_data *model_ptr)\n"); | |
307 | lf_printf(file, "{\n"); | |
308 | lf_printf(file, "}\n"); | |
309 | lf_printf(file, "\n"); | |
310 | } | |
311 | ||
312 | if (!model_mon_info_p) { | |
313 | lf_print_function_type(file, "model_print *", "INLINE_MODEL", "\n"); | |
314 | lf_printf(file, "model_mon_info(model_data *model_ptr)\n"); | |
315 | lf_printf(file, "{\n"); | |
316 | lf_printf(file, " return (model_print *)0;\n"); | |
317 | lf_printf(file, "}\n"); | |
318 | lf_printf(file, "\n"); | |
319 | } | |
320 | ||
321 | if (!model_mon_info_free_p) { | |
322 | lf_print_function_type(file, "void", "INLINE_MODEL", "\n"); | |
323 | lf_printf(file, "model_mon_info_free(model_data *model_ptr,\n"); | |
324 | lf_printf(file, " model_print *info_ptr)\n"); | |
325 | lf_printf(file, "{\n"); | |
326 | lf_printf(file, "}\n"); | |
327 | lf_printf(file, "\n"); | |
328 | } | |
329 | ||
330 | lf_printf(file, "/* Insn functional unit info */\n"); | |
331 | for(model_ptr = models; model_ptr; model_ptr = model_ptr->next) { | |
332 | model_c_passed_data data; | |
333 | ||
334 | lf_printf(file, "static const model_time model_time_%s[] = {\n", model_ptr->name); | |
335 | data.file = file; | |
336 | data.model_ptr = model_ptr; | |
337 | insn_table_traverse_insn(table, | |
338 | NULL, (void *)&data, | |
339 | model_c_insn); | |
340 | ||
341 | lf_printf(file, "};\n"); | |
342 | lf_printf(file, "\n"); | |
343 | lf_printf(file, "\f\n"); | |
344 | } | |
345 | ||
346 | lf_printf(file, "#ifndef _INLINE_C_\n"); | |
347 | lf_printf(file, "const model_time *const model_time_mapping[ (int)nr_models ] = {\n"); | |
348 | lf_printf(file, " (const model_time *const)0,\n"); | |
349 | for(model_ptr = models; model_ptr; model_ptr = model_ptr->next) { | |
350 | lf_printf(file, " model_time_%s,\n", model_ptr->name); | |
351 | } | |
352 | lf_printf(file, "};\n"); | |
353 | lf_printf(file, "#endif\n"); | |
354 | lf_printf(file, "\n"); | |
355 | ||
356 | lf_printf(file, "\f\n"); | |
357 | lf_printf(file, "/* map model enumeration into printable string */\n"); | |
358 | lf_printf(file, "#ifndef _INLINE_C_\n"); | |
359 | lf_printf(file, "const char *model_name[ (int)nr_models ] = {\n"); | |
360 | lf_printf(file, " \"NONE\",\n"); | |
361 | for (model_ptr = models; model_ptr; model_ptr = model_ptr->next) { | |
362 | lf_printf(file, " \"%s\",\n", model_ptr->printable_name); | |
363 | } | |
364 | lf_printf(file, "};\n"); | |
365 | lf_printf(file, "#endif\n"); | |
366 | lf_printf(file, "\n"); | |
367 | ||
368 | lf_print_function_type(file, "void", "INLINE_MODEL", "\n"); | |
369 | lf_printf(file, "model_set(const char *name)\n"); | |
370 | lf_printf(file, "{\n"); | |
371 | if (models) { | |
372 | lf_printf(file, " model_enum model;\n"); | |
373 | lf_printf(file, " for(model = MODEL_%s; model < nr_models; model++) {\n", models->name); | |
374 | lf_printf(file, " if(strcmp(name, model_name[model]) == 0) {\n"); | |
375 | lf_printf(file, " current_model = model;\n"); | |
376 | lf_printf(file, " return;\n"); | |
377 | lf_printf(file, " }\n"); | |
378 | lf_printf(file, " }\n"); | |
379 | lf_printf(file, "\n"); | |
380 | lf_printf(file, " error(\"Unknown model '%%s', Models which are known are:%%s\n\",\n"); | |
381 | lf_printf(file, " name,\n"); | |
382 | lf_printf(file, " \""); | |
383 | for(model_ptr = models; model_ptr; model_ptr = model_ptr->next) { | |
384 | lf_printf(file, "\\n\\t%s", model_ptr->printable_name); | |
385 | } | |
386 | lf_printf(file, "\");\n"); | |
387 | } else { | |
388 | lf_printf(file, " error(\"No models are currently known about\");\n"); | |
389 | } | |
390 | ||
391 | lf_printf(file, "}\n"); | |
392 | } | |
393 |