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