1 /* This file is part of the program psim.
3 Copyright (C) 1994-1998, Andrew Cagney <cagney@highland.com.au>
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_engine_issue_prefix_hook (lf
*file
)
42 lf_printf (file
, "\n");
43 lf_indent_suppress (file
);
44 lf_printf (file
, "#if defined (ENGINE_ISSUE_PREFIX_HOOK)\n");
45 lf_printf (file
, "ENGINE_ISSUE_PREFIX_HOOK();\n");
46 lf_indent_suppress (file
);
47 lf_printf (file
, "#endif\n");
48 lf_printf (file
, "\n");
52 print_engine_issue_postfix_hook (lf
*file
)
54 lf_printf (file
, "\n");
55 lf_indent_suppress (file
);
56 lf_printf (file
, "#if defined (ENGINE_ISSUE_POSTFIX_HOOK)\n");
57 lf_printf (file
, "ENGINE_ISSUE_POSTFIX_HOOK();\n");
58 lf_indent_suppress (file
);
59 lf_printf (file
, "#endif\n");
60 lf_printf (file
, "\n");
65 print_run_body (lf
*file
,
68 /* Output the function to execute real code:
70 Unfortunatly, there are multiple cases to consider vis:
74 Consequently this function is written in multiple different ways */
76 lf_printf (file
, "{\n");
80 lf_printf (file
, "%sinstruction_address cia;\n", options
.module
.global
.prefix
.l
);
82 lf_printf (file
, "int current_cpu = next_cpu_nr;\n");
84 if (options
.gen
.icache
)
86 lf_printf (file
, "/* flush the icache of a possible break insn */\n");
87 lf_printf (file
, "{\n");
88 lf_printf (file
, " int cpu_nr;\n");
89 lf_printf (file
, " for (cpu_nr = 0; cpu_nr < nr_cpus; cpu_nr++)\n");
90 lf_printf (file
, " cpu_flush_icache (STATE_CPU (sd, cpu_nr));\n");
91 lf_printf (file
, "}\n");
98 /* CASE 1: NO SMP (with or with out instruction cache).\n\
100 In this case, we can take advantage of the fact that the current\n\
101 instruction address (CIA) does not need to be read from / written to\n\
102 the CPU object after the execution of an instruction.\n\
104 Instead, CIA is only saved when the main loop exits. This occures\n\
105 when either sim_engine_halt or sim_engine_restart is called. Both of\n\
106 these functions save the current instruction address before halting /\n\
107 restarting the simulator.\n\
109 As a variation, there may also be support for an instruction cracking\n\
114 lf_putstr (file
, "\n");
115 lf_putstr (file
, "/* prime the main loop */\n");
116 lf_putstr (file
, "SIM_ASSERT (current_cpu == 0);\n");
117 lf_putstr (file
, "SIM_ASSERT (nr_cpus == 1);\n");
118 lf_putstr (file
, "cia = CIA_GET (CPU);\n");
120 lf_putstr (file
, "\n");
121 lf_putstr (file
, "while (1)\n");
122 lf_putstr (file
, " {\n");
123 lf_indent (file
, +4);
125 lf_printf (file
, "%sinstruction_address nia;\n",
126 options
.module
.global
.prefix
.l
);
128 lf_printf (file
, "\n");
129 if (!options
.gen
.icache
)
131 lf_printf (file
, "%sinstruction_word instruction_0 = IMEM%d (cia);\n",
132 options
.module
.global
.prefix
.l
,
133 options
.insn_bit_size
);
134 print_engine_issue_prefix_hook (file
);
135 print_idecode_body (file
, table
, "nia = ");
136 print_engine_issue_postfix_hook (file
);
140 lf_putstr (file
, "idecode_cache *cache_entry =\n");
141 lf_putstr (file
, " cpu_icache_entry (cpu, cia);\n");
142 lf_putstr (file
, "if (cache_entry->address == cia)\n");
143 lf_putstr (file
, " {\n");
144 lf_indent (file
, -4);
145 lf_putstr (file
, "/* cache hit */\n");
146 lf_putstr (file
, "idecode_semantic *const semantic = cache_entry->semantic;\n");
147 lf_putstr (file
, "cia = semantic (cpu, cache_entry, cia);\n");
149 lf_indent (file
, -4);
150 lf_putstr (file
, " }\n");
151 lf_putstr (file
, "else\n");
152 lf_putstr (file
, " {\n");
153 lf_indent (file
, +4);
154 lf_putstr (file
, "/* cache miss */\n");
155 if (!options
.gen
.semantic_icache
)
157 lf_putstr (file
, "idecode_semantic *semantic;\n");
159 lf_printf (file
, "instruction_word instruction = IMEM%d (cia);\n",
160 options
.insn_bit_size
);
161 lf_putstr (file
, "if (WITH_MON != 0)\n");
162 lf_putstr (file
, " mon_event (mon_event_icache_miss, cpu, cia);\n");
163 if (options
.gen
.semantic_icache
)
165 lf_putstr (file
, "{\n");
166 lf_indent (file
, +2);
167 print_engine_issue_prefix_hook (file
);
168 print_idecode_body (file
, table
, "nia =");
169 print_engine_issue_postfix_hook (file
);
170 lf_indent (file
, -2);
171 lf_putstr (file
, "}\n");
175 print_engine_issue_prefix_hook (file
);
176 print_idecode_body (file
, table
, "semantic =");
177 lf_putstr (file
, "nia = semantic (cpu, cache_entry, cia);\n");
178 print_engine_issue_postfix_hook (file
);
180 lf_indent (file
, -4);
181 lf_putstr (file
, " }\n");
184 /* update the cpu if necessary */
185 switch (options
.gen
.nia
)
187 case nia_is_cia_plus_one
:
188 lf_printf (file
, "\n");
189 lf_printf (file
, "/* Update the instruction address */\n");
190 lf_printf (file
, "cia = nia;\n");
194 ERROR ("engine gen when NIA complex");
198 lf_putstr (file
, "\n");
199 lf_putstr (file
, "/* process any events */\n");
200 lf_putstr (file
, "if (sim_events_tick (sd))\n");
201 lf_putstr (file
, " {\n");
202 lf_putstr (file
, " CIA_SET (CPU, cia);\n");
203 lf_putstr (file
, " sim_events_process (sd);\n");
204 lf_putstr (file
, " cia = CIA_GET (CPU);\n");
205 lf_putstr (file
, " }\n");
207 lf_indent (file
, -4);
208 lf_printf (file
, " }\n");
215 /* CASE 2: SMP (With or without ICACHE)\n\
217 The complexity here comes from needing to correctly halt the simulator\n\
218 when it is aborted. For instance, if cpu0 requests a restart then\n\
219 cpu1 will normally be the next cpu that is run. Cpu0 being restarted\n\
220 after all the other CPU's and the event queue have been processed */\n\
224 lf_putstr (file
, "\n");
225 lf_printf (file
, "/* have ensured that the event queue is NOT next */\n");
226 lf_printf (file
, "SIM_ASSERT (current_cpu >= 0);\n");
227 lf_printf (file
, "SIM_ASSERT (current_cpu <= nr_cpus - 1);\n");
228 lf_printf (file
, "SIM_ASSERT (nr_cpus <= MAX_NR_PROCESSORS);\n");
230 lf_putstr (file
, "\n");
231 lf_putstr (file
, "while (1)\n");
232 lf_putstr (file
, " {\n");
233 lf_indent (file
, +4);
234 lf_putstr (file
, "sim_cpu *cpu = STATE_CPU (sd, current_cpu);\n");
235 lf_putstr (file
, "instruction_address cia = CIA_GET (cpu);\n");
236 lf_putstr (file
, "\n");
238 if (!options
.gen
.icache
)
240 lf_printf (file
, "instruction_word instruction_0 = IMEM%d (cia);\n",
241 options
.insn_bit_size
);
242 print_engine_issue_prefix_hook (file
);
243 print_idecode_body (file
, table
, "cia =");
244 lf_putstr (file
, "CIA_SET (cpu, cia);\n");
245 print_engine_issue_postfix_hook (file
);
248 if (options
.gen
.icache
)
250 lf_putstr (file
, "engine_cache *cache_entry =\n");
251 lf_putstr (file
, " cpu_icache_entry(processor, cia);\n");
252 lf_putstr (file
, "\n");
253 lf_putstr (file
, "if (cache_entry->address == cia) {\n");
255 lf_indent (file
, +2);
256 lf_putstr (file
, "\n");
257 lf_putstr (file
, "/* cache hit */\n");
258 lf_putstr (file
, "engine_semantic *semantic = cache_entry->semantic;\n");
259 lf_putstr (file
, "cia = semantic(processor, cache_entry, cia);\n");
261 lf_putstr (file
, "cpu_set_program_counter(processor, cia);\n");
262 lf_putstr (file
, "\n");
263 lf_indent (file
, -2);
265 lf_putstr (file
, "}\n");
266 lf_putstr (file
, "else {\n");
268 lf_indent (file
, +2);
269 lf_putstr (file
, "\n");
270 lf_putstr (file
, "/* cache miss */\n");
271 if (!options
.gen
.semantic_icache
)
273 lf_putstr (file
, "engine_semantic *semantic;\n");
275 lf_printf (file
, "instruction_word instruction = IMEM%d (cia);\n",
276 options
.insn_bit_size
);
277 lf_putstr (file
, "if (WITH_MON != 0)\n");
278 lf_putstr (file
, " mon_event(mon_event_icache_miss, processors[current_cpu], cia);\n");
279 if (options
.gen
.semantic_icache
)
281 lf_putstr (file
, "{\n");
282 lf_indent (file
, +2);
283 print_engine_issue_prefix_hook (file
);
284 print_idecode_body(file
, table
, "cia =");
285 print_engine_issue_postfix_hook (file
);
286 lf_indent (file
, -2);
287 lf_putstr (file
, "}\n");
291 print_engine_issue_prefix_hook (file
);
292 print_idecode_body(file
, table
, "semantic = ");
293 lf_putstr (file
, "cia = semantic(processor, cache_entry, cia);\n");
294 print_engine_issue_postfix_hook (file
);
297 lf_putstr (file
, "cpu_set_program_counter(processor, cia);\n");
298 lf_putstr (file
, "\n");
299 lf_indent (file
, -2);
301 lf_putstr (file
, "}\n");
304 lf_putstr (file
, "\n");
305 lf_putstr (file
, "current_cpu += 1;\n");
306 lf_putstr (file
, "if (current_cpu == nr_cpus)\n");
307 lf_putstr (file
, " {\n");
308 lf_putstr (file
, " if (sim_events_tick (sd))\n");
309 lf_putstr (file
, " {\n");
310 lf_putstr (file
, " sim_events_process (sd);\n");
311 lf_putstr (file
, " }\n");
312 lf_putstr (file
, " current_cpu = 0;\n");
313 lf_putstr (file
, " }\n");
316 lf_indent (file
, -4);
317 lf_putstr (file
, " }\n");
321 lf_indent (file
, -2);
322 lf_putstr (file
, "}\n");
326 /****************************************************************/
330 print_jump (lf
*file
,
333 if (!options
.gen
.smp
)
335 lf_putstr (file
, "if (event_queue_tick (sd))\n");
336 lf_putstr (file
, " {\n");
337 lf_putstr (file
, " CPU_CIA (processor) = nia;\n");
338 lf_putstr (file
, " sim_events_process (sd);\n");
339 lf_putstr (file
, " }\n");
340 lf_putstr (file
, "}\n");
346 lf_putstr (file
, "cpu_set_program_counter(processor, nia);\n");
347 lf_putstr (file
, "current_cpu += 1;\n");
348 lf_putstr (file
, "if (current_cpu >= nr_cpus)\n");
349 lf_putstr (file
, " {\n");
350 lf_putstr (file
, " if (sim_events_tick (sd))\n");
351 lf_putstr (file
, " {\n");
352 lf_putstr (file
, " sim_events_process (sd);\n");
353 lf_putstr (file
, " }\n");
354 lf_putstr (file
, " current_cpu = 0;\n");
355 lf_putstr (file
, " }\n");
356 lf_putstr (file
, "processor = processors[current_cpu];\n");
357 lf_putstr (file
, "nia = cpu_get_program_counter(processor);\n");
360 if (options
.gen
.icache
)
362 lf_putstr (file
, "cache_entry = cpu_icache_entry(processor, nia);\n");
363 lf_putstr (file
, "if (cache_entry->address == nia) {\n");
364 lf_putstr (file
, " /* cache hit */\n");
365 lf_putstr (file
, " goto *cache_entry->semantic;\n");
366 lf_putstr (file
, "}\n");
368 lf_putstr (file
, "goto cache_miss;\n");
372 if (!options
.gen
.icache
&& is_tail
)
374 lf_printf (file
, "goto engine;\n");
383 print_jump_insn (lf
*file
,
384 insn_entry
*instruction
,
385 opcode_bits
*expanded_bits
,
386 opcode_field
*opcodes
,
387 cache_entry
*cache_rules
)
389 insn_opcodes opcode_path
;
391 memset (&opcode_path
, 0, sizeof (opcode_path
));
392 opcode_path
.opcode
= opcodes
;
394 /* what we are for the moment */
395 lf_printf (file
, "\n");
396 print_my_defines (file
,
398 instruction
->format_name
,
401 /* output the icache entry */
402 if (options
.gen
.icache
)
404 lf_printf (file
, "\n");
405 lf_indent (file
, -1);
406 print_function_name (file
,
408 instruction
->format_name
,
411 function_name_prefix_icache
);
412 lf_printf (file
, ":\n");
413 lf_indent (file
, +1);
414 lf_printf (file
, "{\n");
415 lf_indent (file
, +2);
416 lf_putstr (file
, "const unsigned_word cia = nia;\n");
417 print_itrace (file
, instruction
, 1/*putting-value-in-cache*/);
418 print_idecode_validate (file
, instruction
, &opcode_path
);
419 lf_printf (file
, "\n");
420 lf_printf (file
, "{\n");
421 lf_indent (file
, +2);
422 print_icache_body (file
,
427 put_values_in_icache
);
428 lf_printf (file
, "cache_entry->address = nia;\n");
429 lf_printf (file
, "cache_entry->semantic = &&");
430 print_function_name (file
,
432 instruction
->format_name
,
435 function_name_prefix_semantics
);
436 lf_printf (file
, ";\n");
437 if (options
.gen
.semantic_icache
)
439 print_semantic_body (file
,
443 print_jump(file
, 1/*is-tail*/);
447 lf_printf (file
, "/* goto ");
448 print_function_name (file
,
450 instruction
->format_name
,
453 function_name_prefix_semantics
);
454 lf_printf (file
, "; */\n");
456 lf_indent (file
, -2);
457 lf_putstr (file
, "}\n");
458 lf_indent (file
, -2);
459 lf_printf (file
, "}\n");
462 /* print the semantics */
463 lf_printf (file
, "\n");
464 lf_indent (file
, -1);
465 print_function_name (file
,
467 instruction
->format_name
,
470 function_name_prefix_semantics
);
471 lf_printf (file
, ":\n");
472 lf_indent (file
, +1);
473 lf_printf (file
, "{\n");
474 lf_indent (file
, +2);
475 lf_putstr (file
, "const unsigned_word cia = nia;\n");
476 print_icache_body (file
,
480 (options
.gen
.direct_access
482 : declare_variables
),
484 ? get_values_from_icache
485 : do_not_use_icache
));
486 print_semantic_body (file
,
490 if (options
.gen
.direct_access
)
491 print_icache_body (file
,
497 ? get_values_from_icache
498 : do_not_use_icache
));
499 print_jump(file
, 1/*is tail*/);
500 lf_indent (file
, -2);
501 lf_printf (file
, "}\n");
508 print_jump_definition (lf
*file
,
513 cache_entry
*cache_rules
= (cache_entry
*)data
;
514 if (entry
->opcode_rule
->with_duplicates
)
516 ASSERT (entry
->nr_insns
== 1
517 && entry
->opcode
== NULL
518 && entry
->parent
!= NULL
519 && entry
->parent
->opcode
!= NULL
);
520 ASSERT (entry
->nr_insns
== 1
521 && entry
->opcode
== NULL
522 && entry
->parent
!= NULL
523 && entry
->parent
->opcode
!= NULL
524 && entry
->parent
->opcode_rule
!= NULL
);
525 print_jump_insn (file
,
527 entry
->expanded_bits
,
533 print_jump_insn (file
,
545 print_jump_internal_function (lf
*file
,
546 function_entry
*function
,
549 if (function
->is_internal
)
551 lf_printf (file
, "\n");
552 lf_print__line_ref (file
, function
->line
);
553 lf_indent (file
, -1);
554 print_function_name (file
,
560 ? function_name_prefix_icache
561 : function_name_prefix_semantics
));
562 lf_printf (file
, ":\n");
563 lf_indent (file
, +1);
564 lf_printf (file
, "{\n");
565 lf_indent (file
, +2);
566 lf_printf (file
, "const unsigned_word cia = nia;\n");
567 table_print_code (file
, function
->code
);
568 lf_print__internal_ref (file
);
569 lf_printf (file
, "error(\"Internal function must longjump\\n\");\n");
570 lf_indent (file
, -2);
571 lf_printf (file
, "}\n");
579 print_jump_body (lf
*file
,
582 cache_entry
*cache_rules
)
584 lf_printf (file
, "{\n");
585 lf_indent (file
, +2);
586 lf_putstr (file
, "jmp_buf halt;\n");
587 lf_putstr (file
, "jmp_buf restart;\n");
588 lf_putstr (file
, "cpu *processor = NULL;\n");
589 lf_putstr (file
, "unsigned_word nia = -1;\n");
590 lf_putstr (file
, "instruction_word instruction = 0;\n");
591 if (options
.gen
.icache
)
593 lf_putstr (file
, "engine_cache *cache_entry = NULL;\n");
597 lf_putstr (file
, "int current_cpu = -1;\n");
600 /* all the switches and tables - they know about jumping */
601 print_idecode_lookups (file
, entry
, cache_rules
);
603 /* start the simulation up */
604 if (options
.gen
.icache
)
606 lf_putstr (file
, "\n");
607 lf_putstr (file
, "{\n");
608 lf_putstr (file
, " int cpu_nr;\n");
609 lf_putstr (file
, " for (cpu_nr = 0; cpu_nr < nr_cpus; cpu_nr++)\n");
610 lf_putstr (file
, " cpu_flush_icache(processors[cpu_nr]);\n");
611 lf_putstr (file
, "}\n");
614 lf_putstr (file
, "\n");
615 lf_putstr (file
, "psim_set_halt_and_restart(system, &halt, &restart);\n");
617 lf_putstr (file
, "\n");
618 lf_putstr (file
, "if (setjmp(halt))\n");
619 lf_putstr (file
, " return;\n");
621 lf_putstr (file
, "\n");
622 lf_putstr (file
, "setjmp(restart);\n");
624 lf_putstr (file
, "\n");
625 if (!options
.gen
.smp
)
627 lf_putstr (file
, "processor = processors[0];\n");
628 lf_putstr (file
, "nia = cpu_get_program_counter(processor);\n");
632 lf_putstr (file
, "current_cpu = psim_last_cpu(system);\n");
635 if (!options
.gen
.icache
)
637 lf_printf (file
, "\n");
638 lf_indent (file
, -1);
639 lf_printf (file
, "engine:\n");
640 lf_indent (file
, +1);
643 print_jump(file
, 0/*is_tail*/);
645 if (options
.gen
.icache
)
647 lf_indent (file
, -1);
648 lf_printf (file
, "cache_miss:\n");
649 lf_indent (file
, +1);
652 print_engine_issue_prefix_hook (file
);
653 lf_putstr (file
, "instruction\n");
654 lf_putstr (file
, " = vm_instruction_map_read(cpu_instruction_map(processor),\n");
655 lf_putstr (file
, " processor, nia);\n");
656 print_engine_issue_prefix_hook (file
);
657 print_idecode_body (file
, entry
, "/*IGORE*/");
658 print_engine_issue_postfix_hook (file
);
660 /* print out a table of all the internals functions */
661 function_entry_traverse (file
, isa
->functions
,
662 print_jump_internal_function
,
665 /* print out a table of all the instructions */
666 ERROR ("Use the list of semantic functions, not travere_tree");
667 gen_entry_traverse_tree (file
, entry
,
670 print_jump_definition
, /* leaf */
673 lf_indent (file
, -2);
674 lf_printf (file
, "}\n");
679 /****************************************************************/
683 print_engine_run_function_header (lf
*file
,
685 function_decl_type decl_type
)
688 lf_printf (file
, "\n");
691 case is_function_declaration
:
692 lf_print__function_type (file
, "void", "INLINE_ENGINE", "\n");
694 case is_function_definition
:
695 lf_print__function_type (file
, "void", "INLINE_ENGINE", " ");
697 case is_function_variable
:
698 lf_printf (file
, "void (*");
701 indent
= print_function_name (file
,
703 NULL
, /* format name */
705 NULL
, /* expanded bits */
706 function_name_prefix_engine
);
709 case is_function_definition
:
710 lf_putstr (file
, "\n(");
713 case is_function_declaration
:
714 indent
+= lf_printf (file
, " (");
716 case is_function_variable
:
717 lf_putstr (file
, ")\n(");
721 lf_indent (file
, +indent
);
722 lf_printf (file
, "SIM_DESC sd,\n");
723 lf_printf (file
, "int next_cpu_nr,\n");
724 lf_printf (file
, "int nr_cpus,\n");
725 lf_printf (file
, "int siggnal)");
726 lf_indent (file
, -indent
);
729 case is_function_definition
:
730 lf_putstr (file
, "\n");
732 case is_function_variable
:
733 case is_function_declaration
:
734 lf_putstr (file
, ";\n");
741 gen_engine_h (lf
*file
,
744 cache_entry
*cache_rules
)
747 for (entry
= gen
->tables
; entry
!= NULL
; entry
= entry
->next
)
749 print_engine_run_function_header (file
,
750 (options
.gen
.multi_sim
753 is_function_declaration
);
759 gen_engine_c(lf
*file
,
762 cache_entry
*cache_rules
)
766 print_includes (file
);
767 print_include_inline (file
, options
.module
.semantics
);
768 print_include (file
, options
.module
.engine
);
769 lf_printf (file
, "\n");
770 lf_printf (file
, "#include \"sim-assert.h\"\n");
771 lf_printf (file
, "\n");
772 print_idecode_globals (file
);
773 lf_printf (file
, "\n");
775 for (entry
= gen
->tables
; entry
!= NULL
; entry
= entry
->next
)
777 switch (options
.gen
.code
)
780 print_idecode_lookups (file
, entry
->table
, cache_rules
);
782 /* output the main engine routine */
783 print_engine_run_function_header (file
,
784 (options
.gen
.multi_sim
787 is_function_definition
);
788 print_run_body (file
, entry
->table
);
792 ERROR ("Jumps currently unimplemented");
794 print_engine_run_function_header (file
,
796 is_function_definition
);
797 print_jump_body (file
, entry
->table
,