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