]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blame - sim/igen/gen-engine.c
Automatic Copyright Year update after running gdb/copyright.py
[thirdparty/binutils-gdb.git] / sim / igen / gen-engine.c
CommitLineData
feaee4bd
AC
1/* The IGEN simulator generator for GDB, the GNU Debugger.
2
4a94e368 3 Copyright 2002-2022 Free Software Foundation, Inc.
feaee4bd
AC
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
4744ac1b 11 the Free Software Foundation; either version 3 of the License, or
feaee4bd
AC
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
4744ac1b 20 along with this program. If not, see <http://www.gnu.org/licenses/>. */
c906108c
SS
21
22#include "misc.h"
23#include "lf.h"
24#include "table.h"
25#include "filter.h"
26
27#include "igen.h"
28
29#include "ld-insn.h"
30#include "ld-decode.h"
31
32#include "gen.h"
33
34#include "gen-idecode.h"
35#include "gen-engine.h"
36#include "gen-icache.h"
37#include "gen-semantics.h"
38
39
40static void
41print_engine_issue_prefix_hook (lf *file)
42{
43 lf_printf (file, "\n");
44 lf_indent_suppress (file);
ac835424
CD
45 lf_printf (file, "#if defined (ENGINE_ISSUE_PREFIX_HOOK)\n");
46 lf_printf (file, "ENGINE_ISSUE_PREFIX_HOOK();\n");
c906108c
SS
47 lf_indent_suppress (file);
48 lf_printf (file, "#endif\n");
49 lf_printf (file, "\n");
50}
51
52static void
53print_engine_issue_postfix_hook (lf *file)
54{
55 lf_printf (file, "\n");
56 lf_indent_suppress (file);
ac835424
CD
57 lf_printf (file, "#if defined (ENGINE_ISSUE_POSTFIX_HOOK)\n");
58 lf_printf (file, "ENGINE_ISSUE_POSTFIX_HOOK();\n");
c906108c
SS
59 lf_indent_suppress (file);
60 lf_printf (file, "#endif\n");
61 lf_printf (file, "\n");
62}
63
64
65static void
4e0bf4c4 66print_run_body (lf *file, gen_entry *table)
c906108c
SS
67{
68 /* Output the function to execute real code:
4e0bf4c4 69
c906108c 70 Unfortunatly, there are multiple cases to consider vis:
4e0bf4c4 71
c906108c 72 <icache> X <smp>
4e0bf4c4 73
c906108c 74 Consequently this function is written in multiple different ways */
4e0bf4c4 75
c906108c
SS
76 lf_printf (file, "{\n");
77 lf_indent (file, +2);
78 if (!options.gen.smp)
79 {
4e0bf4c4
AC
80 lf_printf (file, "%sinstruction_address cia;\n",
81 options.module.global.prefix.l);
c906108c
SS
82 }
83 lf_printf (file, "int current_cpu = next_cpu_nr;\n");
4e0bf4c4 84
c906108c
SS
85 if (options.gen.icache)
86 {
87 lf_printf (file, "/* flush the icache of a possible break insn */\n");
88 lf_printf (file, "{\n");
89 lf_printf (file, " int cpu_nr;\n");
90 lf_printf (file, " for (cpu_nr = 0; cpu_nr < nr_cpus; cpu_nr++)\n");
91 lf_printf (file, " cpu_flush_icache (STATE_CPU (sd, cpu_nr));\n");
92 lf_printf (file, "}\n");
93 }
4e0bf4c4 94
c906108c
SS
95 if (!options.gen.smp)
96 {
4e0bf4c4 97
4e62efb8
RH
98 lf_putstr (file, "\
99/* CASE 1: NO SMP (with or with out instruction cache).\n\
100\n\
101In this case, we can take advantage of the fact that the current\n\
102instruction address (CIA) does not need to be read from / written to\n\
103the CPU object after the execution of an instruction.\n\
104\n\
105Instead, CIA is only saved when the main loop exits. This occures\n\
106when either sim_engine_halt or sim_engine_restart is called. Both of\n\
107these functions save the current instruction address before halting /\n\
108restarting the simulator.\n\
109\n\
110As a variation, there may also be support for an instruction cracking\n\
111cache. */\n\
112\n\
c906108c
SS
113");
114
115 lf_putstr (file, "\n");
116 lf_putstr (file, "/* prime the main loop */\n");
117 lf_putstr (file, "SIM_ASSERT (current_cpu == 0);\n");
118 lf_putstr (file, "SIM_ASSERT (nr_cpus == 1);\n");
034685f9 119 lf_putstr (file, "cia = CPU_PC_GET (CPU);\n");
c906108c
SS
120
121 lf_putstr (file, "\n");
122 lf_putstr (file, "while (1)\n");
123 lf_putstr (file, " {\n");
124 lf_indent (file, +4);
4e0bf4c4 125
c906108c
SS
126 lf_printf (file, "%sinstruction_address nia;\n",
127 options.module.global.prefix.l);
128
129 lf_printf (file, "\n");
130 if (!options.gen.icache)
131 {
4e0bf4c4
AC
132 lf_printf (file,
133 "%sinstruction_word instruction_0 = IMEM%d (cia);\n",
134 options.module.global.prefix.l, options.insn_bit_size);
c906108c
SS
135 print_engine_issue_prefix_hook (file);
136 print_idecode_body (file, table, "nia = ");
137 print_engine_issue_postfix_hook (file);
138 }
139 else
140 {
141 lf_putstr (file, "idecode_cache *cache_entry =\n");
142 lf_putstr (file, " cpu_icache_entry (cpu, cia);\n");
143 lf_putstr (file, "if (cache_entry->address == cia)\n");
144 lf_putstr (file, " {\n");
145 lf_indent (file, -4);
146 lf_putstr (file, "/* cache hit */\n");
4e0bf4c4
AC
147 lf_putstr (file,
148 "idecode_semantic *const semantic = cache_entry->semantic;\n");
c906108c
SS
149 lf_putstr (file, "cia = semantic (cpu, cache_entry, cia);\n");
150 /* tail */
151 lf_indent (file, -4);
152 lf_putstr (file, " }\n");
153 lf_putstr (file, "else\n");
154 lf_putstr (file, " {\n");
155 lf_indent (file, +4);
156 lf_putstr (file, "/* cache miss */\n");
157 if (!options.gen.semantic_icache)
158 {
159 lf_putstr (file, "idecode_semantic *semantic;\n");
160 }
161 lf_printf (file, "instruction_word instruction = IMEM%d (cia);\n",
162 options.insn_bit_size);
163 lf_putstr (file, "if (WITH_MON != 0)\n");
4e0bf4c4
AC
164 lf_putstr (file,
165 " mon_event (mon_event_icache_miss, cpu, cia);\n");
c906108c
SS
166 if (options.gen.semantic_icache)
167 {
168 lf_putstr (file, "{\n");
169 lf_indent (file, +2);
170 print_engine_issue_prefix_hook (file);
171 print_idecode_body (file, table, "nia =");
172 print_engine_issue_postfix_hook (file);
173 lf_indent (file, -2);
174 lf_putstr (file, "}\n");
175 }
176 else
177 {
178 print_engine_issue_prefix_hook (file);
179 print_idecode_body (file, table, "semantic =");
180 lf_putstr (file, "nia = semantic (cpu, cache_entry, cia);\n");
181 print_engine_issue_postfix_hook (file);
182 }
183 lf_indent (file, -4);
184 lf_putstr (file, " }\n");
185 }
4e0bf4c4 186
c906108c
SS
187 /* update the cpu if necessary */
188 switch (options.gen.nia)
189 {
190 case nia_is_cia_plus_one:
191 lf_printf (file, "\n");
192 lf_printf (file, "/* Update the instruction address */\n");
193 lf_printf (file, "cia = nia;\n");
194 break;
195 case nia_is_void:
196 case nia_is_invalid:
197 ERROR ("engine gen when NIA complex");
198 }
199
200 /* events */
201 lf_putstr (file, "\n");
202 lf_putstr (file, "/* process any events */\n");
203 lf_putstr (file, "if (sim_events_tick (sd))\n");
204 lf_putstr (file, " {\n");
034685f9 205 lf_putstr (file, " CPU_PC_SET (CPU, cia);\n");
c906108c 206 lf_putstr (file, " sim_events_process (sd);\n");
034685f9 207 lf_putstr (file, " cia = CPU_PC_GET (CPU);\n");
c906108c
SS
208 lf_putstr (file, " }\n");
209
210 lf_indent (file, -4);
211 lf_printf (file, " }\n");
212 }
4e0bf4c4 213
c906108c
SS
214 if (options.gen.smp)
215 {
4e0bf4c4 216
4e62efb8
RH
217 lf_putstr (file, "\
218/* CASE 2: SMP (With or without ICACHE)\n\
219\n\
220The complexity here comes from needing to correctly halt the simulator\n\
221when it is aborted. For instance, if cpu0 requests a restart then\n\
222cpu1 will normally be the next cpu that is run. Cpu0 being restarted\n\
223after all the other CPU's and the event queue have been processed */\n\
224\n\
c906108c 225");
4e0bf4c4 226
c906108c 227 lf_putstr (file, "\n");
4e0bf4c4
AC
228 lf_printf (file,
229 "/* have ensured that the event queue is NOT next */\n");
c906108c
SS
230 lf_printf (file, "SIM_ASSERT (current_cpu >= 0);\n");
231 lf_printf (file, "SIM_ASSERT (current_cpu <= nr_cpus - 1);\n");
232 lf_printf (file, "SIM_ASSERT (nr_cpus <= MAX_NR_PROCESSORS);\n");
233
234 lf_putstr (file, "\n");
235 lf_putstr (file, "while (1)\n");
236 lf_putstr (file, " {\n");
237 lf_indent (file, +4);
238 lf_putstr (file, "sim_cpu *cpu = STATE_CPU (sd, current_cpu);\n");
034685f9 239 lf_putstr (file, "instruction_address cia = CPU_PC_GET (cpu);\n");
c906108c
SS
240 lf_putstr (file, "\n");
241
242 if (!options.gen.icache)
243 {
244 lf_printf (file, "instruction_word instruction_0 = IMEM%d (cia);\n",
245 options.insn_bit_size);
246 print_engine_issue_prefix_hook (file);
247 print_idecode_body (file, table, "cia =");
034685f9 248 lf_putstr (file, "CPU_PC_SET (cpu, cia);\n");
c906108c
SS
249 print_engine_issue_postfix_hook (file);
250 }
4e0bf4c4 251
c906108c
SS
252 if (options.gen.icache)
253 {
254 lf_putstr (file, "engine_cache *cache_entry =\n");
255 lf_putstr (file, " cpu_icache_entry(processor, cia);\n");
256 lf_putstr (file, "\n");
257 lf_putstr (file, "if (cache_entry->address == cia) {\n");
258 {
259 lf_indent (file, +2);
260 lf_putstr (file, "\n");
261 lf_putstr (file, "/* cache hit */\n");
4e0bf4c4
AC
262 lf_putstr (file,
263 "engine_semantic *semantic = cache_entry->semantic;\n");
264 lf_putstr (file,
265 "cia = semantic(processor, cache_entry, cia);\n");
c906108c
SS
266 /* tail */
267 lf_putstr (file, "cpu_set_program_counter(processor, cia);\n");
268 lf_putstr (file, "\n");
269 lf_indent (file, -2);
270 }
271 lf_putstr (file, "}\n");
272 lf_putstr (file, "else {\n");
273 {
274 lf_indent (file, +2);
275 lf_putstr (file, "\n");
276 lf_putstr (file, "/* cache miss */\n");
277 if (!options.gen.semantic_icache)
278 {
279 lf_putstr (file, "engine_semantic *semantic;\n");
280 }
281 lf_printf (file, "instruction_word instruction = IMEM%d (cia);\n",
282 options.insn_bit_size);
283 lf_putstr (file, "if (WITH_MON != 0)\n");
4e0bf4c4
AC
284 lf_putstr (file,
285 " mon_event(mon_event_icache_miss, processors[current_cpu], cia);\n");
c906108c
SS
286 if (options.gen.semantic_icache)
287 {
288 lf_putstr (file, "{\n");
289 lf_indent (file, +2);
290 print_engine_issue_prefix_hook (file);
4e0bf4c4 291 print_idecode_body (file, table, "cia =");
c906108c
SS
292 print_engine_issue_postfix_hook (file);
293 lf_indent (file, -2);
294 lf_putstr (file, "}\n");
295 }
296 else
297 {
298 print_engine_issue_prefix_hook (file);
4e0bf4c4
AC
299 print_idecode_body (file, table, "semantic = ");
300 lf_putstr (file,
301 "cia = semantic(processor, cache_entry, cia);\n");
c906108c
SS
302 print_engine_issue_postfix_hook (file);
303 }
304 /* tail */
305 lf_putstr (file, "cpu_set_program_counter(processor, cia);\n");
306 lf_putstr (file, "\n");
307 lf_indent (file, -2);
308 }
309 lf_putstr (file, "}\n");
310 }
4e0bf4c4 311
c906108c
SS
312 lf_putstr (file, "\n");
313 lf_putstr (file, "current_cpu += 1;\n");
314 lf_putstr (file, "if (current_cpu == nr_cpus)\n");
315 lf_putstr (file, " {\n");
316 lf_putstr (file, " if (sim_events_tick (sd))\n");
317 lf_putstr (file, " {\n");
318 lf_putstr (file, " sim_events_process (sd);\n");
319 lf_putstr (file, " }\n");
320 lf_putstr (file, " current_cpu = 0;\n");
321 lf_putstr (file, " }\n");
4e0bf4c4 322
c906108c
SS
323 /* tail */
324 lf_indent (file, -4);
325 lf_putstr (file, " }\n");
326 }
4e0bf4c4
AC
327
328
c906108c
SS
329 lf_indent (file, -2);
330 lf_putstr (file, "}\n");
331}
332
333
334/****************************************************************/
335
c906108c
SS
336void
337print_engine_run_function_header (lf *file,
338 char *processor,
339 function_decl_type decl_type)
340{
341 int indent;
342 lf_printf (file, "\n");
343 switch (decl_type)
344 {
345 case is_function_declaration:
346 lf_print__function_type (file, "void", "INLINE_ENGINE", "\n");
347 break;
348 case is_function_definition:
349 lf_print__function_type (file, "void", "INLINE_ENGINE", " ");
350 break;
351 case is_function_variable:
352 lf_printf (file, "void (*");
353 break;
354 }
4e0bf4c4
AC
355 indent = print_function_name (file, "run", NULL, /* format name */
356 processor, NULL, /* expanded bits */
c906108c
SS
357 function_name_prefix_engine);
358 switch (decl_type)
359 {
360 case is_function_definition:
361 lf_putstr (file, "\n(");
362 indent = 1;
363 break;
364 case is_function_declaration:
365 indent += lf_printf (file, " (");
366 break;
367 case is_function_variable:
368 lf_putstr (file, ")\n(");
369 indent = 1;
370 break;
371 }
372 lf_indent (file, +indent);
373 lf_printf (file, "SIM_DESC sd,\n");
374 lf_printf (file, "int next_cpu_nr,\n");
375 lf_printf (file, "int nr_cpus,\n");
376 lf_printf (file, "int siggnal)");
377 lf_indent (file, -indent);
378 switch (decl_type)
379 {
380 case is_function_definition:
381 lf_putstr (file, "\n");
382 break;
383 case is_function_variable:
384 case is_function_declaration:
385 lf_putstr (file, ";\n");
386 break;
387 }
388}
389
390
391void
392gen_engine_h (lf *file,
4e0bf4c4 393 gen_table *gen, insn_table *isa, cache_entry *cache_rules)
c906108c
SS
394{
395 gen_list *entry;
396 for (entry = gen->tables; entry != NULL; entry = entry->next)
397 {
398 print_engine_run_function_header (file,
399 (options.gen.multi_sim
400 ? entry->model->name
4e0bf4c4 401 : NULL), is_function_declaration);
c906108c
SS
402 }
403}
404
405
406void
4e0bf4c4
AC
407gen_engine_c (lf *file,
408 gen_table *gen, insn_table *isa, cache_entry *cache_rules)
c906108c
SS
409{
410 gen_list *entry;
411 /* the intro */
412 print_includes (file);
413 print_include_inline (file, options.module.semantics);
414 print_include (file, options.module.engine);
415 lf_printf (file, "\n");
416 lf_printf (file, "#include \"sim-assert.h\"\n");
417 lf_printf (file, "\n");
418 print_idecode_globals (file);
419 lf_printf (file, "\n");
420
421 for (entry = gen->tables; entry != NULL; entry = entry->next)
422 {
423 switch (options.gen.code)
424 {
425 case generate_calls:
426 print_idecode_lookups (file, entry->table, cache_rules);
4e0bf4c4 427
c906108c
SS
428 /* output the main engine routine */
429 print_engine_run_function_header (file,
430 (options.gen.multi_sim
431 ? entry->model->name
4e0bf4c4 432 : NULL), is_function_definition);
c906108c
SS
433 print_run_body (file, entry->table);
434 break;
4e0bf4c4 435
c906108c
SS
436 case generate_jumps:
437 ERROR ("Jumps currently unimplemented");
c906108c
SS
438 break;
439 }
440 }
441}