📄 gen-idecode.c
字号:
gen_entry *entry, insn_entry * insn, int depth, void *data){ cache_entry *cache_rules = (cache_entry *) data; if (options.generate_expanded_instructions) { ASSERT (entry->nr_insns == 1 && entry->opcode == NULL && entry->parent != NULL && entry->parent->opcode != NULL); ASSERT (entry->nr_insns == 1 && entry->opcode == NULL && entry->parent != NULL && entry->parent->opcode != NULL && entry->parent->opcode_rule != NULL); print_jump_insn (file, entry->insns->words[0]->insn, entry->expanded_bits, entry->opcode, cache_rules); } else { print_jump_insn (file, instruction->words[0]->insn, NULL, NULL, cache_rules); }}#endif#if 0static voidprint_jump_internal_function (lf *file, gen_entry *table, function_entry * function, void *data){ if (function->is_internal) { lf_printf (file, "\n"); lf_print__line_ref (file, function->line); lf_indent (file, -1); print_function_name (file, function->name, NULL, (options.gen.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"); table_print_code (file, function->code); lf_print__internal_ref (file); print_sim_engine_abort (file, "Internal function must longjump"); lf_indent (file, -2); lf_printf (file, "}\n"); }}#endif#if 0static voidprint_jump_until_stop_body (lf *file, insn_table *table, cache_table * cache_rules){ lf_printf (file, "{\n"); lf_indent (file, +2); lf_putstr (file, "jmp_buf halt;\n"); lf_putstr (file, "jmp_buf restart;\n"); lf_putstr (file, "sim_cpu *cpu = 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(cpus[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, "cpu = cpus[0];\n"); lf_putstr (file, "nia = cpu_get_program_counter(cpu);\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(cpu),\n"); lf_putstr (file, " cpu, 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");}#endif/****************************************************************//* 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_entry * instruction, insn_opcodes *opcode_paths){ /* 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 */ { int nr_checks = 0; int word_nr; lf_printf (file, "\n"); lf_indent_suppress (file); lf_printf (file, "#if defined (WITH_RESERVED_BITS)\n"); lf_printf (file, "/* validate: "); print_insn_words (file, instruction); lf_printf (file, " */\n"); for (word_nr = 0; word_nr < instruction->nr_words; word_nr++) { insn_uint check_mask = 0; insn_uint check_val = 0; insn_word_entry *word = instruction->word[word_nr]; int bit_nr; /* form check_mask/check_val containing what needs to be checked in the instruction */ for (bit_nr = 0; bit_nr < options.insn_bit_size; bit_nr++) { insn_bit_entry *bit = word->bit[bit_nr]; insn_field_entry *field = bit->field; /* Make space for the next bit */ check_mask <<= 1; check_val <<= 1; /* Only need to validate constant (and reserved) bits. Skip any others */ if (field->type != insn_field_int && field->type != insn_field_reserved) continue; /* Look through the list of opcode paths that lead to this instruction. See if any have failed to check the relevant bit */ if (opcode_paths != NULL) { insn_opcodes *entry; for (entry = opcode_paths; entry != NULL; entry = entry->next) { opcode_field *opcode; for (opcode = entry->opcode; opcode != NULL; opcode = opcode->parent) { if (opcode->word_nr == word_nr && opcode->first <= bit_nr && opcode->last >= bit_nr) /* we've decoded on this bit */ break; } if (opcode == NULL) /* the bit wasn't decoded on */ break; } if (entry == NULL) /* all the opcode paths decoded on BIT_NR, no need to check it */ continue; } check_mask |= 1; check_val |= bit->value; } /* if any bits not checked by opcode tables, output code to check them */ if (check_mask) { if (nr_checks == 0) { lf_printf (file, "if (WITH_RESERVED_BITS)\n"); lf_printf (file, " {\n"); lf_indent (file, +4); } nr_checks++; if (options.insn_bit_size > 32) { lf_printf (file, "if ((instruction_%d\n", word_nr); lf_printf (file, " & UNSIGNED64 (0x%08lx%08lx))\n", (unsigned long) (check_mask >> 32), (unsigned long) (check_mask)); lf_printf (file, " != UNSIGNED64 (0x%08lx%08lx))\n", (unsigned long) (check_val >> 32), (unsigned long) (check_val)); } else { lf_printf (file, "if ((instruction_%d & 0x%08lx) != 0x%08lx)\n", word_nr, (unsigned long) (check_mask), (unsigned long) (check_val)); } lf_indent (file, +2); print_idecode_invalid (file, "return", invalid_illegal); lf_indent (file, -2); } } if (nr_checks > 0) { lf_indent (file, -4); lf_printf (file, " }\n"); } lf_indent_suppress (file); lf_printf (file, "#endif\n"); } /* 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 (filter_is_member (instruction->flags, "f")) { lf_printf (file, "\n"); lf_indent_suppress (file); lf_printf (file, "#if defined(CURRENT_FLOATING_POINT)\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_invalid (file, "return", invalid_illegal); lf_indent (file, -2); lf_printf (file, "}\n"); lf_indent_suppress (file); lf_printf (file, "#endif\n"); } } /* 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 (filter_is_member (instruction->flags, "f")) { lf_printf (file, "\n"); lf_indent_suppress (file); lf_printf (file, "#if defined(IS_FP_AVAILABLE)\n"); lf_printf (file, "/* Validate: FP available according to cpu */\n"); lf_printf (file, "if (!IS_FP_AVAILABLE) {\n"); lf_indent (file, +2); print_idecode_invalid (file, "return", invalid_fp_unavailable); lf_indent (file, -2); lf_printf (file, "}\n"); lf_indent_suppress (file); lf_printf (file, "#endif\n"); } } /* Validate: Validate Instruction in correct slot Some architectures place restrictions on the slot that an instruction can be issued in */ { if (filter_is_member (instruction->options, "s") || options.gen.slot_verification) { lf_printf (file, "\n"); lf_indent_suppress (file); lf_printf (file, "#if defined(IS_WRONG_SLOT)\n"); lf_printf (file, "/* Validate: Instruction issued in correct slot */\n"); lf_printf (file, "if (IS_WRONG_SLOT) {\n"); lf_indent (file, +2); print_idecode_invalid (file, "return", invalid_wrong_slot); lf_indent (file, -2); lf_printf (file, "}\n"); lf_indent_suppress (file); lf_printf (file, "#endif\n"); } }}/****************************************************************/voidprint_idecode_issue_function_header (lf *file, const char *processor, function_decl_type decl_type, int nr_prefetched_words){ int indent; lf_printf (file, "\n"); switch (decl_type) { case is_function_declaration: lf_print__function_type_function (file, print_semantic_function_type, "INLINE_IDECODE", " "); break; case is_function_definition: lf_print__function_type_function (file, print_semantic_function_type, "INLINE_IDECODE", "\n"); break; case is_function_variable: print_semantic_function_type (file); lf_printf (file, " (*"); break; } indent = print_function_name (file, "issue", NULL, processor, NULL, function_name_prefix_idecode); switch (decl_type) { case is_function_definition: indent += lf_printf (file, " ("); break; case is_function_declaration: lf_putstr (file, "\n("); indent = 1; break; case is_function_variable: lf_putstr (file, ")\n("); indent = 1; break; } lf_indent (file, +indent); print_semantic_function_formal (file, nr_prefetched_words); lf_putstr (file, ")"); lf_indent (file, -indent); switch (decl_type) { case is_function_definition: lf_printf (file, "\n"); break; case is_function_declaration: case is_function_variable: lf_putstr (file, ";\n"); break; }}voidprint_idecode_globals (lf *file){ 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, " unsigned%d mask;\n", options.insn_bit_size); lf_printf (file, " unsigned%d value;\n", options.insn_bit_size); lf_printf (file, " void *function_or_table;\n"); lf_printf (file, "} idecode_table_entry;\n");}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -