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