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
40static void
41print_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
84void
85print_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
104void
105print_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
145void
146print_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
303static void
304print_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
352static void
353print_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
372void
373print_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