summaryrefslogtreecommitdiff
path: root/sim/igen/gen-icache.c
diff options
context:
space:
mode:
Diffstat (limited to 'sim/igen/gen-icache.c')
-rw-r--r--sim/igen/gen-icache.c859
1 files changed, 0 insertions, 859 deletions
diff --git a/sim/igen/gen-icache.c b/sim/igen/gen-icache.c
deleted file mode 100644
index 88d5d412288..00000000000
--- a/sim/igen/gen-icache.c
+++ /dev/null
@@ -1,859 +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, 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);
-}
-
-
-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");
- }
-}