📄 gen-idecode.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-icache.h"#include "gen-semantics.h"static voidlf_print_opcodes (lf *file, gen_entry *table){ if (table !=NULL) { while (1) { ASSERT (table->opcode != NULL); lf_printf (file, "_%d_%d", table->opcode->first, table->opcode->last); if (table->parent == NULL) break; lf_printf (file, "__%d", table->opcode_nr); table = table->parent; } }}static voidprint_idecode_ifetch (lf *file, int previous_nr_prefetched_words, int current_nr_prefetched_words){ int word_nr; for (word_nr = previous_nr_prefetched_words; word_nr < current_nr_prefetched_words; word_nr++) { lf_printf (file, "instruction_word instruction_%d = IMEM%d_IMMED (cia, %d);\n", word_nr, options.insn_bit_size, word_nr); }}/****************************************************************/static voidlf_print_table_name (lf *file, gen_entry *table){ lf_printf (file, "idecode_table"); lf_print_opcodes (file, table);}static voidprint_idecode_table (lf *file, gen_entry *entry, const char *result){ lf_printf (file, "/* prime the search */\n"); lf_printf (file, "idecode_table_entry *table = "); lf_print_table_name (file, entry); lf_printf (file, ";\n"); lf_printf (file, "int opcode = EXTRACTED%d (instruction, %d, %d);\n", options.insn_bit_size, i2target (options.hi_bit_nr, entry->opcode->first), i2target (options.hi_bit_nr, entry->opcode->last)); lf_printf (file, "idecode_table_entry *table_entry = table + opcode;\n"); lf_printf (file, "\n"); lf_printf (file, "/* iterate until a leaf */\n"); lf_printf (file, "while (1) {\n"); lf_printf (file, " signed shift = table_entry->shift;\n"); lf_printf (file, "if (shift == function_entry) break;\n"); lf_printf (file, " if (shift >= 0) {\n"); lf_printf (file, " table = ((idecode_table_entry*)\n"); lf_printf (file, " table_entry->function_or_table);\n"); lf_printf (file, " opcode = ((instruction & table_entry->mask)\n"); lf_printf (file, " >> shift);\n"); lf_printf (file, " table_entry = table + opcode;\n"); lf_printf (file, " }\n"); lf_printf (file, " else {\n"); lf_printf (file, " /* must be a boolean */\n"); lf_printf (file, " ASSERT(table_entry->shift == boolean_entry);\n"); lf_printf (file, " opcode = ((instruction & table_entry->mask)\n"); lf_printf (file, " != table_entry->value);\n"); lf_printf (file, " table = ((idecode_table_entry*)\n"); lf_printf (file, " table_entry->function_or_table);\n"); lf_printf (file, " table_entry = table + opcode;\n"); lf_printf (file, " }\n"); lf_printf (file, "}\n"); lf_printf (file, "\n"); lf_printf (file, "/* call the leaf code */\n"); if (options.gen.code == generate_jumps) { lf_printf (file, "goto *table_entry->function_or_table;\n"); } else { lf_printf (file, "%s ", result); if (options.gen.icache) { lf_printf (file, "(((idecode_icache*)table_entry->function_or_table)\n"); lf_printf (file, " ("); print_icache_function_actual (file, 1); lf_printf (file, "));\n"); } else { lf_printf (file, "((idecode_semantic*)table_entry->function_or_table)\n"); lf_printf (file, " ("); print_semantic_function_actual (file, 1); lf_printf (file, ");\n"); } }}static voidprint_idecode_table_start (lf *file, gen_entry *table, int depth, void *data){ ASSERT (depth == 0); /* start of the table */ if (table->opcode_rule->gen == array_gen) { lf_printf (file, "\n"); lf_printf (file, "static idecode_table_entry "); lf_print_table_name (file, table); lf_printf (file, "[] = {\n"); }}static voidprint_idecode_table_leaf (lf *file, gen_entry *entry, int depth, void *data){ gen_entry *master_entry; ASSERT (entry->parent != NULL); ASSERT (depth == 0); if (entry->combined_parent == NULL) master_entry = entry; else master_entry = entry->combined_parent; /* add an entry to the table */ if (entry->parent->opcode_rule->gen == array_gen) { lf_printf (file, " /*%d*/ { ", entry->opcode_nr); if (entry->opcode == NULL) { ASSERT (entry->nr_insns == 1); /* table leaf entry */ lf_printf (file, "function_entry, 0, 0, "); if (options.gen.code == generate_jumps) { lf_printf (file, "&&"); } print_function_name (file, entry->insns->insn->name, entry->insns->insn->format_name, NULL, master_entry->expanded_bits, (options.gen.icache ? function_name_prefix_icache : function_name_prefix_semantics)); } else if (entry->opcode_rule->gen == switch_gen || entry->opcode_rule->gen == goto_switch_gen || entry->opcode_rule->gen == padded_switch_gen) { /* table calling switch statement */ lf_printf (file, "function_entry, 0, 0, "); if (options.gen.code == generate_jumps) { lf_printf (file, "&&"); } lf_print_table_name (file, entry); } else if (entry->opcode->is_boolean) { /* table `calling' boolean table */ lf_printf (file, "boolean_entry, "); lf_printf (file, "MASK32(%d, %d), ", i2target (options.hi_bit_nr, entry->opcode->first), i2target (options.hi_bit_nr, entry->opcode->last)); lf_printf (file, "INSERTED32(%d, %d, %d), ", entry->opcode->boolean_constant, i2target (options.hi_bit_nr, entry->opcode->first), i2target (options.hi_bit_nr, entry->opcode->last)); lf_print_table_name (file, entry); } else { /* table `calling' another table */ lf_printf (file, "%d, ", options.insn_bit_size - entry->opcode->last - 1); lf_printf (file, "MASK%d(%d,%d), ", options.insn_bit_size, i2target (options.hi_bit_nr, entry->opcode->first), i2target (options.hi_bit_nr, entry->opcode->last)); lf_printf (file, "0, "); lf_print_table_name (file, entry); } lf_printf (file, " },\n"); }}static voidprint_idecode_table_end (lf *file, gen_entry *table, int depth, void *data){ ASSERT (depth == 0); if (table->opcode_rule->gen == array_gen) { lf_printf (file, "};\n"); }}/****************************************************************/static voidprint_goto_switch_name (lf *file, gen_entry *entry){ lf_printf (file, "case_"); if (entry->opcode == NULL) { print_function_name (file, entry->insns->insn->name, entry->insns->insn->format_name, NULL, entry->expanded_bits, (options.gen.icache ? function_name_prefix_icache : function_name_prefix_semantics)); } else { lf_print_table_name (file, entry); }}static voidprint_goto_switch_table_leaf (lf *file, gen_entry *entry, int depth, void *data){ ASSERT (entry->parent != NULL); ASSERT (depth == 0); ASSERT (entry->parent->opcode_rule->gen == goto_switch_gen); ASSERT (entry->parent->opcode); lf_printf (file, "/* %d */ &&", entry->opcode_nr); if (entry->combined_parent != NULL) print_goto_switch_name (file, entry->combined_parent); else print_goto_switch_name (file, entry); lf_printf (file, ",\n");}static voidprint_goto_switch_break (lf *file, gen_entry *entry){ lf_printf (file, "goto break_"); lf_print_table_name (file, entry->parent); lf_printf (file, ";\n");}static voidprint_goto_switch_table (lf *file, gen_entry *table){ lf_printf (file, "const static void *"); lf_print_table_name (file, table); lf_printf (file, "[] = {\n"); lf_indent (file, +2); gen_entry_traverse_tree (file, table, 0, NULL /*start */ , print_goto_switch_table_leaf, NULL /*end */ , NULL /*data */ ); lf_indent (file, -2); lf_printf (file, "};\n");}void print_idecode_switch (lf *file, gen_entry *table, const char *result);static voidprint_idecode_switch_start (lf *file, gen_entry *table, int depth, void *data){ /* 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); if (table->opcode->is_boolean || table->opcode_rule->gen == switch_gen || table->opcode_rule->gen == padded_switch_gen) { lf_printf (file, "switch (EXTRACTED%d (instruction_%d, %d, %d))\n", options.insn_bit_size, table->opcode_rule->word_nr, i2target (options.hi_bit_nr, table->opcode->first), i2target (options.hi_bit_nr, table->opcode->last)); lf_indent (file, +2); lf_printf (file, "{\n"); } else if (table->opcode_rule->gen == goto_switch_gen) { 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_printf (file, "{\n"); lf_indent (file, +2); } print_goto_switch_table (file, table); lf_printf (file, "ASSERT (EXTRACTED%d (instruction_%d, %d, %d)\n", options.insn_bit_size, table->opcode->word_nr, i2target (options.hi_bit_nr, table->opcode->first), i2target (options.hi_bit_nr, table->opcode->last)); lf_printf (file, " < (sizeof ("); lf_print_table_name (file, table); lf_printf (file, ") / sizeof(void*)));\n"); lf_printf (file, "goto *"); lf_print_table_name (file, table); lf_printf (file, "[EXTRACTED%d (instruction_%d, %d, %d)];\n", options.insn_bit_size, table->opcode->word_nr, i2target (options.hi_bit_nr, table->opcode->first), i2target (options.hi_bit_nr, table->opcode->last)); } else { ASSERT ("bad switch" == NULL); }}static voidprint_idecode_switch_leaf (lf *file, gen_entry *entry, int depth, void *data){ const char *result = data; ASSERT (entry->parent != NULL); ASSERT (depth == 0); ASSERT (entry->parent->opcode_rule->gen == switch_gen || entry->parent->opcode_rule->gen == goto_switch_gen || entry->parent->opcode_rule->gen == padded_switch_gen); ASSERT (entry->parent->opcode); /* skip over any instructions combined into another entry */ if (entry->combined_parent != NULL) return; if (entry->parent->opcode->is_boolean && entry->opcode_nr == 0) { /* case: boolean false target */ lf_printf (file, "case %d:\n", entry->parent->opcode->boolean_constant); } else if (entry->parent->opcode->is_boolean && entry->opcode_nr != 0) { /* case: boolean true case */ lf_printf (file, "default:\n"); } else if (entry->parent->opcode_rule->gen == switch_gen || entry->parent->opcode_rule->gen == padded_switch_gen) { /* case: <opcode-nr> - switch */ gen_entry *cob; for (cob = entry; cob != NULL; cob = cob->combined_next) lf_printf (file, "case %d:\n", cob->opcode_nr); } else if (entry->parent->opcode_rule->gen == goto_switch_gen) { /* case: <opcode-nr> - goto-switch */ print_goto_switch_name (file, entry); lf_printf (file, ":\n"); } else { ERROR ("bad switch"); } lf_printf (file, " {\n"); lf_indent (file, +4); { if (entry->opcode == NULL) { /* switch calling leaf */ ASSERT (entry->nr_insns == 1); print_idecode_ifetch (file, entry->nr_prefetched_words, entry->insns->semantic->nr_prefetched_words); switch (options.gen.code) { case generate_jumps: lf_printf (file, "goto "); break; case generate_calls: lf_printf (file, "%s", result); break;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -