📄 gen-icache.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-semantics.h"#include "gen-idecode.h"#include "gen-icache.h"static voidprint_icache_function_header (lf *file, const char *basename, const char *format_name, opcode_bits *expanded_bits, int is_function_definition, int nr_prefetched_words){ lf_printf (file, "\n"); lf_print__function_type_function (file, print_icache_function_type, "EXTERN_ICACHE", " "); print_function_name (file, basename, format_name, NULL, expanded_bits, function_name_prefix_icache); lf_printf (file, "\n("); print_icache_function_formal (file, nr_prefetched_words); lf_printf (file, ")"); if (!is_function_definition) lf_printf (file, ";"); lf_printf (file, "\n");}voidprint_icache_declaration (lf *file, insn_entry * insn, opcode_bits *expanded_bits, insn_opcodes *opcodes, int nr_prefetched_words){ print_icache_function_header (file, insn->name, insn->format_name, expanded_bits, 0 /* is not function definition */ , nr_prefetched_words);}static voidprint_icache_extraction (lf *file, const char *format_name, cache_entry_type cache_type, const char *entry_name, const char *entry_type, const char *entry_expression, char *single_insn_field, line_ref *line, insn_field_entry *cur_field, opcode_bits *expanded_bits, icache_decl_type what_to_declare, icache_body_type what_to_do){ const char *expression; opcode_bits *bits; char *reason; ASSERT (format_name != NULL); ASSERT (entry_name != NULL); /* figure out exactly what should be going on here */ switch (cache_type) { case scratch_value: if ((what_to_do & put_values_in_icache) || what_to_do == do_not_use_icache) { reason = "scratch"; what_to_do = do_not_use_icache; } else return; break; case compute_value: if ((what_to_do & get_values_from_icache) || what_to_do == do_not_use_icache) { reason = "compute"; what_to_do = do_not_use_icache; } else return; break; case cache_value: if ((what_to_declare != undef_variables) || !(what_to_do & put_values_in_icache)) { reason = "cache"; what_to_declare = ((what_to_do & put_values_in_icache) ? declare_variables : what_to_declare); } else return; break; default: abort (); /* Bad switch. */ } /* For the type, default to a simple unsigned */ if (entry_type == NULL || strlen (entry_type) == 0) entry_type = "unsigned"; /* look through the set of expanded sub fields to see if this field has been given a constant value */ for (bits = expanded_bits; bits != NULL; bits = bits->next) { if (bits->field == cur_field) break; } /* Define a storage area for the cache element */ switch (what_to_declare) { case undef_variables: /* We've finished with the #define value - destory it */ lf_indent_suppress (file); lf_printf (file, "#undef %s\n", entry_name); return; case define_variables: /* Using direct access for this entry, clear any prior definition, then define it */ lf_indent_suppress (file); lf_printf (file, "#undef %s\n", entry_name); /* Don't type cast pointer types! */ lf_indent_suppress (file); if (strchr (entry_type, '*') != NULL) lf_printf (file, "#define %s (", entry_name); else lf_printf (file, "#define %s ((%s) ", entry_name, entry_type); break; case declare_variables: /* using variables to define the value */ if (line != NULL) lf_print__line_ref (file, line); lf_printf (file, "%s const %s UNUSED = ", entry_type, entry_name); break; } /* define a value for that storage area as determined by what is in the cache */ if (bits != NULL && single_insn_field != NULL && strcmp (entry_name, single_insn_field) == 0 && strcmp (entry_name, cur_field->val_string) == 0 && ((bits->opcode->is_boolean && bits->value == 0) || (!bits->opcode->is_boolean))) { /* The cache rule is specifying what to do with a simple instruction field. Because of instruction expansion, the field is either a constant value or equal to the specified constant (boolean comparison). (The latter indicated by bits->value == 0). The case of a field not being equal to the specified boolean value is handled later. */ expression = "constant field"; ASSERT (bits->field == cur_field); if (bits->opcode->is_boolean) { ASSERT (bits->value == 0); lf_printf (file, "%d", bits->opcode->boolean_constant); } else if (bits->opcode->last < bits->field->last) { lf_printf (file, "%d", bits->value << (bits->field->last - bits->opcode->last)); } else { lf_printf (file, "%d", bits->value); } } else if (bits != NULL && single_insn_field != NULL && strncmp (entry_name, single_insn_field, strlen (single_insn_field)) == 0 && strncmp (entry_name + strlen (single_insn_field), "_is_", strlen ("_is_")) == 0 && ((bits->opcode->is_boolean && ((unsigned) atol (entry_name + strlen (single_insn_field) + strlen ("_is_")) == bits->opcode->boolean_constant)) || (!bits->opcode->is_boolean))) { /* The cache rule defines an entry for the comparison between a single instruction field and a constant. The value of the comparison in someway matches that of the opcode field that was made constant through expansion. */ expression = "constant compare"; if (bits->opcode->is_boolean) { lf_printf (file, "%d /* %s == %d */", bits->value == 0, single_insn_field, bits->opcode->boolean_constant); } else if (bits->opcode->last < bits->field->last) { lf_printf (file, "%d /* %s == %d */", (atol (entry_name + strlen (single_insn_field) + strlen ("_is_")) == (bits-> value << (bits->field->last - bits->opcode->last))), single_insn_field, (bits-> value << (bits->field->last - bits->opcode->last))); } else { lf_printf (file, "%d /* %s == %d */", (atol (entry_name + strlen (single_insn_field) + strlen ("_is_")) == bits->value), single_insn_field, bits->value); } } else { /* put the field in the local variable, possibly also enter it into the cache */ expression = "extraction"; /* handle the cache */ if ((what_to_do & get_values_from_icache) || (what_to_do & put_values_in_icache)) { lf_printf (file, "cache_entry->crack.%s.%s", format_name, entry_name); if (what_to_do & put_values_in_icache) /* also put it in the cache? */ { lf_printf (file, " = "); } } if ((what_to_do & put_values_in_icache) || what_to_do == do_not_use_icache) { if (cur_field != NULL) { if (entry_expression != NULL && strlen (entry_expression) > 0) error (line, "Instruction field entry with nonempty expression\n"); if (cur_field->first == 0 && cur_field->last == options.insn_bit_size - 1) lf_printf (file, "(instruction_%d)", cur_field->word_nr); else if (cur_field->last == options.insn_bit_size - 1) lf_printf (file, "MASKED%d (instruction_%d, %d, %d)", options.insn_bit_size, cur_field->word_nr, i2target (options.hi_bit_nr, cur_field->first), i2target (options.hi_bit_nr, cur_field->last)); else lf_printf (file, "EXTRACTED%d (instruction_%d, %d, %d)", options.insn_bit_size, cur_field->word_nr, i2target (options.hi_bit_nr, cur_field->first), i2target (options.hi_bit_nr, cur_field->last)); } else { lf_printf (file, "%s", entry_expression); } } } switch (what_to_declare) { case define_variables: lf_printf (file, ")"); break; case undef_variables: break; case declare_variables: lf_printf (file, ";"); break; } ASSERT (reason != NULL && expression != NULL); lf_printf (file, " /* %s - %s */\n", reason, expression);}voidprint_icache_body (lf *file, insn_entry * instruction, opcode_bits *expanded_bits, cache_entry *cache_rules, icache_decl_type what_to_declare, icache_body_type what_to_do, int nr_prefetched_words){ /* extract instruction fields */ lf_printf (file, "/* Extraction: %s\n", instruction->name); lf_printf (file, " "); switch (what_to_declare) { case define_variables: lf_printf (file, "#define"); break; case declare_variables: lf_printf (file, "declare"); break; case undef_variables: lf_printf (file, "#undef"); break; } lf_printf (file, " "); switch (what_to_do) { case get_values_from_icache: lf_printf (file, "get-values-from-icache"); break; case put_values_in_icache: lf_printf (file, "put-values-in-icache"); break; case both_values_and_icache: lf_printf (file, "get-values-from-icache|put-values-in-icache"); break; case do_not_use_icache: lf_printf (file, "do-not-use-icache"); break; } lf_printf (file, "\n "); print_insn_words (file, instruction); lf_printf (file, " */\n"); /* pass zero - fetch from memory any missing instructions. Some of the instructions will have already been fetched (in the instruction array), others will still need fetching. */ switch (what_to_do) { case get_values_from_icache: break; case put_values_in_icache: case both_values_and_icache: case do_not_use_icache: { int word_nr; switch (what_to_declare) { case undef_variables: break; case define_variables: case declare_variables: for (word_nr = nr_prefetched_words; word_nr < instruction->nr_words; word_nr++) { /* FIXME - should be using print_icache_extraction? */ lf_printf (file, "%sinstruction_word instruction_%d UNUSED = ", options.module.global.prefix.l, word_nr); lf_printf (file, "IMEM%d_IMMED (cia, %d)", options.insn_bit_size, word_nr); lf_printf (file, ";\n"); } } } } /* if putting the instruction words in the cache, define references for them */ if (options.gen.insn_in_icache) { /* FIXME: is the instruction_word type correct? */ print_icache_extraction (file, instruction->format_name, cache_value, "insn", /* name */ "instruction_word", /* type */ "instruction", /* expression */ NULL, /* origin */ NULL, /* line */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -