xref: /netbsd-src/external/gpl3/gdb/dist/sim/igen/gen-semantics.c (revision ccd9df534e375a4366c5b55f23782053c7a98d82)
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-semantics.h"
36 #include "gen-icache.h"
37 #include "gen-idecode.h"
38 
39 
40 static void
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
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
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
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       lf_indent (file, +2);
266       lf_print__line_ref (file, instruction->code->line);
267       table_print_code (file, instruction->code);
268       lf_indent (file, -2);
269       lf_printf (file, "}\n");
270       lf_print__internal_ref (file);
271     }
272   else if (filter_is_member (instruction->options, "nop"))
273     {
274       lf_print__internal_ref (file);
275     }
276   else
277     {
278       const char *prefix = "sim_engine_abort (";
279       int indent = strlen (prefix);
280       /* abort so it is implemented now */
281       lf_print__line_ref (file, instruction->line);
282       lf_printf (file, "%sSD, CPU, cia, \\\n", prefix);
283       lf_indent (file, +indent);
284       lf_printf (file, "\"%s:%d:0x%%08lx:%%s unimplemented\\n\", \\\n",
285 		 filter_filename (instruction->line->file_name),
286 		 instruction->line->line_nr);
287       lf_printf (file, "(long) CIA, \\\n");
288       lf_printf (file, "%sitable[MY_INDEX].name);\n",
289 		 options.module.itable.prefix.l);
290       lf_indent (file, -indent);
291       lf_print__internal_ref (file);
292     }
293 
294   /* Close off the conditional execution */
295   if (filter_is_member (instruction->options, "c")
296       || options.gen.conditional_issue)
297     {
298       lf_indent (file, -4);
299       lf_printf (file, "  }\n");
300     }
301 }
302 
303 static void
304 print_c_semantic (lf *file,
305 		  const insn_entry *instruction,
306 		  const opcode_bits *expanded_bits,
307 		  const insn_opcodes *opcodes,
308 		  cache_entry *cache_rules,
309 		  int nr_prefetched_words)
310 {
311 
312   lf_printf (file, "{\n");
313   lf_indent (file, +2);
314 
315   print_my_defines (file,
316 		    instruction->name,
317 		    instruction->format_name, expanded_bits);
318   lf_printf (file, "\n");
319   print_icache_body (file,
320 		     instruction,
321 		     expanded_bits,
322 		     cache_rules,
323 		     (options.gen.direct_access
324 		      ? define_variables
325 		      : declare_variables),
326 		     (options.gen.icache
327 		      ? get_values_from_icache
328 		      : do_not_use_icache), nr_prefetched_words);
329 
330   lf_printf (file, "%sinstruction_address nia;\n",
331 	     options.module.global.prefix.l);
332   print_semantic_body (file, instruction, expanded_bits, opcodes);
333   lf_printf (file, "return nia;\n");
334 
335   /* generate something to clean up any #defines created for the cache */
336   if (options.gen.direct_access)
337     {
338       print_icache_body (file,
339 			 instruction,
340 			 expanded_bits,
341 			 cache_rules,
342 			 undef_variables,
343 			 (options.gen.icache
344 			  ? get_values_from_icache
345 			  : do_not_use_icache), nr_prefetched_words);
346     }
347 
348   lf_indent (file, -2);
349   lf_printf (file, "}\n");
350 }
351 
352 static void
353 print_c_semantic_function (lf *file,
354 			   const insn_entry *instruction,
355 			   const opcode_bits *expanded_bits,
356 			   const insn_opcodes *opcodes,
357 			   cache_entry *cache_rules,
358 			   int nr_prefetched_words)
359 {
360   /* build the semantic routine to execute the instruction */
361   print_semantic_function_header (file,
362 				  instruction->name,
363 				  instruction->format_name,
364 				  expanded_bits,
365 				  1 /*is-function-definition */ ,
366 				  nr_prefetched_words);
367   print_c_semantic (file,
368 		    instruction,
369 		    expanded_bits, opcodes, cache_rules, nr_prefetched_words);
370 }
371 
372 void
373 print_semantic_definition (lf *file,
374 			   const insn_entry *insn,
375 			   const opcode_bits *expanded_bits,
376 			   const insn_opcodes *opcodes,
377 			   cache_entry *cache_rules,
378 			   int nr_prefetched_words)
379 {
380   print_c_semantic_function (file,
381 			     insn,
382 			     expanded_bits,
383 			     opcodes, cache_rules, nr_prefetched_words);
384 }
385