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