* ld-srec/srec.exp: New tests.
[deliverable/binutils-gdb.git] / sim / ppc / igen.c
CommitLineData
c143ef62
MM
1/* This file is part of the program psim.
2
3 Copyright (C) 1994-1995, 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#include <stdio.h>
22#include <ctype.h>
c143ef62
MM
23#include <getopt.h>
24
25#include "misc.h"
26#include "lf.h"
27#include "table.h"
c494cadd
MM
28#include "config.h"
29
30#ifdef HAVE_STRING_H
31#include <string.h>
32#else
33#ifdef HAVE_STRINGS_H
34#include <strings.h>
35#endif
36#endif
37
c143ef62
MM
38
39
40/****************************************************************/
41
42enum {
a983c8f0 43 max_insn_size = 32,
c143ef62
MM
44};
45
a3114052
MM
46static int hi_bit_nr = 0;
47static int insn_size = max_insn_size;
48static int idecode_expand_semantics = 0;
49static int idecode_cache = 0;
50static int number_lines = 1;
c143ef62
MM
51
52
53/****************************************************************/
54
55
a3114052
MM
56static char *cache_idecode_formal =
57"cpu *processor,\n\
58 instruction_word instruction,\n\
59 unsigned_word cia,\n\
60 idecode_cache *cache_entry";
c143ef62 61
a3114052 62static char *cache_idecode_actual = "processor, instruction, cia, cache_entry";
c143ef62 63
a3114052
MM
64static char *cache_semantic_formal =
65"cpu *processor,\n\
66 idecode_cache *cache_entry,\n\
67 unsigned_word cia";
68
69static char *semantic_formal =
70"cpu *processor,\n\
71 instruction_word instruction,\n\
72 unsigned_word cia";
73
74static char *semantic_actual = "processor, instruction, cia";
c143ef62 75
c143ef62
MM
76
77
78/****************************************************************/
79
80
81typedef struct _filter filter;
82struct _filter {
83 char *flag;
84 filter *next;
85};
a3114052 86static filter *filters = NULL;
c143ef62
MM
87
88
89/****************************************************************/
90
91
92typedef struct _cache_rules cache_rules;
93struct _cache_rules {
94 int valid;
95 char *old_name;
96 char *new_name;
97 char *type;
98 char *expression;
99 cache_rules *next;
100};
a3114052 101static cache_rules *cache_table;
c143ef62
MM
102
103
104enum {
105 ca_valid,
106 ca_old_name,
107 ca_new_name,
108 ca_type,
109 ca_expression,
110 nr_cache_rule_fields,
111};
112
113static cache_rules *
114load_cache_rules(char *file_name)
115{
a3114052 116 table *file = table_open(file_name, nr_cache_rule_fields, 0);
c143ef62
MM
117 table_entry *entry;
118 cache_rules *table = NULL;
119 cache_rules **curr_rule = &table;
120 while ((entry = table_entry_read(file)) != NULL) {
121 cache_rules *new_rule = ZALLOC(cache_rules);
a983c8f0 122 new_rule->valid = target_a2i(hi_bit_nr, entry->fields[ca_valid]);
c143ef62
MM
123 new_rule->old_name = entry->fields[ca_old_name];
124 new_rule->new_name = entry->fields[ca_new_name];
125 new_rule->type = (strlen(entry->fields[ca_type])
126 ? entry->fields[ca_type]
127 : NULL);
128 new_rule->expression = (strlen(entry->fields[ca_expression]) > 0
129 ? entry->fields[ca_expression]
130 : NULL);
131 *curr_rule = new_rule;
132 curr_rule = &new_rule->next;
133 }
134 return table;
135}
136
137
138
139static void
140dump_cache_rule(cache_rules* rule,
141 int indent)
142{
143 dumpf(indent, "((cache_rules*)0x%x\n", rule);
144 dumpf(indent, " (valid %d)\n", rule->valid);
145 dumpf(indent, " (old_name \"%s\")\n", rule->old_name);
146 dumpf(indent, " (new_name \"%s\")\n", rule->new_name);
147 dumpf(indent, " (type \"%s\")\n", rule->type);
148 dumpf(indent, " (expression \"%s\")\n", rule->expression);
149 dumpf(indent, " (next 0x%x)\n", rule->next);
150 dumpf(indent, " )\n");
151}
152
153
154static void
155dump_cache_rules(cache_rules* rule, int indent)
156{
157 while (rule) {
158 dump_cache_rule(rule, indent);
159 rule = rule->next;
160 }
161}
162
163
164/****************************************************************/
165
166
167typedef struct _opcode_rules opcode_rules;
168struct _opcode_rules {
169 int first;
170 int last;
171 int force_first;
172 int force_last;
173 int force_slash;
174 char *force_expansion;
175 int use_switch;
176 unsigned special_mask;
177 unsigned special_value;
178 unsigned special_rule;
179 opcode_rules *next;
180};
a3114052 181static opcode_rules *opcode_table;
c143ef62
MM
182
183
184enum {
185 op_first,
186 op_last,
187 op_force_first,
188 op_force_last,
189 op_force_slash,
190 op_force_expansion,
191 op_use_switch,
192 op_special_mask,
193 op_special_value,
194 op_special_rule,
195 nr_opcode_fields,
196};
197
198
199static opcode_rules *
200load_opcode_rules(char *file_name)
201{
a3114052 202 table *file = table_open(file_name, nr_opcode_fields, 0);
c143ef62
MM
203 table_entry *entry;
204 opcode_rules *table = NULL;
205 opcode_rules **curr_rule = &table;
206 while ((entry = table_entry_read(file)) != NULL) {
207 opcode_rules *new_rule = ZALLOC(opcode_rules);
a983c8f0
MM
208 new_rule->first = target_a2i(hi_bit_nr, entry->fields[op_first]);
209 new_rule->last = target_a2i(hi_bit_nr, entry->fields[op_last]);
210 new_rule->force_first = target_a2i(hi_bit_nr, entry->fields[op_force_first]);
211 new_rule->force_last = target_a2i(hi_bit_nr, entry->fields[op_force_last]);
c143ef62
MM
212 new_rule->force_slash = a2i(entry->fields[op_force_slash]);
213 new_rule->force_expansion = entry->fields[op_force_expansion];
214 new_rule->use_switch = a2i(entry->fields[op_use_switch]);
215 new_rule->special_mask = a2i(entry->fields[op_special_mask]);
216 new_rule->special_value = a2i(entry->fields[op_special_value]);
217 new_rule->special_rule = a2i(entry->fields[op_special_rule]);
218 *curr_rule = new_rule;
219 curr_rule = &new_rule->next;
220 }
221 return table;
222}
223
224
225static void
226dump_opcode_rule(opcode_rules *rule,
227 int indent)
228{
229 dumpf(indent, "((opcode_rules*)%p\n", rule);
230 if (rule) {
231 dumpf(indent, " (first %d)\n", rule->first);
232 dumpf(indent, " (last %d)\n", rule->last);
233 dumpf(indent, " (force_first %d)\n", rule->force_first);
234 dumpf(indent, " (force_last %d)\n", rule->force_last);
235 dumpf(indent, " (force_slash %d)\n", rule->force_slash);
236 dumpf(indent, " (force_expansion \"%s\")\n", rule->force_expansion);
237 dumpf(indent, " (use_switch %d)\n", rule->use_switch);
238 dumpf(indent, " (special_mask 0x%x)\n", rule->special_mask);
239 dumpf(indent, " (special_value 0x%x)\n", rule->special_value);
240 dumpf(indent, " (special_rule 0x%x)\n", rule->special_rule);
241 dumpf(indent, " (next 0x%x)\n", rule->next);
242 }
243 dumpf(indent, " )\n");
244}
245
246
247static void
248dump_opcode_rules(opcode_rules *rule,
249 int indent)
250{
251 while (rule) {
252 dump_opcode_rule(rule, indent);
253 rule = rule->next;
254 }
255}
256
257
258/****************************************************************/
259
260typedef struct _insn_field insn_field;
261struct _insn_field {
262 int first;
263 int last;
264 int width;
265 int is_int;
266 int is_slash;
267 int is_string;
268 int val_int;
269 char *pos_string;
270 char *val_string;
271 insn_field *next;
272 insn_field *prev;
273};
274
275typedef struct _insn_fields insn_fields;
276struct _insn_fields {
a983c8f0 277 insn_field *bits[max_insn_size];
c143ef62
MM
278 insn_field *first;
279 insn_field *last;
280 unsigned value;
281};
282
283static insn_fields *
284parse_insn_format(table_entry *entry,
285 char *format)
286{
287 char *chp;
288 insn_fields *fields = ZALLOC(insn_fields);
289
290 /* create a leading sentinal */
291 fields->first = ZALLOC(insn_field);
292 fields->first->first = -1;
293 fields->first->last = -1;
294 fields->first->width = 0;
295
296 /* and a trailing sentinal */
297 fields->last = ZALLOC(insn_field);
298 fields->last->first = insn_size;
299 fields->last->last = insn_size;
300 fields->last->width = 0;
301
302 /* link them together */
303 fields->first->next = fields->last;
304 fields->last->prev = fields->first;
305
306 /* now work through the formats */
307 chp = format;
308
309 while (*chp != '\0') {
310 char *start_pos;
311 char *start_val;
312 int strlen_val;
313 int strlen_pos;
314 insn_field *new_field;
315
316 /* sanity check */
317 if (!isdigit(*chp)) {
318 error("%s:%d: missing position field at `%s'\n",
319 entry->file_name, entry->line_nr, chp);
320 }
321
322 /* break out the bit position */
323 start_pos = chp;
324 while (isdigit(*chp))
325 chp++;
326 strlen_pos = chp - start_pos;
327 if (*chp == '.' && strlen_pos > 0)
328 chp++;
329 else {
330 error("%s:%d: missing field value at %s\n",
331 entry->file_name, entry->line_nr, chp);
332 break;
333 }
334
335 /* break out the value */
336 start_val = chp;
337 while ((*start_val == '/' && *chp == '/')
338 || (isdigit(*start_val) && isdigit(*chp))
339 || (isalpha(*start_val) && (isalnum(*chp) || *chp == '_')))
340 chp++;
341 strlen_val = chp - start_val;
342 if (*chp == ',')
343 chp++;
344 else if (*chp != '\0' || strlen_val == 0) {
345 error("%s:%d: missing field terminator at %s\n",
346 entry->file_name, entry->line_nr, chp);
347 break;
348 }
349
350 /* create a new field and insert it */
351 new_field = ZALLOC(insn_field);
352 new_field->next = fields->last;
353 new_field->prev = fields->last->prev;
354 new_field->next->prev = new_field;
355 new_field->prev->next = new_field;
356
357 /* the value */
358 new_field->val_string = (char*)zalloc(strlen_val+1);
359 strncpy(new_field->val_string, start_val, strlen_val);
360 if (isdigit(*new_field->val_string)) {
361 new_field->val_int = a2i(new_field->val_string);
362 new_field->is_int = 1;
363 }
364 else if (new_field->val_string[0] == '/') {
365 new_field->is_slash = 1;
366 }
367 else {
368 new_field->is_string = 1;
369 }
370
371 /* the pos */
372 new_field->pos_string = (char*)zalloc(strlen_pos+1);
373 strncpy(new_field->pos_string, start_pos, strlen_pos);
a983c8f0 374 new_field->first = target_a2i(hi_bit_nr, new_field->pos_string);
c143ef62
MM
375 new_field->last = new_field->next->first - 1; /* guess */
376 new_field->width = new_field->last - new_field->first + 1; /* guess */
377 new_field->prev->last = new_field->first-1; /*fix*/
378 new_field->prev->width = new_field->first - new_field->prev->first; /*fix*/
379 }
380
381 /* fiddle first/last so that the sentinals `disapear' */
382 ASSERT(fields->first->last < 0);
383 ASSERT(fields->last->first >= insn_size);
384 fields->first = fields->first->next;
385 fields->last = fields->last->prev;
386
387 /* now go over this again, pointing each bit position at a field
388 record */
389 {
390 int i;
391 insn_field *field;
392 field = fields->first;
393 for (i = 0; i < insn_size; i++) {
394 while (field->last < i)
395 field = field->next;
396 fields->bits[i] = field;
397 }
398 }
399
400 /* go over each of the fields, and compute a `value' for the insn */
401 {
402 insn_field *field;
403 fields->value = 0;
404 for (field = fields->first;
405 field->last < insn_size;
406 field = field->next) {
407 fields->value <<= field->width;
408 if (field->is_int)
409 fields->value |= field->val_int;
410 }
411 }
412 return fields;
413}
414
415
416typedef enum {
417 field_constant_int = 1,
418 field_constant_slash = 2,
419 field_constant_string = 3
420} constant_field_types;
421
422
423static int
424insn_field_is_constant(insn_field *field,
425 opcode_rules *rule)
426{
427 /* field is an integer */
428 if (field->is_int)
429 return field_constant_int;
430 /* field is `/' and treating that as a constant */
431 if (field->is_slash && rule->force_slash)
432 return field_constant_slash;
433 /* field, though variable is on the list */
434 if (field->is_string && rule->force_expansion != NULL) {
435 char *forced_fields = rule->force_expansion;
436 while (*forced_fields != '\0') {
437 int field_len;
438 char *end = strchr(forced_fields, ',');
439 if (end == NULL)
440 field_len = strlen(forced_fields);
441 else
442 field_len = end-forced_fields;
443 if (strncmp(forced_fields, field->val_string, field_len) == 0
444 && field->val_string[field_len] == '\0')
445 return field_constant_string;
446 forced_fields += field_len;
447 if (*forced_fields == ',')
448 forced_fields++;
449 }
450 }
451 return 0;
452}
453
454
455static void
456dump_insn_field(insn_field *field,
457 int indent)
458{
459
460 printf("(insn_field*)0x%x\n", (unsigned)field);
461
462 dumpf(indent, "(first %d)\n", field->first);
463
464 dumpf(indent, "(last %d)\n", field->last);
465
466 dumpf(indent, "(width %d)\n", field->width);
467
468 if (field->is_int)
469 dumpf(indent, "(is_int %d)\n", field->val_int);
470
471 if (field->is_slash)
472 dumpf(indent, "(is_slash)\n");
473
474 if (field->is_string)
475 dumpf(indent, "(is_string `%s')\n", field->val_string);
476
477 dumpf(indent, "(next 0x%x)\n", field->next);
478
479 dumpf(indent, "(prev 0x%x)\n", field->prev);
480
481
482}
483
484static void
485dump_insn_fields(insn_fields *fields,
486 int indent)
487{
488 int i;
489
490 printf("(insn_fields*)%p\n", fields);
491
492 dumpf(indent, "(first 0x%x)\n", fields->first);
493 dumpf(indent, "(last 0x%x)\n", fields->last);
494
495 dumpf(indent, "(value 0x%x)\n", fields->value);
496
497 for (i = 0; i < insn_size; i++) {
498 dumpf(indent, "(bits[%d] ", i, fields->bits[i]);
499 dump_insn_field(fields->bits[i], indent+1);
500 dumpf(indent, " )\n");
501 }
502
503}
504
505
506/****************************************************************/
507
508typedef struct _opcode_field opcode_field;
509struct _opcode_field {
510 int first;
511 int last;
512 int is_boolean;
513 opcode_field *parent;
514};
515
c143ef62
MM
516static void
517dump_opcode_field(opcode_field *field, int indent, int levels)
518{
519 printf("(opcode_field*)%p\n", field);
520 if (levels && field != NULL) {
521 dumpf(indent, "(first %d)\n", field->first);
522 dumpf(indent, "(last %d)\n", field->last);
523 dumpf(indent, "(is_boolean %d)\n", field->is_boolean);
524 dumpf(indent, "(parent ");
525 dump_opcode_field(field->parent, indent, levels-1);
526 }
527}
528
529
530/****************************************************************/
531
532typedef struct _insn_bits insn_bits;
533struct _insn_bits {
534 int is_expanded;
535 int value;
536 insn_field *field;
537 opcode_field *opcode;
538 insn_bits *last;
539};
540
541
542static void
543dump_insn_bits(insn_bits *bits, int indent, int levels)
544{
545 printf("(insn_bits*)%p\n", bits);
546
547 if (levels && bits != NULL) {
548 dumpf(indent, "(value %d)\n", bits->value);
549 dumpf(indent, "(opcode ");
550 dump_opcode_field(bits->opcode, indent+1, 0);
551 dumpf(indent, " )\n");
552 dumpf(indent, "(field ");
553 dump_insn_field(bits->field, indent+1);
554 dumpf(indent, " )\n");
555 dumpf(indent, "(last ");
556 dump_insn_bits(bits->last, indent+1, levels-1);
557 }
558}
559
560
561/****************************************************************/
562
563
564typedef enum {
565 insn_format,
566 insn_form,
567 insn_flags,
1dc7c0ed 568 insn_mnemonic,
c143ef62
MM
569 insn_name,
570 insn_comment,
a3114052 571 nr_insn_table_fields
c143ef62 572} insn_table_fields;
c143ef62
MM
573
574typedef enum {
575 function_type = insn_format,
576 function_name = insn_name,
a3114052 577 function_param = insn_comment
c143ef62
MM
578} function_table_fields;
579
a3114052 580typedef enum {
1dc7c0ed
MM
581 model_default = insn_form,
582 model_name = insn_mnemonic,
28816f45 583 model_identifer = insn_name,
a3114052
MM
584 model_func = insn_comment,
585} model_table_fields;
c143ef62
MM
586
587typedef struct _insn insn;
588struct _insn {
589 table_entry *file_entry;
590 insn_fields *fields;
591 insn *next;
592};
593
a3114052
MM
594typedef struct _model_func_unit model_func_unit;
595struct _model_func_unit {
596 model_func_unit *next;
597 char *name;
598 char *comment;
599 int number;
600 unsigned mask;
601};
602
603typedef struct _model model;
604struct _model {
605 model *next;
606 char *name;
28816f45 607 char *printable_name;
a3114052
MM
608 model_func_unit *func_unit_start;
609 model_func_unit *func_unit_end;
610};
611
c143ef62
MM
612typedef struct _insn_table insn_table;
613struct _insn_table {
614 int opcode_nr;
615 insn_bits *expanded_bits;
616 int nr_insn;
617 insn *insns;
618 insn *functions;
a3114052
MM
619 insn *last_function;
620 int max_func_unit_name_len;
621 unsigned max_func_unit_mask;
c143ef62
MM
622 opcode_rules *opcode_rule;
623 opcode_field *opcode;
624 int nr_entries;
625 insn_table *entries;
626 insn_table *sibling;
627 insn_table *parent;
628};
629
a3114052
MM
630typedef enum {
631 insn_model_name,
632 insn_model_unit,
633 insn_model_issue,
634 insn_model_done,
635 insn_model_flags,
636 nr_insn_model_table_fields
637} insn_model_table_fields;
638
639static model *models;
640static model *last_model;
c143ef62 641
28816f45
MM
642static insn *model_macros;
643static insn *last_model_macro;
c143ef62 644
eb4ef197
MM
645static insn *model_functions;
646static insn *last_model_function;
647
1dc7c0ed
MM
648static insn *model_internal;
649static insn *last_model_internal;
650
651static insn *model_data;
652static insn *last_model_data;
653
c143ef62
MM
654static void
655insn_table_insert_function(insn_table *table,
656 table_entry *file_entry)
657{
c143ef62
MM
658 /* create a new function */
659 insn *new_function = ZALLOC(insn);
660 new_function->file_entry = file_entry;
661
662 /* append it to the end of the function list */
a3114052
MM
663 if (table->last_function)
664 table->last_function->next = new_function;
665 else
666 table->functions = new_function;
667 table->last_function = new_function;
668}
669
c143ef62
MM
670static void
671insn_table_insert_insn(insn_table *table,
672 table_entry *file_entry,
673 insn_fields *fields)
674{
675 insn **ptr_to_cur_insn = &table->insns;
676 insn *cur_insn = *ptr_to_cur_insn;
a3114052
MM
677 table_model_entry *insn_model_ptr;
678 model *model_ptr;
c143ef62
MM
679
680 /* create a new instruction */
681 insn *new_insn = ZALLOC(insn);
682 new_insn->file_entry = file_entry;
683 new_insn->fields = fields;
684
a3114052
MM
685 /* Check out any model information returned to make sure the model
686 is correct. */
687 for(insn_model_ptr = file_entry->model_first; insn_model_ptr; insn_model_ptr = insn_model_ptr->next) {
688 char *name = insn_model_ptr->fields[insn_model_name];
689
690 for(model_ptr = models; model_ptr; model_ptr = model_ptr->next) {
691 if (strcmp(name, model_ptr->name) == 0) {
692
693 /* Replace the name field with that of the global model, so that when we
694 want to print it out, we can just compare pointers. */
695 insn_model_ptr->fields[insn_model_name] = model_ptr->name;
696 break;
697 }
698 }
699
700 if (!model_ptr)
701 error("%s:%d: machine model `%s' was not known about\n",
702 file_entry->file_name, file_entry->line_nr, name);
703 }
704
c143ef62
MM
705 /* insert it according to the order of the fields */
706 while (cur_insn != NULL
707 && new_insn->fields->value >= cur_insn->fields->value) {
708 ptr_to_cur_insn = &cur_insn->next;
709 cur_insn = *ptr_to_cur_insn;
710 }
711
712 new_insn->next = cur_insn;
713 *ptr_to_cur_insn = new_insn;
714
715 table->nr_insn++;
716}
717
718
719static opcode_field *
720insn_table_find_opcode_field(insn *insns,
721 opcode_rules *rule,
722 int string_only)
723{
1dc7c0ed 724 opcode_field *curr_opcode = ZALLOC(opcode_field);
c143ef62 725 insn *entry;
c143ef62
MM
726 ASSERT(rule);
727
1dc7c0ed
MM
728 curr_opcode->first = insn_size;
729 curr_opcode->last = -1;
c143ef62
MM
730 for (entry = insns; entry != NULL; entry = entry->next) {
731 insn_fields *fields = entry->fields;
732 opcode_field new_opcode;
733
734 /* find a start point for the opcode field */
735 new_opcode.first = rule->first;
736 while (new_opcode.first <= rule->last
737 && (!string_only
738 || insn_field_is_constant(fields->bits[new_opcode.first],
739 rule) != field_constant_string)
740 && (string_only
741 || !insn_field_is_constant(fields->bits[new_opcode.first],
742 rule)))
743 new_opcode.first = fields->bits[new_opcode.first]->last + 1;
744 ASSERT(new_opcode.first > rule->last
745 || (string_only
746 && insn_field_is_constant(fields->bits[new_opcode.first],
747 rule) == field_constant_string)
748 || (!string_only
749 && insn_field_is_constant(fields->bits[new_opcode.first],
750 rule)));
751
752 /* find the end point for the opcode field */
753 new_opcode.last = rule->last;
754 while (new_opcode.last >= rule->first
755 && (!string_only
756 || insn_field_is_constant(fields->bits[new_opcode.last],
757 rule) != field_constant_string)
758 && (string_only
759 || !insn_field_is_constant(fields->bits[new_opcode.last],
760 rule)))
761 new_opcode.last = fields->bits[new_opcode.last]->first - 1;
762 ASSERT(new_opcode.last < rule->first
763 || (string_only
764 && insn_field_is_constant(fields->bits[new_opcode.last],
765 rule) == field_constant_string)
766 || (!string_only
767 && insn_field_is_constant(fields->bits[new_opcode.last],
768 rule)));
769
770 /* now see if our current opcode needs expanding */
771 if (new_opcode.first <= rule->last
772 && curr_opcode->first > new_opcode.first)
773 curr_opcode->first = new_opcode.first;
774 if (new_opcode.last >= rule->first
775 && curr_opcode->last < new_opcode.last)
776 curr_opcode->last = new_opcode.last;
777
778 }
779
780 /* was any thing interesting found? */
781 if (curr_opcode->first > rule->last) {
782 ASSERT(curr_opcode->last < rule->first);
783 return NULL;
784 }
785 ASSERT(curr_opcode->last >= rule->first);
786 ASSERT(curr_opcode->first <= rule->last);
787
788 /* if something was found, check it includes the forced field range */
789 if (!string_only
790 && curr_opcode->first > rule->force_first) {
791 curr_opcode->first = rule->force_first;
792 }
793 if (!string_only
794 && curr_opcode->last < rule->force_last) {
795 curr_opcode->last = rule->force_last;
796 }
797 /* handle special case elminating any need to do shift after mask */
798 if (string_only
799 && rule->force_last == insn_size-1) {
800 curr_opcode->last = insn_size-1;
801 }
802
803 /* handle any special cases */
804 switch (rule->special_rule) {
805 case 0: /* let the above apply */
806 break;
807 case 1: /* expand a limited nr of bits, ignoring the rest */
808 curr_opcode->first = rule->force_first;
809 curr_opcode->last = rule->force_last;
810 break;
811 case 2: /* boolean field */
812 curr_opcode->is_boolean = 1;
813 break;
814 }
815
816 return curr_opcode;
817}
818
819
820static void
821insn_table_insert_expanded(insn_table *table,
822 insn *old_insn,
823 int new_opcode_nr,
824 insn_bits *new_bits)
825{
826 insn_table **ptr_to_cur_entry = &table->entries;
827 insn_table *cur_entry = *ptr_to_cur_entry;
828
829 /* find the new table for this entry */
830 while (cur_entry != NULL
831 && cur_entry->opcode_nr < new_opcode_nr) {
832 ptr_to_cur_entry = &cur_entry->sibling;
833 cur_entry = *ptr_to_cur_entry;
834 }
835
836 if (cur_entry == NULL || cur_entry->opcode_nr != new_opcode_nr) {
837 insn_table *new_entry = ZALLOC(insn_table);
838 new_entry->opcode_nr = new_opcode_nr;
839 new_entry->expanded_bits = new_bits;
840 new_entry->opcode_rule = table->opcode_rule->next;
841 new_entry->sibling = cur_entry;
842 new_entry->parent = table;
843 *ptr_to_cur_entry = new_entry;
844 cur_entry = new_entry;
845 table->nr_entries++;
846 }
847 /* ASSERT new_bits == cur_entry bits */
848 ASSERT(cur_entry != NULL && cur_entry->opcode_nr == new_opcode_nr);
849 insn_table_insert_insn(cur_entry,
850 old_insn->file_entry,
851 old_insn->fields);
852}
853
854static void
855insn_table_expand_opcode(insn_table *table,
856 insn *instruction,
857 int field_nr,
858 int opcode_nr,
859 insn_bits *bits)
860{
861
862 if (field_nr > table->opcode->last) {
863 insn_table_insert_expanded(table, instruction, opcode_nr, bits);
864 }
865 else {
866 insn_field *field = instruction->fields->bits[field_nr];
867 if (field->is_int || field->is_slash) {
868 ASSERT(field->first >= table->opcode->first
869 && field->last <= table->opcode->last);
870 insn_table_expand_opcode(table, instruction, field->last+1,
871 ((opcode_nr << field->width) + field->val_int),
872 bits);
873 }
874 else {
875 int val;
876 int last_pos = ((field->last < table->opcode->last)
877 ? field->last : table->opcode->last);
878 int first_pos = ((field->first > table->opcode->first)
879 ? field->first : table->opcode->first);
880 int width = last_pos - first_pos + 1;
881 int last_val = (table->opcode->is_boolean
882 ? 2 : (1 << width));
883 for (val = 0; val < last_val; val++) {
884 insn_bits *new_bits = ZALLOC(insn_bits);
885 new_bits->field = field;
886 new_bits->value = val;
887 new_bits->last = bits;
888 new_bits->opcode = table->opcode;
889 insn_table_expand_opcode(table, instruction, last_pos+1,
890 ((opcode_nr << width) | val),
891 new_bits);
892 }
893 }
894 }
895}
896
897static void
898insn_table_insert_expanding(insn_table *table,
899 insn *entry)
900{
901 insn_table_expand_opcode(table,
902 entry,
903 table->opcode->first,
904 0,
905 table->expanded_bits);
906}
907
908
909static void
910insn_table_expand_insns(insn_table *table)
911{
912
913 ASSERT(table->nr_insn >= 1);
914
915 /* determine a valid opcode */
916 while (table->opcode_rule) {
917 /* specials only for single instructions */
918 if ((table->nr_insn > 1
919 && table->opcode_rule->special_mask == 0
920 && table->opcode_rule->special_rule == 0)
921 || (table->nr_insn == 1
922 && table->opcode_rule->special_mask != 0
923 && ((table->insns->fields->value
924 & table->opcode_rule->special_mask)
925 == table->opcode_rule->special_value))
926 || (idecode_expand_semantics
927 && table->opcode_rule->special_mask == 0
928 && table->opcode_rule->special_rule == 0))
929 table->opcode =
930 insn_table_find_opcode_field(table->insns,
931 table->opcode_rule,
932 table->nr_insn == 1/*string*/
933 );
934 if (table->opcode != NULL)
935 break;
936 table->opcode_rule = table->opcode_rule->next;
937 }
938
939 /* did we find anything */
940 if (table->opcode == NULL) {
941 return;
942 }
943 ASSERT(table->opcode != NULL);
944
945 /* back link what we found to its parent */
946 if (table->parent != NULL) {
947 ASSERT(table->parent->opcode != NULL);
948 table->opcode->parent = table->parent->opcode;
949 }
950
951 /* expand the raw instructions according to the opcode */
952 {
953 insn *entry;
954 for (entry = table->insns; entry != NULL; entry = entry->next) {
955 insn_table_insert_expanding(table, entry);
956 }
957 }
958
959 /* and do the same for the sub entries */
960 {
961 insn_table *entry;
962 for (entry = table->entries; entry != NULL; entry = entry->sibling) {
963 insn_table_expand_insns(entry);
964 }
965 }
966}
967
968
1dc7c0ed
MM
969static void
970model_table_insert(insn_table *table,
971 table_entry *file_entry)
972{
973 /* create a new model */
974 model *new_model = ZALLOC(model);
975 model_func_unit *func_unit;
976 char *ptr, *end, *end_name, *comment, *name;
977 int ch;
978 int name_len;
979 int func_name_len;
980 unsigned unit, mask;
981 int number;
982
983 new_model->name = file_entry->fields[model_identifer];
984 new_model->printable_name = file_entry->fields[model_name];
985 name_len = strlen(new_model->name);
986
987 /* append it to the end of the model list */
988 if (last_model)
989 last_model->next = new_model;
990 else
991 models = new_model;
992 last_model = new_model;
993
994 /* Parse the function units separated by commas */
995 unit = 1;
996 for (ptr = file_entry->fields[model_func];
997 ((ch = *ptr) != '\0') && (ch != '\n');
998 ptr = (*end == ',') ? end+1 : end) {
999
1000 while (ch == ' ' || ch == '\t')
1001 ch = *++ptr;
1002
1003 if (!ch || ch == '\n')
1004 break;
1005
1006 /* Search for comma or newline ending field */
1007 end = ptr;
1008 end_name = (char *)0;
1009
1010 if (ch == ',')
1011 continue;
1012
1013 while (ch != '\0' && ch != ',' && ch != '\n') {
1014 if (end_name == (char *)0 && (ch == '=' || isspace(ch)))
1015 end_name = end;
1016
1017 ch = *++end;
1018 }
1019 if (!end_name)
1020 end_name = end;
1021
1022 func_unit = ZALLOC(model_func_unit);
1023 if (new_model->func_unit_end)
1024 new_model->func_unit_end->next = func_unit;
1025 else
1026 new_model->func_unit_start = func_unit;
1027
1028 new_model->func_unit_end = func_unit;
1029
1030 /* Record function unit name as model name _ unit name */
1031 func_name_len = name_len + end_name - ptr + 2;
1032 if (table->max_func_unit_name_len < func_name_len)
1033 table->max_func_unit_name_len = func_name_len;
1034
1035 func_unit->name = name = (char *)zalloc(func_name_len);
1036 memcpy(name, new_model->name, name_len);
1037 name[name_len] = '_';
1038 memcpy(name + name_len + 1, ptr, end_name - ptr);
1039
1040 /* See if there are multiple functional units */
1041 if (*end_name == '=') {
1042 number = 0;
1043 for(end_name++; end_name < end && isdigit(*end_name); end_name++)
1044 number = number * 10 + (*end_name - '0');
1045 } else {
1046 number = 1;
1047 }
1048
1049 /* Now figure out the mask for these unit(s) */
1050 func_unit->number = number;
1051 mask = 0;
1052 while (number--) {
1053 ASSERT(unit != 0);
1054 mask |= unit;
1055 unit <<= 1;
1056 }
1057 func_unit->mask = mask;
1058 table->max_func_unit_mask |= mask;
1059
1060 /* Now figure out comments */
1061 for (comment = end_name; comment < end && ((ch = *comment) == ' ' || ch == '\t'); comment++)
1062 ;
1063
1064 if (comment < end) {
1065 func_unit->comment = (char *)zalloc(end - comment + 1);
1066 memcpy(func_unit->comment, comment, end - comment);
1067 }
1068 }
1069
1070 /* Add an 'sentinel' function unit at the end to simpify the loop */
1071 func_unit = ZALLOC(model_func_unit);
1072 if (new_model->func_unit_end)
1073 new_model->func_unit_end->next = func_unit;
1074 else
1075 new_model->func_unit_start = func_unit;
1076
1077 new_model->func_unit_end = func_unit;
1078
1079 /* Record function unit name as model name _ unit name */
1080 func_name_len = name_len + sizeof("_SENTINEL");
1081 if (table->max_func_unit_name_len < func_name_len)
1082 table->max_func_unit_name_len = func_name_len;
1083
1084 func_unit->name = name = (char *)zalloc(func_name_len);
1085 func_unit->number = 0;
1086 func_unit->mask = unit;
1087 func_unit->comment = "dummy";
1088 table->max_func_unit_mask |= unit;
1089
1090 memcpy(name, new_model->name, name_len);
1091 strcpy(name + name_len, "_SENTINEL");
1092}
1093
1094static void
1095model_table_insert_specific(insn_table *table,
1096 table_entry *file_entry,
1097 insn **start_ptr,
1098 insn **end_ptr)
1099{
1100 insn *ptr = ZALLOC(insn);
1101 ptr->file_entry = file_entry;
1102 if (*end_ptr)
1103 (*end_ptr)->next = ptr;
1104 else
1105 (*start_ptr) = ptr;
1106 (*end_ptr) = ptr;
1107}
1108
1109
c143ef62
MM
1110
1111static insn_table *
1112insn_table_load_insns(char *file_name)
1113{
a3114052 1114 table *file = table_open(file_name, nr_insn_table_fields, nr_insn_model_table_fields);
c143ef62
MM
1115 insn_table *table = ZALLOC(insn_table);
1116 table_entry *file_entry;
1117 table->opcode_rule = opcode_table;
1118
1119 while ((file_entry = table_entry_read(file)) != NULL) {
1120 if (it_is("function", file_entry->fields[insn_flags])
1121 || it_is("internal", file_entry->fields[insn_flags])) {
1122 insn_table_insert_function(table, file_entry);
1123 }
a3114052
MM
1124 else if (it_is("model", file_entry->fields[insn_flags])) {
1125 model_table_insert(table, file_entry);
1126 }
28816f45 1127 else if (it_is("model-macro", file_entry->fields[insn_flags])) {
1dc7c0ed 1128 model_table_insert_specific(table, file_entry, &model_macros, &last_model_macro);
eb4ef197
MM
1129 }
1130 else if (it_is("model-function", file_entry->fields[insn_flags])) {
1dc7c0ed
MM
1131 model_table_insert_specific(table, file_entry, &model_functions, &last_model_function);
1132 }
1133 else if (it_is("model-internal", file_entry->fields[insn_flags])) {
1134 model_table_insert_specific(table, file_entry, &model_internal, &last_model_internal);
1135 }
1136 else if (it_is("model-data", file_entry->fields[insn_flags])) {
1137 model_table_insert_specific(table, file_entry, &model_data, &last_model_data);
28816f45 1138 }
c143ef62
MM
1139 else {
1140 insn_fields *fields;
1141 /* skip instructions that aren't relevant to the mode */
1142 filter *filt = filters;
1143 while (filt != NULL) {
1144 if (it_is(filt->flag, file_entry->fields[insn_flags]))
1145 break;
1146 filt = filt->next;
1147 }
1148 if (filt == NULL) {
1149 /* create/insert the new instruction */
1150 fields = parse_insn_format(file_entry,
1151 file_entry->fields[insn_format]);
1152 insn_table_insert_insn(table, file_entry, fields);
1153 }
1154 }
1155 }
1156 return table;
1157}
1158
1159
1160static void
1161dump_insn(insn *entry, int indent, int levels)
1162{
1163 printf("(insn*)%p\n", entry);
1164
1165 if (levels && entry != NULL) {
1166
1167 dumpf(indent, "(file_entry ");
1168 dump_table_entry(entry->file_entry, indent+1);
1169 dumpf(indent, " )\n");
1170
1171 dumpf(indent, "(fields ");
1172 dump_insn_fields(entry->fields, indent+1);
1173 dumpf(indent, " )\n");
1174
1175 dumpf(indent, "(next ");
1176 dump_insn(entry->next, indent+1, levels-1);
1177 dumpf(indent, " )\n");
1178
1179 }
1180
1181}
1182
1183
1184static void
1185dump_insn_table(insn_table *table,
1186 int indent, int levels)
1187{
1188
1189 printf("(insn_table*)%p\n", table);
1190
1191 if (levels && table != NULL) {
1192
1193 dumpf(indent, "(opcode_nr %d)\n", table->opcode_nr);
1194
1195 dumpf(indent, "(expanded_bits ");
1196 dump_insn_bits(table->expanded_bits, indent+1, -1);
1197 dumpf(indent, " )\n");
1198
1199 dumpf(indent, "(int nr_insn %d)\n", table->nr_insn);
1200
1201 dumpf(indent, "(insns ");
1202 dump_insn(table->insns, indent+1, table->nr_insn);
1203 dumpf(indent, " )\n");
1204
1205 dumpf(indent, "(opcode_rule ");
1206 dump_opcode_rule(table->opcode_rule, indent+1);
1207 dumpf(indent, " )\n");
1208
1209 dumpf(indent, "(opcode ");
1210 dump_opcode_field(table->opcode, indent+1, 1);
1211 dumpf(indent, " )\n");
1212
1213 dumpf(indent, "(nr_entries %d)\n", table->entries);
1214 dumpf(indent, "(entries ");
1215 dump_insn_table(table->entries, indent+1, table->nr_entries);
1216 dumpf(indent, " )\n");
1217
1218 dumpf(indent, "(sibling ", table->sibling);
1219 dump_insn_table(table->sibling, indent+1, levels-1);
1220 dumpf(indent, " )\n");
1221
1222 dumpf(indent, "(parent ", table->parent);
1223 dump_insn_table(table->parent, indent+1, 0);
1224 dumpf(indent, " )\n");
1225
1226 }
1227}
1228
1229
1230/****************************************************************/
1231
1232
1233static void
1234lf_print_insn_bits(lf *file, insn_bits *bits)
1235{
1236 if (bits == NULL)
1237 return;
1238 lf_print_insn_bits(file, bits->last);
1239 lf_putchr(file, '_');
1240 lf_putstr(file, bits->field->val_string);
1241 if (!bits->opcode->is_boolean || bits->value == 0) {
1242 if (bits->opcode->last < bits->field->last)
1243 lf_putint(file, bits->value << (bits->field->last - bits->opcode->last));
1244 else
1245 lf_putint(file, bits->value);
1246 }
1247}
1248
1249static void
1250lf_print_opcodes(lf *file,
1251 insn_table *table)
1252{
1253 if (table != NULL) {
1254 while (1) {
1255 lf_printf(file, "_%d_%d",
1256 table->opcode->first,
1257 table->opcode->last);
1258 if (table->parent == NULL) break;
1259 lf_printf(file, "__%d", table->opcode_nr);
1260 table = table->parent;
1261 }
1262 }
1263}
1264
1265static void
1266lf_print_table_name(lf *file,
1267 insn_table *table)
1268{
1269 lf_printf(file, "idecode_table");
1270 lf_print_opcodes(file, table);
1271}
1272
1273
1274
1275typedef enum {
1276 function_name_prefix_semantics,
1277 function_name_prefix_idecode,
1278 function_name_prefix_itable,
1279 function_name_prefix_none
1280} lf_function_name_prefixes;
1281
1282static void
1283lf_print_function_name(lf *file,
1284 char *basename,
1285 insn_bits *expanded_bits,
1286 lf_function_name_prefixes prefix)
1287{
1288
1289 /* the prefix */
1290 switch (prefix) {
1291 case function_name_prefix_semantics:
1292 lf_putstr(file, "semantic_");
1293 break;
1294 case function_name_prefix_idecode:
1295 lf_printf(file, "idecode_");
1296 break;
1297 case function_name_prefix_itable:
1298 lf_putstr(file, "itable_");
1299 break;
1300 default:
1301 break;
1302 }
1303
1304 /* the function name */
1305 {
1306 char *pos;
1307 for (pos = basename;
1308 *pos != '\0';
1309 pos++) {
1310 switch (*pos) {
1311 case '/':
1312 case '-':
1313 break;
1314 case ' ':
1315 lf_putchr(file, '_');
1316 break;
1317 default:
1318 lf_putchr(file, *pos);
1319 break;
1320 }
1321 }
1322 }
1323
1324 /* the suffix */
1325 if (idecode_expand_semantics)
1326 lf_print_insn_bits(file, expanded_bits);
1327}
1328
1329
1330static void
1331lf_print_idecode_table(lf *file,
1332 insn_table *entry)
1333{
1334 int can_assume_leaf;
1335 opcode_rules *opcode_rule;
1336
1337 /* have a look at the rule table, if all table rules follow all
1338 switch rules, I can assume that all end points are leaves */
1339 opcode_rule = opcode_table;
1340 while (opcode_rule != NULL
1341 && opcode_rule->use_switch)
1342 opcode_rule = opcode_rule->next;
1343 while (opcode_rule != NULL
1344 && opcode_rule->use_switch
1345 && opcode_rule->special_rule)
1346 opcode_rule = opcode_rule->next;
1347 can_assume_leaf = opcode_rule == NULL;
1348
1349 lf_printf(file, "{\n");
1350 lf_indent(file, +2);
1351 {
1352 lf_printf(file, "idecode_table_entry *table = ");
1353 lf_print_table_name(file, entry);
1354 lf_printf(file, ";\n");
1355 lf_printf(file, "int opcode = EXTRACTED32(instruction, %d, %d);\n",
a983c8f0
MM
1356 i2target(hi_bit_nr, entry->opcode->first),
1357 i2target(hi_bit_nr, entry->opcode->last));
c143ef62
MM
1358 lf_printf(file, "idecode_table_entry *table_entry = table + opcode;\n");
1359 lf_printf(file, "while (1) {\n");
1360 lf_indent(file, +2);
1361 {
1dc7c0ed 1362 lf_printf(file, "/* nonzero mask -> another table */\n");
c143ef62
MM
1363 lf_printf(file, "while (table_entry->mask != 0) {\n");
1364 lf_indent(file, +2);
1365 {
1366 lf_printf(file, "table = ((idecode_table_entry*)\n");
1367 lf_printf(file, " table_entry->function_or_table);\n");
1368 lf_printf(file, "opcode = ((instruction & table_entry->mask)\n");
1369 lf_printf(file, " >> table_entry->shift);\n");
1370 lf_printf(file, "table_entry = table + opcode;\n");
1371 }
1372 lf_indent(file, -2);
1373 lf_printf(file, "}\n");
1dc7c0ed
MM
1374 lf_printf(file, "ASSERT(table_entry->mask == 0);\n");
1375 if (can_assume_leaf)
1376 lf_printf(file, "ASSERT(table_entry->shift == 0);\n");
1377 else {
1378 lf_printf(file, "if (table_entry->shift == 0)\n");
1379 lf_indent(file, +2);
c143ef62 1380 }
1dc7c0ed
MM
1381 if (idecode_cache) {
1382 lf_printf(file, "return (((idecode_crack*)\n");
1383 lf_printf(file, " table_entry->function_or_table)\n");
1384 lf_printf(file, " (%s));\n", cache_idecode_actual);
c143ef62
MM
1385 }
1386 else {
1dc7c0ed
MM
1387 lf_printf(file, "return (((idecode_semantic*)\n");
1388 lf_printf(file, " table_entry->function_or_table)\n");
1389 lf_printf(file, " (%s));\n", semantic_actual);
c143ef62
MM
1390 }
1391 if (!can_assume_leaf) {
1dc7c0ed
MM
1392 lf_indent(file, -2);
1393 lf_printf(file, "/* must be a boolean */\n");
c143ef62
MM
1394 lf_printf(file, "opcode = (instruction & table_entry->shift) != 0;\n");
1395 lf_printf(file, "table = ((idecode_table_entry*)\n");
1396 lf_printf(file, " table_entry->function_or_table);\n");
1397 lf_printf(file, "table_entry = table + opcode;\n");
1398 }
1399 }
1400 lf_indent(file, -2);
1401 lf_printf(file, "}\n");
1402 }
1403 lf_indent(file, -2);
1404 lf_printf(file, "}\n");
1405}
1406
1407
1408static void
1409lf_print_my_prefix(lf *file,
1410 table_entry *file_entry,
1411 int idecode)
1412{
1413 lf_printf(file, "const char *const my_prefix = \n");
1414 lf_printf(file, " \"%s:%s:%s:%d\";\n",
1415 filter_filename (file_entry->file_name),
1416 (idecode ? "idecode" : "semantics"),
1417 file_entry->fields[insn_name],
1418 file_entry->line_nr);
1419}
1420
1421
1422static void
1423lf_print_ptrace(lf *file,
1424 int idecode)
1425{
1426 lf_printf(file, "\n");
1427 lf_printf(file, "ITRACE(trace_%s, (\"\\n\"));\n",
1428 (idecode ? "idecode" : "semantics"));
1429}
1430
1431
1432/****************************************************************/
1433
1434typedef void leaf_handler
1435(insn_table *entry,
1436 void *data,
1437 int depth);
1438typedef void padding_handler
1439(insn_table *table,
1440 void *data,
1441 int depth,
1442 int opcode_nr);
1443
1444
1445static void
1446insn_table_traverse_tree(insn_table *table,
1447 void *data,
1448 int depth,
1449 leaf_handler *start,
1450 leaf_handler *leaf,
1451 leaf_handler *end,
1452 padding_handler *padding)
1453{
1454 insn_table *entry;
1455 int entry_nr;
1456
1457 ASSERT(table != NULL
1458 && table->opcode != NULL
1459 && table->nr_entries > 0
1460 && table->entries != 0);
1461
1462 if (start != NULL && depth >= 0)
1463 start(table, data, depth);
1464
1465 for (entry_nr = 0, entry = table->entries;
1466 entry_nr < (table->opcode->is_boolean
1467 ? 2
1468 : (1 << (table->opcode->last - table->opcode->first + 1)));
1469 entry_nr ++) {
1470 if (entry == NULL
1471 || (!table->opcode->is_boolean
1472 && entry_nr < entry->opcode_nr)) {
1473 if (padding != NULL && depth >= 0)
1474 padding(table, data, depth, entry_nr);
1475 }
1476 else {
1477 ASSERT(entry != NULL && (entry->opcode_nr == entry_nr
1478 || table->opcode->is_boolean));
1479 if (entry->opcode != NULL && depth != 0) {
1480 insn_table_traverse_tree(entry, data, depth+1,
1481 start, leaf, end, padding);
1482 }
1483 else if (depth >= 0) {
1484 if (leaf != NULL)
1485 leaf(entry, data, depth);
1486 }
1487 entry = entry->sibling;
1488 }
1489 }
1490 if (end != NULL && depth >= 0)
1491 end(table, data, depth);
1492}
1493
1494
1495typedef void function_handler
1496(insn_table *table,
1497 void *data,
1498 table_entry *function);
1499
1500static void
1501insn_table_traverse_function(insn_table *table,
1502 void *data,
1503 function_handler *leaf)
1504{
1505 insn *function;
1506 for (function = table->functions;
1507 function != NULL;
1508 function = function->next) {
1509 leaf(table, data, function->file_entry);
1510 }
1511}
1512
1513
1514typedef void insn_handler
1515(insn_table *table,
1516 void *data,
1517 insn *instruction);
1518
1519static void
1520insn_table_traverse_insn(insn_table *table,
1521 void *data,
1522 insn_handler *leaf)
1523{
1524 insn *instruction;
1525 for (instruction = table->insns;
1526 instruction != NULL;
1527 instruction = instruction->next) {
1528 leaf(table, data, instruction);
1529 }
1530}
1531
1532
1533static void
1534update_depth(insn_table *entry,
1535 void *data,
1536 int depth)
1537{
1538 int *max_depth = (int*)data;
1539 if (*max_depth < depth)
1540 *max_depth = depth;
1541}
1542
1543
1544static int
1545insn_table_depth(insn_table *table)
1546{
1547 int depth = 0;
1548 insn_table_traverse_tree(table,
1549 &depth,
1550 1,
1551 NULL, /*start*/
1552 update_depth,
1553 NULL, /*end*/
1554 NULL); /*padding*/
1555 return depth;
1556}
1557
1558
1559/****************************************************************/
1560
1561static void
1562dump_traverse_start(insn_table *table,
1563 void *data,
1564 int depth)
1565{
1566 dumpf(depth*2, "(%d\n", table->opcode_nr);
1567}
1568
1569static void
1570dump_traverse_leaf(insn_table *entry,
1571 void *data,
1572 int depth)
1573{
1574 ASSERT(entry->nr_entries == 0
1575 && entry->nr_insn == 1
1576 && entry->opcode == NULL);
1577 dumpf(depth*2, ".%d %s\n", entry->opcode_nr,
1578 entry->insns->file_entry->fields[insn_format]);
1579}
1580
1581static void
1582dump_traverse_end(insn_table *table,
1583 void *data,
1584 int depth)
1585{
1586 dumpf(depth*2, ")\n");
1587}
1588
1589static void
1590dump_traverse_padding(insn_table *table,
1591 void *data,
1592 int depth,
1593 int opcode_nr)
1594{
1595 dumpf(depth*2, ".<%d>\n", opcode_nr);
1596}
1597
1598
1599static void
1600dump_traverse(insn_table *table)
1601{
1602 insn_table_traverse_tree(table, NULL, 1,
1603 dump_traverse_start,
1604 dump_traverse_leaf,
1605 dump_traverse_end,
1606 dump_traverse_padding);
1607}
1608
1609
1610/****************************************************************/
1611
1612
1613static void
1dc7c0ed
MM
1614lf_print_semantic_function_header(lf *file,
1615 char *basename,
1616 insn_bits *expanded_bits,
1617 int is_function_definition,
1618 int is_inline_function)
c143ef62
MM
1619{
1620 lf_printf(file, "\n");
28816f45 1621 lf_printf(file, "STATIC_SEMANTICS unsigned_word ");
c143ef62
MM
1622 lf_print_function_name(file,
1623 basename,
1624 expanded_bits,
1625 function_name_prefix_semantics);
1dc7c0ed 1626 lf_printf(file, "\n(%s)",
c143ef62 1627 (idecode_cache ? cache_semantic_formal : semantic_formal));
1dc7c0ed
MM
1628 if (!is_function_definition)
1629 lf_printf(file, ";");
1630 lf_printf(file, "\n");
c143ef62
MM
1631}
1632
1633
1634static void
1635semantics_h_leaf(insn_table *entry,
1636 void *data,
1637 int depth)
1638{
1639 lf *file = (lf*)data;
1640 ASSERT(entry->nr_insn == 1);
1dc7c0ed
MM
1641 lf_print_semantic_function_header(file,
1642 entry->insns->file_entry->fields[insn_name],
1643 entry->expanded_bits,
1644 0/* isnt function definition*/,
1645 !idecode_cache && entry->parent->opcode_rule->use_switch);
c143ef62
MM
1646}
1647
1648static void
1649semantics_h_insn(insn_table *entry,
1650 void *data,
1651 insn *instruction)
1652{
1653 lf *file = (lf*)data;
1dc7c0ed
MM
1654 lf_print_semantic_function_header(file,
1655 instruction->file_entry->fields[insn_name],
1656 NULL,
1657 0/*isnt function definition*/,
1658 0/*isnt inline function*/);
c143ef62
MM
1659}
1660
1661static void
1662semantics_h_function(insn_table *entry,
1663 void *data,
1664 table_entry *function)
1665{
1666 lf *file = (lf*)data;
1667 if (function->fields[function_type] == NULL
1668 || function->fields[function_type][0] == '\0') {
1dc7c0ed
MM
1669 lf_print_semantic_function_header(file,
1670 function->fields[function_name],
1671 NULL,
1672 0/*isnt function definition*/,
1673 1/*is inline function*/);
c143ef62
MM
1674 }
1675 else {
1676 lf_printf(file, "\n");
1677 lf_printf(file, "INLINE_SEMANTICS %s %s\n(%s);\n",
1678 function->fields[function_type],
1679 function->fields[function_name],
1680 function->fields[function_param]);
1681 }
1682}
1683
1684
1685static void
1686gen_semantics_h(insn_table *table, lf *file)
1687{
1688
1689 lf_print_copyleft(file);
1690 lf_printf(file, "\n");
1691 lf_printf(file, "#ifndef _SEMANTICS_H_\n");
1692 lf_printf(file, "#define _SEMANTICS_H_\n");
1693 lf_printf(file, "\n");
1694 lf_printf(file, "#ifndef INLINE_SEMANTICS\n");
1695 lf_printf(file, "#define INLINE_SEMANTICS\n");
1696 lf_printf(file, "#endif\n");
1697 lf_printf(file, "\n");
28816f45
MM
1698 lf_printf(file, "#ifndef STATIC_SEMANTICS\n");
1699 lf_printf(file, "#define STATIC_SEMANTICS\n");
1700 lf_printf(file, "#endif\n");
1701 lf_printf(file, "\n");
c143ef62
MM
1702 lf_printf(file, "\n");
1703
1704 /* output a declaration for all functions */
1705 insn_table_traverse_function(table,
1706 file,
1707 semantics_h_function);
1708
1709 /* output a declaration for all instructions */
1710 if (idecode_expand_semantics)
1711 insn_table_traverse_tree(table,
1712 file,
1713 1,
1714 NULL, /* start */
1715 semantics_h_leaf, /* leaf */
1716 NULL, /* end */
1717 NULL); /* padding */
1718 else
1719 insn_table_traverse_insn(table,
1720 file,
1721 semantics_h_insn);
1722
1723 lf_printf(file, "\n");
1724 lf_printf(file, "#endif /* _SEMANTICS_H_ */\n");
1725
1726}
1727
1728/****************************************************************/
1729
1730typedef struct _icache_tree icache_tree;
1731struct _icache_tree {
1732 char *name;
1733 icache_tree *next;
1734 icache_tree *children;
1735};
1736
1737static icache_tree *
1738icache_tree_insert(icache_tree *tree,
1739 char *name)
1740{
1741 icache_tree *new_tree;
1742 /* find it */
1743 icache_tree **ptr_to_cur_tree = &tree->children;
1744 icache_tree *cur_tree = *ptr_to_cur_tree;
1745 while (cur_tree != NULL
1746 && strcmp(cur_tree->name, name) < 0) {
1747 ptr_to_cur_tree = &cur_tree->next;
1748 cur_tree = *ptr_to_cur_tree;
1749 }
1750 ASSERT(cur_tree == NULL
1751 || strcmp(cur_tree->name, name) >= 0);
1752 /* already in the tree */
1753 if (cur_tree != NULL
1754 && strcmp(cur_tree->name, name) == 0)
1755 return cur_tree;
1756 /* missing, insert it */
1757 ASSERT(cur_tree == NULL
1758 || strcmp(cur_tree->name, name) > 0);
1759 new_tree = ZALLOC(icache_tree);
1760 new_tree->name = name;
1761 new_tree->next = cur_tree;
1762 *ptr_to_cur_tree = new_tree;
1763 return new_tree;
1764}
1765
1766
1767static icache_tree *
1768insn_table_cache_fields(insn_table *table)
1769{
1770 icache_tree *tree = ZALLOC(icache_tree);
1771 insn *instruction;
1772 for (instruction = table->insns;
1773 instruction != NULL;
1774 instruction = instruction->next) {
1775 insn_field *field;
1776 icache_tree *form =
1777 icache_tree_insert(tree,
1778 instruction->file_entry->fields[insn_form]);
1779 for (field = instruction->fields->first;
1780 field != NULL;
1781 field = field->next) {
1782 if (field->is_string)
1783 icache_tree_insert(form, field->val_string);
1784 }
1785 }
1786 return tree;
1787}
1788
1789
1790
1791static void
1792gen_icache_h(icache_tree *tree,
1793 lf *file)
1794{
1795 lf_print_copyleft(file);
1796 lf_printf(file, "\n");
1797 lf_printf(file, "#ifndef _ICACHE_H_\n");
1798 lf_printf(file, "#define _ICACHE_H_\n");
1799 lf_printf(file, "\n");
1800 lf_printf(file, "#ifndef INLINE_ICACHE\n");
1801 lf_printf(file, "#define INLINE_ICACHE\n");
1802 lf_printf(file, "#endif\n");
1803 lf_printf(file, "\n");
1804
1805 lf_printf(file, "#define WITH_IDECODE_CACHE_SIZE %d\n",
1806 idecode_cache);
1807 lf_printf(file, "\n");
1808
1809 /* create an instruction cache if being used */
1810 if (idecode_cache) {
1811 icache_tree *form;
1812 lf_printf(file, "typedef struct _idecode_cache {\n");
1813 lf_printf(file, " unsigned_word address;\n");
1814 lf_printf(file, " void *semantic;\n");
1815 lf_printf(file, " union {\n");
1816 for (form = tree->children;
1817 form != NULL;
1818 form = form->next) {
1819 icache_tree *field;
1820 lf_printf(file, " struct {\n");
1821 for (field = form->children;
1822 field != NULL;
1823 field = field->next) {
1824 cache_rules *cache_rule;
1825 int found_rule = 0;
1826 for (cache_rule = cache_table;
1827 cache_rule != NULL;
1828 cache_rule = cache_rule->next) {
1829 if (strcmp(field->name, cache_rule->old_name) == 0) {
1830 found_rule = 1;
1831 if (cache_rule->new_name != NULL)
1832 lf_printf(file, " %s %s; /* %s */\n",
1833 (cache_rule->type == NULL
1834 ? "unsigned"
1835 : cache_rule->type),
1836 cache_rule->new_name,
1837 cache_rule->old_name);
1838 }
1839 }
1840 if (!found_rule)
1841 lf_printf(file, " unsigned %s;\n", field->name);
1842 }
1843 lf_printf(file, " } %s;\n", form->name);
1844 }
1845 lf_printf(file, " } crack;\n");
1846 lf_printf(file, "} idecode_cache;\n");
1847 }
1848 else {
1849 /* alernativly, since no cache, #define the fields to be
1850 extractions from the instruction variable */
1851 cache_rules *cache_rule;
1852 lf_printf(file, "\n");
1853 for (cache_rule = cache_table;
1854 cache_rule != NULL;
1855 cache_rule = cache_rule->next) {
1856 if (cache_rule->expression != NULL
1857 && strlen(cache_rule->expression) > 0)
1858 lf_printf(file, "#define %s %s\n",
1859 cache_rule->new_name, cache_rule->expression);
1860 }
1861 }
1862
1863 lf_printf(file, "\n");
1864 lf_printf(file, "#endif /* _ICACHE_H_ */\n");
1865}
1866
1867
1868
1869
1870/****************************************************************/
1871
1872
1873static void
1874lf_print_c_extraction(lf *file,
1875 insn *instruction,
1876 char *field_name,
1877 char *field_type,
1878 char *field_expression,
1879 insn_field *cur_field,
1880 insn_bits *bits,
1881 int get_value_from_cache,
1882 int put_value_in_cache)
1883{
1884 ASSERT(field_name != NULL);
1885 if (bits != NULL
1886 && (!bits->opcode->is_boolean || bits->value == 0)
1887 && strcmp(field_name, cur_field->val_string) == 0) {
1888 ASSERT(bits->field == cur_field);
1889 ASSERT(field_type == NULL);
1890 table_entry_lf_c_line_nr(file, instruction->file_entry);
1891 lf_printf(file, "const unsigned %s = ",
1892 field_name);
1893 if (bits->opcode->last < bits->field->last)
1894 lf_printf(file, "%d;\n",
1895 bits->value << (bits->field->last - bits->opcode->last));
1896 else
1897 lf_printf(file, "%d;\n", bits->value);
1898 }
1899 else {
1900 /* put the field in the local variable */
1901 table_entry_lf_c_line_nr(file, instruction->file_entry);
1902 lf_printf(file, "%s const %s = ",
1903 field_type == NULL ? "unsigned" : field_type,
1904 field_name);
1905 /* getting it from the cache */
1906 if (get_value_from_cache || put_value_in_cache) {
1907 lf_printf(file, "cache_entry->crack.%s.%s",
1908 instruction->file_entry->fields[insn_form],
1909 field_name);
1910 if (put_value_in_cache) /* also put it in the cache? */
1911 lf_printf(file, " = ");
1912 }
1913 if (!get_value_from_cache) {
1914 if (strcmp(field_name, cur_field->val_string) == 0)
1915 lf_printf(file, "EXTRACTED32(instruction, %d, %d)",
a983c8f0
MM
1916 i2target(hi_bit_nr, cur_field->first),
1917 i2target(hi_bit_nr, cur_field->last));
c143ef62
MM
1918 else if (field_expression != NULL)
1919 lf_printf(file, "%s", field_expression);
1920 else
1921 lf_printf(file, "eval_%s", field_name);
1922 }
1923 lf_printf(file, ";\n");
1924 }
1925}
1926
1927
1928static void
1929lf_print_c_extractions(lf *file,
1930 insn *instruction,
1931 insn_bits *expanded_bits,
1932 int get_value_from_cache,
1933 int put_value_in_cache)
1934{
1935 insn_field *cur_field;
1936
1937 /* extract instruction fields */
1938 lf_printf(file, "/* extraction: %s */\n",
1939 instruction->file_entry->fields[insn_format]);
1940
1941 for (cur_field = instruction->fields->first;
1942 cur_field->first < insn_size;
1943 cur_field = cur_field->next) {
1944 if (cur_field->is_string) {
1945 insn_bits *bits;
1946 int found_rule = 0;
1947 /* find any corresponding value */
1948 for (bits = expanded_bits;
1949 bits != NULL;
1950 bits = bits->last) {
1951 if (bits->field == cur_field)
1952 break;
1953 }
1954 /* try the cache rule table for what to do */
1955 if (get_value_from_cache || put_value_in_cache) {
1956 cache_rules *cache_rule;
1957 for (cache_rule = cache_table;
1958 cache_rule != NULL;
1959 cache_rule = cache_rule->next) {
1960 if (strcmp(cur_field->val_string, cache_rule->old_name) == 0) {
1961 found_rule = 1;
1962 if (cache_rule->valid > 1 && put_value_in_cache)
1963 lf_print_c_extraction(file,
1964 instruction,
1965 cache_rule->new_name,
1966 cache_rule->type,
1967 cache_rule->expression,
1968 cur_field,
1969 bits,
1970 0,
1971 0);
1972 else if (cache_rule->valid == 1)
1973 lf_print_c_extraction(file,
1974 instruction,
1975 cache_rule->new_name,
1976 cache_rule->type,
1977 cache_rule->expression,
1978 cur_field,
1979 bits,
1980 get_value_from_cache,
1981 put_value_in_cache);
1982 }
1983 }
1984 }
1985 if (found_rule == 0)
1986 lf_print_c_extraction(file,
1987 instruction,
1988 cur_field->val_string,
1989 0,
1990 0,
1991 cur_field,
1992 bits,
1993 get_value_from_cache,
1994 put_value_in_cache);
1995 /* if any (XXX == 0), output a corresponding test */
1996 if (instruction->file_entry->annex != NULL) {
1997 char *field_name = cur_field->val_string;
1998 char *is_0_ptr = instruction->file_entry->annex;
1999 int field_len = strlen(field_name);
2000 if (strlen(is_0_ptr) >= (strlen("_is_0") + field_len)) {
2001 is_0_ptr += field_len;
2002 while ((is_0_ptr = strstr(is_0_ptr, "_is_0")) != NULL) {
2003 if (strncmp(is_0_ptr - field_len, field_name, field_len) == 0
2004 && !isalpha(is_0_ptr[ - field_len - 1])) {
2005 table_entry_lf_c_line_nr(file, instruction->file_entry);
2006 lf_printf(file, "const unsigned %s_is_0 = (", field_name);
2007 if (bits != NULL)
2008 lf_printf(file, "%d", bits->value);
2009 else
2010 lf_printf(file, "%s", field_name);
2011 lf_printf(file, " == 0);\n");
2012 break;
2013 }
2014 is_0_ptr += strlen("_is_0");
2015 }
2016 }
2017 }
2018 /* any thing else ... */
2019 }
2020 }
2021 lf_print_lf_c_line_nr(file);
2022}
2023
2024
2025static void
2026lf_print_idecode_illegal(lf *file)
2027{
2028 if (idecode_cache)
2029 lf_printf(file, "return idecode_illegal(%s);\n", cache_idecode_actual);
2030 else
2031 lf_printf(file, "return semantic_illegal(%s);\n", semantic_actual);
2032}
2033
2034
2035static void
2036lf_print_idecode_floating_point_unavailable(lf *file)
2037{
2038 if (idecode_cache)
2039 lf_printf(file, "return idecode_floating_point_unavailable(%s);\n",
2040 cache_idecode_actual);
2041 else
2042 lf_printf(file, "return semantic_floating_point_unavailable(%s);\n",
2043 semantic_actual);
2044}
2045
2046
2047/* Output code to do any final checks on the decoded instruction.
2048 This includes things like verifying any on decoded fields have the
2049 correct value and checking that (for floating point) floating point
2050 hardware isn't disabled */
2051
2052static void
2053lf_print_c_validate(lf *file,
2054 insn *instruction,
2055 opcode_field *opcodes)
2056{
2057 /* Validate: unchecked instruction fields
2058
2059 If any constant fields in the instruction were not checked by the
2060 idecode tables, output code to check that they have the correct
2061 value here */
2062 {
2063 unsigned check_mask = 0;
2064 unsigned check_val = 0;
2065 insn_field *field;
2066 opcode_field *opcode;
2067
2068 /* form check_mask/check_val containing what needs to be checked
2069 in the instruction */
2070 for (field = instruction->fields->first;
2071 field->first < insn_size;
2072 field = field->next) {
2073
2074 check_mask <<= field->width;
2075 check_val <<= field->width;
2076
2077 /* is it a constant that could need validating? */
2078 if (!field->is_int && !field->is_slash)
2079 continue;
2080
2081 /* has it been checked by a table? */
2082 for (opcode = opcodes; opcode != NULL; opcode = opcode->parent) {
2083 if (field->first >= opcode->first
2084 && field->last <= opcode->last)
2085 break;
2086 }
2087 if (opcode != NULL)
2088 continue;
2089
2090 check_mask |= (1 << field->width)-1;
2091 check_val |= field->val_int;
2092 }
2093
2094 /* if any bits not checked by opcode tables, output code to check them */
2095 if (check_mask) {
2096 lf_printf(file, "\n");
2097 lf_printf(file, "/* validate: %s */\n",
2098 instruction->file_entry->fields[insn_format]);
a3114052 2099 lf_printf(file, "if (WITH_RESERVED_BITS && (instruction & 0x%x) != 0x%x)\n",
c143ef62
MM
2100 check_mask, check_val);
2101 lf_indent(file, +2);
2102 lf_print_idecode_illegal(file);
2103 lf_indent(file, -2);
2104 }
2105 }
2106
2107 /* Validate floating point hardware
2108
2109 If the simulator is being built with out floating point hardware
2110 (different to it being disabled in the MSR) then floating point
2111 instructions are invalid */
2112 {
2113 if (it_is("f", instruction->file_entry->fields[insn_flags])) {
2114 lf_printf(file, "\n");
2115 lf_printf(file, "/* Validate: FP hardware exists */\n");
2116 lf_printf(file, "if (CURRENT_FLOATING_POINT != HARD_FLOATING_POINT)\n");
2117 lf_indent(file, +2);
2118 lf_print_idecode_illegal(file);
2119 lf_indent(file, -2);
2120 }
2121 }
2122
2123 /* Validate: Floating Point available
2124
2125 If floating point is not available, we enter a floating point
2126 unavailable interrupt into the cache instead of the instruction
2127 proper.
2128
2129 The PowerPC spec requires a CSI after MSR[FP] is changed and when
2130 ever a CSI occures we flush the instruction cache. */
2131
2132 {
2133 if (it_is("f", instruction->file_entry->fields[insn_flags])) {
2134 lf_printf(file, "\n");
2135 lf_printf(file, "/* Validate: FP available according to MSR[FP] */\n");
2136 lf_printf(file, "if (!IS_FP_AVAILABLE(processor))\n");
2137 lf_indent(file, +2);
2138 lf_print_idecode_floating_point_unavailable(file);
2139 lf_indent(file, -2);
2140 }
2141 }
2142}
2143
2144
2145static void
2146lf_print_c_cracker(lf *file,
2147 insn *instruction,
2148 insn_bits *expanded_bits,
2149 opcode_field *opcodes)
2150{
2151
2152 /* function header */
2153 lf_printf(file, "{\n");
2154 lf_indent(file, +2);
2155
2156 lf_print_my_prefix(file,
2157 instruction->file_entry,
2158 1/*putting-value-in-cache*/);
2159
2160 lf_print_ptrace(file,
2161 1/*putting-value-in-cache*/);
2162
2163 lf_print_c_validate(file, instruction, opcodes);
2164
2165 lf_printf(file, "\n");
2166 lf_printf(file, "{\n");
2167 lf_indent(file, +2);
2168 lf_print_c_extractions(file,
2169 instruction,
2170 expanded_bits,
2171 0/*get_value_from_cache*/,
2172 1/*put_value_in_cache*/);
2173 lf_indent(file, -2);
2174 lf_printf(file, "}\n");
2175
2176 /* return the function propper (main sorts this one out) */
2177 lf_printf(file, "\n");
2178 lf_printf(file, "/* semantic routine */\n");
2179 table_entry_lf_c_line_nr(file, instruction->file_entry);
2180 lf_printf(file, "return ");
2181 lf_print_function_name(file,
2182 instruction->file_entry->fields[insn_name],
2183 expanded_bits,
2184 function_name_prefix_semantics);
2185 lf_printf(file, ";\n");
2186
2187 lf_print_lf_c_line_nr(file);
2188 lf_indent(file, -2);
2189 lf_printf(file, "}\n");
2190}
2191
2192
2193static void
2194lf_print_c_semantic(lf *file,
2195 insn *instruction,
2196 insn_bits *expanded_bits,
2197 opcode_field *opcodes)
2198{
2199
2200 lf_printf(file, "{\n");
2201 lf_indent(file, +2);
2202
2203 lf_print_my_prefix(file,
2204 instruction->file_entry,
2205 0/*not putting value in cache*/);
a983c8f0 2206 lf_printf(file, "unsigned_word nia = cia + %d;\n", insn_size / 8);
c143ef62
MM
2207
2208 lf_printf(file, "\n");
2209 lf_print_c_extractions(file,
2210 instruction,
2211 expanded_bits,
2212 idecode_cache/*get_value_from_cache*/,
2213 0/*put_value_in_cache*/);
2214
2215 lf_print_ptrace(file,
2216 0/*put_value_in_cache*/);
2217
2218 /* validate the instruction, if a cache this has already been done */
2219 if (!idecode_cache)
2220 lf_print_c_validate(file, instruction, opcodes);
2221
2222 /* generate the profileing call - this is delayed until after the
2223 instruction has been verified */
2224 lf_printf(file, "\n");
2225 lf_printf(file, "if (WITH_MON & MONITOR_INSTRUCTION_ISSUE)\n");
2226 lf_printf(file, " mon_issue(");
2227 lf_print_function_name(file,
2228 instruction->file_entry->fields[insn_name],
2229 NULL,
2230 function_name_prefix_itable);
2231 lf_printf(file, ", processor, cia);\n");
2232
2233 /* generate the code (or at least something */
2234 if (instruction->file_entry->annex != NULL) {
2235 /* true code */
2236 lf_printf(file, "\n");
2237 table_entry_lf_c_line_nr(file, instruction->file_entry);
2238 lf_printf(file, "{\n");
2239 lf_indent(file, +2);
2240 lf_print_c_code(file, instruction->file_entry->annex);
2241 lf_indent(file, -2);
2242 lf_printf(file, "}\n");
2243 lf_print_lf_c_line_nr(file);
2244 }
2245 else if (it_is("nop", instruction->file_entry->fields[insn_flags])) {
2246 lf_print_lf_c_line_nr(file);
2247 }
2248 else if (it_is("f", instruction->file_entry->fields[insn_flags])) {
2249 /* unimplemented floating point instruction - call for assistance */
2250 lf_printf(file, "\n");
2251 lf_printf(file, "/* unimplemented floating point instruction - call for assistance */\n");
2252 table_entry_lf_c_line_nr(file, instruction->file_entry);
2253 lf_putstr(file, "floating_point_assist_interrupt(processor, cia);\n");
2254 lf_print_lf_c_line_nr(file);
2255 }
2256 else {
2257 /* abort so it is implemented now */
2258 table_entry_lf_c_line_nr(file, instruction->file_entry);
2259 lf_putstr(file, "error(\"%s: unimplemented, cia=0x%x\\n\", my_prefix, cia);\n");
2260 lf_print_lf_c_line_nr(file);
2261 lf_printf(file, "\n");
2262 }
2263
2264 /* the function footer */
2265 lf_printf(file, "return nia;\n");
2266 lf_indent(file, -2);
2267 lf_printf(file, "}\n");
2268}
2269
c143ef62
MM
2270static void
2271lf_print_c_semantic_function(lf *file,
2272 insn *instruction,
2273 insn_bits *expanded_bits,
1dc7c0ed
MM
2274 opcode_field *opcodes,
2275 int is_inline_function)
c143ef62
MM
2276{
2277
2278 /* build the semantic routine to execute the instruction */
1dc7c0ed
MM
2279 lf_print_semantic_function_header(file,
2280 instruction->file_entry->fields[insn_name],
2281 expanded_bits,
2282 1/*is-function-definition*/,
2283 is_inline_function);
c143ef62
MM
2284 lf_print_c_semantic(file,
2285 instruction,
2286 expanded_bits,
2287 opcodes);
2288}
2289
2290
2291static void
2292semantics_c_leaf(insn_table *entry,
2293 void *data,
2294 int depth)
2295{
2296 lf *file = (lf*)data;
2297 ASSERT(entry->nr_insn == 1
2298 && entry->opcode == NULL
2299 && entry->parent != NULL
2300 && entry->parent->opcode != NULL);
2301 lf_print_c_semantic_function(file,
2302 entry->insns,
2303 entry->expanded_bits,
1dc7c0ed
MM
2304 entry->parent->opcode,
2305 !idecode_cache && entry->parent->opcode_rule->use_switch);
c143ef62
MM
2306}
2307
2308static void
2309semantics_c_insn(insn_table *table,
2310 void *data,
2311 insn *instruction)
2312{
2313 lf *file = (lf*)data;
2314 lf_print_c_semantic_function(file, instruction,
1dc7c0ed
MM
2315 NULL, NULL,
2316 0/*isnt_inline_function*/);
c143ef62
MM
2317}
2318
2319static void
2320semantics_c_function(insn_table *table,
2321 void *data,
2322 table_entry *function)
2323{
2324 lf *file = (lf*)data;
2325 if (function->fields[function_type] == NULL
2326 || function->fields[function_type][0] == '\0') {
1dc7c0ed
MM
2327 lf_print_semantic_function_header(file,
2328 function->fields[function_name],
2329 NULL,
2330 1/*is function definition*/,
2331 1/*is inline function*/);
c143ef62
MM
2332 }
2333 else {
2334 lf_printf(file, "\n");
2335 lf_printf(file, "INLINE_SEMANTICS %s\n%s(%s)\n",
2336 function->fields[function_type],
2337 function->fields[function_name],
2338 function->fields[function_param]);
2339 }
2340 table_entry_lf_c_line_nr(file, function);
2341 lf_printf(file, "{\n");
2342 lf_indent(file, +2);
2343 lf_print_c_code(file, function->annex);
2344 lf_indent(file, -2);
2345 lf_printf(file, "}\n");
2346 lf_print_lf_c_line_nr(file);
2347}
2348
2349
2350
2351static void
2352gen_semantics_c(insn_table *table, lf *file)
2353{
2354 lf_print_copyleft(file);
2355 lf_printf(file, "\n");
2356 lf_printf(file, "#ifndef _SEMANTICS_C_\n");
2357 lf_printf(file, "#define _SEMANTICS_C_\n");
2358 lf_printf(file, "\n");
2359 lf_printf(file, "#ifndef STATIC_INLINE_SEMANTICS\n");
2360 lf_printf(file, "#define STATIC_INLINE_SEMANTICS STATIC_INLINE\n");
2361 lf_printf(file, "#endif\n");
2362 lf_printf(file, "\n");
2363 lf_printf(file, "#include \"cpu.h\"\n");
2364 lf_printf(file, "#include \"idecode.h\"\n");
2365 lf_printf(file, "#include \"semantics.h\"\n");
2366 lf_printf(file, "\n");
2367
2368 /* output a definition (c-code) for all functions */
2369 insn_table_traverse_function(table,
2370 file,
2371 semantics_c_function);
2372
2373 /* output a definition (c-code) for all instructions */
2374 if (idecode_expand_semantics)
2375 insn_table_traverse_tree(table,
2376 file,
2377 1,
2378 NULL, /* start */
2379 semantics_c_leaf,
2380 NULL, /* end */
2381 NULL); /* padding */
2382 else
2383 insn_table_traverse_insn(table,
2384 file,
2385 semantics_c_insn);
2386
2387 lf_printf(file, "\n");
2388 lf_printf(file, "#endif /* _SEMANTICS_C_ */\n");
2389}
2390
2391
2392/****************************************************************/
2393
2394static void
2395gen_idecode_h(insn_table *table, lf *file)
2396{
2397 lf_print_copyleft(file);
2398 lf_printf(file, "\n");
2399 lf_printf(file, "#ifndef _IDECODE_H_\n");
2400 lf_printf(file, "#define _IDECODE_H_\n");
2401 lf_printf(file, "\n");
2402 lf_printf(file, "#ifndef INLINE_IDECODE\n");
2403 lf_printf(file, "#define INLINE_IDECODE\n");
2404 lf_printf(file, "#endif\n");
2405 lf_printf(file, "\n");
2406 lf_printf(file, "#include \"idecode_expression.h\"\n");
2407 lf_printf(file, "#include \"idecode_fields.h\"\n");
2408 lf_printf(file, "#include \"idecode_branch.h\"\n");
2409 lf_printf(file, "\n");
2410 lf_printf(file, "#include \"icache.h\"\n");
2411 lf_printf(file, "\n");
2412 lf_printf(file, "typedef unsigned_word idecode_semantic\n(%s);\n",
2413 (idecode_cache ? cache_semantic_formal : semantic_formal));
2414 lf_printf(file, "\n");
2415 if (idecode_cache)
2416 lf_printf(file, "INLINE_IDECODE idecode_semantic *idecode\n(%s);\n",
2417 cache_idecode_formal);
2418 else
2419 lf_printf(file, "INLINE_IDECODE unsigned_word idecode_issue\n(%s);\n",
2420 semantic_formal);
2421 lf_printf(file, "\n");
2422 lf_printf(file, "#endif /* _IDECODE_H_ */\n");
2423}
2424
2425
2426/****************************************************************/
2427
2428
2429static void
2430idecode_table_start(insn_table *table,
2431 void *data,
2432 int depth)
2433{
2434 lf *file = (lf*)data;
2435 ASSERT(depth == 0);
2436 /* start of the table */
2437 if (!table->opcode_rule->use_switch) {
2438 lf_printf(file, "\n");
2439 lf_printf(file, "static idecode_table_entry ");
2440 lf_print_table_name(file, table);
2441 lf_printf(file, "[] = {\n");
2442 }
2443}
2444
2445static void
2446idecode_table_leaf(insn_table *entry,
2447 void *data,
2448 int depth)
2449{
2450 lf *file = (lf*)data;
2451 ASSERT(entry->parent != NULL);
2452 ASSERT(depth == 0);
2453
2454 /* add an entry to the table */
2455 if (!entry->parent->opcode_rule->use_switch) {
2456 if (entry->opcode == NULL) {
2457 /* table leaf entry */
2458 lf_printf(file, " /*%d*/ { 0, 0, ", entry->opcode_nr);
2459 lf_print_function_name(file,
2460 entry->insns->file_entry->fields[insn_name],
2461 entry->expanded_bits,
2462 (idecode_cache
2463 ? function_name_prefix_idecode
2464 : function_name_prefix_semantics));
2465 lf_printf(file, " },\n");
2466 }
2467 else if (entry->opcode_rule->use_switch) {
2468 /* table calling switch statement */
1dc7c0ed 2469 lf_printf(file, " /*%d*/ { 0, 0, ",
c143ef62
MM
2470 entry->opcode_nr);
2471 lf_print_table_name(file, entry);
2472 lf_printf(file, " },\n");
2473 }
2474 else {
2475 /* table `calling' another table */
2476 lf_printf(file, " /*%d*/ { ", entry->opcode_nr);
2477 if (entry->opcode->is_boolean)
2478 lf_printf(file, "MASK32(%d,%d), 0, ",
a983c8f0
MM
2479 i2target(hi_bit_nr, entry->opcode->first),
2480 i2target(hi_bit_nr, entry->opcode->last));
c143ef62
MM
2481 else
2482 lf_printf(file, "%d, MASK32(%d,%d), ",
2483 insn_size - entry->opcode->last - 1,
a983c8f0
MM
2484 i2target(hi_bit_nr, entry->opcode->first),
2485 i2target(hi_bit_nr, entry->opcode->last));
c143ef62
MM
2486 lf_print_table_name(file, entry);
2487 lf_printf(file, " },\n");
2488 }
2489 }
2490}
2491
2492static void
2493idecode_table_end(insn_table *table,
2494 void *data,
2495 int depth)
2496{
2497 lf *file = (lf*)data;
2498 ASSERT(depth == 0);
2499
2500 if (!table->opcode_rule->use_switch) {
2501 lf_printf(file, "};\n");
2502 }
2503}
2504
2505static void
2506idecode_table_padding(insn_table *table,
2507 void *data,
2508 int depth,
2509 int opcode_nr)
2510{
2511 lf *file = (lf*)data;
2512 ASSERT(depth == 0);
2513
2514 if (!table->opcode_rule->use_switch) {
2515 lf_printf(file, " /*%d*/ { 0, 0, %s_illegal },\n",
2516 opcode_nr, (idecode_cache ? "idecode" : "semantic"));
2517 }
2518}
2519
2520
2521/****************************************************************/
2522
2523
2524void lf_print_idecode_switch
2525(lf *file,
2526 insn_table *table);
2527
2528
2529static void
2530idecode_switch_start(insn_table *table,
2531 void *data,
2532 int depth)
2533{
2534 lf *file = (lf*)data;
2535 ASSERT(depth == 0);
2536 ASSERT(table->opcode_rule->use_switch);
2537
2538 lf_printf(file, "switch (EXTRACTED32(instruction, %d, %d)) {\n",
a983c8f0
MM
2539 i2target(hi_bit_nr, table->opcode->first),
2540 i2target(hi_bit_nr, table->opcode->last));
c143ef62
MM
2541}
2542
2543
2544static void
2545idecode_switch_leaf(insn_table *entry,
2546 void *data,
2547 int depth)
2548{
2549 lf *file = (lf*)data;
2550 ASSERT(entry->parent != NULL);
2551 ASSERT(depth == 0);
2552 ASSERT(entry->parent->opcode_rule->use_switch);
1dc7c0ed 2553 ASSERT(entry->parent->opcode);
c143ef62 2554
1dc7c0ed
MM
2555 if (!entry->parent->opcode->is_boolean
2556 || entry->opcode_nr == 0)
2557 lf_printf(file, "case %d:\n", entry->opcode_nr);
2558 else
2559 lf_printf(file, "default:\n");
c143ef62
MM
2560 lf_indent(file, +2);
2561 {
2562 if (entry->opcode == NULL) {
2563 /* switch calling leaf */
2564 lf_printf(file, "return ");
2565 lf_print_function_name(file,
2566 entry->insns->file_entry->fields[insn_name],
2567 entry->expanded_bits,
2568 (idecode_cache
2569 ? function_name_prefix_idecode
2570 : function_name_prefix_semantics));
2571 if (idecode_cache)
2572 lf_printf(file, "(%s);\n", cache_idecode_actual);
2573 else
2574 lf_printf(file, "(%s);\n", semantic_actual);
2575 }
2576 else if (entry->opcode_rule->use_switch) {
2577 /* switch calling switch */
2578 lf_print_idecode_switch(file, entry);
2579 }
2580 else {
1dc7c0ed 2581 /* switch looking up a table */
c143ef62
MM
2582 lf_print_idecode_table(file, entry);
2583 }
2584 lf_printf(file, "break;\n");
2585 }
2586 lf_indent(file, -2);
2587}
2588
2589
2590static void
2591lf_print_idecode_switch_illegal(lf *file)
2592{
2593 lf_indent(file, +2);
2594 lf_print_idecode_illegal(file);
2595 lf_printf(file, "break;\n");
2596 lf_indent(file, -2);
2597}
2598
2599static void
2600idecode_switch_end(insn_table *table,
2601 void *data,
2602 int depth)
2603{
2604 lf *file = (lf*)data;
2605 ASSERT(depth == 0);
2606 ASSERT(table->opcode_rule->use_switch);
1dc7c0ed 2607 ASSERT(table->opcode);
c143ef62 2608
1dc7c0ed
MM
2609 if (table->opcode_rule->use_switch == 1
2610 && !table->opcode->is_boolean) {
c143ef62
MM
2611 lf_printf(file, "default:\n");
2612 lf_print_idecode_switch_illegal(file);
2613 }
2614 lf_printf(file, "}\n");
2615}
2616
2617static void
2618idecode_switch_padding(insn_table *table,
2619 void *data,
2620 int depth,
2621 int opcode_nr)
2622{
2623 lf *file = (lf*)data;
2624
2625 ASSERT(depth == 0);
2626 ASSERT(table->opcode_rule->use_switch);
2627
2628 if (table->opcode_rule->use_switch > 1) {
2629 lf_printf(file, "case %d:\n", opcode_nr);
2630 lf_print_idecode_switch_illegal(file);
2631 }
2632}
2633
2634
2635void
2636lf_print_idecode_switch(lf *file,
2637 insn_table *table)
2638{
2639 insn_table_traverse_tree(table,
2640 file,
2641 0,
2642 idecode_switch_start,
2643 idecode_switch_leaf,
2644 idecode_switch_end,
2645 idecode_switch_padding);
2646}
2647
2648
1dc7c0ed
MM
2649static void
2650lf_print_idecode_switch_function_header(lf *file,
2651 insn_table *table,
2652 int is_function_definition)
2653{
2654 lf_printf(file, "\n");
2655 lf_printf(file, "static ");
2656 if (idecode_cache)
2657 lf_printf(file, "idecode_semantic *");
2658 else
2659 lf_printf(file, "unsigned_word");
2660 if (is_function_definition)
2661 lf_printf(file, "\n");
2662 else
2663 lf_printf(file, " ");
2664 lf_print_table_name(file, table);
2665 lf_printf(file, "\n(%s)",
2666 (idecode_cache ? cache_idecode_formal : semantic_formal));
2667 if (!is_function_definition)
2668 lf_printf(file, ";");
2669 lf_printf(file, "\n");
2670}
2671
2672
2673static void
2674idecode_declare_if_switch(insn_table *table,
2675 void *data,
2676 int depth)
2677{
2678 lf *file = (lf*)data;
2679
2680 if (table->opcode_rule->use_switch
2681 && table->parent != NULL /* don't declare the top one yet */
2682 && !table->parent->opcode_rule->use_switch) {
2683 lf_print_idecode_switch_function_header(file,
2684 table,
2685 0/*isnt function definition*/);
2686 }
2687}
2688
2689
c143ef62
MM
2690static void
2691idecode_expand_if_switch(insn_table *table,
2692 void *data,
2693 int depth)
2694{
2695 lf *file = (lf*)data;
2696
2697 if (table->opcode_rule->use_switch
2698 && table->parent != NULL /* don't expand the top one yet */
2699 && !table->parent->opcode_rule->use_switch) {
1dc7c0ed
MM
2700 lf_print_idecode_switch_function_header(file,
2701 table,
2702 1/*is function definition*/);
c143ef62
MM
2703 lf_printf(file, "{\n");
2704 {
2705 lf_indent(file, +2);
2706 lf_print_idecode_switch(file, table);
2707 lf_indent(file, -2);
2708 }
2709 lf_printf(file, "}\n");
2710 }
2711}
2712
2713
2714static void
2715lf_print_c_cracker_function(lf *file,
2716 insn *instruction,
2717 insn_bits *expanded_bits,
1dc7c0ed
MM
2718 opcode_field *opcodes,
2719 int is_inline_function)
c143ef62
MM
2720{
2721 /* if needed, generate code to enter this routine into a cache */
2722 lf_printf(file, "\n");
28816f45 2723 lf_printf(file, "STATIC_IDECODE idecode_semantic *\n");
c143ef62
MM
2724 lf_print_function_name(file,
2725 instruction->file_entry->fields[insn_name],
2726 expanded_bits,
2727 function_name_prefix_idecode);
2728 lf_printf(file, "\n(%s)\n", cache_idecode_formal);
2729
2730 lf_print_c_cracker(file,
2731 instruction,
2732 expanded_bits,
2733 opcodes);
2734}
2735
2736static void
2737idecode_crack_leaf(insn_table *entry,
2738 void *data,
2739 int depth)
2740{
2741 lf *file = (lf*)data;
2742 ASSERT(entry->nr_insn == 1
2743 && entry->opcode == NULL
2744 && entry->parent != NULL
1dc7c0ed
MM
2745 && entry->parent->opcode != NULL
2746 && entry->parent->opcode_rule != NULL);
c143ef62
MM
2747 lf_print_c_cracker_function(file,
2748 entry->insns,
2749 entry->expanded_bits,
1dc7c0ed
MM
2750 entry->opcode,
2751 entry->parent->opcode_rule->use_switch);
c143ef62
MM
2752}
2753
2754static void
2755idecode_crack_insn(insn_table *entry,
2756 void *data,
2757 insn *instruction)
2758{
2759 lf *file = (lf*)data;
2760 lf_print_c_cracker_function(file,
2761 instruction,
2762 NULL,
1dc7c0ed
MM
2763 NULL,
2764 0/*isnt inline function*/);
c143ef62
MM
2765}
2766
2767static void
2768idecode_c_internal_function(insn_table *table,
2769 void *data,
2770 table_entry *function)
2771{
2772 lf *file = (lf*)data;
2773 ASSERT(idecode_cache != 0);
2774 if (it_is("internal", function->fields[insn_flags])) {
2775 lf_printf(file, "\n");
2776 lf_printf(file, "STATIC_INLINE_IDECODE idecode_semantic *\n");
2777 lf_print_function_name(file,
2778 function->fields[insn_name],
2779 NULL,
2780 function_name_prefix_idecode);
2781 lf_printf(file, "\n(%s)\n", cache_idecode_formal);
2782 lf_printf(file, "{\n");
2783 lf_indent(file, +2);
2784 lf_printf(file, "/* semantic routine */\n");
2785 table_entry_lf_c_line_nr(file, function);
2786 lf_printf(file, "return ");
2787 lf_print_function_name(file,
2788 function->fields[insn_name],
2789 NULL,
2790 function_name_prefix_semantics);
2791 lf_printf(file, ";\n");
2792
2793 lf_print_lf_c_line_nr(file);
2794 lf_indent(file, -2);
2795 lf_printf(file, "}\n");
2796 }
2797}
2798
2799
2800/****************************************************************/
2801
2802static void
2803gen_idecode_c(insn_table *table, lf *file)
2804{
2805 int depth;
2806
2807 /* the intro */
2808 lf_print_copyleft(file);
2809 lf_printf(file, "\n");
2810 lf_printf(file, "\n");
2811 lf_printf(file, "#ifndef _IDECODE_C_\n");
2812 lf_printf(file, "#define _IDECODE_C_\n");
2813 lf_printf(file, "\n");
2814 lf_printf(file, "#ifndef STATIC_INLINE_IDECODE\n");
2815 lf_printf(file, "#define STATIC_INLINE_IDECODE STATIC_INLINE\n");
2816 lf_printf(file, "#endif\n");
2817 lf_printf(file, "\n");
28816f45
MM
2818 lf_printf(file, "#ifndef STATIC_IDECODE\n");
2819 lf_printf(file, "#define STATIC_IDECODE\n");
2820 lf_printf(file, "#endif\n");
2821 lf_printf(file, "\n");
c143ef62
MM
2822 lf_printf(file, "#include \"cpu.h\"\n");
2823 lf_printf(file, "#include \"idecode.h\"\n");
2824 lf_printf(file, "#include \"semantics.h\"\n");
2825 lf_printf(file, "\n");
2826 lf_printf(file, "\n");
2827 lf_printf(file, "typedef idecode_semantic *idecode_crack\n(%s);\n",
2828 (idecode_cache ? cache_idecode_formal : semantic_formal));
2829 lf_printf(file, "\n");
2830 lf_printf(file, "typedef struct _idecode_table_entry {\n");
2831 lf_printf(file, " unsigned shift;\n");
2832 lf_printf(file, " unsigned mask;\n");
2833 lf_printf(file, " void *function_or_table;\n");
2834 lf_printf(file, "} idecode_table_entry;\n");
2835 lf_printf(file, "\n");
2836 lf_printf(file, "\n");
2837
2838 /* output `internal' invalid/floating-point unavailable functions
2839 where needed */
2840 if (idecode_cache) {
2841 insn_table_traverse_function(table,
2842 file,
2843 idecode_c_internal_function);
2844 }
2845
2846 /* output cracking functions where needed */
2847 if (idecode_cache) {
2848 if (idecode_expand_semantics)
2849 insn_table_traverse_tree(table,
2850 file,
2851 1,
2852 NULL,
2853 idecode_crack_leaf,
2854 NULL,
2855 NULL);
2856 else
2857 insn_table_traverse_insn(table,
2858 file,
2859 idecode_crack_insn);
2860 }
2861
1dc7c0ed
MM
2862 /* output switch function declarations where needed by tables */
2863 insn_table_traverse_tree(table,
2864 file,
2865 1,
2866 idecode_declare_if_switch, /* START */
2867 NULL, NULL, NULL);
c143ef62
MM
2868
2869 /* output tables where needed */
2870 for (depth = insn_table_depth(table);
2871 depth > 0;
2872 depth--) {
2873 insn_table_traverse_tree(table,
2874 file,
2875 1-depth,
2876 idecode_table_start,
2877 idecode_table_leaf,
2878 idecode_table_end,
2879 idecode_table_padding);
2880 }
2881
2882 /* output switch functions where needed */
2883 insn_table_traverse_tree(table,
2884 file,
2885 1,
2886 idecode_expand_if_switch, /* START */
2887 NULL, NULL, NULL);
2888
2889 /* output the main idecode routine */
2890 lf_printf(file, "\n");
2891 if (idecode_cache)
2892 lf_printf(file, "INLINE_IDECODE idecode_semantic *\nidecode\n(%s)\n",
2893 cache_idecode_formal);
2894 else
2895 lf_printf(file, "INLINE_IDECODE unsigned_word\nidecode_issue\n(%s)\n",
2896 semantic_formal);
2897 lf_printf(file, "{\n");
2898 lf_indent(file, +2);
2899 if (table->opcode_rule->use_switch)
2900 lf_print_idecode_switch(file, table);
2901 else
2902 lf_print_idecode_table(file, table);
2903 lf_indent(file, -2);
2904 lf_printf(file, "}\n");
2905 lf_printf(file, "\n");
1dc7c0ed 2906 lf_printf(file, "#endif /* _IDECODE_C_ */\n");
c143ef62
MM
2907}
2908
2909
2910/****************************************************************/
2911
2912static void
2913itable_h_insn(insn_table *entry,
2914 void *data,
2915 insn *instruction)
2916{
2917 lf *file = (lf*)data;
2918 lf_printf(file, " ");
2919 lf_print_function_name(file,
2920 instruction->file_entry->fields[insn_name],
2921 NULL,
2922 function_name_prefix_itable);
2923 lf_printf(file, ",\n");
2924}
2925
2926
2927static void
2928gen_itable_h(insn_table *table, lf *file)
2929{
2930
2931 lf_print_copyleft(file);
2932 lf_printf(file, "\n");
2933 lf_printf(file, "#ifndef _ITABLE_H_\n");
2934 lf_printf(file, "#define _ITABLE_H_\n");
2935 lf_printf(file, "\n");
2936 lf_printf(file, "#ifndef INLINE_ITABLE\n");
2937 lf_printf(file, "#define INLINE_ITABLE\n");
2938 lf_printf(file, "#endif\n");
2939 lf_printf(file, "\n");
2940 lf_printf(file, "\n");
2941
2942 /* output an enumerated type for each instruction */
2943 lf_printf(file, "typedef enum {\n");
2944 insn_table_traverse_insn(table,
2945 file,
2946 itable_h_insn);
2947 lf_printf(file, " nr_itable_entries,\n");
2948 lf_printf(file, "} itable_index;\n");
2949 lf_printf(file, "\n");
2950
2951 /* output the table that contains the actual instruction info */
2952 lf_printf(file, "typedef struct _itable_instruction_info {\n");
2953 lf_printf(file, " itable_index nr;\n");
2954 lf_printf(file, " char *format;\n");
2955 lf_printf(file, " char *form;\n");
2956 lf_printf(file, " char *flags;\n");
1dc7c0ed 2957 lf_printf(file, " char *mnemonic;\n");
c143ef62
MM
2958 lf_printf(file, " char *name;\n");
2959 lf_printf(file, "} itable_info;\n");
2960 lf_printf(file, "\n");
2961 lf_printf(file, "extern itable_info itable[nr_itable_entries];\n");
2962
2963 lf_printf(file, "\n");
2964 lf_printf(file, "#endif /* _ITABLE_C_ */\n");
2965
2966}
2967
2968/****************************************************************/
2969
2970static void
2971itable_c_insn(insn_table *entry,
2972 void *data,
2973 insn *instruction)
2974{
2975 lf *file = (lf*)data;
2976 char **fields = instruction->file_entry->fields;
2977 lf_printf(file, " { ");
2978 lf_print_function_name(file,
2979 instruction->file_entry->fields[insn_name],
2980 NULL,
2981 function_name_prefix_itable);
2982 lf_printf(file, ",\n");
2983 lf_printf(file, " \"%s\",\n", fields[insn_format]);
2984 lf_printf(file, " \"%s\",\n", fields[insn_form]);
2985 lf_printf(file, " \"%s\",\n", fields[insn_flags]);
1dc7c0ed 2986 lf_printf(file, " \"%s\",\n", fields[insn_mnemonic]);
c143ef62
MM
2987 lf_printf(file, " \"%s\",\n", fields[insn_name]);
2988 lf_printf(file, " },\n");
2989}
2990
2991
2992static void
2993gen_itable_c(insn_table *table, lf *file)
2994{
2995
2996 lf_print_copyleft(file);
2997 lf_printf(file, "\n");
2998 lf_printf(file, "#ifndef _ITABLE_C_\n");
2999 lf_printf(file, "#define _ITABLE_C_\n");
3000 lf_printf(file, "\n");
3001 lf_printf(file, "#ifndef STATIC_INLINE_ITABLE\n");
3002 lf_printf(file, "#define STATIC_INLINE_ITABLE STATIC_INLINE\n");
3003 lf_printf(file, "#endif\n");
3004 lf_printf(file, "\n");
3005 lf_printf(file, "#include \"itable.h\"\n");
3006 lf_printf(file, "\n");
3007
3008 /* output the table that contains the actual instruction info */
3009 lf_printf(file, "itable_info itable[nr_itable_entries] = {\n");
3010 insn_table_traverse_insn(table,
3011 file,
3012 itable_c_insn);
3013 lf_printf(file, "};\n");
3014 lf_printf(file, "\n");
3015
3016 lf_printf(file, "\n");
3017 lf_printf(file, "#endif /* _ITABLE_C_ */\n");
a3114052
MM
3018}
3019
3020/****************************************************************/
3021
eb4ef197 3022static void
1dc7c0ed
MM
3023model_c_or_h_data(insn_table *table,
3024 lf *file,
3025 table_entry *data)
3026{
3027 if (data->annex) {
3028 table_entry_lf_c_line_nr(file, data);
3029 lf_print_c_code(file, data->annex);
3030 lf_print_lf_c_line_nr(file);
3031 lf_printf(file, "\n");
3032 }
3033}
3034
3035static void
3036model_c_or_h_function(insn_table *entry,
3037 lf *file,
3038 table_entry *function,
3039 char *prefix)
eb4ef197
MM
3040{
3041 if (function->fields[function_type] == NULL
3042 || function->fields[function_type][0] == '\0') {
1dc7c0ed 3043 error("Model function type not specified for %s", function->fields[function_name]);
eb4ef197
MM
3044 }
3045 else {
3046 lf_printf(file, "\n");
1dc7c0ed
MM
3047 lf_printf(file, "%s %s %s\n(%s);\n",
3048 prefix,
eb4ef197
MM
3049 function->fields[function_type],
3050 function->fields[function_name],
3051 function->fields[function_param]);
3052 }
1dc7c0ed 3053 lf_printf(file, "\n");
eb4ef197
MM
3054}
3055
a3114052
MM
3056static void
3057gen_model_h(insn_table *table, lf *file)
3058{
eb4ef197 3059 insn *insn_ptr;
a3114052
MM
3060 model *model_ptr;
3061 model_func_unit *func_unit_ptr;
28816f45 3062 insn *macro;
a3114052
MM
3063 int hex_size;
3064
3065 lf_print_copyleft(file);
3066 lf_printf(file, "\n");
3067 lf_printf(file, "#ifndef _MODEL_H_\n");
3068 lf_printf(file, "#define _MODEL_H_\n");
3069 lf_printf(file, "\n");
eb4ef197 3070
1dc7c0ed 3071 for(macro = model_macros; macro; macro = macro->next) {
ac79ccd4 3072 model_c_or_h_data(table, file, macro->file_entry);
eb4ef197
MM
3073 }
3074
a3114052
MM
3075 lf_printf(file, "#ifndef INLINE_MODEL\n");
3076 lf_printf(file, "#define INLINE_MODEL\n");
3077 lf_printf(file, "#endif\n");
28816f45
MM
3078 lf_printf(file, "#ifndef STATIC_INLINE_MODEL\n");
3079 lf_printf(file, "#define STATIC_INLINE_MODEL STATIC_INLINE\n");
3080 lf_printf(file, "#endif\n");
3081 lf_printf(file, "\n");
f35df46c
MM
3082 lf_printf(file, "#ifndef STATIC_MODEL\n");
3083 lf_printf(file, "#define STATIC_MODEL\n");
3084 lf_printf(file, "#endif\n");
3085 lf_printf(file, "\n");
39c32461
MM
3086 lf_printf(file, "#ifndef EXTERN_MODEL\n");
3087 lf_printf(file, "#define EXTERN_MODEL extern\n");
3088 lf_printf(file, "#endif\n");
a3114052
MM
3089 lf_printf(file, "\n");
3090
a3114052
MM
3091 if (table->max_func_unit_mask > 0xffff) {
3092 hex_size = 8;
28816f45
MM
3093 lf_printf(file, "#ifndef MODEL_UNITS\n");
3094 lf_printf(file, "#define MODEL_UNITS unsigned32\n");
3095 lf_printf(file, "#endif\n");
3096 lf_printf(file, "\n");
3097
3098 lf_printf(file, "#ifndef MODEL_CYCLES\n");
3099 lf_printf(file, "#define MODEL_CYCLES unsigned16\n");
3100 lf_printf(file, "#endif\n");
3101 lf_printf(file, "\n");
a3114052
MM
3102 } else {
3103 hex_size = 4;
28816f45
MM
3104 lf_printf(file, "#ifndef MODEL_UNITS\n");
3105 lf_printf(file, "#define MODEL_UNITS unsigned16\n");
3106 lf_printf(file, "#endif\n");
3107 lf_printf(file, "\n");
3108
3109 lf_printf(file, "#ifndef MODEL_CYCLES\n");
3110 lf_printf(file, "#define MODEL_CYCLES unsigned8\n");
3111 lf_printf(file, "#endif\n");
3112 lf_printf(file, "\n");
a3114052 3113 }
28816f45
MM
3114
3115 lf_printf(file, "#ifndef MODEL_FLAGS\n");
3116 lf_printf(file, "#define MODEL_FLAGS unsigned32\n");
3117 lf_printf(file, "#endif\n");
3118 lf_printf(file, "\n");
3119
3120 lf_printf(file, "typedef struct _model_time {\t/* Instruction cycle time */\n");
3121 lf_printf(file, " MODEL_UNITS units;\n");
3122 lf_printf(file, " MODEL_CYCLES initial;\n");
3123 lf_printf(file, " MODEL_CYCLES finish;\n");
3124 lf_printf(file, " MODEL_FLAGS flags;\n");
a3114052
MM
3125 lf_printf(file, "} model_time;\n");
3126 lf_printf(file, "\n");
3127
3128 lf_printf(file, "typedef enum _model_enum {\n");
3129 lf_printf(file, " MODEL_NONE,\n");
3130 for (model_ptr = models; model_ptr; model_ptr = model_ptr->next) {
3131 lf_printf(file, " MODEL_%s,\n", model_ptr->name);
3132 }
3133 lf_printf(file, " nr_models\n");
3134 lf_printf(file, "} model_enum;\n");
3135 lf_printf(file, "\n");
3136
28816f45
MM
3137 lf_printf(file, "#define DEFAULT_MODEL MODEL_%s\n", (models) ? models->name : "NONE");
3138 lf_printf(file, "\n");
3139
a3114052
MM
3140 for (model_ptr = models; model_ptr; model_ptr = model_ptr->next) {
3141 for (func_unit_ptr = model_ptr->func_unit_start; func_unit_ptr; func_unit_ptr = func_unit_ptr->next) {
3142 if (func_unit_ptr->comment) {
3143 lf_printf(file, "#define %-*s 0x%.*x /* %s functional unit */\n",
3144 table->max_func_unit_name_len, func_unit_ptr->name,
3145 hex_size, func_unit_ptr->mask,
3146 func_unit_ptr->comment);
3147 } else {
3148 lf_printf(file, "#define %-*s 0x%.*x\n",
3149 table->max_func_unit_name_len, func_unit_ptr->name,
3150 hex_size, func_unit_ptr->mask);
3151 }
3152 }
3153 lf_printf(file, "\n");
3154 }
3155
39c32461
MM
3156 lf_printf(file, "EXTERN_MODEL model_enum current_model;\n");
3157 lf_printf(file, "EXTERN_MODEL const char *model_name[ (int)nr_models ];\n");
3158 lf_printf(file, "EXTERN_MODEL const char *const *const model_func_unit_name[ (int)nr_models ];\n");
3159 lf_printf(file, "EXTERN_MODEL const model_time *const model_time_mapping[ (int)nr_models ];\n");
28816f45
MM
3160 lf_printf(file, "\n");
3161 lf_printf(file, "INLINE_MODEL void model_set\n");
3162 lf_printf(file, "(const char *name);\n");
eb4ef197
MM
3163
3164 for(insn_ptr = model_functions; insn_ptr; insn_ptr = insn_ptr->next) {
1dc7c0ed 3165 model_c_or_h_function(table, file, insn_ptr->file_entry, "INLINE_MODEL");
eb4ef197
MM
3166 lf_printf(file, "\n");
3167 }
3168
a3114052
MM
3169 lf_printf(file, "\n");
3170 lf_printf(file, "#endif /* _MODEL_H_ */\n");
3171}
3172
3173/****************************************************************/
3174
1dc7c0ed
MM
3175typedef struct _model_c_passed_data model_c_passed_data;
3176struct _model_c_passed_data {
a3114052
MM
3177 lf *file;
3178 model *model_ptr;
3179};
3180
3181static void
3182model_c_insn(insn_table *entry,
3183 void *data,
3184 insn *instruction)
3185{
1dc7c0ed 3186 model_c_passed_data *data_ptr = (model_c_passed_data *)data;
a3114052 3187 lf *file = data_ptr->file;
28816f45 3188 char *current_name = data_ptr->model_ptr->name;
a3114052
MM
3189 table_model_entry *model_ptr = instruction->file_entry->model_first;
3190 int i;
3191
3192 while (model_ptr) {
28816f45 3193 if (model_ptr->fields[insn_model_name] == current_name) {
a3114052
MM
3194 lf_printf(file, " {");
3195 for(i = insn_model_unit; i < nr_insn_model_table_fields; i++) {
3196 lf_printf(file, " %s,", model_ptr->fields[i]);
3197 }
1dc7c0ed 3198 lf_printf(file, " }, /* %s */\n", instruction->file_entry->fields[insn_name]);
a3114052
MM
3199 return;
3200 }
3201
3202 model_ptr = model_ptr->next;
3203 }
3204
28816f45 3205 lf_printf(file, " { %s_SENTINEL },\n", current_name);
a3114052
MM
3206}
3207
eb4ef197
MM
3208static void
3209model_c_function(insn_table *table,
3210 lf *file,
1dc7c0ed
MM
3211 table_entry *function,
3212 const char *prefix)
eb4ef197
MM
3213{
3214 if (function->fields[function_type] == NULL
3215 || function->fields[function_type][0] == '\0') {
1dc7c0ed 3216 error("Model function return type not specified for %s", function->fields[function_name]);
eb4ef197
MM
3217 }
3218 else {
3219 lf_printf(file, "\n");
1dc7c0ed
MM
3220 lf_printf(file, "%s %s\n%s(%s)\n",
3221 prefix,
eb4ef197
MM
3222 function->fields[function_type],
3223 function->fields[function_name],
3224 function->fields[function_param]);
3225 }
3226 table_entry_lf_c_line_nr(file, function);
3227 lf_printf(file, "{\n");
3228 if (function->annex) {
3229 lf_indent(file, +2);
3230 lf_print_c_code(file, function->annex);
3231 lf_indent(file, -2);
3232 }
3233 lf_printf(file, "}\n");
3234 lf_print_lf_c_line_nr(file);
1dc7c0ed 3235 lf_printf(file, "\n");
eb4ef197
MM
3236}
3237
a3114052
MM
3238static void
3239gen_model_c(insn_table *table, lf *file)
3240{
eb4ef197 3241 insn *insn_ptr;
a3114052
MM
3242 model *model_ptr;
3243 model_func_unit *func_unit_ptr;
3244 int i;
3245
3246 lf_print_copyleft(file);
3247 lf_printf(file, "\n");
3248 lf_printf(file, "#ifndef _MODEL_C_\n");
3249 lf_printf(file, "#define _MODEL_C_\n");
3250 lf_printf(file, "\n");
a3114052
MM
3251 lf_printf(file, "#include \"cpu.h\"\n");
3252 lf_printf(file, "\n");
3253
1dc7c0ed
MM
3254 for(insn_ptr = model_data; insn_ptr; insn_ptr = insn_ptr->next) {
3255 model_c_or_h_data(table, file, insn_ptr->file_entry);
3256 }
3257
3258 for(insn_ptr = model_internal; insn_ptr; insn_ptr = insn_ptr->next) {
3259 model_c_or_h_function(table, file, insn_ptr->file_entry, "STATIC_INLINE_MODEL");
3260 }
3261
a3114052 3262 lf_printf(file, "/* map model enumeration into printable string */\n");
f35df46c 3263 lf_printf(file, "STATIC_MODEL const char *model_name[ (int)nr_models ] = {\n");
a3114052
MM
3264 lf_printf(file, " \"NONE\",\n");
3265 for (model_ptr = models; model_ptr; model_ptr = model_ptr->next) {
28816f45 3266 lf_printf(file, " \"%s\",\n", model_ptr->printable_name);
a3114052
MM
3267 }
3268 lf_printf(file, "};\n");
3269 lf_printf(file, "\n");
3270
3271 lf_printf(file, "/* Emit each model's individual function unit names */\n");
3272 lf_printf(file, "static const char *const model_func_unit_name_NONE[] = {\n");
3273 lf_printf(file, " \"none\",\n");
3274 lf_printf(file, " (const char *)0\n");
3275 lf_printf(file, "};\n");
3276 lf_printf(file, "\n");
3277
3278 for (model_ptr = models; model_ptr; model_ptr = model_ptr->next) {
3279 lf_printf(file, "static const char *const model_func_unit_name_%s[] = {\n", model_ptr->name);
3280 lf_printf(file, " \"none\",\n");
3281 for (func_unit_ptr = model_ptr->func_unit_start; func_unit_ptr; func_unit_ptr = func_unit_ptr->next) {
3282
3283 if (func_unit_ptr->comment)
3284 lf_printf(file, " \"%s %s functional unit\",\n", func_unit_ptr->name, func_unit_ptr->comment);
3285 else
3286 lf_printf(file, " \"%s\",\n", func_unit_ptr->name);
3287
3288 for(i = 2; i < func_unit_ptr->number; i++) {
3289 if (func_unit_ptr->comment)
3290 lf_printf(file, " \"%s %s functional unit #%d\",\n", func_unit_ptr->name,
3291 func_unit_ptr->comment, i);
3292 else
3293 lf_printf(file, " \"%s #%d\",\n", func_unit_ptr->name, i);
3294 }
3295 }
3296
3297 lf_printf(file, " (const char *)0\n");
3298 lf_printf(file, "};\n");
3299 lf_printf(file, "\n");
3300 }
3301
3302 lf_printf(file, "/* Array to map model,function unit number to printable string. */\n");
f35df46c 3303 lf_printf(file, "STATIC_MODEL const char *const *const model_func_unit_name[] = {\n");
a3114052
MM
3304 lf_printf(file, " model_func_unit_name_NONE,\n");
3305 for(model_ptr = models; model_ptr; model_ptr = model_ptr->next) {
3306 lf_printf(file, " model_func_unit_name_%s,\n", model_ptr->name);
3307 }
3308 lf_printf(file, "};\n");
3309 lf_printf(file, "\n");
eb4ef197 3310 lf_printf(file, "\f\n");
a3114052
MM
3311
3312 lf_printf(file, "/* Insn functional unit info */\n");
3313 for(model_ptr = models; model_ptr; model_ptr = model_ptr->next) {
1dc7c0ed 3314 model_c_passed_data data;
a3114052
MM
3315
3316 lf_printf(file, "static const model_time model_time_%s[] = {\n", model_ptr->name);
3317 data.file = file;
3318 data.model_ptr = model_ptr;
3319 insn_table_traverse_insn(table,
3320 (void *)&data,
3321 model_c_insn);
3322
3323 lf_printf(file, "};\n");
3324 lf_printf(file, "\n");
eb4ef197 3325 lf_printf(file, "\f\n");
a3114052
MM
3326 }
3327
f35df46c 3328 lf_printf(file, "STATIC_MODEL const model_time *const model_time_mapping[ (int)nr_models ] = {\n");
a3114052
MM
3329 lf_printf(file, " (const model_time *const)0,\n");
3330 for(model_ptr = models; model_ptr; model_ptr = model_ptr->next) {
3331 lf_printf(file, " model_time_%s,\n", model_ptr->name);
3332 }
3333 lf_printf(file, "};\n");
3334 lf_printf(file, "\n");
3335
1dc7c0ed
MM
3336 for(insn_ptr = model_internal; insn_ptr; insn_ptr = insn_ptr->next) {
3337 model_c_function(table, file, insn_ptr->file_entry, "STATIC_INLINE_MODEL");
3338 }
3339
eb4ef197 3340 for(insn_ptr = model_functions; insn_ptr; insn_ptr = insn_ptr->next) {
1dc7c0ed 3341 model_c_function(table, file, insn_ptr->file_entry, "INLINE_MODEL");
eb4ef197
MM
3342 }
3343
28816f45
MM
3344 lf_printf(file, "INLINE_MODEL void\n");
3345 lf_printf(file, "model_set(const char *name)\n");
3346 lf_printf(file, "{\n");
3347 if (models) {
3348 lf_printf(file, " model_enum model;\n");
3349 lf_printf(file, " for(model = MODEL_%s; model < nr_models; model++) {\n", models->name);
fe439e0f 3350 lf_printf(file, " if(strcmp(name, model_name[model]) == 0) {\n");
28816f45
MM
3351 lf_printf(file, " current_model = model;\n");
3352 lf_printf(file, " return;\n");
3353 lf_printf(file, " }\n");
3354 lf_printf(file, " }\n");
3355 lf_printf(file, "\n");
3356 lf_printf(file, " error(\"Unknown model '%%s', Models which are known are:%%s\n\",\n");
3357 lf_printf(file, " name,\n");
3358 lf_printf(file, " \"");
3359 for(model_ptr = models; model_ptr; model_ptr = model_ptr->next) {
3360 lf_printf(file, "\\n\\t%s", model_ptr->printable_name);
3361 }
3362 lf_printf(file, "\");\n");
3363 } else {
3364 lf_printf(file, " error(\"No models are currently known about\");\n");
3365 }
3366
3367 lf_printf(file, "}\n");
3368 lf_printf(file, "\n");
3369
a3114052 3370 lf_printf(file, "#endif /* _MODEL_C_ */\n");
c143ef62
MM
3371
3372}
3373
3374/****************************************************************/
3375
3376
3377int
3378main(int argc,
3379 char **argv,
3380 char **envp)
3381{
3382 insn_table *instructions = NULL;
3383 icache_tree *cache_fields = NULL;
3384 char *real_file_name = NULL;
3385 int ch;
3386
3387 if (argc == 1) {
3388 printf("Usage:\n");
a983c8f0
MM
3389 printf(" igen <config-opts> ... <input-opts>... <output-opts>...\n");
3390 printf("Config options:\n");
3391 printf(" -f <filter-out-flag> eg -f 64 to skip 64bit instructions\n");
3392 printf(" -e Expand (duplicate) semantic functions\n");
3393 printf(" -r <icache-size> Generate cracking cache version\n");
3394 printf(" -l Supress line numbering in output files\n");
3395 printf(" -b <bit-size> Set the number of bits in an instruction\n");
3396 printf(" -h <high-bit> Set the nr of the high (msb bit)\n");
3397 printf("Input options (ucase version also dumps loaded table):\n");
3398 printf(" -[Oo] <opcode-rules>\n");
3399 printf(" -[Kk] <cache-rules>\n");
3400 printf(" -[Ii] <instruction-table>\n");
3401 printf("Output options:\n");
3402 printf(" -[Cc] <output-file> output icache.h(C) invalid(c)\n");
3403 printf(" -[Dd] <output-file> output idecode.h(D) idecode.c(d)\n");
a3114052 3404 printf(" -[Mm] <output-file> output model.h(M) model.c(M)\n");
a983c8f0
MM
3405 printf(" -[Ss] <output-file> output schematic.h(S) schematic.c(s)\n");
3406 printf(" -[Tt] <table> output itable.h(T) itable.c(t)\n");
c143ef62
MM
3407 }
3408
3409 while ((ch = getopt(argc, argv,
a3114052 3410 "leb:h:r:f:I:i:O:o:K:k:M:m:n:S:s:D:d:T:t:C:")) != -1) {
c143ef62
MM
3411 fprintf(stderr, "\t-%c %s\n", ch, (optarg ? optarg : ""));
3412 switch(ch) {
3413 case 'l':
3414 number_lines = 0;
3415 break;
3416 case 'e':
3417 idecode_expand_semantics = 1;
3418 break;
3419 case 'r':
3420 idecode_cache = a2i(optarg);
3421 break;
a983c8f0
MM
3422 case 'b':
3423 insn_size = a2i(optarg);
3424 ASSERT(insn_size > 0 && insn_size <= max_insn_size
3425 && (hi_bit_nr == insn_size-1 || hi_bit_nr == 0));
3426 break;
3427 case 'h':
3428 hi_bit_nr = a2i(optarg);
3429 ASSERT(hi_bit_nr == insn_size-1 || hi_bit_nr == 0);
3430 break;
c143ef62
MM
3431 case 'f':
3432 {
3433 filter *new_filter = ZALLOC(filter);
3434 new_filter->flag = strdup(optarg);
3435 new_filter->next = filters;
3436 filters = new_filter;
3437 break;
3438 }
3439 case 'I':
3440 case 'i':
3441 ASSERT(opcode_table != NULL);
3442 ASSERT(cache_table != NULL);
3443 instructions = insn_table_load_insns(optarg);
3444 fprintf(stderr, "\texpanding ...\n");
3445 insn_table_expand_insns(instructions);
3446 fprintf(stderr, "\tcache fields ...\n");
3447 cache_fields = insn_table_cache_fields(instructions);
3448 if (ch == 'I') {
3449 dump_traverse(instructions);
3450 dump_insn_table(instructions, 0, 1);
3451 }
3452 break;
3453 case 'O':
3454 case 'o':
3455 opcode_table = load_opcode_rules(optarg);
3456 if (ch == 'O')
3457 dump_opcode_rules(opcode_table, 0);
3458 break;
3459 case 'K':
3460 case 'k':
3461 cache_table = load_cache_rules(optarg);
3462 if (ch == 'K')
3463 dump_cache_rules(cache_table, 0);
3464 break;
3465 case 'n':
3466 real_file_name = strdup(optarg);
3467 break;
3468 case 'S':
3469 case 's':
3470 case 'D':
3471 case 'd':
a3114052
MM
3472 case 'M':
3473 case 'm':
c143ef62
MM
3474 case 'T':
3475 case 't':
3476 case 'C':
3477 {
3478 lf *file = lf_open(optarg, real_file_name, number_lines);
3479 ASSERT(instructions != NULL);
3480 switch (ch) {
3481 case 'S':
3482 gen_semantics_h(instructions, file);
3483 break;
3484 case 's':
3485 gen_semantics_c(instructions, file);
3486 break;
3487 case 'D':
3488 gen_idecode_h(instructions, file);
3489 break;
3490 case 'd':
3491 gen_idecode_c(instructions, file);
3492 break;
a3114052
MM
3493 case 'M':
3494 gen_model_h(instructions, file);
3495 break;
3496 case 'm':
3497 gen_model_c(instructions, file);
3498 break;
c143ef62
MM
3499 case 'T':
3500 gen_itable_h(instructions, file);
3501 break;
3502 case 't':
3503 gen_itable_c(instructions, file);
3504 break;
3505 case 'C':
3506 gen_icache_h(cache_fields, file);
3507 break;
3508 }
3509 lf_close(file);
3510 }
3511 real_file_name = NULL;
3512 break;
3513 default:
3514 error("unknown option\n");
3515 }
3516 }
3517 return 0;
3518}
This page took 0.173157 seconds and 4 git commands to generate.