xref: /netbsd-src/external/gpl3/gdb/dist/sim/igen/gen-icache.c (revision 71f621822dbfd5073a314948bec169b7bb05f7be)
1 /* The IGEN simulator generator for GDB, the GNU Debugger.
2 
3    Copyright 2002-2024 Free Software Foundation, Inc.
4 
5    Contributed by Andrew Cagney.
6 
7    This file is part of GDB.
8 
9    This program is free software; you can redistribute it and/or modify
10    it under the terms of the GNU General Public License as published by
11    the Free Software Foundation; either version 3 of the License, or
12    (at your option) any later version.
13 
14    This program is distributed in the hope that it will be useful,
15    but WITHOUT ANY WARRANTY; without even the implied warranty of
16    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17    GNU General Public License for more details.
18 
19    You should have received a copy of the GNU General Public License
20    along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
21 
22 #include <stdlib.h>
23 
24 #include "misc.h"
25 #include "lf.h"
26 #include "table.h"
27 #include "filter.h"
28 #include "igen.h"
29 
30 #include "ld-insn.h"
31 #include "ld-decode.h"
32 
33 #include "gen.h"
34 
35 #include "gen-semantics.h"
36 #include "gen-idecode.h"
37 #include "gen-icache.h"
38 
39 
40 
41 static void
42 print_icache_function_header (lf *file,
43 			      const char *basename,
44 			      const char *format_name,
45 			      const opcode_bits *expanded_bits,
46 			      int is_function_definition,
47 			      int nr_prefetched_words)
48 {
49   lf_printf (file, "\n");
50   lf_print__function_type_function (file, print_icache_function_type,
51 				    "EXTERN_ICACHE", " ");
52   print_function_name (file,
53 		       basename, format_name, NULL,
54 		       expanded_bits, function_name_prefix_icache);
55   lf_printf (file, "\n(");
56   print_icache_function_formal (file, nr_prefetched_words);
57   lf_printf (file, ")");
58   if (!is_function_definition)
59     lf_printf (file, ";");
60   lf_printf (file, "\n");
61 }
62 
63 
64 void
65 print_icache_declaration (lf *file,
66 			  const insn_entry *insn,
67 			  const opcode_bits *expanded_bits,
68 			  const insn_opcodes *opcodes,
69 			  int nr_prefetched_words)
70 {
71   print_icache_function_header (file,
72 				insn->name,
73 				insn->format_name,
74 				expanded_bits,
75 				0 /* is not function definition */ ,
76 				nr_prefetched_words);
77 }
78 
79 
80 
81 static void
82 print_icache_extraction (lf *file,
83 			 const char *format_name,
84 			 cache_entry_type cache_type,
85 			 const char *entry_name,
86 			 const char *entry_type,
87 			 const char *entry_expression,
88 			 const char *single_insn_field,
89 			 line_ref *line,
90 			 insn_field_entry *cur_field,
91 			 const opcode_bits *expanded_bits,
92 			 icache_decl_type what_to_declare,
93 			 icache_body_type what_to_do)
94 {
95   const char *expression;
96   const opcode_bits *bits;
97   const char *reason;
98   ASSERT (format_name != NULL);
99   ASSERT (entry_name != NULL);
100 
101   /* figure out exactly what should be going on here */
102   switch (cache_type)
103     {
104     case scratch_value:
105       if ((what_to_do & put_values_in_icache)
106 	  || what_to_do == do_not_use_icache)
107 	{
108 	  reason = "scratch";
109 	  what_to_do = do_not_use_icache;
110 	}
111       else
112 	return;
113       break;
114     case compute_value:
115       if ((what_to_do & get_values_from_icache)
116 	  || what_to_do == do_not_use_icache)
117 	{
118 	  reason = "compute";
119 	  what_to_do = do_not_use_icache;
120 	}
121       else
122 	return;
123       break;
124     case cache_value:
125       if ((what_to_declare != undef_variables)
126 	  || !(what_to_do & put_values_in_icache))
127 	{
128 	  reason = "cache";
129 	  what_to_declare = ((what_to_do & put_values_in_icache)
130 			     ? declare_variables : what_to_declare);
131 	}
132       else
133 	return;
134       break;
135     default:
136       abort ();			/* Bad switch.  */
137     }
138 
139   /* For the type, default to a simple unsigned */
140   if (entry_type == NULL || strlen (entry_type) == 0)
141     entry_type = "unsigned";
142 
143   /* look through the set of expanded sub fields to see if this field
144      has been given a constant value */
145   for (bits = expanded_bits; bits != NULL; bits = bits->next)
146     {
147       if (bits->field == cur_field)
148 	break;
149     }
150 
151   /* Define a storage area for the cache element */
152   switch (what_to_declare)
153     {
154     case undef_variables:
155       /* We've finished with the #define value - destory it */
156       lf_indent_suppress (file);
157       lf_printf (file, "#undef %s\n", entry_name);
158       return;
159     case define_variables:
160       /* Using direct access for this entry, clear any prior
161          definition, then define it */
162       lf_indent_suppress (file);
163       lf_printf (file, "#undef %s\n", entry_name);
164       /* Don't type cast pointer types! */
165       lf_indent_suppress (file);
166       if (strchr (entry_type, '*') != NULL)
167 	lf_printf (file, "#define %s (", entry_name);
168       else
169 	lf_printf (file, "#define %s ((%s) ", entry_name, entry_type);
170       break;
171     case declare_variables:
172       /* using variables to define the value */
173       if (line != NULL)
174 	lf_print__line_ref (file, line);
175       lf_printf (file, "%s const %s UNUSED = ", entry_type, entry_name);
176       break;
177     }
178 
179 
180   /* define a value for that storage area as determined by what is in
181      the cache */
182   if (bits != NULL
183       && single_insn_field != NULL
184       && strcmp (entry_name, single_insn_field) == 0
185       && strcmp (entry_name, cur_field->val_string) == 0
186       && ((bits->opcode->is_boolean && bits->value == 0)
187 	  || (!bits->opcode->is_boolean)))
188     {
189       /* The cache rule is specifying what to do with a simple
190          instruction field.
191 
192          Because of instruction expansion, the field is either a
193          constant value or equal to the specified constant (boolean
194          comparison). (The latter indicated by bits->value == 0).
195 
196          The case of a field not being equal to the specified boolean
197          value is handled later. */
198       expression = "constant field";
199       ASSERT (bits->field == cur_field);
200       if (bits->opcode->is_boolean)
201 	{
202 	  ASSERT (bits->value == 0);
203 	  lf_printf (file, "%d", bits->opcode->boolean_constant);
204 	}
205       else if (bits->opcode->last < bits->field->last)
206 	{
207 	  lf_printf (file, "%d",
208 		     bits->value << (bits->field->last - bits->opcode->last));
209 	}
210       else
211 	{
212 	  lf_printf (file, "%d", bits->value);
213 	}
214     }
215   else if (bits != NULL
216 	   && single_insn_field != NULL
217 	   && strncmp (entry_name,
218 		       single_insn_field,
219 		       strlen (single_insn_field)) == 0
220 	   && strncmp (entry_name + strlen (single_insn_field),
221 		       "_is_",
222 		       strlen ("_is_")) == 0
223 	   && ((bits->opcode->is_boolean
224 		&& ((unsigned)
225 		    atol (entry_name + strlen (single_insn_field) +
226 			  strlen ("_is_")) == bits->opcode->boolean_constant))
227 	       || (!bits->opcode->is_boolean)))
228     {
229       /* The cache rule defines an entry for the comparison between a
230          single instruction field and a constant.  The value of the
231          comparison in someway matches that of the opcode field that
232          was made constant through expansion. */
233       expression = "constant compare";
234       if (bits->opcode->is_boolean)
235 	{
236 	  lf_printf (file, "%d /* %s == %d */",
237 		     bits->value == 0,
238 		     single_insn_field, bits->opcode->boolean_constant);
239 	}
240       else if (bits->opcode->last < bits->field->last)
241 	{
242 	  lf_printf (file, "%d /* %s == %d */",
243 		     (atol
244 		      (entry_name + strlen (single_insn_field) +
245 		       strlen ("_is_")) ==
246 		      (bits->
247 		       value << (bits->field->last - bits->opcode->last))),
248 		     single_insn_field,
249 		     (bits->
250 		      value << (bits->field->last - bits->opcode->last)));
251 	}
252       else
253 	{
254 	  lf_printf (file, "%d /* %s == %d */",
255 		     (atol
256 		      (entry_name + strlen (single_insn_field) +
257 		       strlen ("_is_")) == bits->value), single_insn_field,
258 		     bits->value);
259 	}
260     }
261   else
262     {
263       /* put the field in the local variable, possibly also enter it
264          into the cache */
265       expression = "extraction";
266       /* handle the cache */
267       if ((what_to_do & get_values_from_icache)
268 	  || (what_to_do & put_values_in_icache))
269 	{
270 	  lf_printf (file, "cache_entry->crack.%s.%s",
271 		     format_name, entry_name);
272 	  if (what_to_do & put_values_in_icache)	/* also put it in the cache? */
273 	    {
274 	      lf_printf (file, " = ");
275 	    }
276 	}
277       if ((what_to_do & put_values_in_icache)
278 	  || what_to_do == do_not_use_icache)
279 	{
280 	  if (cur_field != NULL)
281 	    {
282 	      if (entry_expression != NULL && strlen (entry_expression) > 0)
283 		error (line,
284 		       "Instruction field entry with nonempty expression\n");
285 	      if (cur_field->first == 0
286 		  && cur_field->last == options.insn_bit_size - 1)
287 		lf_printf (file, "(instruction_%d)", cur_field->word_nr);
288 	      else if (cur_field->last == options.insn_bit_size - 1)
289 		lf_printf (file, "MASKED%d (instruction_%d, %d, %d)",
290 			   options.insn_bit_size,
291 			   cur_field->word_nr,
292 			   i2target (options.hi_bit_nr, cur_field->first),
293 			   i2target (options.hi_bit_nr, cur_field->last));
294 	      else
295 		lf_printf (file, "EXTRACTED%d (instruction_%d, %d, %d)",
296 			   options.insn_bit_size,
297 			   cur_field->word_nr,
298 			   i2target (options.hi_bit_nr, cur_field->first),
299 			   i2target (options.hi_bit_nr, cur_field->last));
300 	    }
301 	  else
302 	    {
303 	      lf_printf (file, "%s", entry_expression);
304 	    }
305 	}
306     }
307 
308   switch (what_to_declare)
309     {
310     case define_variables:
311       lf_printf (file, ")");
312       break;
313     case undef_variables:
314       break;
315     case declare_variables:
316       lf_printf (file, ";");
317       break;
318     }
319 
320   ASSERT (reason != NULL && expression != NULL);
321   lf_printf (file, " /* %s - %s */\n", reason, expression);
322 }
323 
324 
325 void
326 print_icache_body (lf *file,
327 		   const insn_entry *instruction,
328 		   const opcode_bits *expanded_bits,
329 		   cache_entry *cache_rules,
330 		   icache_decl_type what_to_declare,
331 		   icache_body_type what_to_do, int nr_prefetched_words)
332 {
333   /* extract instruction fields */
334   lf_printf (file, "/* Extraction: %s\n", instruction->name);
335   lf_printf (file, "     ");
336   switch (what_to_declare)
337     {
338     case define_variables:
339       lf_printf (file, "#define");
340       break;
341     case declare_variables:
342       lf_printf (file, "declare");
343       break;
344     case undef_variables:
345       lf_printf (file, "#undef");
346       break;
347     }
348   lf_printf (file, " ");
349   switch (what_to_do)
350     {
351     case get_values_from_icache:
352       lf_printf (file, "get-values-from-icache");
353       break;
354     case put_values_in_icache:
355       lf_printf (file, "put-values-in-icache");
356       break;
357     case both_values_and_icache:
358       lf_printf (file, "get-values-from-icache|put-values-in-icache");
359       break;
360     case do_not_use_icache:
361       lf_printf (file, "do-not-use-icache");
362       break;
363     }
364   lf_printf (file, "\n     ");
365   print_insn_words (file, instruction);
366   lf_printf (file, " */\n");
367 
368   /* pass zero - fetch from memory any missing instructions.
369 
370      Some of the instructions will have already been fetched (in the
371      instruction array), others will still need fetching. */
372   switch (what_to_do)
373     {
374     case get_values_from_icache:
375       break;
376     case put_values_in_icache:
377     case both_values_and_icache:
378     case do_not_use_icache:
379       {
380 	int word_nr;
381 	switch (what_to_declare)
382 	  {
383 	  case undef_variables:
384 	    break;
385 	  case define_variables:
386 	  case declare_variables:
387 	    for (word_nr = nr_prefetched_words;
388 		 word_nr < instruction->nr_words; word_nr++)
389 	      {
390 		/* FIXME - should be using print_icache_extraction? */
391 		lf_printf (file,
392 			   "%sinstruction_word instruction_%d UNUSED = ",
393 			   options.module.global.prefix.l, word_nr);
394 		lf_printf (file, "IMEM%d_IMMED (cia, %d)",
395 			   options.insn_bit_size, word_nr);
396 		lf_printf (file, ";\n");
397 	      }
398 	  }
399       }
400     }
401 
402   /* if putting the instruction words in the cache, define references
403      for them */
404   if (options.gen.insn_in_icache)
405     {
406       /* FIXME: is the instruction_word type correct? */
407       print_icache_extraction (file, instruction->format_name, cache_value, "insn",	/* name */
408 			       "instruction_word",	/* type */
409 			       "instruction",	/* expression */
410 			       NULL,	/* origin */
411 			       NULL,	/* line */
412 			       NULL, NULL, what_to_declare, what_to_do);
413     }
414   lf_printf (file, "\n");
415 
416   /* pass one - process instruction fields.
417 
418      If there is no cache rule, the default is to enter the field into
419      the cache */
420   {
421     insn_word_entry *word;
422     for (word = instruction->words; word != NULL; word = word->next)
423       {
424 	insn_field_entry *cur_field;
425 	for (cur_field = word->first;
426 	     cur_field->first < options.insn_bit_size;
427 	     cur_field = cur_field->next)
428 	  {
429 	    /* Always expand named fields (even if constant), so
430 	       references are valid.  */
431 	    if (cur_field->type == insn_field_string)
432 	      {
433 		cache_entry *cache_rule;
434 		cache_entry_type value_type = cache_value;
435 		line_ref *value_line = instruction->line;
436 		/* check the cache table to see if it contains a rule
437 		   overriding the default cache action for an
438 		   instruction field */
439 		for (cache_rule = cache_rules;
440 		     cache_rule != NULL; cache_rule = cache_rule->next)
441 		  {
442 		    if (filter_is_subset (instruction->field_names,
443 					  cache_rule->original_fields)
444 			&& strcmp (cache_rule->name,
445 				   cur_field->val_string) == 0)
446 		      {
447 			value_type = cache_rule->entry_type;
448 			value_line = cache_rule->line;
449 			if (value_type == compute_value)
450 			  {
451 			    options.warning (cache_rule->line,
452 					     "instruction field of type `compute' changed to `cache'\n");
453 			    cache_rule->entry_type = cache_value;
454 			  }
455 			break;
456 		      }
457 		  }
458 		/* Define an entry for the field within the
459 		   instruction */
460 		print_icache_extraction (file, instruction->format_name, value_type, cur_field->val_string,	/* name */
461 					 NULL,	/* type */
462 					 NULL,	/* expression */
463 					 cur_field->val_string,	/* insn field */
464 					 value_line,
465 					 cur_field,
466 					 expanded_bits,
467 					 what_to_declare, what_to_do);
468 	      }
469 	  }
470       }
471   }
472 
473   /* pass two - any cache fields not processed above */
474   {
475     cache_entry *cache_rule;
476     for (cache_rule = cache_rules;
477 	 cache_rule != NULL; cache_rule = cache_rule->next)
478       {
479 	if (filter_is_subset (instruction->field_names,
480 			      cache_rule->original_fields)
481 	    && !filter_is_member (instruction->field_names, cache_rule->name))
482 	  {
483 	    const char *single_field =
484 	      filter_next (cache_rule->original_fields, "");
485 	    if (filter_next (cache_rule->original_fields, single_field) !=
486 		NULL)
487 	      single_field = NULL;
488 	    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 */
489 				     expanded_bits,
490 				     what_to_declare, what_to_do);
491 	  }
492       }
493   }
494 
495   lf_print__internal_ref (file);
496 }
497 
498 
499 
500 typedef struct _form_fields form_fields;
501 struct _form_fields
502 {
503   char *name;
504   filter *fields;
505   form_fields *next;
506 };
507 
508 static form_fields *
509 insn_table_cache_fields (const insn_table *isa)
510 {
511   form_fields *forms = NULL;
512   insn_entry *insn;
513   for (insn = isa->insns; insn != NULL; insn = insn->next)
514     {
515       form_fields **form = &forms;
516       while (1)
517 	{
518 	  if (*form == NULL)
519 	    {
520 	      /* new format name, add it */
521 	      form_fields *new_form = ZALLOC (form_fields);
522 	      new_form->name = insn->format_name;
523 	      filter_add (&new_form->fields, insn->field_names);
524 	      *form = new_form;
525 	      break;
526 	    }
527 	  else if (strcmp ((*form)->name, insn->format_name) == 0)
528 	    {
529 	      /* already present, add field names to the existing list */
530 	      filter_add (&(*form)->fields, insn->field_names);
531 	      break;
532 	    }
533 	  form = &(*form)->next;
534 	}
535     }
536   return forms;
537 }
538 
539 
540 
541 extern void
542 print_icache_struct (lf *file, const insn_table *isa, cache_entry *cache_rules)
543 {
544   /* Create a list of all the different instruction formats with their
545      corresponding field names. */
546   form_fields *formats = insn_table_cache_fields (isa);
547 
548   lf_printf (file, "\n");
549   lf_printf (file, "#define WITH_%sIDECODE_CACHE_SIZE %d\n",
550 	     options.module.global.prefix.u,
551 	     (options.gen.icache ? options.gen.icache_size : 0));
552   lf_printf (file, "\n");
553 
554   /* create an instruction cache if being used */
555   if (options.gen.icache)
556     {
557       lf_printf (file, "typedef struct _%sidecode_cache {\n",
558 		 options.module.global.prefix.l);
559       lf_indent (file, +2);
560       {
561 	form_fields *format;
562 	lf_printf (file, "unsigned_word address;\n");
563 	lf_printf (file, "void *semantic;\n");
564 	lf_printf (file, "union {\n");
565 	lf_indent (file, +2);
566 	for (format = formats; format != NULL; format = format->next)
567 	  {
568 	    lf_printf (file, "struct {\n");
569 	    lf_indent (file, +2);
570 	    {
571 	      cache_entry *cache_rule;
572 	      const char *field;
573 	      /* space for any instruction words */
574 	      if (options.gen.insn_in_icache)
575 		lf_printf (file, "instruction_word insn[%d];\n",
576 			   isa->max_nr_words);
577 	      /* define an entry for any applicable cache rules */
578 	      for (cache_rule = cache_rules;
579 		   cache_rule != NULL; cache_rule = cache_rule->next)
580 		{
581 		  /* nb - sort of correct - should really check against
582 		     individual instructions */
583 		  if (filter_is_subset
584 		      (format->fields, cache_rule->original_fields))
585 		    {
586 		      const char *memb;
587 		      lf_printf (file, "%s %s;",
588 				 (cache_rule->type == NULL
589 				  ? "unsigned"
590 				  : cache_rule->type), cache_rule->name);
591 		      lf_printf (file, " /*");
592 		      for (memb =
593 			   filter_next (cache_rule->original_fields, "");
594 			   memb != NULL;
595 			   memb =
596 			   filter_next (cache_rule->original_fields, memb))
597 			{
598 			  lf_printf (file, " %s", memb);
599 			}
600 		      lf_printf (file, " */\n");
601 		    }
602 		}
603 	      /* define an entry for any fields not covered by a cache rule */
604 	      for (field = filter_next (format->fields, "");
605 		   field != NULL; field = filter_next (format->fields, field))
606 		{
607 		  cache_entry *cache_rule;
608 		  int found_rule = 0;
609 		  for (cache_rule = cache_rules;
610 		       cache_rule != NULL; cache_rule = cache_rule->next)
611 		    {
612 		      if (strcmp (cache_rule->name, field) == 0)
613 			{
614 			  found_rule = 1;
615 			  break;
616 			}
617 		    }
618 		  if (!found_rule)
619 		    lf_printf (file, "unsigned %s; /* default */\n", field);
620 		}
621 	    }
622 	    lf_indent (file, -2);
623 	    lf_printf (file, "} %s;\n", format->name);
624 	  }
625 	lf_indent (file, -2);
626 	lf_printf (file, "} crack;\n");
627       }
628       lf_indent (file, -2);
629       lf_printf (file, "} %sidecode_cache;\n",
630 		 options.module.global.prefix.l);
631     }
632   else
633     {
634       /* alernativly, since no cache, emit a dummy definition for
635          idecode_cache so that code refering to the type can still compile */
636       lf_printf (file, "typedef void %sidecode_cache;\n",
637 		 options.module.global.prefix.l);
638     }
639   lf_printf (file, "\n");
640 }
641 
642 
643 
644 static void
645 print_icache_function (lf *file,
646 		       const insn_entry *instruction,
647 		       const opcode_bits *expanded_bits,
648 		       const insn_opcodes *opcodes,
649 		       cache_entry *cache_rules, int nr_prefetched_words)
650 {
651   int indent;
652 
653   /* generate code to enter decoded instruction into the icache */
654   lf_printf (file, "\n");
655   lf_print__function_type_function (file, print_icache_function_type,
656 				    "EXTERN_ICACHE", "\n");
657   indent = print_function_name (file,
658 				instruction->name,
659 				instruction->format_name,
660 				NULL,
661 				expanded_bits, function_name_prefix_icache);
662   indent += lf_printf (file, " ");
663   lf_indent (file, +indent);
664   lf_printf (file, "(");
665   print_icache_function_formal (file, nr_prefetched_words);
666   lf_printf (file, ")\n");
667   lf_indent (file, -indent);
668 
669   /* function header */
670   lf_printf (file, "{\n");
671   lf_indent (file, +2);
672 
673   print_my_defines (file,
674 		    instruction->name,
675 		    instruction->format_name, expanded_bits);
676   print_itrace (file, instruction, 1 /*putting-value-in-cache */ );
677 
678   print_idecode_validate (file, instruction, opcodes);
679 
680   lf_printf (file, "\n");
681   lf_printf (file, "{\n");
682   lf_indent (file, +2);
683   if (options.gen.semantic_icache)
684     lf_printf (file, "unsigned_word nia;\n");
685   print_icache_body (file,
686 		     instruction,
687 		     expanded_bits,
688 		     cache_rules,
689 		     (options.gen.direct_access
690 		      ? define_variables
691 		      : declare_variables),
692 		     (options.gen.semantic_icache
693 		      ? both_values_and_icache
694 		      : put_values_in_icache), nr_prefetched_words);
695 
696   lf_printf (file, "\n");
697   lf_printf (file, "cache_entry->address = cia;\n");
698   lf_printf (file, "cache_entry->semantic = ");
699   print_function_name (file,
700 		       instruction->name,
701 		       instruction->format_name,
702 		       NULL, expanded_bits, function_name_prefix_semantics);
703   lf_printf (file, ";\n");
704   lf_printf (file, "\n");
705 
706   if (options.gen.semantic_icache)
707     {
708       lf_printf (file, "/* semantic routine */\n");
709       print_semantic_body (file, instruction, expanded_bits, opcodes);
710       lf_printf (file, "return nia;\n");
711     }
712 
713   if (!options.gen.semantic_icache)
714     {
715       lf_printf (file, "/* return the function proper */\n");
716       lf_printf (file, "return ");
717       print_function_name (file,
718 			   instruction->name,
719 			   instruction->format_name,
720 			   NULL,
721 			   expanded_bits, function_name_prefix_semantics);
722       lf_printf (file, ";\n");
723     }
724 
725   if (options.gen.direct_access)
726     {
727       print_icache_body (file,
728 			 instruction,
729 			 expanded_bits,
730 			 cache_rules,
731 			 undef_variables,
732 			 (options.gen.semantic_icache
733 			  ? both_values_and_icache
734 			  : put_values_in_icache), nr_prefetched_words);
735     }
736 
737   lf_indent (file, -2);
738   lf_printf (file, "}\n");
739   lf_indent (file, -2);
740   lf_printf (file, "}\n");
741 }
742 
743 
744 void
745 print_icache_definition (lf *file,
746 			 const insn_entry *insn,
747 			 const opcode_bits *expanded_bits,
748 			 const insn_opcodes *opcodes,
749 			 cache_entry *cache_rules, int nr_prefetched_words)
750 {
751   print_icache_function (file,
752 			 insn,
753 			 expanded_bits,
754 			 opcodes, cache_rules, nr_prefetched_words);
755 }
756 
757 
758 
759 void
760 print_icache_internal_function_declaration (lf *file,
761 					    const function_entry *function,
762 					    void *data)
763 {
764   ASSERT (options.gen.icache);
765   if (function->is_internal)
766     {
767       lf_printf (file, "\n");
768       lf_print__function_type_function (file, print_icache_function_type,
769 					"INLINE_ICACHE", "\n");
770       print_function_name (file,
771 			   function->name,
772 			   NULL, NULL, NULL, function_name_prefix_icache);
773       lf_printf (file, "\n(");
774       print_icache_function_formal (file, 0);
775       lf_printf (file, ");\n");
776     }
777 }
778 
779 
780 void
781 print_icache_internal_function_definition (lf *file,
782 					   const function_entry *function,
783 					   void *data)
784 {
785   ASSERT (options.gen.icache);
786   if (function->is_internal)
787     {
788       lf_printf (file, "\n");
789       lf_print__function_type_function (file, print_icache_function_type,
790 					"INLINE_ICACHE", "\n");
791       print_function_name (file,
792 			   function->name,
793 			   NULL, NULL, NULL, function_name_prefix_icache);
794       lf_printf (file, "\n(");
795       print_icache_function_formal (file, 0);
796       lf_printf (file, ")\n");
797       lf_printf (file, "{\n");
798       lf_indent (file, +2);
799       lf_printf (file, "/* semantic routine */\n");
800       if (options.gen.semantic_icache)
801 	{
802 	  lf_print__line_ref (file, function->code->line);
803 	  table_print_code (file, function->code);
804 	  lf_printf (file,
805 		     "error (\"Internal function must longjump\\n\");\n");
806 	  lf_printf (file, "return 0;\n");
807 	}
808       else
809 	{
810 	  lf_printf (file, "return ");
811 	  print_function_name (file,
812 			       function->name,
813 			       NULL,
814 			       NULL, NULL, function_name_prefix_semantics);
815 	  lf_printf (file, ";\n");
816 	}
817 
818       lf_print__internal_ref (file);
819       lf_indent (file, -2);
820       lf_printf (file, "}\n");
821     }
822 }
823