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