diff options
author | Stan Shebs <shebs@codesourcery.com> | 1999-04-16 01:34:07 +0000 |
---|---|---|
committer | Stan Shebs <shebs@codesourcery.com> | 1999-04-16 01:34:07 +0000 |
commit | 071ea11e85eb9d529cc5eb3d35f6247466a21b99 (patch) | |
tree | 5deda65b8d7b04d1f4cbc534c3206d328e1267ec /sim/igen/gen-icache.c | |
parent | 1730ec6b1848f0f32154277f788fb29f88d8475b (diff) | |
download | gdb-071ea11e85eb9d529cc5eb3d35f6247466a21b99.zip gdb-071ea11e85eb9d529cc5eb3d35f6247466a21b99.tar.gz gdb-071ea11e85eb9d529cc5eb3d35f6247466a21b99.tar.bz2 |
Initial creation of sourceware repository
Diffstat (limited to 'sim/igen/gen-icache.c')
-rw-r--r-- | sim/igen/gen-icache.c | 852 |
1 files changed, 0 insertions, 852 deletions
diff --git a/sim/igen/gen-icache.c b/sim/igen/gen-icache.c deleted file mode 100644 index 31c5ab9..0000000 --- a/sim/igen/gen-icache.c +++ /dev/null @@ -1,852 +0,0 @@ -/* This file is part of the program psim. - - Copyright (C) 1994-1998, Andrew Cagney <cagney@highland.com.au> - - 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 void -print_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"); -} - - -void -print_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 void -print_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; - } - - /* 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, define it */ - lf_indent_suppress (file); - 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); -} - - -void -print_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 */ - NULL, NULL, - what_to_declare, - what_to_do); - } - lf_printf(file, "\n"); - - /* pass one - process instruction fields. - - If there is no cache rule, the default is to enter the field into - the cache */ - { - insn_word_entry *word; - for (word = instruction->words; - word != NULL; - word = word->next) - { - insn_field_entry *cur_field; - for (cur_field = word->first; - cur_field->first < options.insn_bit_size; - cur_field = cur_field->next) - { - if (cur_field->type == insn_field_string) - { - cache_entry *cache_rule; - cache_entry_type value_type = cache_value; - line_ref *value_line = instruction->line; - /* check the cache table to see if it contains a rule - overriding the default cache action for an - instruction field */ - for (cache_rule = cache_rules; - cache_rule != NULL; - cache_rule = cache_rule->next) - { - if (filter_is_subset (instruction->field_names, - cache_rule->original_fields) - && strcmp (cache_rule->name, cur_field->val_string) == 0) - { - value_type = cache_rule->entry_type; - value_line = cache_rule->line; - if (value_type == compute_value) - { - options.warning (cache_rule->line, - "instruction field of type `compute' changed to `cache'\n"); - cache_rule->entry_type = cache_value; - } - break; - } - } - /* Define an entry for the field within the - instruction */ - print_icache_extraction (file, - instruction->format_name, - value_type, - cur_field->val_string, /* name */ - NULL, /* type */ - NULL, /* expression */ - cur_field->val_string, /* insn field */ - value_line, - cur_field, - expanded_bits, - what_to_declare, - what_to_do); - } - } - } - } - - /* pass two - any cache fields not processed above */ - { - cache_entry *cache_rule; - for (cache_rule = cache_rules; - cache_rule != NULL; - cache_rule = cache_rule->next) - { - if (filter_is_subset (instruction->field_names, - cache_rule->original_fields) - && !filter_is_member (instruction->field_names, - cache_rule->name)) - { - char *single_field = filter_next (cache_rule->original_fields, ""); - if (filter_next (cache_rule->original_fields, single_field) != NULL) - single_field = NULL; - print_icache_extraction (file, - instruction->format_name, - cache_rule->entry_type, - cache_rule->name, - cache_rule->type, - cache_rule->expression, - single_field, - cache_rule->line, - NULL, /* cur_field */ - expanded_bits, - what_to_declare, - what_to_do); - } - } - } - - lf_print__internal_ref (file); -} - - - -typedef struct _form_fields form_fields; -struct _form_fields { - char *name; - filter *fields; - form_fields *next; -}; - -static form_fields * -insn_table_cache_fields (insn_table *isa) -{ - form_fields *forms = NULL; - insn_entry *insn; - for (insn = isa->insns; - insn != NULL; - insn = insn->next) { - form_fields **form = &forms; - while (1) - { - if (*form == NULL) - { - /* new format name, add it */ - form_fields *new_form = ZALLOC (form_fields); - new_form->name = insn->format_name; - filter_add (&new_form->fields, insn->field_names); - *form = new_form; - break; - } - else if (strcmp ((*form)->name, insn->format_name) == 0) - { - /* already present, add field names to the existing list */ - filter_add (&(*form)->fields, insn->field_names); - break; - } - form = &(*form)->next; - } - } - return forms; -} - - - -extern void -print_icache_struct (lf *file, - insn_table *isa, - cache_entry *cache_rules) -{ - /* Create a list of all the different instruction formats with their - corresponding field names. */ - form_fields *formats = insn_table_cache_fields (isa); - - lf_printf (file, "\n"); - lf_printf (file, "#define WITH_%sIDECODE_CACHE_SIZE %d\n", - options.module.global.prefix.u, - (options.gen.icache ? options.gen.icache_size : 0)); - lf_printf (file, "\n"); - - /* create an instruction cache if being used */ - if (options.gen.icache) { - lf_printf (file, "typedef struct _%sidecode_cache {\n", - options.module.global.prefix.l); - lf_indent (file, +2); - { - form_fields *format; - lf_printf (file, "unsigned_word address;\n"); - lf_printf (file, "void *semantic;\n"); - lf_printf (file, "union {\n"); - lf_indent (file, +2); - for (format = formats; - format != NULL; - format = format->next) - { - lf_printf (file, "struct {\n"); - lf_indent (file, +2); - { - cache_entry *cache_rule; - char *field; - /* space for any instruction words */ - if (options.gen.insn_in_icache) - lf_printf (file, "instruction_word insn[%d];\n", isa->max_nr_words); - /* define an entry for any applicable cache rules */ - for (cache_rule = cache_rules; - cache_rule != NULL; - cache_rule = cache_rule->next) - { - /* nb - sort of correct - should really check against - individual instructions */ - if (filter_is_subset (format->fields, cache_rule->original_fields)) - { - char *memb; - lf_printf (file, "%s %s;", - (cache_rule->type == NULL - ? "unsigned" - : cache_rule->type), - cache_rule->name); - lf_printf (file, " /*"); - for (memb = filter_next (cache_rule->original_fields, ""); - memb != NULL; - memb = filter_next (cache_rule->original_fields, memb)) - { - lf_printf (file, " %s", memb); - } - lf_printf (file, " */\n"); - } - } - /* define an entry for any fields not covered by a cache rule */ - for (field = filter_next (format->fields, ""); - field != NULL; - field = filter_next (format->fields, field)) - { - cache_entry *cache_rule; - int found_rule = 0; - for (cache_rule = cache_rules; - cache_rule != NULL; - cache_rule = cache_rule->next) - { - if (strcmp (cache_rule->name, field) == 0) - { - found_rule = 1; - break; - } - } - if (!found_rule) - lf_printf (file, "unsigned %s; /* default */\n", field); - } - } - lf_indent (file, -2); - lf_printf (file, "} %s;\n", format->name); - } - lf_indent (file, -2); - lf_printf (file, "} crack;\n"); - } - lf_indent (file, -2); - lf_printf (file, "} %sidecode_cache;\n", options.module.global.prefix.l); - } - else - { - /* alernativly, since no cache, emit a dummy definition for - idecode_cache so that code refering to the type can still compile */ - lf_printf(file, "typedef void %sidecode_cache;\n", - options.module.global.prefix.l); - } - lf_printf (file, "\n"); -} - - - -static void -print_icache_function (lf *file, - insn_entry *instruction, - opcode_bits *expanded_bits, - insn_opcodes *opcodes, - cache_entry *cache_rules, - int nr_prefetched_words) -{ - int indent; - - /* generate code to enter decoded instruction into the icache */ - lf_printf(file, "\n"); - lf_print__function_type_function (file, print_icache_function_type, - "EXTERN_ICACHE", "\n"); - indent = print_function_name (file, - instruction->name, - instruction->format_name, - NULL, - expanded_bits, - function_name_prefix_icache); - indent += lf_printf (file, " "); - lf_indent (file, +indent); - lf_printf (file, "("); - print_icache_function_formal (file, nr_prefetched_words); - lf_printf (file, ")\n"); - lf_indent (file, -indent); - - /* function header */ - lf_printf (file, "{\n"); - lf_indent (file, +2); - - print_my_defines (file, - instruction->name, - instruction->format_name, - expanded_bits); - print_itrace (file, instruction, 1/*putting-value-in-cache*/); - - print_idecode_validate (file, instruction, opcodes); - - lf_printf (file, "\n"); - lf_printf (file, "{\n"); - lf_indent (file, +2); - if (options.gen.semantic_icache) - lf_printf (file, "unsigned_word nia;\n"); - print_icache_body (file, - instruction, - expanded_bits, - cache_rules, - (options.gen.direct_access - ? define_variables - : declare_variables), - (options.gen.semantic_icache - ? both_values_and_icache - : put_values_in_icache), - nr_prefetched_words); - - lf_printf (file, "\n"); - lf_printf (file, "cache_entry->address = cia;\n"); - lf_printf (file, "cache_entry->semantic = "); - print_function_name (file, - instruction->name, - instruction->format_name, - NULL, - expanded_bits, - function_name_prefix_semantics); - lf_printf (file, ";\n"); - lf_printf (file, "\n"); - - if (options.gen.semantic_icache) { - lf_printf (file, "/* semantic routine */\n"); - print_semantic_body (file, - instruction, - expanded_bits, - opcodes); - lf_printf (file, "return nia;\n"); - } - - if (!options.gen.semantic_icache) - { - lf_printf (file, "/* return the function proper */\n"); - lf_printf (file, "return "); - print_function_name (file, - instruction->name, - instruction->format_name, - NULL, - expanded_bits, - function_name_prefix_semantics); - lf_printf (file, ";\n"); - } - - if (options.gen.direct_access) - { - print_icache_body (file, - instruction, - expanded_bits, - cache_rules, - undef_variables, - (options.gen.semantic_icache - ? both_values_and_icache - : put_values_in_icache), - nr_prefetched_words); - } - - lf_indent (file, -2); - lf_printf (file, "}\n"); - lf_indent (file, -2); - lf_printf (file, "}\n"); -} - - -void -print_icache_definition (lf *file, - insn_entry *insn, - opcode_bits *expanded_bits, - insn_opcodes *opcodes, - cache_entry *cache_rules, - int nr_prefetched_words) -{ - print_icache_function (file, - insn, - expanded_bits, - opcodes, - cache_rules, - nr_prefetched_words); -} - - - -void -print_icache_internal_function_declaration (lf *file, - function_entry *function, - void *data) -{ - ASSERT (options.gen.icache); - if (function->is_internal) - { - lf_printf (file, "\n"); - lf_print__function_type_function (file, print_icache_function_type, - "INLINE_ICACHE", "\n"); - print_function_name (file, - function->name, - NULL, - NULL, - NULL, - function_name_prefix_icache); - lf_printf (file, "\n("); - print_icache_function_formal (file, 0); - lf_printf (file, ");\n"); - } -} - - -void -print_icache_internal_function_definition (lf *file, - function_entry *function, - void *data) -{ - ASSERT (options.gen.icache); - if (function->is_internal) - { - lf_printf (file, "\n"); - lf_print__function_type_function (file, print_icache_function_type, - "INLINE_ICACHE", "\n"); - print_function_name (file, - function->name, - NULL, - NULL, - NULL, - function_name_prefix_icache); - lf_printf (file, "\n("); - print_icache_function_formal (file, 0); - lf_printf (file, ")\n"); - lf_printf (file, "{\n"); - lf_indent (file, +2); - lf_printf (file, "/* semantic routine */\n"); - if (options.gen.semantic_icache) - { - lf_print__line_ref (file, function->code->line); - table_print_code (file, function->code); - lf_printf (file, "error (\"Internal function must longjump\\n\");\n"); - lf_printf (file, "return 0;\n"); - } - else - { - lf_printf (file, "return "); - print_function_name (file, - function->name, - NULL, - NULL, - NULL, - function_name_prefix_semantics); - lf_printf (file, ";\n"); - } - - lf_print__internal_ref (file); - lf_indent (file, -2); - lf_printf (file, "}\n"); - } -} |