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