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