📄 gen-idecode.c
字号:
/* normal goto */ lf_printf(file, "case %d:\n", entry->opcode_nr); } else if (entry->parent->opcode_rule->gen == goto_switch_gen) { /* lf_indent(file, -1); */ print_goto_switch_name(file, entry); lf_printf(file, ":\n"); /* lf_indent(file, +1); */ } else { ASSERT("bad switch" == NULL); } lf_indent(file, +2); { if (entry->opcode == NULL) { /* switch calling leaf */ if ((code & generate_jumps)) lf_printf(file, "goto "); if ((code & generate_calls)) lf_printf(file, "%s ", result); print_function_name(file, entry->insns->file_entry->fields[insn_name], entry->expanded_bits, ((code & generate_with_icache) ? function_name_prefix_icache : function_name_prefix_semantics)); if ((code & generate_calls)) lf_printf(file, "(%s)", SEMANTIC_FUNCTION_ACTUAL); lf_printf(file, ";\n"); } else if (entry->opcode_rule->gen == switch_gen || entry->opcode_rule->gen == goto_switch_gen || entry->opcode_rule->gen == padded_switch_gen) { /* switch calling switch */ print_idecode_switch(file, entry, result); } else { /* switch looking up a table */ lf_printf(file, "{\n"); lf_indent(file, -2); print_idecode_table(file, entry, result); lf_indent(file, -2); lf_printf(file, "}\n"); } if (entry->parent->opcode->is_boolean || entry->parent->opcode_rule->gen == switch_gen || entry->parent->opcode_rule->gen == padded_switch_gen) { lf_printf(file, "break;\n"); } else if (entry->parent->opcode_rule->gen == goto_switch_gen) { print_goto_switch_break(file, entry); } else { ASSERT("bad switch" == NULL); } } lf_indent(file, -2);}static voidprint_idecode_switch_illegal(lf *file, const char *result){ lf_indent(file, +2); print_idecode_illegal(file, result); lf_printf(file, "break;\n"); lf_indent(file, -2);}static voididecode_switch_end(insn_table *table, lf *file, void *data, int depth){ const char *result = data; ASSERT(depth == 0); ASSERT(table->opcode_rule->gen == switch_gen || table->opcode_rule->gen == goto_switch_gen || table->opcode_rule->gen == padded_switch_gen); ASSERT(table->opcode); if (table->opcode->is_boolean) { lf_printf(file, "}\n"); } else if (table->opcode_rule->gen == switch_gen || table->opcode_rule->gen == padded_switch_gen) { lf_printf(file, "default:\n"); switch (table->opcode_rule->gen) { case switch_gen: print_idecode_switch_illegal(file, result); break; case padded_switch_gen: lf_printf(file, " error(\"Internal error - bad switch generated\\n\");\n"); lf_printf(file, " break;\n"); break; default: ASSERT("bad switch" == NULL); } lf_printf(file, "}\n"); } else if (table->opcode_rule->gen == goto_switch_gen) { lf_printf(file, "illegal_"); lf_print_table_name(file, table); lf_printf(file, ":\n"); print_idecode_illegal(file, result); lf_printf(file, "break_"); lf_print_table_name(file, table); lf_printf(file, ":;\n"); if (table->parent != NULL && (table->parent->opcode_rule->gen == switch_gen || table->parent->opcode_rule->gen == goto_switch_gen || table->parent->opcode_rule->gen == padded_switch_gen)) { lf_indent(file, -2); lf_printf(file, "}\n"); } } else { ASSERT("bad switch" == NULL); }}static voididecode_switch_padding(insn_table *table, lf *file, void *data, int depth, int opcode_nr){ const char *result = data; ASSERT(depth == 0); ASSERT(table->opcode_rule->gen == switch_gen || table->opcode_rule->gen == goto_switch_gen || table->opcode_rule->gen == padded_switch_gen); switch (table->opcode_rule->gen) { case switch_gen: break; case padded_switch_gen: lf_printf(file, "case %d:\n", opcode_nr); print_idecode_switch_illegal(file, result); break; case goto_switch_gen: /* no padding needed */ break; default: ASSERT("bad switch" != NULL); }}voidprint_idecode_switch(lf *file, insn_table *table, const char *result){ insn_table_traverse_tree(table, file, (void*)result, 0, idecode_switch_start, idecode_switch_leaf, idecode_switch_end, idecode_switch_padding);}static voidprint_idecode_switch_function_header(lf *file, insn_table *table, int is_function_definition){ lf_printf(file, "\n"); if ((code & generate_calls)) { lf_printf(file, "static "); if ((code & generate_with_icache)) lf_printf(file, "idecode_semantic *"); else lf_printf(file, "unsigned_word"); if (is_function_definition) lf_printf(file, "\n"); else lf_printf(file, " "); lf_print_table_name(file, table); lf_printf(file, "\n(%s)", ICACHE_FUNCTION_FORMAL); if (!is_function_definition) lf_printf(file, ";"); lf_printf(file, "\n"); } if ((code & generate_jumps) && is_function_definition) { lf_indent(file, -1); lf_print_table_name(file, table); lf_printf(file, ":\n"); lf_indent(file, +1); }}static voididecode_declare_if_switch(insn_table *table, lf *file, void *data, int depth){ if ((table->opcode_rule->gen == switch_gen || table->opcode_rule->gen == goto_switch_gen || table->opcode_rule->gen == padded_switch_gen) && table->parent != NULL /* don't declare the top one yet */ && table->parent->opcode_rule->gen == array_gen) { print_idecode_switch_function_header(file, table, 0/*isnt function definition*/); }}static voididecode_expand_if_switch(insn_table *table, lf *file, void *data, int depth){ if ((table->opcode_rule->gen == switch_gen || table->opcode_rule->gen == goto_switch_gen || table->opcode_rule->gen == padded_switch_gen) && table->parent != NULL /* don't expand the top one yet */ && table->parent->opcode_rule->gen == array_gen) { print_idecode_switch_function_header(file, table, 1/*is function definition*/); if ((code & generate_calls)) { lf_printf(file, "{\n"); lf_indent(file, +2); } print_idecode_switch(file, table, "return"); if ((code & generate_calls)) { lf_indent(file, -2); lf_printf(file, "}\n"); } }}/****************************************************************/static voidprint_idecode_lookups(lf *file, insn_table *table, cache_table *cache_rules){ int depth; /* output switch function declarations where needed by tables */ insn_table_traverse_tree(table, file, NULL, 1, idecode_declare_if_switch, /* START */ NULL, NULL, NULL); /* output tables where needed */ for (depth = insn_table_depth(table); depth > 0; depth--) { insn_table_traverse_tree(table, file, NULL, 1-depth, print_idecode_table_start, print_idecode_table_leaf, print_idecode_table_end, print_idecode_table_padding); } /* output switch functions where needed */ insn_table_traverse_tree(table, file, NULL, 1, idecode_expand_if_switch, /* START */ NULL, NULL, NULL);}static voidprint_idecode_body(lf *file, insn_table *table, const char *result){ if (table->opcode_rule->gen == switch_gen || table->opcode_rule->gen == goto_switch_gen || table->opcode_rule->gen == padded_switch_gen) print_idecode_switch(file, table, result); else print_idecode_table(file, table, result);}/****************************************************************/static voidprint_run_until_stop_body(lf *file, insn_table *table, int can_stop){ /* Output the function to execute real code: Unfortunatly, there are multiple cases to consider vis: <icache> X <smp> X <events> X <keep-running-flag> X ... Consequently this function is written in multiple different ways */ lf_putstr(file, "{\n"); lf_indent(file, +2); lf_putstr(file, "jmp_buf halt;\n"); lf_putstr(file, "jmp_buf restart;\n"); if (!generate_smp) { lf_putstr(file, "cpu *processor = NULL;\n"); lf_putstr(file, "unsigned_word cia = -1;\n"); } lf_putstr(file, "int last_cpu;\n"); if (generate_smp) { lf_putstr(file, "int current_cpu;\n"); } if ((code & generate_with_icache)) { lf_putstr(file, "int cpu_nr;\n"); lf_putstr(file, "\n"); lf_putstr(file, "/* flush the icache of a possible break insn */\n"); lf_putstr(file, "for (cpu_nr = 0; cpu_nr < nr_cpus; cpu_nr++)\n"); lf_putstr(file, " cpu_flush_icache(processors[cpu_nr]);\n"); } lf_putstr(file, "\n"); lf_putstr(file, "/* set the halt target initially */\n"); lf_putstr(file, "psim_set_halt_and_restart(system, &halt, NULL);\n"); lf_putstr(file, "if (setjmp(halt))\n"); lf_putstr(file, " return;\n"); lf_putstr(file, "\n"); lf_putstr(file, "/* where were we before the halt? */\n"); lf_putstr(file, "last_cpu = psim_last_cpu(system);\n"); lf_putstr(file, "\n"); lf_putstr(file, "/* check for need to force event processing first */\n"); lf_putstr(file, "if (WITH_EVENTS) {\n"); lf_putstr(file, " if (last_cpu == nr_cpus) {\n"); lf_putstr(file, " /* halted during event processing */\n"); lf_putstr(file, " event_queue_process(events);\n"); lf_putstr(file, " last_cpu = -1;\n"); lf_putstr(file, " }\n"); lf_putstr(file, " else if (last_cpu == nr_cpus - 1) {\n"); lf_putstr(file, " /* last cpu did halt */\n"); lf_putstr(file, " if (event_queue_tick(events)) {\n"); lf_putstr(file, " event_queue_process(events);\n"); lf_putstr(file, " }\n"); lf_putstr(file, " last_cpu = -1;\n"); lf_putstr(file, " }\n"); lf_putstr(file, "}\n"); lf_putstr(file, "else {\n"); lf_putstr(file, " if (last_cpu == nr_cpus - 1)\n"); lf_putstr(file, " /* cpu zero is next */\n"); lf_putstr(file, " last_cpu = -1;\n"); lf_putstr(file, "}\n"); lf_putstr(file, "\n"); lf_putstr(file, "/* have ensured that the event queue can not be first */\n"); lf_putstr(file, "ASSERT(last_cpu >= -1 && last_cpu < nr_cpus - 1);\n"); if (!generate_smp) { lf_putstr(file, "\n\/* 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 does not need to be returned to the cpu object\n\ after every execution of an instruction. Instead it only needs to\n\ be saved when either A. the main loop exits or B. A cpu-halt or\n\ cpu-restart call forces the loop to be re-enered. The later\n\ functions always save the current cpu instruction address.\n\\n\ Two subcases also exist that with and that without an instruction\n\ cache.\n\\n\ An additional complexity is the need to ensure that a 1:1 ratio\n\ is maintained between the execution of an instruction and the\n\ incrementing of the simulation clock */");
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -