xref: /netbsd-src/external/gpl3/gdb/dist/sim/igen/gen-itable.c (revision 71f621822dbfd5073a314948bec169b7bb05f7be)
1 /* The IGEN simulator generator for GDB, the GNU Debugger.
2 
3    Copyright 2002-2024 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,
118 	     "const char * const %sitable_%s_names[nr_%sitable_%ss + 1] = {\n",
119 	     options.module.itable.prefix.l, name,
120 	     options.module.itable.prefix.l, name);
121   lf_indent (file, +2);
122   for (elem = filter_next (set, "");
123        elem != NULL; elem = filter_next (set, elem))
124     {
125       lf_printf (file, "\"%s\",\n", elem);
126     }
127   lf_printf (file, "0,\n");
128   lf_indent (file, -2);
129   lf_printf (file, "};\n");
130 }
131 
132 extern void
133 gen_itable_h (lf *file, const insn_table *isa)
134 {
135   itable_info *info = ZALLOC (itable_info);
136 
137   /* output an enumerated type for each instruction */
138   lf_printf (file, "typedef enum {\n");
139   insn_table_traverse_insn (file, isa, itable_h_insn, info);
140   lf_printf (file, "  nr_%sitable_entries,\n",
141 	     options.module.itable.prefix.l);
142   lf_printf (file, "} %sitable_index;\n", options.module.itable.prefix.l);
143   lf_printf (file, "\n");
144 
145   /* output an enumeration type for each flag */
146   itable_print_enum (file, isa->flags, "flag");
147   lf_printf (file, "extern const char * const %sitable_flag_names[];\n",
148 	     options.module.itable.prefix.l);
149   lf_printf (file, "\n");
150 
151   /* output an enumeration of all the possible options */
152   itable_print_enum (file, isa->options, "option");
153   lf_printf (file, "extern const char * const %sitable_option_names[];\n",
154 	     options.module.itable.prefix.l);
155   lf_printf (file, "\n");
156 
157   /* output an enumeration of all the processor models */
158   itable_print_enum (file, isa->model->processors, "processor");
159   lf_printf (file, "extern const char * const %sitable_processor_names[];\n",
160 	     options.module.itable.prefix.l);
161   lf_printf (file, "\n");
162 
163   /* output the table that contains the actual instruction info */
164   lf_printf (file, "typedef struct _%sitable_instruction_info {\n",
165 	     options.module.itable.prefix.l);
166   lf_printf (file, "  %sitable_index nr;\n", options.module.itable.prefix.l);
167   lf_printf (file, "  const char *format;\n");
168   lf_printf (file, "  const char *form;\n");
169   lf_printf (file, "  const char *flags;\n");
170 
171   /* nr_itable_* may be zero, so we add 1 to avoid an
172      illegal zero-sized array. */
173   lf_printf (file, "  const char flag[nr_%sitable_flags + 1];\n",
174 	     options.module.itable.prefix.l);
175   lf_printf (file, "  const char *options;\n");
176   lf_printf (file, "  const char option[nr_%sitable_options + 1];\n",
177 	     options.module.itable.prefix.l);
178   lf_printf (file, "  const char *processors;\n");
179   lf_printf (file, "  const char processor[nr_%sitable_processors + 1];\n",
180 	     options.module.itable.prefix.l);
181   lf_printf (file, "  const char *name;\n");
182   lf_printf (file, "  const char *file;\n");
183   lf_printf (file, "  int line_nr;\n");
184   lf_printf (file, "} %sitable_info;\n", options.module.itable.prefix.l);
185   lf_printf (file, "\n");
186   lf_printf (file,
187 	     "extern const %sitable_info %sitable[nr_%sitable_entries];\n",
188 	     options.module.itable.prefix.l, options.module.itable.prefix.l,
189 	     options.module.itable.prefix.l);
190   if (strlen (options.module.itable.prefix.l) > 0)
191     {
192       lf_indent_suppress (file);
193       lf_printf (file, "#define itable %sitable\n",
194 		 options.module.itable.prefix.l);
195     }
196   lf_printf (file, "\n");
197 
198   /* output an enum defining the max size of various itable members */
199   lf_printf (file, "enum {\n");
200   lf_printf (file, "  sizeof_%sitable_form = %d,\n",
201 	     options.module.itable.prefix.l, info->sizeof_form);
202   lf_printf (file, "  sizeof_%sitable_name = %d,\n",
203 	     options.module.itable.prefix.l, info->sizeof_name);
204   lf_printf (file, "  sizeof_%sitable_file = %d,\n",
205 	     options.module.itable.prefix.l, info->sizeof_file);
206   lf_printf (file, "};\n");
207 }
208 
209 
210 /****************************************************************/
211 
212 static void
213 itable_print_set (lf *file, const filter *set, const filter *members)
214 {
215   const char *elem;
216   lf_printf (file, "\"");
217   elem = filter_next (members, "");
218   if (elem != NULL)
219     {
220       while (1)
221 	{
222 	  lf_printf (file, "%s", elem);
223 	  elem = filter_next (members, elem);
224 	  if (elem == NULL)
225 	    break;
226 	  lf_printf (file, ",");
227 	}
228     }
229   lf_printf (file, "\",\n");
230 
231   lf_printf (file, "{");
232   for (elem = filter_next (set, "");
233        elem != NULL; elem = filter_next (set, elem))
234     {
235       if (filter_is_member (members, elem))
236 	{
237 	  lf_printf (file, " 1,");
238 	}
239       else
240 	{
241 	  lf_printf (file, " 0,");
242 	}
243 
244     }
245   /* always print a dummy element, to avoid empty initializers. */
246   lf_printf (file, " 99 },\n");
247 }
248 
249 
250 static void
251 itable_c_insn (lf *file,
252 	       const insn_table *isa,
253 	       const insn_entry *instruction,
254 	       void *data)
255 {
256   lf_printf (file, "{ ");
257   lf_indent (file, +2);
258   print_function_name (file,
259 		       instruction->name,
260 		       instruction->format_name,
261 		       NULL, NULL, function_name_prefix_itable);
262   lf_printf (file, ",\n");
263   lf_printf (file, "\"");
264   print_insn_words (file, instruction);
265   lf_printf (file, "\",\n");
266   lf_printf (file, "\"%s\",\n", instruction->format_name);
267 
268   itable_print_set (file, isa->flags, instruction->flags);
269   itable_print_set (file, isa->options, instruction->options);
270   itable_print_set (file, isa->model->processors, instruction->processors);
271 
272   lf_printf (file, "\"%s\",\n", instruction->name);
273   lf_printf (file, "\"%s\",\n",
274 	     filter_filename (instruction->line->file_name));
275   lf_printf (file, "%d,\n", instruction->line->line_nr);
276   lf_printf (file, "},\n");
277   lf_indent (file, -2);
278 }
279 
280 
281 extern void
282 gen_itable_c (lf *file, const insn_table *isa)
283 {
284   /* leader */
285   lf_printf (file, "#include \"%sitable.h\"\n",
286 	     options.module.itable.prefix.l);
287   lf_printf (file, "\n");
288 
289   /* FIXME - output model data??? */
290   /* FIXME - output assembler data??? */
291 
292   /* output the flag, option and processor name tables */
293   itable_print_names (file, isa->flags, "flag");
294   itable_print_names (file, isa->options, "option");
295   itable_print_names (file, isa->model->processors, "processor");
296 
297   /* output the table that contains the actual instruction info */
298   lf_printf (file, "const %sitable_info %sitable[nr_%sitable_entries] = {\n",
299 	     options.module.itable.prefix.l,
300 	     options.module.itable.prefix.l, options.module.itable.prefix.l);
301   insn_table_traverse_insn (file, isa, itable_c_insn, NULL);
302 
303   lf_printf (file, "};\n");
304 }
305