diff options
Diffstat (limited to 'sim/ppc/gen-icache.c')
-rw-r--r-- | sim/ppc/gen-icache.c | 646 |
1 files changed, 0 insertions, 646 deletions
diff --git a/sim/ppc/gen-icache.c b/sim/ppc/gen-icache.c deleted file mode 100644 index bd585a6..0000000 --- a/sim/ppc/gen-icache.c +++ /dev/null @@ -1,646 +0,0 @@ -/* This file is part of the program psim. - - Copyright (C) 1994-1995, 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 "ld-decode.h" -#include "ld-cache.h" -#include "ld-insn.h" - -#include "igen.h" - -#include "gen-semantics.h" -#include "gen-idecode.h" -#include "gen-icache.h" - - - -static void -print_icache_function_header(lf *file, - const char *basename, - insn_bits *expanded_bits, - int is_function_definition) -{ - lf_printf(file, "\n"); - lf_print_function_type(file, ICACHE_FUNCTION_TYPE, "EXTERN_ICACHE", " "); - print_function_name(file, - basename, - expanded_bits, - function_name_prefix_icache); - lf_printf(file, "\n(%s)", ICACHE_FUNCTION_FORMAL); - if (!is_function_definition) - lf_printf(file, ";"); - lf_printf(file, "\n"); -} - - -void -print_icache_declaration(insn_table *entry, - lf *file, - void *data, - insn *instruction, - int depth) -{ - if (generate_expanded_instructions) { - ASSERT(entry->nr_insn == 1); - print_icache_function_header(file, - entry->insns->file_entry->fields[insn_name], - entry->expanded_bits, - 0/* is not function definition */); - } - else { - print_icache_function_header(file, - instruction->file_entry->fields[insn_name], - NULL, - 0/* is not function definition */); - } -} - - - -static void -print_icache_extraction(lf *file, - insn *instruction, - const char *entry_name, - const char *entry_type, - const char *entry_expression, - const char *original_name, - const char *file_name, - int line_nr, - insn_field *cur_field, - insn_bits *bits, - icache_decl_type what_to_declare, - icache_body_type what_to_do) -{ - ASSERT(entry_name != NULL); - - /* Define a storage area for the cache element */ - if (what_to_declare == undef_variables) { - /* We've finished with the value - destory it */ - lf_indent_suppress(file); - lf_printf(file, "#undef %s\n", entry_name); - return; - } - else if (what_to_declare == define_variables) { - lf_indent_suppress(file); - lf_printf(file, "#define %s ", entry_name); - } - else { - if (file_name != NULL) - lf_print__external_reference(file, line_nr, file_name); - lf_printf(file, "%s const %s UNUSED = ", - entry_type == NULL ? "unsigned" : entry_type, - entry_name); - } - - /* define a value for that storage area as determined by what is in - the cache */ - if (bits != NULL - && strcmp(entry_name, cur_field->val_string) == 0 - && ((bits->opcode->is_boolean && bits->value == 0) - || (!bits->opcode->is_boolean))) { - /* The field has been made constant (as a result of expanding - instructions or similar). Remember that for a boolean field, - value is either 0 (implying the required boolean_constant) or - nonzero (implying some other value) - Define the variable - accordingly */ - ASSERT(bits->field == cur_field); - ASSERT(entry_type == NULL); - if (bits->opcode->is_boolean) - 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 - && bits->opcode->is_boolean - && original_name != NULL - && strncmp(entry_name, - original_name, strlen(original_name)) == 0 - && strncmp(entry_name + strlen(original_name), - "_is_", strlen("_is_")) == 0 - && (atol(entry_name + strlen(original_name) + strlen("_is_")) - == bits->opcode->boolean_constant)) { - /* An entry, derived from ORIGINAL_NAME, is testing to see of the - ORIGINAL_NAME has a specific constant value. That value - matching a boolean bit field */ - lf_printf(file, "%d /* %s == %d */", - bits->value == 0, original_name, bits->opcode->boolean_constant); - } - else { - /* put the field in the local variable, possibly also enter it - into the cache */ - /* 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", - instruction->file_entry->fields[insn_form], - 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 && strcmp(entry_name, cur_field->val_string) == 0) - lf_printf(file, "EXTRACTED32(instruction, %d, %d)", - i2target(hi_bit_nr, cur_field->first), - i2target(hi_bit_nr, cur_field->last)); - else if (entry_expression != NULL) - lf_printf(file, "%s", entry_expression); - else - lf_printf(file, "eval_%s", entry_name); - } - } - - if ((what_to_declare == define_variables) - || (what_to_declare == undef_variables)) - lf_printf(file, "\n"); - else - lf_printf(file, ";\n"); -} - - -void -print_icache_body(lf *file, - insn *instruction, - insn_bits *expanded_bits, - cache_table *cache_rules, - icache_decl_type what_to_declare, - icache_body_type what_to_do) -{ - insn_field *cur_field; - - /* extract instruction fields */ - lf_printf(file, "/* extraction: %s ", - instruction->file_entry->fields[insn_format]); - 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"); - - for (cur_field = instruction->fields->first; - cur_field->first < insn_bit_size; - cur_field = cur_field->next) { - if (cur_field->is_string) { - insn_bits *bits; - int found_rule = 0; - /* find any corresponding value */ - for (bits = expanded_bits; - bits != NULL; - bits = bits->last) { - if (bits->field == cur_field) - break; - } - /* try the cache rule table for what to do */ - { - cache_table *cache_rule; - for (cache_rule = cache_rules; - cache_rule != NULL; - cache_rule = cache_rule->next) { - if (strcmp(cur_field->val_string, cache_rule->field_name) == 0) { - found_rule = 1; - if (cache_rule->type == scratch_value - && ((what_to_do & put_values_in_icache) - || what_to_do == do_not_use_icache)) - print_icache_extraction(file, - instruction, - cache_rule->derived_name, - cache_rule->type_def, - cache_rule->expression, - cache_rule->field_name, - cache_rule->file_entry->file_name, - cache_rule->file_entry->line_nr, - cur_field, - bits, - what_to_declare, - do_not_use_icache); - else if (cache_rule->type == compute_value - && ((what_to_do & get_values_from_icache) - || what_to_do == do_not_use_icache)) - print_icache_extraction(file, - instruction, - cache_rule->derived_name, - cache_rule->type_def, - cache_rule->expression, - cache_rule->field_name, - cache_rule->file_entry->file_name, - cache_rule->file_entry->line_nr, - cur_field, - bits, - what_to_declare, - do_not_use_icache); - else if (cache_rule->type == cache_value - && ((what_to_declare != undef_variables) - || !(what_to_do & put_values_in_icache))) - print_icache_extraction(file, - instruction, - cache_rule->derived_name, - cache_rule->type_def, - cache_rule->expression, - cache_rule->field_name, - cache_rule->file_entry->file_name, - cache_rule->file_entry->line_nr, - cur_field, - bits, - ((what_to_do & put_values_in_icache) - ? declare_variables - : what_to_declare), - what_to_do); - } - } - } - /* No rule at all, assume that it should go into the cache */ - if (found_rule == 0 - && ((what_to_declare != undef_variables) - || !(what_to_do & put_values_in_icache))) - print_icache_extraction(file, - instruction, - cur_field->val_string, - NULL, NULL, NULL, /* type, exp, orig */ - instruction->file_entry->file_name, - instruction->file_entry->line_nr, - cur_field, - bits, - ((what_to_do & put_values_in_icache) - ? declare_variables - : what_to_declare), - what_to_do); - /* any thing else ... */ - } - } - - lf_print__internal_reference(file); - - if ((code & generate_with_insn_in_icache)) { - lf_printf(file, "\n"); - print_icache_extraction(file, - instruction, - "insn", - "instruction_word", - "instruction", - NULL, /* origin */ - NULL, 0, /* file_name & line_nr */ - NULL, NULL, - what_to_declare, - what_to_do); - } -} - - - -typedef struct _icache_tree icache_tree; -struct _icache_tree { - char *name; - icache_tree *next; - icache_tree *children; -}; - -static icache_tree * -icache_tree_insert(icache_tree *tree, - char *name) -{ - icache_tree *new_tree; - /* find it */ - icache_tree **ptr_to_cur_tree = &tree->children; - icache_tree *cur_tree = *ptr_to_cur_tree; - while (cur_tree != NULL - && strcmp(cur_tree->name, name) < 0) { - ptr_to_cur_tree = &cur_tree->next; - cur_tree = *ptr_to_cur_tree; - } - ASSERT(cur_tree == NULL - || strcmp(cur_tree->name, name) >= 0); - /* already in the tree */ - if (cur_tree != NULL - && strcmp(cur_tree->name, name) == 0) - return cur_tree; - /* missing, insert it */ - ASSERT(cur_tree == NULL - || strcmp(cur_tree->name, name) > 0); - new_tree = ZALLOC(icache_tree); - new_tree->name = name; - new_tree->next = cur_tree; - *ptr_to_cur_tree = new_tree; - return new_tree; -} - - -static icache_tree * -insn_table_cache_fields(insn_table *table) -{ - icache_tree *tree = ZALLOC(icache_tree); - insn *instruction; - for (instruction = table->insns; - instruction != NULL; - instruction = instruction->next) { - insn_field *field; - icache_tree *form = - icache_tree_insert(tree, - instruction->file_entry->fields[insn_form]); - for (field = instruction->fields->first; - field != NULL; - field = field->next) { - if (field->is_string) - icache_tree_insert(form, field->val_string); - } - } - return tree; -} - - - -extern void -print_icache_struct(insn_table *instructions, - cache_table *cache_rules, - lf *file) -{ - icache_tree *tree = insn_table_cache_fields(instructions); - - lf_printf(file, "\n"); - lf_printf(file, "#define WITH_IDECODE_CACHE_SIZE %d\n", - (code & generate_with_icache) ? icache_size : 0); - lf_printf(file, "\n"); - - /* create an instruction cache if being used */ - if ((code & generate_with_icache)) { - icache_tree *form; - lf_printf(file, "typedef struct _idecode_cache {\n"); - lf_printf(file, " unsigned_word address;\n"); - lf_printf(file, " void *semantic;\n"); - lf_printf(file, " union {\n"); - for (form = tree->children; - form != NULL; - form = form->next) { - icache_tree *field; - lf_printf(file, " struct {\n"); - if (code & generate_with_insn_in_icache) - lf_printf(file, " instruction_word insn;\n"); - for (field = form->children; - field != NULL; - field = field->next) { - cache_table *cache_rule; - int found_rule = 0; - for (cache_rule = cache_rules; - cache_rule != NULL; - cache_rule = cache_rule->next) { - if (strcmp(field->name, cache_rule->field_name) == 0) { - found_rule = 1; - if (cache_rule->derived_name != NULL) - lf_printf(file, " %s %s; /* %s */\n", - (cache_rule->type_def == NULL - ? "unsigned" - : cache_rule->type_def), - cache_rule->derived_name, - cache_rule->field_name); - } - } - if (!found_rule) - lf_printf(file, " unsigned %s;\n", field->name); - } - lf_printf(file, " } %s;\n", form->name); - } - lf_printf(file, " } crack;\n"); - lf_printf(file, "} idecode_cache;\n"); - } - 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 idecode_cache;\n"); - } - lf_printf(file, "\n"); -} - - - -static void -print_icache_function(lf *file, - insn *instruction, - insn_bits *expanded_bits, - opcode_field *opcodes, - cache_table *cache_rules) -{ - int indent; - - /* generate code to enter decoded instruction into the icache */ - lf_printf(file, "\n"); - lf_print_function_type(file, ICACHE_FUNCTION_TYPE, "EXTERN_ICACHE", "\n"); - indent = print_function_name(file, - instruction->file_entry->fields[insn_name], - expanded_bits, - function_name_prefix_icache); - lf_indent(file, +indent); - lf_printf(file, "(%s)\n", ICACHE_FUNCTION_FORMAL); - lf_indent(file, -indent); - - /* function header */ - lf_printf(file, "{\n"); - lf_indent(file, +2); - - print_my_defines(file, expanded_bits, instruction->file_entry); - print_itrace(file, instruction->file_entry, 1/*putting-value-in-cache*/); - - print_idecode_validate(file, instruction, opcodes); - - lf_printf(file, "\n"); - lf_printf(file, "{\n"); - lf_indent(file, +2); - if ((code & generate_with_semantic_icache)) - lf_printf(file, "unsigned_word nia;\n"); - print_icache_body(file, - instruction, - expanded_bits, - cache_rules, - ((code & generate_with_direct_access) - ? define_variables - : declare_variables), - ((code & generate_with_semantic_icache) - ? both_values_and_icache - : put_values_in_icache)); - - lf_printf(file, "\n"); - lf_printf(file, "cache_entry->address = cia;\n"); - lf_printf(file, "cache_entry->semantic = "); - print_function_name(file, - instruction->file_entry->fields[insn_name], - expanded_bits, - function_name_prefix_semantics); - lf_printf(file, ";\n"); - lf_printf(file, "\n"); - - if ((code & generate_with_semantic_icache)) { - lf_printf(file, "/* semantic routine */\n"); - print_semantic_body(file, - instruction, - expanded_bits, - opcodes); - lf_printf(file, "return nia;\n"); - } - - if (!(code & generate_with_semantic_icache)) { - lf_printf(file, "/* return the function proper */\n"); - lf_printf(file, "return "); - print_function_name(file, - instruction->file_entry->fields[insn_name], - expanded_bits, - function_name_prefix_semantics); - lf_printf(file, ";\n"); - } - - if ((code & generate_with_direct_access)) - print_icache_body(file, - instruction, - expanded_bits, - cache_rules, - undef_variables, - ((code & generate_with_semantic_icache) - ? both_values_and_icache - : put_values_in_icache)); - - lf_indent(file, -2); - lf_printf(file, "}\n"); - lf_indent(file, -2); - lf_printf(file, "}\n"); -} - - -void -print_icache_definition(insn_table *entry, - lf *file, - void *data, - insn *instruction, - int depth) -{ - cache_table *cache_rules = (cache_table*)data; - if (generate_expanded_instructions) { - ASSERT(entry->nr_insn == 1 - && entry->opcode == NULL - && entry->parent != NULL - && entry->parent->opcode != NULL); - ASSERT(entry->nr_insn == 1 - && entry->opcode == NULL - && entry->parent != NULL - && entry->parent->opcode != NULL - && entry->parent->opcode_rule != NULL); - print_icache_function(file, - entry->insns, - entry->expanded_bits, - entry->opcode, - cache_rules); - } - else { - print_icache_function(file, - instruction, - NULL, - NULL, - cache_rules); - } -} - - - -void -print_icache_internal_function_declaration(insn_table *table, - lf *file, - void *data, - table_entry *function) -{ - ASSERT((code & generate_with_icache) != 0); - if (it_is("internal", function->fields[insn_flags])) { - lf_printf(file, "\n"); - lf_print_function_type(file, ICACHE_FUNCTION_TYPE, "INLINE_ICACHE", - "\n"); - print_function_name(file, - function->fields[insn_name], - NULL, - function_name_prefix_icache); - lf_printf(file, "\n(%s);\n", ICACHE_FUNCTION_FORMAL); - } -} - - -void -print_icache_internal_function_definition(insn_table *table, - lf *file, - void *data, - table_entry *function) -{ - ASSERT((code & generate_with_icache) != 0); - if (it_is("internal", function->fields[insn_flags])) { - lf_printf(file, "\n"); - lf_print_function_type(file, ICACHE_FUNCTION_TYPE, "INLINE_ICACHE", - "\n"); - print_function_name(file, - function->fields[insn_name], - NULL, - function_name_prefix_icache); - lf_printf(file, "\n(%s)\n", ICACHE_FUNCTION_FORMAL); - lf_printf(file, "{\n"); - lf_indent(file, +2); - lf_printf(file, "/* semantic routine */\n"); - table_entry_print_cpp_line_nr(file, function); - if ((code & generate_with_semantic_icache)) { - lf_print__c_code(file, function->annex); - 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->fields[insn_name], - NULL, - function_name_prefix_semantics); - lf_printf(file, ";\n"); - } - - lf_print__internal_reference(file); - lf_indent(file, -2); - lf_printf(file, "}\n"); - } -} |