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