📄 gen-idecode.c
字号:
static voidprint_jump_definition(insn_table *entry, lf *file, void *data, insn *instruction, int depth){ cache_table *cache_rules = (cache_table*)data; if (generate_expanded_instructions) { ASSERT(entry->nr_insn == 1 && entry->opcode == NULL && entry->parent != NULL && entry->parent->opcode != NULL); ASSERT(entry->nr_insn == 1 && entry->opcode == NULL && entry->parent != NULL && entry->parent->opcode != NULL && entry->parent->opcode_rule != NULL); print_jump_insn(file, entry->insns, entry->expanded_bits, entry->opcode, cache_rules); } else { print_jump_insn(file, instruction, NULL, NULL, cache_rules); }}static voidprint_jump_internal_function(insn_table *table, lf *file, void *data, table_entry *function){ if (it_is("internal", function->fields[insn_flags])) { lf_printf(file, "\n"); table_entry_print_cpp_line_nr(file, function); lf_indent(file, -1); print_function_name(file, function->fields[insn_name], NULL, ((code & generate_with_icache) ? function_name_prefix_icache : function_name_prefix_semantics)); lf_printf(file, ":\n"); lf_indent(file, +1); lf_printf(file, "{\n"); lf_indent(file, +2); lf_printf(file, "const unsigned_word cia = nia;\n"); lf_print__c_code(file, function->annex); lf_print__internal_reference(file); lf_printf(file, "error(\"Internal function must longjump\\n\");\n"); lf_indent(file, -2); lf_printf(file, "}\n"); }}static voidprint_jump_until_stop_body(lf *file, insn_table *table, cache_table *cache_rules, int can_stop){ lf_printf(file, "{\n"); lf_indent(file, +2); if (!can_stop) lf_printf(file, "int *keep_running = NULL;\n"); lf_putstr(file, "jmp_buf halt;\n"); lf_putstr(file, "jmp_buf restart;\n"); lf_putstr(file, "cpu *processor = NULL;\n"); lf_putstr(file, "unsigned_word nia = -1;\n"); lf_putstr(file, "instruction_word instruction = 0;\n"); if ((code & generate_with_icache)) { lf_putstr(file, "idecode_cache *cache_entry = NULL;\n"); } if (generate_smp) { lf_putstr(file, "int current_cpu = -1;\n"); } /* all the switches and tables - they know about jumping */ print_idecode_lookups(file, table, cache_rules); /* start the simulation up */ if ((code & generate_with_icache)) { lf_putstr(file, "\n"); lf_putstr(file, "{\n"); lf_putstr(file, " int cpu_nr;\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, "\n"); lf_putstr(file, "psim_set_halt_and_restart(system, &halt, &restart);\n"); lf_putstr(file, "\n"); lf_putstr(file, "if (setjmp(halt))\n"); lf_putstr(file, " return;\n"); lf_putstr(file, "\n"); lf_putstr(file, "setjmp(restart);\n"); lf_putstr(file, "\n"); if (!generate_smp) { lf_putstr(file, "processor = processors[0];\n"); lf_putstr(file, "nia = cpu_get_program_counter(processor);\n"); } else { lf_putstr(file, "current_cpu = psim_last_cpu(system);\n"); } if (!(code & generate_with_icache)) { lf_printf(file, "\n"); lf_indent(file, -1); lf_printf(file, "idecode:\n"); lf_indent(file, +1); } print_jump(file, 0/*is_tail*/); if ((code & generate_with_icache)) { lf_indent(file, -1); lf_printf(file, "cache_miss:\n"); lf_indent(file, +1); } lf_putstr(file, "instruction\n"); lf_putstr(file, " = vm_instruction_map_read(cpu_instruction_map(processor),\n"); lf_putstr(file, " processor, nia);\n"); print_idecode_body(file, table, "/*IGORE*/"); /* print out a table of all the internals functions */ insn_table_traverse_function(table, file, NULL, print_jump_internal_function); /* print out a table of all the instructions */ if (generate_expanded_instructions) insn_table_traverse_tree(table, file, cache_rules, 1, NULL, /* start */ print_jump_definition, /* leaf */ NULL, /* end */ NULL); /* padding */ else insn_table_traverse_insn(table, file, cache_rules, print_jump_definition); lf_indent(file, -2); lf_printf(file, "}\n");}/****************************************************************/static voidprint_idecode_floating_point_unavailable(lf *file){ if ((code & generate_jumps)) lf_printf(file, "goto %s_floating_point_unavailable;\n", (code & generate_with_icache) ? "icache" : "semantic"); else if ((code & generate_with_icache)) lf_printf(file, "return icache_floating_point_unavailable(%s);\n", ICACHE_FUNCTION_ACTUAL); else lf_printf(file, "return semantic_floating_point_unavailable(%s);\n", SEMANTIC_FUNCTION_ACTUAL);}/* Output code to do any final checks on the decoded instruction. This includes things like verifying any on decoded fields have the correct value and checking that (for floating point) floating point hardware isn't disabled */voidprint_idecode_validate(lf *file, insn *instruction, opcode_field *opcodes){ /* Validate: unchecked instruction fields If any constant fields in the instruction were not checked by the idecode tables, output code to check that they have the correct value here */ { unsigned check_mask = 0; unsigned check_val = 0; insn_field *field; opcode_field *opcode; /* form check_mask/check_val containing what needs to be checked in the instruction */ for (field = instruction->fields->first; field->first < insn_bit_size; field = field->next) { check_mask <<= field->width; check_val <<= field->width; /* is it a constant that could need validating? */ if (!field->is_int && !field->is_slash) continue; /* has it been checked by a table? */ for (opcode = opcodes; opcode != NULL; opcode = opcode->parent) { if (field->first >= opcode->first && field->last <= opcode->last) break; } if (opcode != NULL) continue; check_mask |= (1 << field->width)-1; check_val |= field->val_int; } /* if any bits not checked by opcode tables, output code to check them */ if (check_mask) { lf_printf(file, "\n"); lf_printf(file, "/* validate: %s */\n", instruction->file_entry->fields[insn_format]); lf_printf(file, "if (WITH_RESERVED_BITS && (instruction & 0x%x) != 0x%x)\n", check_mask, check_val); lf_indent(file, +2); print_idecode_illegal(file, "return"); lf_indent(file, -2); } } /* Validate floating point hardware If the simulator is being built with out floating point hardware (different to it being disabled in the MSR) then floating point instructions are invalid */ { if (it_is("f", instruction->file_entry->fields[insn_flags])) { lf_printf(file, "\n"); lf_printf(file, "/* Validate: FP hardware exists */\n"); lf_printf(file, "if (CURRENT_FLOATING_POINT != HARD_FLOATING_POINT)\n"); lf_indent(file, +2); print_idecode_illegal(file, "return"); lf_indent(file, -2); } } /* Validate: Floating Point available If floating point is not available, we enter a floating point unavailable interrupt into the cache instead of the instruction proper. The PowerPC spec requires a CSI after MSR[FP] is changed and when ever a CSI occures we flush the instruction cache. */ { if (it_is("f", instruction->file_entry->fields[insn_flags])) { lf_printf(file, "\n"); lf_printf(file, "/* Validate: FP available according to MSR[FP] */\n"); lf_printf(file, "if (!IS_FP_AVAILABLE(processor))\n"); lf_indent(file, +2); print_idecode_floating_point_unavailable(file); lf_indent(file, -2); } }}/****************************************************************/static voidprint_idecode_run_function_header(lf *file, int can_stop, int is_definition){ int indent; lf_printf(file, "\n"); lf_print_function_type(file, "void", "PSIM_INLINE_IDECODE", (is_definition ? " " : "\n")); indent = lf_putstr(file, (can_stop ? "idecode_run_until_stop" : "idecode_run")); if (is_definition) lf_putstr(file, "\n"); else lf_indent(file, +indent); lf_putstr(file, "(psim *system,\n"); if (can_stop) lf_putstr(file, " volatile int *keep_running,\n"); lf_printf(file, " event_queue *events,\n"); lf_putstr(file, " cpu *const processors[],\n"); lf_putstr(file, " const int nr_cpus)"); if (is_definition) lf_putstr(file, ";"); else lf_indent(file, -indent); lf_putstr(file, "\n");}voidgen_idecode_h(lf *file, insn_table *table, cache_table *cache_rules){ lf_printf(file, "/* The idecode_*.h functions shall move to support */\n"); lf_printf(file, "#include \"idecode_expression.h\"\n"); lf_printf(file, "#include \"idecode_fields.h\"\n"); lf_printf(file, "#include \"idecode_branch.h\"\n"); lf_printf(file, "\n"); print_icache_struct(table, cache_rules, file); lf_printf(file, "\n"); lf_printf(file, "#define WITH_IDECODE_SMP %d\n", generate_smp); lf_printf(file, "\n"); print_idecode_run_function_header(file, 0/*can stop*/, 1/*is definition*/); print_idecode_run_function_header(file, 1/*can stop*/, 1/*is definition*/);}voidgen_idecode_c(lf *file, insn_table *table, cache_table *cache_rules){ /* the intro */ lf_printf(file, "#include \"inline.c\"\n"); lf_printf(file, "\n"); lf_printf(file, "#include \"cpu.h\"\n"); lf_printf(file, "#include \"idecode.h\"\n"); lf_printf(file, "#include \"semantics.h\"\n"); lf_printf(file, "#include \"icache.h\"\n"); lf_printf(file, "#ifdef HAVE_COMMON_FPU\n"); lf_printf(file, "#include \"sim-inline.h\"\n"); lf_printf(file, "#include \"sim-fpu.h\"\n"); lf_printf(file, "#endif\n"); lf_printf(file, "#include \"support.h\"\n"); lf_printf(file, "\n"); lf_printf(file, "#include <setjmp.h>\n"); lf_printf(file, "\n"); lf_printf(file, "enum {\n"); lf_printf(file, " /* greater or equal to zero => table */\n"); lf_printf(file, " function_entry = -1,\n"); lf_printf(file, " boolean_entry = -2,\n"); lf_printf(file, "};\n"); lf_printf(file, "\n"); lf_printf(file, "typedef struct _idecode_table_entry {\n"); lf_printf(file, " int shift;\n"); lf_printf(file, " instruction_word mask;\n"); lf_printf(file, " instruction_word value;"); lf_printf(file, " void *function_or_table;\n"); lf_printf(file, "} idecode_table_entry;\n"); lf_printf(file, "\n"); lf_printf(file, "\n"); if ((code & generate_calls)) { print_idecode_lookups(file, table, cache_rules); /* output the main idecode routine */ print_idecode_run_function_header(file, 0/*can stop*/, 0/*is definition*/); print_run_until_stop_body(file, table, 0/* have stop argument */); print_idecode_run_function_header(file, 1/*can stop*/, 0/*is definition*/); print_run_until_stop_body(file, table, 1/* no stop argument */); } else if ((code & generate_jumps)) { print_idecode_run_function_header(file, 0/*can stop*/, 0/*is definition*/); print_jump_until_stop_body(file, table, cache_rules, 0 /* have stop argument */); print_idecode_run_function_header(file, 1/*can stop*/, 0/*is definition*/); print_jump_until_stop_body(file, table, cache_rules, 1/* have stop argument */); } else { error("Something is wrong!\n"); }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -