Home | History | Annotate | Line # | Download | only in ppc
gen-icache.c revision 1.1.1.2
      1      1.1  christos /*  This file is part of the program psim.
      2      1.1  christos 
      3      1.1  christos     Copyright (C) 1994-1997, Andrew Cagney <cagney (at) highland.com.au>
      4      1.1  christos 
      5      1.1  christos     This program is free software; you can redistribute it and/or modify
      6      1.1  christos     it under the terms of the GNU General Public License as published by
      7      1.1  christos     the Free Software Foundation; either version 3 of the License, or
      8      1.1  christos     (at your option) any later version.
      9      1.1  christos 
     10      1.1  christos     This program is distributed in the hope that it will be useful,
     11      1.1  christos     but WITHOUT ANY WARRANTY; without even the implied warranty of
     12      1.1  christos     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     13      1.1  christos     GNU General Public License for more details.
     14      1.1  christos 
     15      1.1  christos     You should have received a copy of the GNU General Public License
     16      1.1  christos     along with this program; if not, see <http://www.gnu.org/licenses/>.
     17      1.1  christos 
     18      1.1  christos     */
     19      1.1  christos 
     20  1.1.1.2  christos #include <stdlib.h>
     21      1.1  christos 
     22      1.1  christos #include "misc.h"
     23      1.1  christos #include "lf.h"
     24      1.1  christos #include "table.h"
     25      1.1  christos 
     26      1.1  christos #include "filter.h"
     27      1.1  christos 
     28      1.1  christos #include "ld-decode.h"
     29      1.1  christos #include "ld-cache.h"
     30      1.1  christos #include "ld-insn.h"
     31      1.1  christos 
     32      1.1  christos #include "igen.h"
     33      1.1  christos 
     34      1.1  christos #include "gen-semantics.h"
     35      1.1  christos #include "gen-idecode.h"
     36      1.1  christos #include "gen-icache.h"
     37      1.1  christos 
     38      1.1  christos 
     39      1.1  christos 
     40      1.1  christos static void
     41      1.1  christos print_icache_function_header(lf *file,
     42      1.1  christos 			     const char *basename,
     43      1.1  christos 			     insn_bits *expanded_bits,
     44      1.1  christos 			     int is_function_definition)
     45      1.1  christos {
     46      1.1  christos   lf_printf(file, "\n");
     47      1.1  christos   lf_print_function_type(file, ICACHE_FUNCTION_TYPE, "EXTERN_ICACHE", " ");
     48      1.1  christos   print_function_name(file,
     49      1.1  christos 		      basename,
     50      1.1  christos 		      expanded_bits,
     51      1.1  christos 		      function_name_prefix_icache);
     52      1.1  christos   lf_printf(file, "\n(%s)", ICACHE_FUNCTION_FORMAL);
     53      1.1  christos   if (!is_function_definition)
     54      1.1  christos     lf_printf(file, ";");
     55      1.1  christos   lf_printf(file, "\n");
     56      1.1  christos }
     57      1.1  christos 
     58      1.1  christos 
     59      1.1  christos void
     60      1.1  christos print_icache_declaration(insn_table *entry,
     61      1.1  christos 			 lf *file,
     62      1.1  christos 			 void *data,
     63      1.1  christos 			 insn *instruction,
     64      1.1  christos 			 int depth)
     65      1.1  christos {
     66      1.1  christos   if (generate_expanded_instructions) {
     67      1.1  christos     ASSERT(entry->nr_insn == 1);
     68      1.1  christos     print_icache_function_header(file,
     69      1.1  christos 				 entry->insns->file_entry->fields[insn_name],
     70      1.1  christos 				 entry->expanded_bits,
     71      1.1  christos 				 0/* is not function definition */);
     72      1.1  christos   }
     73      1.1  christos   else {
     74      1.1  christos     print_icache_function_header(file,
     75      1.1  christos 				 instruction->file_entry->fields[insn_name],
     76      1.1  christos 				 NULL,
     77      1.1  christos 				 0/* is not function definition */);
     78      1.1  christos   }
     79      1.1  christos }
     80      1.1  christos 
     81      1.1  christos 
     82      1.1  christos 
     83      1.1  christos static void
     84      1.1  christos print_icache_extraction(lf *file,
     85      1.1  christos 			insn *instruction,
     86      1.1  christos 			const char *entry_name,
     87      1.1  christos 			const char *entry_type,
     88      1.1  christos 			const char *entry_expression,
     89      1.1  christos 			const char *original_name,
     90      1.1  christos 			const char *file_name,
     91      1.1  christos 			int line_nr,
     92      1.1  christos 			insn_field *cur_field,
     93      1.1  christos 			insn_bits *bits,
     94      1.1  christos 			icache_decl_type what_to_declare,
     95      1.1  christos 			icache_body_type what_to_do,
     96      1.1  christos 			const char *reason)
     97      1.1  christos {
     98      1.1  christos   const char *expression;
     99      1.1  christos   ASSERT(entry_name != NULL);
    100      1.1  christos 
    101      1.1  christos   /* Define a storage area for the cache element */
    102      1.1  christos   if (what_to_declare == undef_variables) {
    103      1.1  christos     /* We've finished with the value - destory it */
    104      1.1  christos     lf_indent_suppress(file);
    105      1.1  christos     lf_printf(file, "#undef %s\n", entry_name);
    106      1.1  christos     return;
    107      1.1  christos   }
    108      1.1  christos   else if (what_to_declare == define_variables) {
    109      1.1  christos     lf_indent_suppress(file);
    110      1.1  christos     lf_printf(file, "#define %s ", entry_name);
    111      1.1  christos   }
    112      1.1  christos   else {
    113      1.1  christos     if (file_name != NULL)
    114      1.1  christos       lf_print__external_reference(file, line_nr, file_name);
    115  1.1.1.2  christos     lf_printf(file, "%s const %s ATTRIBUTE_UNUSED = ",
    116      1.1  christos 	      entry_type == NULL ? "unsigned" : entry_type,
    117      1.1  christos 	      entry_name);
    118      1.1  christos   }
    119      1.1  christos 
    120      1.1  christos   /* define a value for that storage area as determined by what is in
    121      1.1  christos      the cache */
    122      1.1  christos   if (bits != NULL
    123      1.1  christos       && strcmp(entry_name, cur_field->val_string) == 0
    124      1.1  christos       && ((bits->opcode->is_boolean && bits->value == 0)
    125      1.1  christos 	  || (!bits->opcode->is_boolean))) {
    126      1.1  christos     /* The simple field has been made constant (as a result of
    127      1.1  christos        expanding instructions or similar).  Remember that for a
    128      1.1  christos        boolean field, value is either 0 (implying the required
    129      1.1  christos        boolean_constant) or nonzero (implying some other value and
    130      1.1  christos        handled later below) - Define the variable accordingly */
    131      1.1  christos     expression = "constant field";
    132      1.1  christos     ASSERT(bits->field == cur_field);
    133      1.1  christos     ASSERT(entry_type == NULL);
    134      1.1  christos     if (bits->opcode->is_boolean)
    135      1.1  christos       lf_printf(file, "%d", bits->opcode->boolean_constant);
    136      1.1  christos     else if (bits->opcode->last < bits->field->last)
    137      1.1  christos       lf_printf(file, "%d",
    138      1.1  christos 		bits->value << (bits->field->last - bits->opcode->last));
    139      1.1  christos     else
    140      1.1  christos       lf_printf(file, "%d", bits->value);
    141      1.1  christos   }
    142      1.1  christos   else if (bits != NULL
    143      1.1  christos 	   && original_name != NULL
    144      1.1  christos 	   && strncmp(entry_name,
    145      1.1  christos 		      original_name, strlen(original_name)) == 0
    146      1.1  christos 	   && strncmp(entry_name + strlen(original_name),
    147      1.1  christos 		      "_is_", strlen("_is_")) == 0
    148      1.1  christos 	   && ((bits->opcode->is_boolean
    149      1.1  christos 		&& (atol(entry_name + strlen(original_name) + strlen("_is_"))
    150      1.1  christos 		    == bits->opcode->boolean_constant))
    151      1.1  christos 	       || (!bits->opcode->is_boolean))) {
    152      1.1  christos     expression = "constant compare";
    153      1.1  christos     /* An entry, derived from ORIGINAL_NAME, is testing to see of the
    154      1.1  christos        ORIGINAL_NAME has a specific constant value.  That value
    155      1.1  christos        matching a boolean or constant field */
    156      1.1  christos     if (bits->opcode->is_boolean)
    157      1.1  christos       lf_printf(file, "%d /* %s == %d */",
    158      1.1  christos 		bits->value == 0,
    159      1.1  christos 		original_name,
    160      1.1  christos 		bits->opcode->boolean_constant);
    161      1.1  christos     else if (bits->opcode->last < bits->field->last)
    162      1.1  christos       lf_printf(file, "%d /* %s == %d */",
    163      1.1  christos 		(atol(entry_name + strlen(original_name) + strlen("_is_"))
    164      1.1  christos 		 == (bits->value << (bits->field->last - bits->opcode->last))),
    165      1.1  christos 		original_name,
    166      1.1  christos 		(bits->value << (bits->field->last - bits->opcode->last)));
    167      1.1  christos     else
    168      1.1  christos       lf_printf(file, "%d /* %s == %d */",
    169      1.1  christos 		(atol(entry_name + strlen(original_name) + strlen("_is_"))
    170      1.1  christos 		 == bits->value),
    171      1.1  christos 		original_name,
    172      1.1  christos 		bits->value);
    173      1.1  christos   }
    174      1.1  christos   else {
    175      1.1  christos     /* put the field in the local variable, possibly also enter it
    176      1.1  christos        into the cache */
    177      1.1  christos     expression = "extraction";
    178      1.1  christos     /* handle the cache */
    179      1.1  christos     if ((what_to_do & get_values_from_icache)
    180      1.1  christos 	|| (what_to_do & put_values_in_icache)) {
    181      1.1  christos       lf_printf(file, "cache_entry->crack.%s.%s",
    182      1.1  christos 		instruction->file_entry->fields[insn_form],
    183      1.1  christos 		entry_name);
    184      1.1  christos       if (what_to_do & put_values_in_icache) /* also put it in the cache? */
    185      1.1  christos 	lf_printf(file, " = ");
    186      1.1  christos     }
    187      1.1  christos     if ((what_to_do & put_values_in_icache)
    188      1.1  christos 	|| what_to_do == do_not_use_icache) {
    189      1.1  christos       if (cur_field != NULL && strcmp(entry_name, cur_field->val_string) == 0)
    190      1.1  christos 	lf_printf(file, "EXTRACTED32(instruction, %d, %d)",
    191      1.1  christos 		  i2target(hi_bit_nr, cur_field->first),
    192      1.1  christos 		  i2target(hi_bit_nr, cur_field->last));
    193      1.1  christos       else if (entry_expression != NULL)
    194      1.1  christos 	lf_printf(file, "%s", entry_expression);
    195      1.1  christos       else
    196      1.1  christos 	lf_printf(file, "eval_%s", entry_name);
    197      1.1  christos     }
    198      1.1  christos   }
    199      1.1  christos 
    200      1.1  christos   if (!((what_to_declare == define_variables)
    201      1.1  christos 	|| (what_to_declare == undef_variables)))
    202      1.1  christos     lf_printf(file, ";");
    203      1.1  christos   if (reason != NULL)
    204      1.1  christos     lf_printf(file, " /* %s - %s */", reason, expression);
    205      1.1  christos   lf_printf(file, "\n");
    206      1.1  christos }
    207      1.1  christos 
    208      1.1  christos 
    209      1.1  christos void
    210      1.1  christos print_icache_body(lf *file,
    211      1.1  christos 		  insn *instruction,
    212      1.1  christos 		  insn_bits *expanded_bits,
    213      1.1  christos 		  cache_table *cache_rules,
    214      1.1  christos 		  icache_decl_type what_to_declare,
    215      1.1  christos 		  icache_body_type what_to_do)
    216      1.1  christos {
    217      1.1  christos   insn_field *cur_field;
    218      1.1  christos 
    219      1.1  christos   /* extract instruction fields */
    220      1.1  christos   lf_printf(file, "/* extraction: %s ",
    221      1.1  christos 	    instruction->file_entry->fields[insn_format]);
    222      1.1  christos   switch (what_to_declare) {
    223      1.1  christos   case define_variables:
    224      1.1  christos     lf_printf(file, "#define");
    225      1.1  christos     break;
    226      1.1  christos   case declare_variables:
    227      1.1  christos     lf_printf(file, "declare");
    228      1.1  christos     break;
    229      1.1  christos   case undef_variables:
    230      1.1  christos     lf_printf(file, "#undef");
    231      1.1  christos     break;
    232      1.1  christos   }
    233      1.1  christos   lf_printf(file, " ");
    234      1.1  christos   switch (what_to_do) {
    235      1.1  christos   case get_values_from_icache:
    236      1.1  christos     lf_printf(file, "get-values-from-icache");
    237      1.1  christos     break;
    238      1.1  christos   case put_values_in_icache:
    239      1.1  christos     lf_printf(file, "put-values-in-icache");
    240      1.1  christos     break;
    241      1.1  christos   case both_values_and_icache:
    242      1.1  christos     lf_printf(file, "get-values-from-icache|put-values-in-icache");
    243      1.1  christos     break;
    244      1.1  christos   case do_not_use_icache:
    245      1.1  christos     lf_printf(file, "do-not-use-icache");
    246      1.1  christos     break;
    247      1.1  christos   }
    248      1.1  christos   lf_printf(file, " */\n");
    249      1.1  christos 
    250      1.1  christos   for (cur_field = instruction->fields->first;
    251      1.1  christos        cur_field->first < insn_bit_size;
    252      1.1  christos        cur_field = cur_field->next) {
    253      1.1  christos     if (cur_field->is_string) {
    254      1.1  christos       insn_bits *bits;
    255      1.1  christos       int found_rule = 0;
    256      1.1  christos       /* find any corresponding value */
    257      1.1  christos       for (bits = expanded_bits;
    258      1.1  christos 	   bits != NULL;
    259      1.1  christos 	   bits = bits->last) {
    260      1.1  christos 	if (bits->field == cur_field)
    261      1.1  christos 	  break;
    262      1.1  christos       }
    263      1.1  christos       /* try the cache rule table for what to do */
    264      1.1  christos       {
    265      1.1  christos 	cache_table *cache_rule;
    266      1.1  christos 	for (cache_rule = cache_rules;
    267      1.1  christos 	     cache_rule != NULL;
    268      1.1  christos 	     cache_rule = cache_rule->next) {
    269      1.1  christos 	  if (strcmp(cur_field->val_string, cache_rule->field_name) == 0) {
    270      1.1  christos 	    found_rule = 1;
    271      1.1  christos 	    if (cache_rule->type == scratch_value
    272      1.1  christos 		&& ((what_to_do & put_values_in_icache)
    273      1.1  christos 		    || what_to_do == do_not_use_icache))
    274      1.1  christos 	      print_icache_extraction(file,
    275      1.1  christos 				      instruction,
    276      1.1  christos 				      cache_rule->derived_name,
    277      1.1  christos 				      cache_rule->type_def,
    278      1.1  christos 				      cache_rule->expression,
    279      1.1  christos 				      cache_rule->field_name,
    280      1.1  christos 				      cache_rule->file_entry->file_name,
    281      1.1  christos 				      cache_rule->file_entry->line_nr,
    282      1.1  christos 				      cur_field,
    283      1.1  christos 				      bits,
    284      1.1  christos 				      what_to_declare,
    285      1.1  christos 				      do_not_use_icache,
    286      1.1  christos 				      "icache scratch");
    287      1.1  christos 	    else if (cache_rule->type == compute_value
    288      1.1  christos 		     && ((what_to_do & get_values_from_icache)
    289      1.1  christos 			 || what_to_do == do_not_use_icache))
    290      1.1  christos 	      print_icache_extraction(file,
    291      1.1  christos 				      instruction,
    292      1.1  christos 				      cache_rule->derived_name,
    293      1.1  christos 				      cache_rule->type_def,
    294      1.1  christos 				      cache_rule->expression,
    295      1.1  christos 				      cache_rule->field_name,
    296      1.1  christos 				      cache_rule->file_entry->file_name,
    297      1.1  christos 				      cache_rule->file_entry->line_nr,
    298      1.1  christos 				      cur_field,
    299      1.1  christos 				      bits,
    300      1.1  christos 				      what_to_declare,
    301      1.1  christos 				      do_not_use_icache,
    302      1.1  christos 				      "semantic compute");
    303      1.1  christos 	    else if (cache_rule->type == cache_value
    304      1.1  christos 		     && ((what_to_declare != undef_variables)
    305      1.1  christos 			 || !(what_to_do & put_values_in_icache)))
    306      1.1  christos 	      print_icache_extraction(file,
    307      1.1  christos 				      instruction,
    308      1.1  christos 				      cache_rule->derived_name,
    309      1.1  christos 				      cache_rule->type_def,
    310      1.1  christos 				      cache_rule->expression,
    311      1.1  christos 				      cache_rule->field_name,
    312      1.1  christos 				      cache_rule->file_entry->file_name,
    313      1.1  christos 				      cache_rule->file_entry->line_nr,
    314      1.1  christos 				      cur_field,
    315      1.1  christos 				      bits,
    316      1.1  christos 				      ((what_to_do & put_values_in_icache)
    317      1.1  christos 				       ? declare_variables
    318      1.1  christos 				       : what_to_declare),
    319      1.1  christos 				      what_to_do,
    320      1.1  christos 				      "in icache");
    321      1.1  christos 	  }
    322      1.1  christos 	}
    323      1.1  christos       }
    324      1.1  christos       /* No rule at all, assume that this is needed in the semantic
    325      1.1  christos          function (when values are extracted from the icache) and
    326      1.1  christos          hence must be put into the cache */
    327      1.1  christos       if (found_rule == 0
    328      1.1  christos 	  && ((what_to_declare != undef_variables)
    329      1.1  christos 	      || !(what_to_do & put_values_in_icache)))
    330      1.1  christos 	print_icache_extraction(file,
    331      1.1  christos 				instruction,
    332      1.1  christos 				cur_field->val_string,
    333      1.1  christos 				NULL, NULL, NULL, /* type, exp, orig */
    334      1.1  christos 				instruction->file_entry->file_name,
    335      1.1  christos 				instruction->file_entry->line_nr,
    336      1.1  christos 				cur_field,
    337      1.1  christos 				bits,
    338      1.1  christos 				((what_to_do & put_values_in_icache)
    339      1.1  christos 				 ? declare_variables
    340      1.1  christos 				 : what_to_declare),
    341      1.1  christos 				what_to_do,
    342      1.1  christos 				"default in icache");
    343      1.1  christos       /* any thing else ... */
    344      1.1  christos     }
    345      1.1  christos   }
    346      1.1  christos 
    347      1.1  christos   lf_print__internal_reference(file);
    348      1.1  christos 
    349      1.1  christos   if ((code & generate_with_insn_in_icache)) {
    350      1.1  christos     lf_printf(file, "\n");
    351      1.1  christos     print_icache_extraction(file,
    352      1.1  christos 			    instruction,
    353      1.1  christos 			    "insn",
    354      1.1  christos 			    "instruction_word",
    355      1.1  christos 			    "instruction",
    356      1.1  christos 			    NULL, /* origin */
    357      1.1  christos 			    NULL, 0, /* file_name & line_nr */
    358      1.1  christos 			    NULL, NULL,
    359      1.1  christos 			    what_to_declare,
    360      1.1  christos 			    what_to_do,
    361      1.1  christos 			    NULL);
    362      1.1  christos   }
    363      1.1  christos }
    364      1.1  christos 
    365      1.1  christos 
    366      1.1  christos 
    367      1.1  christos typedef struct _icache_tree icache_tree;
    368      1.1  christos struct _icache_tree {
    369  1.1.1.2  christos   const char *name;
    370      1.1  christos   icache_tree *next;
    371      1.1  christos   icache_tree *children;
    372      1.1  christos };
    373      1.1  christos 
    374      1.1  christos static icache_tree *
    375      1.1  christos icache_tree_insert(icache_tree *tree,
    376  1.1.1.2  christos 		   const char *name)
    377      1.1  christos {
    378      1.1  christos   icache_tree *new_tree;
    379      1.1  christos   /* find it */
    380      1.1  christos   icache_tree **ptr_to_cur_tree = &tree->children;
    381      1.1  christos   icache_tree *cur_tree = *ptr_to_cur_tree;
    382      1.1  christos   while (cur_tree != NULL
    383      1.1  christos 	 && strcmp(cur_tree->name, name) < 0) {
    384      1.1  christos     ptr_to_cur_tree = &cur_tree->next;
    385      1.1  christos     cur_tree = *ptr_to_cur_tree;
    386      1.1  christos   }
    387      1.1  christos   ASSERT(cur_tree == NULL
    388      1.1  christos 	 || strcmp(cur_tree->name, name) >= 0);
    389      1.1  christos   /* already in the tree */
    390      1.1  christos   if (cur_tree != NULL
    391      1.1  christos       && strcmp(cur_tree->name, name) == 0)
    392      1.1  christos     return cur_tree;
    393      1.1  christos   /* missing, insert it */
    394      1.1  christos   ASSERT(cur_tree == NULL
    395      1.1  christos 	 || strcmp(cur_tree->name, name) > 0);
    396      1.1  christos   new_tree = ZALLOC(icache_tree);
    397      1.1  christos   new_tree->name = name;
    398      1.1  christos   new_tree->next = cur_tree;
    399      1.1  christos   *ptr_to_cur_tree = new_tree;
    400      1.1  christos   return new_tree;
    401      1.1  christos }
    402      1.1  christos 
    403      1.1  christos 
    404      1.1  christos static icache_tree *
    405      1.1  christos insn_table_cache_fields(insn_table *table)
    406      1.1  christos {
    407      1.1  christos   icache_tree *tree = ZALLOC(icache_tree);
    408      1.1  christos   insn *instruction;
    409      1.1  christos   for (instruction = table->insns;
    410      1.1  christos        instruction != NULL;
    411      1.1  christos        instruction = instruction->next) {
    412      1.1  christos     insn_field *field;
    413      1.1  christos     icache_tree *form =
    414      1.1  christos       icache_tree_insert(tree,
    415      1.1  christos 			 instruction->file_entry->fields[insn_form]);
    416      1.1  christos     for (field = instruction->fields->first;
    417      1.1  christos 	 field != NULL;
    418      1.1  christos 	 field = field->next) {
    419      1.1  christos       if (field->is_string)
    420      1.1  christos 	icache_tree_insert(form, field->val_string);
    421      1.1  christos     }
    422      1.1  christos   }
    423      1.1  christos   return tree;
    424      1.1  christos }
    425      1.1  christos 
    426      1.1  christos 
    427      1.1  christos 
    428      1.1  christos extern void
    429      1.1  christos print_icache_struct(insn_table *instructions,
    430      1.1  christos 		    cache_table *cache_rules,
    431      1.1  christos 		    lf *file)
    432      1.1  christos {
    433      1.1  christos   icache_tree *tree = insn_table_cache_fields(instructions);
    434      1.1  christos 
    435      1.1  christos   lf_printf(file, "\n");
    436      1.1  christos   lf_printf(file, "#define WITH_IDECODE_CACHE_SIZE %d\n",
    437      1.1  christos 	    (code & generate_with_icache) ? icache_size : 0);
    438      1.1  christos   lf_printf(file, "\n");
    439      1.1  christos 
    440      1.1  christos   /* create an instruction cache if being used */
    441      1.1  christos   if ((code & generate_with_icache)) {
    442      1.1  christos     icache_tree *form;
    443      1.1  christos     lf_printf(file, "typedef struct _idecode_cache {\n");
    444      1.1  christos     lf_printf(file, "  unsigned_word address;\n");
    445      1.1  christos     lf_printf(file, "  void *semantic;\n");
    446      1.1  christos     lf_printf(file, "  union {\n");
    447      1.1  christos     for (form = tree->children;
    448      1.1  christos 	 form != NULL;
    449      1.1  christos 	 form = form->next) {
    450      1.1  christos       icache_tree *field;
    451      1.1  christos       lf_printf(file, "    struct {\n");
    452      1.1  christos       if (code & generate_with_insn_in_icache)
    453      1.1  christos 	lf_printf(file, "      instruction_word insn;\n");
    454      1.1  christos       for (field = form->children;
    455      1.1  christos 	   field != NULL;
    456      1.1  christos 	   field = field->next) {
    457      1.1  christos 	cache_table *cache_rule;
    458      1.1  christos 	int found_rule = 0;
    459      1.1  christos 	for (cache_rule = cache_rules;
    460      1.1  christos 	     cache_rule != NULL;
    461      1.1  christos 	     cache_rule = cache_rule->next) {
    462      1.1  christos 	  if (strcmp(field->name, cache_rule->field_name) == 0) {
    463      1.1  christos 	    found_rule = 1;
    464      1.1  christos 	    if (cache_rule->derived_name != NULL)
    465      1.1  christos 	      lf_printf(file, "      %s %s; /* %s */\n",
    466      1.1  christos 			(cache_rule->type_def == NULL
    467      1.1  christos 			 ? "unsigned"
    468      1.1  christos 			 : cache_rule->type_def),
    469      1.1  christos 			cache_rule->derived_name,
    470      1.1  christos 			cache_rule->field_name);
    471      1.1  christos 	  }
    472      1.1  christos 	}
    473      1.1  christos 	if (!found_rule)
    474      1.1  christos 	  lf_printf(file, "      unsigned %s;\n", field->name);
    475      1.1  christos       }
    476      1.1  christos       lf_printf(file, "    } %s;\n", form->name);
    477      1.1  christos     }
    478      1.1  christos     lf_printf(file, "  } crack;\n");
    479      1.1  christos     lf_printf(file, "} idecode_cache;\n");
    480      1.1  christos   }
    481      1.1  christos   else {
    482      1.1  christos     /* alernativly, since no cache, emit a dummy definition for
    483      1.1  christos        idecode_cache so that code refering to the type can still compile */
    484      1.1  christos     lf_printf(file, "typedef void idecode_cache;\n");
    485      1.1  christos   }
    486      1.1  christos   lf_printf(file, "\n");
    487      1.1  christos }
    488      1.1  christos 
    489      1.1  christos 
    490      1.1  christos 
    491      1.1  christos static void
    492      1.1  christos print_icache_function(lf *file,
    493      1.1  christos 		      insn *instruction,
    494      1.1  christos 		      insn_bits *expanded_bits,
    495      1.1  christos 		      opcode_field *opcodes,
    496      1.1  christos 		      cache_table *cache_rules)
    497      1.1  christos {
    498      1.1  christos   int indent;
    499      1.1  christos 
    500      1.1  christos   /* generate code to enter decoded instruction into the icache */
    501      1.1  christos   lf_printf(file, "\n");
    502      1.1  christos   lf_print_function_type(file, ICACHE_FUNCTION_TYPE, "EXTERN_ICACHE", "\n");
    503      1.1  christos   indent = print_function_name(file,
    504      1.1  christos 			       instruction->file_entry->fields[insn_name],
    505      1.1  christos 			       expanded_bits,
    506      1.1  christos 			       function_name_prefix_icache);
    507      1.1  christos   lf_indent(file, +indent);
    508      1.1  christos   lf_printf(file, "(%s)\n", ICACHE_FUNCTION_FORMAL);
    509      1.1  christos   lf_indent(file, -indent);
    510      1.1  christos 
    511      1.1  christos   /* function header */
    512      1.1  christos   lf_printf(file, "{\n");
    513      1.1  christos   lf_indent(file, +2);
    514      1.1  christos 
    515      1.1  christos   print_my_defines(file, expanded_bits, instruction->file_entry);
    516      1.1  christos   print_itrace(file, instruction->file_entry, 1/*putting-value-in-cache*/);
    517      1.1  christos 
    518      1.1  christos   print_idecode_validate(file, instruction, opcodes);
    519      1.1  christos 
    520      1.1  christos   lf_printf(file, "\n");
    521      1.1  christos   lf_printf(file, "{\n");
    522      1.1  christos   lf_indent(file, +2);
    523      1.1  christos   if ((code & generate_with_semantic_icache))
    524      1.1  christos     lf_printf(file, "unsigned_word nia;\n");
    525      1.1  christos   print_icache_body(file,
    526      1.1  christos 		    instruction,
    527      1.1  christos 		    expanded_bits,
    528      1.1  christos 		    cache_rules,
    529      1.1  christos 		    ((code & generate_with_direct_access)
    530      1.1  christos 		     ? define_variables
    531      1.1  christos 		     : declare_variables),
    532      1.1  christos 		    ((code & generate_with_semantic_icache)
    533      1.1  christos 		     ? both_values_and_icache
    534      1.1  christos 		     : put_values_in_icache));
    535      1.1  christos 
    536      1.1  christos   lf_printf(file, "\n");
    537      1.1  christos   lf_printf(file, "cache_entry->address = cia;\n");
    538      1.1  christos   lf_printf(file, "cache_entry->semantic = ");
    539      1.1  christos   print_function_name(file,
    540      1.1  christos 		      instruction->file_entry->fields[insn_name],
    541      1.1  christos 		      expanded_bits,
    542      1.1  christos 		      function_name_prefix_semantics);
    543      1.1  christos   lf_printf(file, ";\n");
    544      1.1  christos   lf_printf(file, "\n");
    545      1.1  christos 
    546      1.1  christos   if ((code & generate_with_semantic_icache)) {
    547      1.1  christos     lf_printf(file, "/* semantic routine */\n");
    548      1.1  christos     print_semantic_body(file,
    549      1.1  christos 			instruction,
    550      1.1  christos 			expanded_bits,
    551      1.1  christos 			opcodes);
    552      1.1  christos     lf_printf(file, "return nia;\n");
    553      1.1  christos   }
    554      1.1  christos 
    555      1.1  christos   if (!(code & generate_with_semantic_icache)) {
    556      1.1  christos     lf_printf(file, "/* return the function proper */\n");
    557      1.1  christos     lf_printf(file, "return ");
    558      1.1  christos     print_function_name(file,
    559      1.1  christos 			instruction->file_entry->fields[insn_name],
    560      1.1  christos 			expanded_bits,
    561      1.1  christos 			function_name_prefix_semantics);
    562      1.1  christos     lf_printf(file, ";\n");
    563      1.1  christos   }
    564      1.1  christos 
    565      1.1  christos   if ((code & generate_with_direct_access))
    566      1.1  christos     print_icache_body(file,
    567      1.1  christos 		      instruction,
    568      1.1  christos 		      expanded_bits,
    569      1.1  christos 		      cache_rules,
    570      1.1  christos 		      undef_variables,
    571      1.1  christos 		      ((code & generate_with_semantic_icache)
    572      1.1  christos 		       ? both_values_and_icache
    573      1.1  christos 		       : put_values_in_icache));
    574      1.1  christos 
    575      1.1  christos   lf_indent(file, -2);
    576      1.1  christos   lf_printf(file, "}\n");
    577      1.1  christos   lf_indent(file, -2);
    578      1.1  christos   lf_printf(file, "}\n");
    579      1.1  christos }
    580      1.1  christos 
    581      1.1  christos 
    582      1.1  christos void
    583      1.1  christos print_icache_definition(insn_table *entry,
    584      1.1  christos 			lf *file,
    585      1.1  christos 			void *data,
    586      1.1  christos 			insn *instruction,
    587      1.1  christos 			int depth)
    588      1.1  christos {
    589      1.1  christos   cache_table *cache_rules = (cache_table*)data;
    590      1.1  christos   if (generate_expanded_instructions) {
    591      1.1  christos     ASSERT(entry->nr_insn == 1
    592      1.1  christos 	   && entry->opcode == NULL
    593      1.1  christos 	   && entry->parent != NULL
    594      1.1  christos 	   && entry->parent->opcode != NULL);
    595      1.1  christos     ASSERT(entry->nr_insn == 1
    596      1.1  christos 	   && entry->opcode == NULL
    597      1.1  christos 	   && entry->parent != NULL
    598      1.1  christos 	   && entry->parent->opcode != NULL
    599      1.1  christos 	   && entry->parent->opcode_rule != NULL);
    600      1.1  christos     print_icache_function(file,
    601      1.1  christos 			  entry->insns,
    602      1.1  christos 			  entry->expanded_bits,
    603      1.1  christos 			  entry->opcode,
    604      1.1  christos 			  cache_rules);
    605      1.1  christos   }
    606      1.1  christos   else {
    607      1.1  christos     print_icache_function(file,
    608      1.1  christos 			  instruction,
    609      1.1  christos 			  NULL,
    610      1.1  christos 			  NULL,
    611      1.1  christos 			  cache_rules);
    612      1.1  christos   }
    613      1.1  christos }
    614      1.1  christos 
    615      1.1  christos 
    616      1.1  christos 
    617      1.1  christos void
    618      1.1  christos print_icache_internal_function_declaration(insn_table *table,
    619      1.1  christos 					   lf *file,
    620      1.1  christos 					   void *data,
    621      1.1  christos 					   table_entry *function)
    622      1.1  christos {
    623      1.1  christos   ASSERT((code & generate_with_icache) != 0);
    624      1.1  christos   if (it_is("internal", function->fields[insn_flags])) {
    625      1.1  christos     lf_printf(file, "\n");
    626      1.1  christos     lf_print_function_type(file, ICACHE_FUNCTION_TYPE, "PSIM_INLINE_ICACHE",
    627      1.1  christos 			   "\n");
    628      1.1  christos     print_function_name(file,
    629      1.1  christos 			function->fields[insn_name],
    630      1.1  christos 			NULL,
    631      1.1  christos 			function_name_prefix_icache);
    632      1.1  christos     lf_printf(file, "\n(%s);\n", ICACHE_FUNCTION_FORMAL);
    633      1.1  christos   }
    634      1.1  christos }
    635      1.1  christos 
    636      1.1  christos 
    637      1.1  christos void
    638      1.1  christos print_icache_internal_function_definition(insn_table *table,
    639      1.1  christos 					  lf *file,
    640      1.1  christos 					  void *data,
    641      1.1  christos 					  table_entry *function)
    642      1.1  christos {
    643      1.1  christos   ASSERT((code & generate_with_icache) != 0);
    644      1.1  christos   if (it_is("internal", function->fields[insn_flags])) {
    645      1.1  christos     lf_printf(file, "\n");
    646      1.1  christos     lf_print_function_type(file, ICACHE_FUNCTION_TYPE, "PSIM_INLINE_ICACHE",
    647      1.1  christos 			   "\n");
    648      1.1  christos     print_function_name(file,
    649      1.1  christos 			function->fields[insn_name],
    650      1.1  christos 			NULL,
    651      1.1  christos 			function_name_prefix_icache);
    652      1.1  christos     lf_printf(file, "\n(%s)\n", ICACHE_FUNCTION_FORMAL);
    653      1.1  christos     lf_printf(file, "{\n");
    654      1.1  christos     lf_indent(file, +2);
    655      1.1  christos     lf_printf(file, "/* semantic routine */\n");
    656      1.1  christos     table_entry_print_cpp_line_nr(file, function);
    657      1.1  christos     if ((code & generate_with_semantic_icache)) {
    658      1.1  christos       lf_print__c_code(file, function->annex);
    659      1.1  christos       lf_printf(file, "error(\"Internal function must longjump\\n\");\n");
    660      1.1  christos       lf_printf(file, "return 0;\n");
    661      1.1  christos     }
    662      1.1  christos     else {
    663      1.1  christos       lf_printf(file, "return ");
    664      1.1  christos       print_function_name(file,
    665      1.1  christos 			  function->fields[insn_name],
    666      1.1  christos 			  NULL,
    667      1.1  christos 			  function_name_prefix_semantics);
    668      1.1  christos       lf_printf(file, ";\n");
    669      1.1  christos     }
    670      1.1  christos 
    671      1.1  christos     lf_print__internal_reference(file);
    672      1.1  christos     lf_indent(file, -2);
    673      1.1  christos     lf_printf(file, "}\n");
    674      1.1  christos   }
    675      1.1  christos }
    676