📄 gen-engine.c
字号:
/* The IGEN simulator generator for GDB, the GNU Debugger. Copyright 2002 Free Software Foundation, Inc. Contributed by Andrew Cagney. This file is part of GDB. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */#include "misc.h"#include "lf.h"#include "table.h"#include "filter.h"#include "igen.h"#include "ld-insn.h"#include "ld-decode.h"#include "gen.h"#include "gen-idecode.h"#include "gen-engine.h"#include "gen-icache.h"#include "gen-semantics.h"static voidprint_engine_issue_prefix_hook (lf *file){ lf_printf (file, "\n"); lf_indent_suppress (file); lf_printf (file, "#if defined (ENGINE_ISSUE_PREFIX_HOOK)\n"); lf_printf (file, "ENGINE_ISSUE_PREFIX_HOOK();\n"); lf_indent_suppress (file); lf_printf (file, "#endif\n"); lf_printf (file, "\n");}static voidprint_engine_issue_postfix_hook (lf *file){ lf_printf (file, "\n"); lf_indent_suppress (file); lf_printf (file, "#if defined (ENGINE_ISSUE_POSTFIX_HOOK)\n"); lf_printf (file, "ENGINE_ISSUE_POSTFIX_HOOK();\n"); lf_indent_suppress (file); lf_printf (file, "#endif\n"); lf_printf (file, "\n");}static voidprint_run_body (lf *file, gen_entry *table){ /* Output the function to execute real code: Unfortunatly, there are multiple cases to consider vis: <icache> X <smp> Consequently this function is written in multiple different ways */ lf_printf (file, "{\n"); lf_indent (file, +2); if (!options.gen.smp) { lf_printf (file, "%sinstruction_address cia;\n", options.module.global.prefix.l); } lf_printf (file, "int current_cpu = next_cpu_nr;\n"); if (options.gen.icache) { lf_printf (file, "/* flush the icache of a possible break insn */\n"); lf_printf (file, "{\n"); lf_printf (file, " int cpu_nr;\n"); lf_printf (file, " for (cpu_nr = 0; cpu_nr < nr_cpus; cpu_nr++)\n"); lf_printf (file, " cpu_flush_icache (STATE_CPU (sd, cpu_nr));\n"); lf_printf (file, "}\n"); } if (!options.gen.smp) { lf_putstr (file, "\/* CASE 1: NO SMP (with or with out instruction cache).\n\\n\In this case, we can take advantage of the fact that the current\n\instruction address (CIA) does not need to be read from / written to\n\the CPU object after the execution of an instruction.\n\\n\Instead, CIA is only saved when the main loop exits. This occures\n\when either sim_engine_halt or sim_engine_restart is called. Both of\n\these functions save the current instruction address before halting /\n\restarting the simulator.\n\\n\As a variation, there may also be support for an instruction cracking\n\cache. */\n\\n\"); lf_putstr (file, "\n"); lf_putstr (file, "/* prime the main loop */\n"); lf_putstr (file, "SIM_ASSERT (current_cpu == 0);\n"); lf_putstr (file, "SIM_ASSERT (nr_cpus == 1);\n"); lf_putstr (file, "cia = CIA_GET (CPU);\n"); lf_putstr (file, "\n"); lf_putstr (file, "while (1)\n"); lf_putstr (file, " {\n"); lf_indent (file, +4); lf_printf (file, "%sinstruction_address nia;\n", options.module.global.prefix.l); lf_printf (file, "\n"); if (!options.gen.icache) { lf_printf (file, "%sinstruction_word instruction_0 = IMEM%d (cia);\n", options.module.global.prefix.l, options.insn_bit_size); print_engine_issue_prefix_hook (file); print_idecode_body (file, table, "nia = "); print_engine_issue_postfix_hook (file); } else { lf_putstr (file, "idecode_cache *cache_entry =\n"); lf_putstr (file, " cpu_icache_entry (cpu, cia);\n"); lf_putstr (file, "if (cache_entry->address == cia)\n"); lf_putstr (file, " {\n"); lf_indent (file, -4); lf_putstr (file, "/* cache hit */\n"); lf_putstr (file, "idecode_semantic *const semantic = cache_entry->semantic;\n"); lf_putstr (file, "cia = semantic (cpu, cache_entry, cia);\n"); /* tail */ lf_indent (file, -4); lf_putstr (file, " }\n"); lf_putstr (file, "else\n"); lf_putstr (file, " {\n"); lf_indent (file, +4); lf_putstr (file, "/* cache miss */\n"); if (!options.gen.semantic_icache) { lf_putstr (file, "idecode_semantic *semantic;\n"); } lf_printf (file, "instruction_word instruction = IMEM%d (cia);\n", options.insn_bit_size); lf_putstr (file, "if (WITH_MON != 0)\n"); lf_putstr (file, " mon_event (mon_event_icache_miss, cpu, cia);\n"); if (options.gen.semantic_icache) { lf_putstr (file, "{\n"); lf_indent (file, +2); print_engine_issue_prefix_hook (file); print_idecode_body (file, table, "nia ="); print_engine_issue_postfix_hook (file); lf_indent (file, -2); lf_putstr (file, "}\n"); } else { print_engine_issue_prefix_hook (file); print_idecode_body (file, table, "semantic ="); lf_putstr (file, "nia = semantic (cpu, cache_entry, cia);\n"); print_engine_issue_postfix_hook (file); } lf_indent (file, -4); lf_putstr (file, " }\n"); } /* update the cpu if necessary */ switch (options.gen.nia) { case nia_is_cia_plus_one: lf_printf (file, "\n"); lf_printf (file, "/* Update the instruction address */\n"); lf_printf (file, "cia = nia;\n"); break; case nia_is_void: case nia_is_invalid: ERROR ("engine gen when NIA complex"); } /* events */ lf_putstr (file, "\n"); lf_putstr (file, "/* process any events */\n"); lf_putstr (file, "if (sim_events_tick (sd))\n"); lf_putstr (file, " {\n"); lf_putstr (file, " CIA_SET (CPU, cia);\n"); lf_putstr (file, " sim_events_process (sd);\n"); lf_putstr (file, " cia = CIA_GET (CPU);\n"); lf_putstr (file, " }\n"); lf_indent (file, -4); lf_printf (file, " }\n"); } if (options.gen.smp) { lf_putstr (file, "\/* CASE 2: SMP (With or without ICACHE)\n\\n\The complexity here comes from needing to correctly halt the simulator\n\when it is aborted. For instance, if cpu0 requests a restart then\n\cpu1 will normally be the next cpu that is run. Cpu0 being restarted\n\after all the other CPU's and the event queue have been processed */\n\\n\"); lf_putstr (file, "\n"); lf_printf (file, "/* have ensured that the event queue is NOT next */\n"); lf_printf (file, "SIM_ASSERT (current_cpu >= 0);\n"); lf_printf (file, "SIM_ASSERT (current_cpu <= nr_cpus - 1);\n"); lf_printf (file, "SIM_ASSERT (nr_cpus <= MAX_NR_PROCESSORS);\n"); lf_putstr (file, "\n"); lf_putstr (file, "while (1)\n"); lf_putstr (file, " {\n"); lf_indent (file, +4); lf_putstr (file, "sim_cpu *cpu = STATE_CPU (sd, current_cpu);\n"); lf_putstr (file, "instruction_address cia = CIA_GET (cpu);\n"); lf_putstr (file, "\n"); if (!options.gen.icache) { lf_printf (file, "instruction_word instruction_0 = IMEM%d (cia);\n", options.insn_bit_size); print_engine_issue_prefix_hook (file); print_idecode_body (file, table, "cia ="); lf_putstr (file, "CIA_SET (cpu, cia);\n"); print_engine_issue_postfix_hook (file); } if (options.gen.icache) { lf_putstr (file, "engine_cache *cache_entry =\n"); lf_putstr (file, " cpu_icache_entry(processor, cia);\n"); lf_putstr (file, "\n"); lf_putstr (file, "if (cache_entry->address == cia) {\n"); { lf_indent (file, +2); lf_putstr (file, "\n"); lf_putstr (file, "/* cache hit */\n"); lf_putstr (file, "engine_semantic *semantic = cache_entry->semantic;\n"); lf_putstr (file, "cia = semantic(processor, cache_entry, cia);\n"); /* tail */ lf_putstr (file, "cpu_set_program_counter(processor, cia);\n"); lf_putstr (file, "\n"); lf_indent (file, -2); } lf_putstr (file, "}\n"); lf_putstr (file, "else {\n"); { lf_indent (file, +2); lf_putstr (file, "\n"); lf_putstr (file, "/* cache miss */\n"); if (!options.gen.semantic_icache) { lf_putstr (file, "engine_semantic *semantic;\n"); } lf_printf (file, "instruction_word instruction = IMEM%d (cia);\n", options.insn_bit_size); lf_putstr (file, "if (WITH_MON != 0)\n"); lf_putstr (file, " mon_event(mon_event_icache_miss, processors[current_cpu], cia);\n"); if (options.gen.semantic_icache) { lf_putstr (file, "{\n"); lf_indent (file, +2); print_engine_issue_prefix_hook (file); print_idecode_body (file, table, "cia ="); print_engine_issue_postfix_hook (file); lf_indent (file, -2); lf_putstr (file, "}\n"); } else { print_engine_issue_prefix_hook (file); print_idecode_body (file, table, "semantic = "); lf_putstr (file, "cia = semantic(processor, cache_entry, cia);\n"); print_engine_issue_postfix_hook (file); } /* tail */ lf_putstr (file, "cpu_set_program_counter(processor, cia);\n"); lf_putstr (file, "\n"); lf_indent (file, -2); } lf_putstr (file, "}\n"); } lf_putstr (file, "\n"); lf_putstr (file, "current_cpu += 1;\n"); lf_putstr (file, "if (current_cpu == nr_cpus)\n"); lf_putstr (file, " {\n"); lf_putstr (file, " if (sim_events_tick (sd))\n"); lf_putstr (file, " {\n"); lf_putstr (file, " sim_events_process (sd);\n"); lf_putstr (file, " }\n"); lf_putstr (file, " current_cpu = 0;\n"); lf_putstr (file, " }\n"); /* tail */ lf_indent (file, -4); lf_putstr (file, " }\n"); } lf_indent (file, -2); lf_putstr (file, "}\n");}/****************************************************************/#if 0static voidprint_jump (lf *file, int is_tail){ if (!options.gen.smp) { lf_putstr (file, "if (event_queue_tick (sd))\n"); lf_putstr (file, " {\n"); lf_putstr (file, " CPU_CIA (processor) = nia;\n"); lf_putstr (file, " sim_events_process (sd);\n"); lf_putstr (file, " }\n"); lf_putstr (file, "}\n"); } if (options.gen.smp) { if (is_tail) lf_putstr (file, "cpu_set_program_counter(processor, nia);\n"); lf_putstr (file, "current_cpu += 1;\n"); lf_putstr (file, "if (current_cpu >= nr_cpus)\n"); lf_putstr (file, " {\n"); lf_putstr (file, " if (sim_events_tick (sd))\n"); lf_putstr (file, " {\n"); lf_putstr (file, " sim_events_process (sd);\n"); lf_putstr (file, " }\n"); lf_putstr (file, " current_cpu = 0;\n"); lf_putstr (file, " }\n"); lf_putstr (file, "processor = processors[current_cpu];\n"); lf_putstr (file, "nia = cpu_get_program_counter(processor);\n"); } if (options.gen.icache) { lf_putstr (file, "cache_entry = cpu_icache_entry(processor, nia);\n"); lf_putstr (file, "if (cache_entry->address == nia) {\n"); lf_putstr (file, " /* cache hit */\n"); lf_putstr (file, " goto *cache_entry->semantic;\n"); lf_putstr (file, "}\n"); if (is_tail) { lf_putstr (file, "goto cache_miss;\n"); } } if (!options.gen.icache && is_tail) { lf_printf (file, "goto engine;\n"); }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -