xref: /netbsd-src/external/gpl3/gdb.old/dist/sim/igen/gen-itable.c (revision 8b657b0747480f8989760d71343d6dd33f8d4cf9)
1 /* The IGEN simulator generator for GDB, the GNU Debugger.
2 
3    Copyright 2002-2023 Free Software Foundation, Inc.
4 
5    Contributed by Andrew Cagney.
6 
7    This file is part of GDB.
8 
9    This program is free software; you can redistribute it and/or modify
10    it under the terms of the GNU General Public License as published by
11    the Free Software Foundation; either version 3 of the License, or
12    (at your option) any later version.
13 
14    This program is distributed in the hope that it will be useful,
15    but WITHOUT ANY WARRANTY; without even the implied warranty of
16    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17    GNU General Public License for more details.
18 
19    You should have received a copy of the GNU General Public License
20    along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
21 
22 
23 
24 #include "misc.h"
25 #include "lf.h"
26 #include "table.h"
27 #include "filter.h"
28 #include "igen.h"
29 
30 #include "ld-insn.h"
31 #include "ld-decode.h"
32 
33 #include "gen.h"
34 
35 #include "gen-itable.h"
36 
37 
38 typedef struct _itable_info
39 {
40   int sizeof_form;
41   int sizeof_name;
42   int sizeof_file;
43 }
44 itable_info;
45 
46 
47 static void
48 itable_h_insn (lf *file,
49 	       const insn_table *entry,
50 	       const insn_entry *instruction,
51 	       void *data)
52 {
53   int len;
54   itable_info *info = data;
55   lf_print__line_ref (file, instruction->line);
56   lf_printf (file, "  ");
57   print_function_name (file,
58 		       instruction->name,
59 		       instruction->format_name,
60 		       NULL, NULL, function_name_prefix_itable);
61   lf_printf (file, ",\n");
62   /* update summary info */
63   len = strlen (instruction->format_name);
64   if (info->sizeof_form <= len)
65     info->sizeof_form = len + 1;
66   len = strlen (instruction->name);
67   if (info->sizeof_name <= len)
68     info->sizeof_name = len + 1;
69   len = strlen (filter_filename (instruction->line->file_name));
70   if (info->sizeof_file <= len)
71     info->sizeof_file = len + 1;
72 }
73 
74 
75 /* print the list of all the different options */
76 
77 static void
78 itable_print_enum (lf *file, const filter *set, const char *name)
79 {
80   const char *elem;
81   lf_printf (file, "typedef enum {\n");
82   lf_indent (file, +2);
83   for (elem = filter_next (set, "");
84        elem != NULL; elem = filter_next (set, elem))
85     {
86       lf_printf (file, "%sitable_%s_%s,\n",
87 		 options.module.itable.prefix.l, name, elem);
88       if (strlen (options.module.itable.prefix.l) > 0)
89 	{
90 	  lf_indent_suppress (file);
91 	  lf_printf (file, "#define itable_%s_%s %sitable_%s_%s\n",
92 		     name, elem, options.module.itable.prefix.l, name, elem);
93 	}
94     }
95   lf_printf (file, "nr_%sitable_%ss,\n", options.module.itable.prefix.l,
96 	     name);
97 
98   lf_indent (file, -2);
99   lf_printf (file, "} %sitable_%ss;\n", options.module.itable.prefix.l, name);
100   if (strlen (options.module.itable.prefix.l) > 0)
101     {
102       lf_indent_suppress (file);
103       lf_printf (file, "#define itable_%ss %sitable_%ss\n",
104 		 name, options.module.itable.prefix.l, name);
105       lf_indent_suppress (file);
106       lf_printf (file, "#define nr_itable_%ss nr_%sitable_%ss\n",
107 		 name, options.module.itable.prefix.l, name);
108     }
109 }
110 
111 /* print an array of the option names as strings */
112 
113 static void
114 itable_print_names (lf *file, const filter *set, const char *name)
115 {
116   const char *elem;
117   lf_printf (file, "const char *%sitable_%s_names[nr_%sitable_%ss + 1] = {\n",
118 	     options.module.itable.prefix.l, name,
119 	     options.module.itable.prefix.l, name);
120   lf_indent (file, +2);
121   for (elem = filter_next (set, "");
122        elem != NULL; elem = filter_next (set, elem))
123     {
124       lf_printf (file, "\"%s\",\n", elem);
125     }
126   lf_printf (file, "0,\n");
127   lf_indent (file, -2);
128   lf_printf (file, "};\n");
129 }
130 
131 extern void
132 gen_itable_h (lf *file, const insn_table *isa)
133 {
134   itable_info *info = ZALLOC (itable_info);
135 
136   /* output an enumerated type for each instruction */
137   lf_printf (file, "typedef enum {\n");
138   insn_table_traverse_insn (file, isa, itable_h_insn, info);
139   lf_printf (file, "  nr_%sitable_entries,\n",
140 	     options.module.itable.prefix.l);
141   lf_printf (file, "} %sitable_index;\n", options.module.itable.prefix.l);
142   lf_printf (file, "\n");
143 
144   /* output an enumeration type for each flag */
145   itable_print_enum (file, isa->flags, "flag");
146   lf_printf (file, "extern const char *%sitable_flag_names[];\n",
147 	     options.module.itable.prefix.l);
148   lf_printf (file, "\n");
149 
150   /* output an enumeration of all the possible options */
151   itable_print_enum (file, isa->options, "option");
152   lf_printf (file, "extern const char *%sitable_option_names[];\n",
153 	     options.module.itable.prefix.l);
154   lf_printf (file, "\n");
155 
156   /* output an enumeration of all the processor models */
157   itable_print_enum (file, isa->model->processors, "processor");
158   lf_printf (file, "extern const char *%sitable_processor_names[];\n",
159 	     options.module.itable.prefix.l);
160   lf_printf (file, "\n");
161 
162   /* output the table that contains the actual instruction info */
163   lf_printf (file, "typedef struct _%sitable_instruction_info {\n",
164 	     options.module.itable.prefix.l);
165   lf_printf (file, "  %sitable_index nr;\n", options.module.itable.prefix.l);
166   lf_printf (file, "  char *format;\n");
167   lf_printf (file, "  char *form;\n");
168   lf_printf (file, "  char *flags;\n");
169 
170   /* nr_itable_* may be zero, so we add 1 to avoid an
171      illegal zero-sized array. */
172   lf_printf (file, "  char flag[nr_%sitable_flags + 1];\n",
173 	     options.module.itable.prefix.l);
174   lf_printf (file, "  char *options;\n");
175   lf_printf (file, "  char option[nr_%sitable_options + 1];\n",
176 	     options.module.itable.prefix.l);
177   lf_printf (file, "  char *processors;\n");
178   lf_printf (file, "  char processor[nr_%sitable_processors + 1];\n",
179 	     options.module.itable.prefix.l);
180   lf_printf (file, "  char *name;\n");
181   lf_printf (file, "  char *file;\n");
182   lf_printf (file, "  int line_nr;\n");
183   lf_printf (file, "} %sitable_info;\n", options.module.itable.prefix.l);
184   lf_printf (file, "\n");
185   lf_printf (file, "extern %sitable_info %sitable[nr_%sitable_entries];\n",
186 	     options.module.itable.prefix.l, options.module.itable.prefix.l,
187 	     options.module.itable.prefix.l);
188   if (strlen (options.module.itable.prefix.l) > 0)
189     {
190       lf_indent_suppress (file);
191       lf_printf (file, "#define itable %sitable\n",
192 		 options.module.itable.prefix.l);
193     }
194   lf_printf (file, "\n");
195 
196   /* output an enum defining the max size of various itable members */
197   lf_printf (file, "enum {\n");
198   lf_printf (file, "  sizeof_%sitable_form = %d,\n",
199 	     options.module.itable.prefix.l, info->sizeof_form);
200   lf_printf (file, "  sizeof_%sitable_name = %d,\n",
201 	     options.module.itable.prefix.l, info->sizeof_name);
202   lf_printf (file, "  sizeof_%sitable_file = %d,\n",
203 	     options.module.itable.prefix.l, info->sizeof_file);
204   lf_printf (file, "};\n");
205 }
206 
207 
208 /****************************************************************/
209 
210 static void
211 itable_print_set (lf *file, const filter *set, const filter *members)
212 {
213   const char *elem;
214   lf_printf (file, "\"");
215   elem = filter_next (members, "");
216   if (elem != NULL)
217     {
218       while (1)
219 	{
220 	  lf_printf (file, "%s", elem);
221 	  elem = filter_next (members, elem);
222 	  if (elem == NULL)
223 	    break;
224 	  lf_printf (file, ",");
225 	}
226     }
227   lf_printf (file, "\",\n");
228 
229   lf_printf (file, "{");
230   for (elem = filter_next (set, "");
231        elem != NULL; elem = filter_next (set, elem))
232     {
233       if (filter_is_member (members, elem))
234 	{
235 	  lf_printf (file, " 1,");
236 	}
237       else
238 	{
239 	  lf_printf (file, " 0,");
240 	}
241 
242     }
243   /* always print a dummy element, to avoid empty initializers. */
244   lf_printf (file, " 99 },\n");
245 }
246 
247 
248 static void
249 itable_c_insn (lf *file,
250 	       const insn_table *isa,
251 	       const insn_entry *instruction,
252 	       void *data)
253 {
254   lf_printf (file, "{ ");
255   lf_indent (file, +2);
256   print_function_name (file,
257 		       instruction->name,
258 		       instruction->format_name,
259 		       NULL, NULL, function_name_prefix_itable);
260   lf_printf (file, ",\n");
261   lf_printf (file, "\"");
262   print_insn_words (file, instruction);
263   lf_printf (file, "\",\n");
264   lf_printf (file, "\"%s\",\n", instruction->format_name);
265 
266   itable_print_set (file, isa->flags, instruction->flags);
267   itable_print_set (file, isa->options, instruction->options);
268   itable_print_set (file, isa->model->processors, instruction->processors);
269 
270   lf_printf (file, "\"%s\",\n", instruction->name);
271   lf_printf (file, "\"%s\",\n",
272 	     filter_filename (instruction->line->file_name));
273   lf_printf (file, "%d,\n", instruction->line->line_nr);
274   lf_printf (file, "},\n");
275   lf_indent (file, -2);
276 }
277 
278 
279 extern void
280 gen_itable_c (lf *file, const insn_table *isa)
281 {
282   /* leader */
283   lf_printf (file, "#include \"%sitable.h\"\n",
284 	     options.module.itable.prefix.l);
285   lf_printf (file, "\n");
286 
287   /* FIXME - output model data??? */
288   /* FIXME - output assembler data??? */
289 
290   /* output the flag, option and processor name tables */
291   itable_print_names (file, isa->flags, "flag");
292   itable_print_names (file, isa->options, "option");
293   itable_print_names (file, isa->model->processors, "processor");
294 
295   /* output the table that contains the actual instruction info */
296   lf_printf (file, "%sitable_info %sitable[nr_%sitable_entries] = {\n",
297 	     options.module.itable.prefix.l,
298 	     options.module.itable.prefix.l, options.module.itable.prefix.l);
299   insn_table_traverse_insn (file, isa, itable_c_insn, NULL);
300 
301   lf_printf (file, "};\n");
302 }
303