1 /* This file is part of the program psim.
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 2 of the License, or
8 (at your option) any later version.
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
29 #include "ld-decode.h"
33 #include "gen-idecode.h"
34 #include "gen-engine.h"
35 #include "gen-icache.h"
36 #include "gen-semantics.h"
40 print_run_body (lf *file,
43 /* Output the function to execute real code:
45 Unfortunatly, there are multiple cases to consider vis:
49 Consequently this function is written in multiple different ways */
51 lf_printf (file, "{\n");
55 lf_printf (file, "instruction_address cia;\n");
57 lf_printf (file, "int current_cpu = next_cpu_nr;\n");
59 if (options.gen.icache)
61 lf_printf (file, "/* flush the icache of a possible break insn */\n");
62 lf_printf (file, "{\n");
63 lf_printf (file, " int cpu_nr;\n");
64 lf_printf (file, " for (cpu_nr = 0; cpu_nr < nr_cpus; cpu_nr++)\n");
65 lf_printf (file, " cpu_flush_icache (STATE_CPU (sd, cpu_nr));\n");
66 lf_printf (file, "}\n");
73 /* CASE 1: NO SMP (with or with out instruction cache).
75 In this case, we can take advantage of the fact that the current
76 instruction address (CIA) does not need to be read from / written to
77 the CPU object after the execution of an instruction.
79 Instead, CIA is only saved when the main loop exits. This occures
80 when either sim_engine_halt or sim_engine_restart is called. Both of
81 these functions save the current instruction address before halting /
82 restarting the simulator.
84 As a variation, there may also be support for an instruction cracking
89 lf_putstr (file, "\n");
90 lf_putstr (file, "/* prime the main loop */\n");
91 lf_putstr (file, "SIM_ASSERT (current_cpu == 0);\n");
92 lf_putstr (file, "SIM_ASSERT (nr_cpus == 1);\n");
93 lf_putstr (file, "cia = CIA_GET (CPU);\n");
95 lf_putstr (file, "\n");
96 lf_putstr (file, "while (1)\n");
97 lf_putstr (file, " {\n");
100 lf_printf (file, "%sinstruction_address nia;\n",
101 options.prefix.global.name);
103 lf_printf (file, "\n");
104 if (!options.gen.icache)
106 lf_printf (file, "%sinstruction_word instruction_0 = IMEM (cia);\n",
107 options.prefix.global.name);
108 lf_printf (file, "\n");
109 lf_indent_suppress (file);
110 lf_printf (file, "#if defined (%sENGINE_ISSUE_PREFIX_HOOK)\n",
111 options.prefix.global.name);
112 lf_printf (file, "%sENGINE_ISSUE_PREFIX_HOOK();\n",
113 options.prefix.global.name);
114 lf_indent_suppress (file);
115 lf_printf (file, "#endif\n");
116 lf_printf (file, "\n");
117 print_idecode_body (file, table, "nia = ");
118 lf_printf (file, "\n");
119 lf_indent_suppress (file);
120 lf_printf (file, "#if defined (%sENGINE_ISSUE_POSTFIX_HOOK)\n",
121 options.prefix.global.name);
122 lf_printf (file, "%sENGINE_ISSUE_POSTFIX_HOOK();\n",
123 options.prefix.global.name);
124 lf_indent_suppress (file);
125 lf_printf (file, "#endif\n");
126 lf_printf (file, "\n");
130 lf_putstr (file, "idecode_cache *cache_entry =\n");
131 lf_putstr (file, " cpu_icache_entry (cpu, cia);\n");
132 lf_putstr (file, "if (cache_entry->address == cia)\n");
133 lf_putstr (file, " {\n");
134 lf_indent (file, -4);
135 lf_putstr (file, "/* cache hit */\n");
136 lf_putstr (file, "idecode_semantic *const semantic = cache_entry->semantic;\n");
137 lf_putstr (file, "cia = semantic (cpu, cache_entry, cia);\n");
139 lf_indent (file, -4);
140 lf_putstr (file, " }\n");
141 lf_putstr (file, "else\n");
142 lf_putstr (file, " {\n");
143 lf_indent (file, +4);
144 lf_putstr (file, "/* cache miss */\n");
145 if (!options.gen.semantic_icache)
147 lf_putstr (file, "idecode_semantic *semantic;\n");
149 lf_putstr (file, "instruction_word instruction = IMEM (cia);\n");
150 lf_putstr (file, "if (WITH_MON != 0)\n");
151 lf_putstr (file, " mon_event (mon_event_icache_miss, cpu, cia);\n");
152 if (options.gen.semantic_icache)
154 lf_putstr (file, "{\n");
155 lf_indent (file, +2);
156 print_idecode_body (file, table, "nia =");
157 lf_indent (file, -2);
158 lf_putstr (file, "}\n");
162 print_idecode_body (file, table, "semantic =");
163 lf_putstr (file, "nia = semantic (cpu, cache_entry, cia);\n");
165 lf_indent (file, -4);
166 lf_putstr (file, " }\n");
169 /* update the cpu if necessary */
170 switch (options.gen.nia)
172 case nia_is_cia_plus_one:
173 lf_printf (file, "\n");
174 lf_printf (file, "/* Update the instruction address */\n");
175 lf_printf (file, "cia = nia;\n");
179 ERROR ("engine gen when NIA complex");
183 lf_putstr (file, "\n");
184 lf_putstr (file, "/* process any events */\n");
185 lf_putstr (file, "if (sim_events_tick (sd))\n");
186 lf_putstr (file, " {\n");
187 lf_putstr (file, " CIA_SET (CPU, cia);\n");
188 lf_putstr (file, " sim_events_process (sd);\n");
189 lf_putstr (file, " }\n");
191 lf_indent (file, -4);
192 lf_printf (file, " }\n");
199 /* CASE 2: SMP (With or without ICACHE)
201 The complexity here comes from needing to correctly halt the simulator
202 when it is aborted. For instance, if cpu0 requests a restart then
203 cpu1 will normally be the next cpu that is run. Cpu0 being restarted
204 after all the other CPU's and the event queue have been processed */
208 lf_putstr (file, "\n");
209 lf_printf (file, "/* have ensured that the event queue is current */\n");
210 lf_printf (file, "SIM_ASSERT (current_cpu >= 0);\n");
211 lf_printf (file, "SIM_ASSERT (current_cpu < nr_cpus - 1);\n");
212 lf_printf (file, "SIM_ASSERT (nr_cpus <= MAX_NR_PROCESSORS);\n");
214 lf_putstr (file, "\n");
215 lf_putstr (file, "while (1)\n");
216 lf_putstr (file, " {\n");
217 lf_indent (file, +4);
219 lf_putstr (file, "\n");
220 lf_putstr (file, "current_cpu += 1;\n");
221 lf_putstr (file, "if (current_cpu == nr_cpus)\n");
222 lf_putstr (file, " {\n");
223 lf_putstr (file, " if (sim_events_tick (sd))\n");
224 lf_putstr (file, " {\n");
225 lf_putstr (file, " sim_events_process (sd);\n");
226 lf_putstr (file, " }\n");
227 lf_putstr (file, " current_cpu = 0;\n");
228 lf_putstr (file, " }\n");
230 lf_putstr (file, "\n");
231 lf_putstr (file, "{\n");
232 lf_indent (file, +2);
233 lf_putstr (file, "sim_cpu *cpu = STATE_CPU (sd, current_cpu);\n");
234 lf_putstr (file, "instruction_address cia = CIA_GET (cpu);\n");
236 if (!options.gen.icache)
238 lf_putstr (file, "instruction_word instruction_0 = IMEM (cia);\n");
239 print_idecode_body (file, table, "cia =");
240 lf_putstr (file, "CIA_SET (cpu, cia);\n");
243 if (options.gen.icache)
245 lf_putstr (file, "engine_cache *cache_entry =\n");
246 lf_putstr (file, " cpu_icache_entry(processor, cia);\n");
247 lf_putstr (file, "\n");
248 lf_putstr (file, "if (cache_entry->address == cia) {\n");
250 lf_indent (file, +2);
251 lf_putstr (file, "\n");
252 lf_putstr (file, "/* cache hit */\n");
253 lf_putstr (file, "engine_semantic *semantic = cache_entry->semantic;\n");
254 lf_putstr (file, "cia = semantic(processor, cache_entry, cia);\n");
256 lf_putstr (file, "cpu_set_program_counter(processor, cia);\n");
257 lf_putstr (file, "\n");
258 lf_indent (file, -2);
260 lf_putstr (file, "}\n");
261 lf_putstr (file, "else {\n");
263 lf_indent (file, +2);
264 lf_putstr (file, "\n");
265 lf_putstr (file, "/* cache miss */\n");
266 if (!options.gen.semantic_icache)
268 lf_putstr (file, "engine_semantic *semantic;\n");
270 lf_putstr (file, "instruction_word instruction = IMEM (cia);\n");
271 lf_putstr (file, "if (WITH_MON != 0)\n");
272 lf_putstr (file, " mon_event(mon_event_icache_miss, processors[current_cpu], cia);\n");
273 if (options.gen.semantic_icache)
275 lf_putstr (file, "{\n");
276 lf_indent (file, +2);
277 print_idecode_body(file, table, "cia =");
278 lf_indent (file, -2);
279 lf_putstr (file, "}\n");
283 print_idecode_body(file, table, "semantic = ");
284 lf_putstr (file, "cia = semantic(processor, cache_entry, cia);\n");
287 lf_putstr (file, "cpu_set_program_counter(processor, cia);\n");
288 lf_putstr (file, "\n");
289 lf_indent (file, -2);
291 lf_putstr (file, "}\n");
295 lf_indent (file, -2);
296 lf_putstr (file, "}\n");
299 lf_indent (file, -4);
300 lf_putstr (file, " }\n");
304 lf_indent (file, -2);
305 lf_putstr (file, "}\n");
309 /****************************************************************/
313 print_jump (lf *file,
316 if (!options.gen.smp)
318 lf_putstr (file, "if (event_queue_tick (sd))\n");
319 lf_putstr (file, " {\n");
320 lf_putstr (file, " CPU_CIA (processor) = nia;\n");
321 lf_putstr (file, " sim_events_process (sd);\n");
322 lf_putstr (file, " }\n");
323 lf_putstr (file, "}\n");
329 lf_putstr (file, "cpu_set_program_counter(processor, nia);\n");
330 lf_putstr (file, "current_cpu += 1;\n");
331 lf_putstr (file, "if (current_cpu >= nr_cpus)\n");
332 lf_putstr (file, " {\n");
333 lf_putstr (file, " if (sim_events_tick (sd))\n");
334 lf_putstr (file, " {\n");
335 lf_putstr (file, " sim_events_process (sd);\n");
336 lf_putstr (file, " }\n");
337 lf_putstr (file, " current_cpu = 0;\n");
338 lf_putstr (file, " }\n");
339 lf_putstr (file, "processor = processors[current_cpu];\n");
340 lf_putstr (file, "nia = cpu_get_program_counter(processor);\n");
343 if (options.gen.icache)
345 lf_putstr (file, "cache_entry = cpu_icache_entry(processor, nia);\n");
346 lf_putstr (file, "if (cache_entry->address == nia) {\n");
347 lf_putstr (file, " /* cache hit */\n");
348 lf_putstr (file, " goto *cache_entry->semantic;\n");
349 lf_putstr (file, "}\n");
351 lf_putstr (file, "goto cache_miss;\n");
355 if (!options.gen.icache && is_tail)
357 lf_printf (file, "goto engine;\n");
366 print_jump_insn (lf *file,
367 insn_entry *instruction,
368 opcode_bits *expanded_bits,
369 opcode_field *opcodes,
370 cache_entry *cache_rules)
372 insn_opcodes opcode_path;
374 memset (&opcode_path, 0, sizeof (opcode_path));
375 opcode_path.opcode = opcodes;
377 /* what we are for the moment */
378 lf_printf (file, "\n");
379 print_my_defines (file,
381 instruction->format_name,
384 /* output the icache entry */
385 if (options.gen.icache)
387 lf_printf (file, "\n");
388 lf_indent (file, -1);
389 print_function_name (file,
391 instruction->format_name,
394 function_name_prefix_icache);
395 lf_printf (file, ":\n");
396 lf_indent (file, +1);
397 lf_printf (file, "{\n");
398 lf_indent (file, +2);
399 lf_putstr (file, "const unsigned_word cia = nia;\n");
400 print_itrace (file, instruction, 1/*putting-value-in-cache*/);
401 print_idecode_validate (file, instruction, &opcode_path);
402 lf_printf (file, "\n");
403 lf_printf (file, "{\n");
404 lf_indent (file, +2);
405 print_icache_body (file,
410 put_values_in_icache);
411 lf_printf (file, "cache_entry->address = nia;\n");
412 lf_printf (file, "cache_entry->semantic = &&");
413 print_function_name (file,
415 instruction->format_name,
418 function_name_prefix_semantics);
419 lf_printf (file, ";\n");
420 if (options.gen.semantic_icache)
422 print_semantic_body (file,
426 print_jump(file, 1/*is-tail*/);
430 lf_printf (file, "/* goto ");
431 print_function_name (file,
433 instruction->format_name,
436 function_name_prefix_semantics);
437 lf_printf (file, "; */\n");
439 lf_indent (file, -2);
440 lf_putstr (file, "}\n");
441 lf_indent (file, -2);
442 lf_printf (file, "}\n");
445 /* print the semantics */
446 lf_printf (file, "\n");
447 lf_indent (file, -1);
448 print_function_name (file,
450 instruction->format_name,
453 function_name_prefix_semantics);
454 lf_printf (file, ":\n");
455 lf_indent (file, +1);
456 lf_printf (file, "{\n");
457 lf_indent (file, +2);
458 lf_putstr (file, "const unsigned_word cia = nia;\n");
459 print_icache_body (file,
463 (options.gen.direct_access
465 : declare_variables),
467 ? get_values_from_icache
468 : do_not_use_icache));
469 print_semantic_body (file,
473 if (options.gen.direct_access)
474 print_icache_body (file,
480 ? get_values_from_icache
481 : do_not_use_icache));
482 print_jump(file, 1/*is tail*/);
483 lf_indent (file, -2);
484 lf_printf (file, "}\n");
491 print_jump_definition (lf *file,
496 cache_entry *cache_rules = (cache_entry*)data;
497 if (entry->opcode_rule->with_duplicates)
499 ASSERT (entry->nr_insns == 1
500 && entry->opcode == NULL
501 && entry->parent != NULL
502 && entry->parent->opcode != NULL);
503 ASSERT (entry->nr_insns == 1
504 && entry->opcode == NULL
505 && entry->parent != NULL
506 && entry->parent->opcode != NULL
507 && entry->parent->opcode_rule != NULL);
508 print_jump_insn (file,
510 entry->expanded_bits,
516 print_jump_insn (file,
528 print_jump_internal_function (lf *file,
529 function_entry *function,
532 if (function->is_internal)
534 lf_printf (file, "\n");
535 lf_print__line_ref (file, function->line);
536 lf_indent (file, -1);
537 print_function_name (file,
543 ? function_name_prefix_icache
544 : function_name_prefix_semantics));
545 lf_printf (file, ":\n");
546 lf_indent (file, +1);
547 lf_printf (file, "{\n");
548 lf_indent (file, +2);
549 lf_printf (file, "const unsigned_word cia = nia;\n");
550 table_print_code (file, function->code);
551 lf_print__internal_ref (file);
552 lf_printf (file, "error(\"Internal function must longjump\\n\");\n");
553 lf_indent (file, -2);
554 lf_printf (file, "}\n");
562 print_jump_body (lf *file,
565 cache_entry *cache_rules)
567 lf_printf (file, "{\n");
568 lf_indent (file, +2);
569 lf_putstr (file, "jmp_buf halt;\n");
570 lf_putstr (file, "jmp_buf restart;\n");
571 lf_putstr (file, "cpu *processor = NULL;\n");
572 lf_putstr (file, "unsigned_word nia = -1;\n");
573 lf_putstr (file, "instruction_word instruction = 0;\n");
574 if (options.gen.icache)
576 lf_putstr (file, "engine_cache *cache_entry = NULL;\n");
580 lf_putstr (file, "int current_cpu = -1;\n");
583 /* all the switches and tables - they know about jumping */
584 print_idecode_lookups (file, entry, cache_rules);
586 /* start the simulation up */
587 if (options.gen.icache)
589 lf_putstr (file, "\n");
590 lf_putstr (file, "{\n");
591 lf_putstr (file, " int cpu_nr;\n");
592 lf_putstr (file, " for (cpu_nr = 0; cpu_nr < nr_cpus; cpu_nr++)\n");
593 lf_putstr (file, " cpu_flush_icache(processors[cpu_nr]);\n");
594 lf_putstr (file, "}\n");
597 lf_putstr (file, "\n");
598 lf_putstr (file, "psim_set_halt_and_restart(system, &halt, &restart);\n");
600 lf_putstr (file, "\n");
601 lf_putstr (file, "if (setjmp(halt))\n");
602 lf_putstr (file, " return;\n");
604 lf_putstr (file, "\n");
605 lf_putstr (file, "setjmp(restart);\n");
607 lf_putstr (file, "\n");
608 if (!options.gen.smp)
610 lf_putstr (file, "processor = processors[0];\n");
611 lf_putstr (file, "nia = cpu_get_program_counter(processor);\n");
615 lf_putstr (file, "current_cpu = psim_last_cpu(system);\n");
618 if (!options.gen.icache)
620 lf_printf (file, "\n");
621 lf_indent (file, -1);
622 lf_printf (file, "engine:\n");
623 lf_indent (file, +1);
626 print_jump(file, 0/*is_tail*/);
628 if (options.gen.icache)
630 lf_indent (file, -1);
631 lf_printf (file, "cache_miss:\n");
632 lf_indent (file, +1);
635 lf_putstr (file, "instruction\n");
636 lf_putstr (file, " = vm_instruction_map_read(cpu_instruction_map(processor),\n");
637 lf_putstr (file, " processor, nia);\n");
638 print_idecode_body (file, entry, "/*IGORE*/");
640 /* print out a table of all the internals functions */
641 function_entry_traverse (file, isa->functions,
642 print_jump_internal_function,
645 /* print out a table of all the instructions */
646 ERROR ("Use the list of semantic functions, not travere_tree");
647 gen_entry_traverse_tree (file, entry,
650 print_jump_definition, /* leaf */
653 lf_indent (file, -2);
654 lf_printf (file, "}\n");
659 /****************************************************************/
663 print_engine_run_function_header (lf *file,
665 function_decl_type decl_type)
668 lf_printf (file, "\n");
671 case is_function_declaration:
672 lf_print__function_type (file, "void", "INLINE_ENGINE", "\n");
674 case is_function_definition:
675 lf_print__function_type (file, "void", "INLINE_ENGINE", " ");
677 case is_function_variable:
678 lf_printf (file, "void (*");
681 indent = print_function_name (file,
683 NULL, /* format name */
685 NULL, /* expanded bits */
686 function_name_prefix_engine);
689 case is_function_definition:
690 lf_putstr (file, "\n(");
693 case is_function_declaration:
694 indent += lf_printf (file, " (");
696 case is_function_variable:
697 lf_putstr (file, ")\n(");
701 lf_indent (file, +indent);
702 lf_printf (file, "SIM_DESC sd,\n");
703 lf_printf (file, "int next_cpu_nr,\n");
704 lf_printf (file, "int nr_cpus,\n");
705 lf_printf (file, "int siggnal)");
706 lf_indent (file, -indent);
709 case is_function_definition:
710 lf_putstr (file, "\n");
712 case is_function_variable:
713 case is_function_declaration:
714 lf_putstr (file, ";\n");
721 gen_engine_h (lf *file,
724 cache_entry *cache_rules)
727 for (entry = gen->tables; entry != NULL; entry = entry->next)
729 print_engine_run_function_header (file,
730 (options.gen.multi_sim
733 is_function_declaration);
739 gen_engine_c(lf *file,
742 cache_entry *cache_rules)
746 lf_printf (file, "#include \"sim-inline.c\"\n");
747 lf_printf (file, "\n");
748 lf_printf (file, "#include \"sim-main.h\"\n");
749 lf_printf (file, "#include \"itable.h\"\n");
750 lf_printf (file, "#include \"idecode.h\"\n");
751 lf_printf (file, "#include \"semantics.h\"\n");
752 lf_printf (file, "#include \"icache.h\"\n");
753 lf_printf (file, "#include \"engine.h\"\n");
754 lf_printf (file, "#include \"support.h\"\n");
755 lf_printf (file, "\n");
756 lf_printf (file, "#include \"sim-assert.h\"\n");
757 lf_printf (file, "\n");
758 print_idecode_globals (file);
759 lf_printf (file, "\n");
761 for (entry = gen->tables; entry != NULL; entry = entry->next)
763 switch (options.gen.code)
766 print_idecode_lookups (file, entry->table, cache_rules);
768 /* output the main engine routine */
769 print_engine_run_function_header (file,
770 (options.gen.multi_sim
773 is_function_definition);
774 print_run_body (file, entry->table);
778 ERROR ("Jumps currently unimplemented");
780 print_engine_run_function_header (file,
782 is_function_definition);
783 print_jump_body (file, entry->table,