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-semantics.h"
36 #include "gen-icache.h"
37 #include "gen-idecode.h"
38 
39 
40 static void
print_semantic_function_header(lf * file,const char * basename,const char * format_name,const opcode_bits * expanded_bits,int is_function_definition,int nr_prefetched_words)41 print_semantic_function_header (lf *file,
42                                         const char *basename,
43                                         const char *format_name,
44                                         const opcode_bits *expanded_bits,
45                                         int is_function_definition,
46                                         int nr_prefetched_words)
47 {
48   int indent;
49   lf_printf (file, "\n");
50   lf_print__function_type_function (file, print_semantic_function_type,
51                                             "EXTERN_SEMANTICS",
52                                             (is_function_definition ? "\n" : " "));
53   indent = print_function_name (file,
54                                         basename,
55                                         format_name,
56                                         NULL,
57                                         expanded_bits,
58                                         function_name_prefix_semantics);
59   if (is_function_definition)
60     {
61       indent += lf_printf (file, " ");
62       lf_indent (file, +indent);
63     }
64   else
65     {
66       lf_printf (file, "\n");
67     }
68   lf_printf (file, "(");
69   lf_indent (file, +1);
70   print_semantic_function_formal (file, nr_prefetched_words);
71   lf_indent (file, -1);
72   lf_printf (file, ")");
73   if (is_function_definition)
74     {
75       lf_indent (file, -indent);
76     }
77   else
78     {
79       lf_printf (file, ";");
80     }
81   lf_printf (file, "\n");
82 }
83 
84 void
print_semantic_declaration(lf * file,const insn_entry * insn,const opcode_bits * expanded_bits,const insn_opcodes * opcodes,int nr_prefetched_words)85 print_semantic_declaration (lf *file,
86                                   const insn_entry *insn,
87                                   const opcode_bits *expanded_bits,
88                                   const insn_opcodes *opcodes,
89                                   int nr_prefetched_words)
90 {
91   print_semantic_function_header (file,
92                                           insn->name,
93                                           insn->format_name,
94                                           expanded_bits,
95                                           0 /* is not function definition */ ,
96                                           nr_prefetched_words);
97 }
98 
99 
100 
101 /* generate the semantics.c file */
102 
103 
104 void
print_idecode_invalid(lf * file,const char * result,invalid_type type)105 print_idecode_invalid (lf *file, const char *result, invalid_type type)
106 {
107   const char *name;
108   switch (type)
109     {
110     default:
111       name = "unknown";
112       break;
113     case invalid_illegal:
114       name = "illegal";
115       break;
116     case invalid_fp_unavailable:
117       name = "fp_unavailable";
118       break;
119     case invalid_wrong_slot:
120       name = "wrong_slot";
121       break;
122     }
123   if (options.gen.code == generate_jumps)
124     {
125       lf_printf (file, "goto %s_%s;\n",
126                      (options.gen.icache ? "icache" : "semantic"), name);
127     }
128   else if (options.gen.icache)
129     {
130       lf_printf (file, "%s %sicache_%s (", result,
131                      options.module.global.prefix.l, name);
132       print_icache_function_actual (file, 0);
133       lf_printf (file, ");\n");
134     }
135   else
136     {
137       lf_printf (file, "%s %ssemantic_%s (", result,
138                      options.module.global.prefix.l, name);
139       print_semantic_function_actual (file, 0);
140       lf_printf (file, ");\n");
141     }
142 }
143 
144 
145 void
print_semantic_body(lf * file,const insn_entry * instruction,const opcode_bits * expanded_bits,const insn_opcodes * opcodes)146 print_semantic_body (lf *file,
147                          const insn_entry *instruction,
148                          const opcode_bits *expanded_bits,
149                          const insn_opcodes *opcodes)
150 {
151   /* validate the instruction, if a cache this has already been done */
152   if (!options.gen.icache)
153     {
154       print_idecode_validate (file, instruction, opcodes);
155     }
156 
157   print_itrace (file, instruction, 0 /*put_value_in_cache */ );
158 
159   /* generate the instruction profile call - this is delayed until
160      after the instruction has been verified.  The count macro
161      generated is prefixed by ITABLE_PREFIX */
162   {
163     lf_printf (file, "\n");
164     lf_indent_suppress (file);
165     lf_printf (file, "#if defined (%sPROFILE_COUNT_INSN)\n",
166                  options.module.itable.prefix.u);
167     lf_printf (file, "%sPROFILE_COUNT_INSN (CPU, CIA, MY_INDEX);\n",
168                  options.module.itable.prefix.u);
169     lf_indent_suppress (file);
170     lf_printf (file, "#endif\n");
171   }
172 
173   /* generate the model call - this is delayed until after the
174      instruction has been verified */
175   {
176     lf_printf (file, "\n");
177     lf_indent_suppress (file);
178     lf_printf (file, "#if defined (WITH_MON)\n");
179     lf_printf (file, "/* monitoring: */\n");
180     lf_printf (file, "if (WITH_MON & MONITOR_INSTRUCTION_ISSUE)\n");
181     lf_printf (file, "  mon_issue (");
182     print_function_name (file,
183                                instruction->name,
184                                instruction->format_name,
185                                NULL, NULL, function_name_prefix_itable);
186     lf_printf (file, ", cpu, cia);\n");
187     lf_indent_suppress (file);
188     lf_printf (file, "#endif\n");
189     lf_printf (file, "\n");
190   }
191 
192   /* determine the new instruction address */
193   {
194     lf_printf (file, "/* keep the next instruction address handy */\n");
195     if (options.gen.nia == nia_is_invalid)
196       {
197           lf_printf (file, "nia = %sINVALID_INSTRUCTION_ADDRESS;\n",
198                        options.module.global.prefix.u);
199       }
200     else
201       {
202           int nr_immeds = instruction->nr_words - 1;
203           if (options.gen.delayed_branch)
204             {
205               if (nr_immeds > 0)
206                 {
207                     lf_printf (file, "cia.dp += %d * %d; %s\n",
208                                  options.insn_bit_size / 8, nr_immeds,
209                                  "/* skip dp immeds */");
210                 }
211               lf_printf (file, "nia.ip = cia.dp; %s\n",
212                            "/* instruction pointer */");
213               lf_printf (file, "nia.dp = cia.dp + %d; %s\n",
214                            options.insn_bit_size / 8,
215                            "/* delayed-slot pointer */");
216             }
217           else
218             {
219               if (nr_immeds > 0)
220                 {
221                     lf_printf (file, "nia = cia + %d * (%d + 1); %s\n",
222                                  options.insn_bit_size / 8, nr_immeds,
223                                  "/* skip immeds as well */");
224 
225                 }
226               else
227                 {
228                     lf_printf (file, "nia = cia + %d;\n",
229                                  options.insn_bit_size / 8);
230                 }
231             }
232       }
233   }
234 
235   /* if conditional, generate code to verify that the instruction
236      should be issued */
237   if (filter_is_member (instruction->options, "c")
238       || options.gen.conditional_issue)
239     {
240       lf_printf (file, "\n");
241       lf_printf (file, "/* execute only if conditional passes */\n");
242       lf_printf (file, "if (IS_CONDITION_OK)\n");
243       lf_printf (file, "  {\n");
244       lf_indent (file, +4);
245       /* FIXME - need to log a conditional failure */
246     }
247 
248   /* Architecture expects a REG to be zero.  Instead of having to
249      check every read to see if it is refering to that REG just zap it
250      at the start of every instruction */
251   if (options.gen.zero_reg)
252     {
253       lf_printf (file, "\n");
254       lf_printf (file, "/* Architecture expects REG to be zero */\n");
255       lf_printf (file, "GPR_CLEAR(%d);\n", options.gen.zero_reg_nr);
256     }
257 
258   /* generate the code (or at least something */
259   lf_printf (file, "\n");
260   lf_printf (file, "/* semantics: */\n");
261   if (instruction->code != NULL)
262     {
263       /* true code */
264       lf_printf (file, "{\n");
265       /* NB: Do not indent the code.  If the .igen source files cause a compiler
266            warning, the diagnostics can read the line from the original source,
267            but use column offsets from the generated files, causing columns to be
268            misaligned.  It makes the generated code slightly more difficult to
269            read, but accurate compiler diagnostics relative to the original source
270            are more important here.
271       lf_indent (file, +2); */
272       lf_print__line_ref (file, instruction->code->line);
273       table_print_code (file, instruction->code);
274       /* NB: Disabled -- see above.
275       lf_indent (file, -2); */
276       lf_printf (file, "}\n");
277       lf_print__internal_ref (file);
278     }
279   else if (filter_is_member (instruction->options, "nop"))
280     {
281       lf_print__internal_ref (file);
282     }
283   else
284     {
285       const char *prefix = "sim_engine_abort (";
286       int indent = strlen (prefix);
287       /* abort so it is implemented now */
288       lf_print__line_ref (file, instruction->line);
289       lf_printf (file, "%sSD, CPU, cia, \\\n", prefix);
290       lf_indent (file, +indent);
291       lf_printf (file, "\"%s:%d:0x%%08lx:%%s unimplemented\\n\", \\\n",
292                      filter_filename (instruction->line->file_name),
293                      instruction->line->line_nr);
294       lf_printf (file, "(long) CIA, \\\n");
295       lf_printf (file, "%sitable[MY_INDEX].name);\n",
296                      options.module.itable.prefix.l);
297       lf_indent (file, -indent);
298       lf_print__internal_ref (file);
299     }
300 
301   /* Close off the conditional execution */
302   if (filter_is_member (instruction->options, "c")
303       || options.gen.conditional_issue)
304     {
305       lf_indent (file, -4);
306       lf_printf (file, "  }\n");
307     }
308 }
309 
310 static void
print_c_semantic(lf * file,const insn_entry * instruction,const opcode_bits * expanded_bits,const insn_opcodes * opcodes,cache_entry * cache_rules,int nr_prefetched_words)311 print_c_semantic (lf *file,
312                       const insn_entry *instruction,
313                       const opcode_bits *expanded_bits,
314                       const insn_opcodes *opcodes,
315                       cache_entry *cache_rules,
316                       int nr_prefetched_words)
317 {
318 
319   lf_printf (file, "{\n");
320   lf_indent (file, +2);
321 
322   print_my_defines (file,
323                         instruction->name,
324                         instruction->format_name, expanded_bits);
325   lf_printf (file, "\n");
326   print_icache_body (file,
327                          instruction,
328                          expanded_bits,
329                          cache_rules,
330                          (options.gen.direct_access
331                           ? define_variables
332                           : declare_variables),
333                          (options.gen.icache
334                           ? get_values_from_icache
335                           : do_not_use_icache), nr_prefetched_words);
336 
337   lf_printf (file, "%sinstruction_address nia;\n",
338                options.module.global.prefix.l);
339   print_semantic_body (file, instruction, expanded_bits, opcodes);
340   lf_printf (file, "return nia;\n");
341 
342   /* generate something to clean up any #defines created for the cache */
343   if (options.gen.direct_access)
344     {
345       print_icache_body (file,
346                                instruction,
347                                expanded_bits,
348                                cache_rules,
349                                undef_variables,
350                                (options.gen.icache
351                                 ? get_values_from_icache
352                                 : do_not_use_icache), nr_prefetched_words);
353     }
354 
355   lf_indent (file, -2);
356   lf_printf (file, "}\n");
357 }
358 
359 static void
print_c_semantic_function(lf * file,const insn_entry * instruction,const opcode_bits * expanded_bits,const insn_opcodes * opcodes,cache_entry * cache_rules,int nr_prefetched_words)360 print_c_semantic_function (lf *file,
361                                  const insn_entry *instruction,
362                                  const opcode_bits *expanded_bits,
363                                  const insn_opcodes *opcodes,
364                                  cache_entry *cache_rules,
365                                  int nr_prefetched_words)
366 {
367   /* build the semantic routine to execute the instruction */
368   print_semantic_function_header (file,
369                                           instruction->name,
370                                           instruction->format_name,
371                                           expanded_bits,
372                                           1 /*is-function-definition */ ,
373                                           nr_prefetched_words);
374   print_c_semantic (file,
375                         instruction,
376                         expanded_bits, opcodes, cache_rules, nr_prefetched_words);
377 }
378 
379 void
print_semantic_definition(lf * file,const insn_entry * insn,const opcode_bits * expanded_bits,const insn_opcodes * opcodes,cache_entry * cache_rules,int nr_prefetched_words)380 print_semantic_definition (lf *file,
381                                  const insn_entry *insn,
382                                  const opcode_bits *expanded_bits,
383                                  const insn_opcodes *opcodes,
384                                  cache_entry *cache_rules,
385                                  int nr_prefetched_words)
386 {
387   print_c_semantic_function (file,
388                                    insn,
389                                    expanded_bits,
390                                    opcodes, cache_rules, nr_prefetched_words);
391 }
392