📄 gen-idecode.c
字号:
/* This file is part of the program psim. Copyright 1994, 1995, 1996, 1997, 2003 Andrew Cagney 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 "ld-decode.h"#include "ld-cache.h"#include "ld-insn.h"#include "igen.h"#include "gen-idecode.h"#include "gen-icache.h"#include "gen-semantics.h"static voidlf_print_opcodes(lf *file, insn_table *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 voidlf_print_table_name(lf *file, insn_table *table){ lf_printf(file, "idecode_table"); lf_print_opcodes(file, table);}static voidprint_idecode_table(lf *file, insn_table *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 = EXTRACTED32(instruction, %d, %d);\n", i2target(hi_bit_nr, entry->opcode->first), i2target(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 ((code & generate_jumps)) { lf_printf(file, "goto *table_entry->function_or_table;\n"); } else { lf_printf(file, "%s ", result); if ((code & generate_with_icache)) { lf_printf(file, "(((idecode_icache*)table_entry->function_or_table)\n"); lf_printf(file, " (%s));\n", ICACHE_FUNCTION_ACTUAL); } else { lf_printf(file, "((idecode_semantic*)table_entry->function_or_table)\n"); lf_printf(file, " (%s);\n", SEMANTIC_FUNCTION_ACTUAL); } }}static voidprint_idecode_table_start(insn_table *table, lf *file, void *data, int depth){ 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(insn_table *entry, lf *file, void *data, insn *instruction, int depth){ ASSERT(entry->parent != NULL); ASSERT(depth == 0); /* 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) { /* table leaf entry */ lf_printf(file, "function_entry, 0, 0, "); if ((code & generate_jumps)) lf_printf(file, "&&"); 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)); } 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 ((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(hi_bit_nr, entry->opcode->first), i2target(hi_bit_nr, entry->opcode->last)); lf_printf(file, "INSERTED32(%d, %d, %d), ", entry->opcode->boolean_constant, i2target(hi_bit_nr, entry->opcode->first), i2target(hi_bit_nr, entry->opcode->last)); lf_print_table_name(file, entry); } else { /* table `calling' another table */ lf_printf(file, "%d, ", insn_bit_size - entry->opcode->last - 1); lf_printf(file, "MASK32(%d,%d), ", i2target(hi_bit_nr, entry->opcode->first), i2target(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(insn_table *table, lf *file, void *data, int depth){ ASSERT(depth == 0); if (table->opcode_rule->gen == array_gen) { lf_printf(file, "};\n"); }}static voidprint_idecode_table_padding(insn_table *table, lf *file, void *data, int depth, int opcode_nr){ ASSERT(depth == 0); if (table->opcode_rule->gen == array_gen) { lf_printf(file, " /*%d*/ { function_entry, 0, 0, ", opcode_nr); if ((code & generate_jumps)) lf_printf(file, "&&"); lf_printf(file, "%s_illegal },\n", ((code & generate_with_icache) ? "icache" : "semantic")); }}/****************************************************************/static voidprint_goto_switch_name(lf *file, insn_table *entry){ lf_printf(file, "case_"); if (entry->opcode == NULL) 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)); else lf_print_table_name(file, entry);}static voidprint_goto_switch_table_leaf(insn_table *entry, lf *file, void *data, insn *instruction, int depth){ ASSERT(entry->parent != NULL); ASSERT(depth == 0); ASSERT(entry->parent->opcode_rule->gen == goto_switch_gen); ASSERT(entry->parent->opcode); lf_printf(file, "&&"); print_goto_switch_name(file, entry); lf_printf(file, ",\n");}static voidprint_goto_switch_table_padding(insn_table *table, lf *file, void *data, int depth, int opcode_nr){ ASSERT(depth == 0); ASSERT(table->opcode_rule->gen == goto_switch_gen); lf_printf(file, "&&illegal_"); lf_print_table_name(file, table); lf_printf(file, ",\n");}static voidprint_goto_switch_break(lf *file, insn_table *entry){ lf_printf(file, "goto break_"); lf_print_table_name(file, entry->parent); lf_printf(file, ";\n");}static voidprint_goto_switch_table(lf *file, insn_table *table){ lf_printf(file, "const static void *"); lf_print_table_name(file, table); lf_printf(file, "[] = {\n"); lf_indent(file, +2); insn_table_traverse_tree(table, file, NULL/*data*/, 0, NULL/*start*/, print_goto_switch_table_leaf, NULL/*end*/, print_goto_switch_table_padding); lf_indent(file, -2); lf_printf(file, "};\n");}void print_idecode_switch(lf *file, insn_table *table, const char *result);static voididecode_switch_start(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); if (table->opcode->is_boolean || table->opcode_rule->gen == switch_gen || table->opcode_rule->gen == padded_switch_gen) { lf_printf(file, "switch (EXTRACTED32(instruction, %d, %d)) {\n", i2target(hi_bit_nr, table->opcode->first), i2target(hi_bit_nr, table->opcode->last)); } 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(EXTRACTED32(instruction, %d, %d)\n", i2target(hi_bit_nr, table->opcode->first), i2target(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, "[EXTRACTED32(instruction, %d, %d)];\n", i2target(hi_bit_nr, table->opcode->first), i2target(hi_bit_nr, table->opcode->last)); } else { ASSERT("bad switch" == NULL); }}static voididecode_switch_leaf(insn_table *entry, lf *file, void *data, insn *instruction, int depth){ 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); if (entry->parent->opcode->is_boolean && entry->opcode_nr == 0) { /* 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) { /* 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) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -