]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blob - sim/ppc/igen.c
Add floating point model specific support; Redo method model specific support is...
[thirdparty/binutils-gdb.git] / sim / ppc / igen.c
1 /* This file is part of the program psim.
2
3 Copyright (C) 1994-1995, Andrew Cagney <cagney@highland.com.au>
4
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 2 of the License, or
8 (at your option) any later version.
9
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
18
19 */
20
21 #include <stdio.h>
22 #include <ctype.h>
23 #include <getopt.h>
24
25 #include "misc.h"
26 #include "lf.h"
27 #include "table.h"
28 #include "config.h"
29
30 #ifdef HAVE_STRING_H
31 #include <string.h>
32 #else
33 #ifdef HAVE_STRINGS_H
34 #include <strings.h>
35 #endif
36 #endif
37
38
39
40 /****************************************************************/
41
42 enum {
43 max_insn_size = 32,
44 };
45
46 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_name = insn_mnemonic,
582 model_identifer = insn_name,
583 model_default = insn_comment,
584 } model_table_fields;
585
586 typedef struct _insn insn;
587 struct _insn {
588 table_entry *file_entry;
589 insn_fields *fields;
590 insn *next;
591 };
592
593 typedef struct _model model;
594 struct _model {
595 model *next;
596 char *name;
597 char *printable_name;
598 char *insn_default;
599 table_model_entry *func_unit_start;
600 table_model_entry *func_unit_end;
601 };
602
603 typedef struct _insn_table insn_table;
604 struct _insn_table {
605 int opcode_nr;
606 insn_bits *expanded_bits;
607 int nr_insn;
608 insn *insns;
609 insn *functions;
610 insn *last_function;
611 opcode_rules *opcode_rule;
612 opcode_field *opcode;
613 int nr_entries;
614 insn_table *entries;
615 insn_table *sibling;
616 insn_table *parent;
617 };
618
619 typedef enum {
620 insn_model_name,
621 insn_model_fields,
622 nr_insn_model_table_fields
623 } insn_model_table_fields;
624
625 static model *models;
626 static model *last_model;
627
628 static insn *model_macros;
629 static insn *last_model_macro;
630
631 static insn *model_functions;
632 static insn *last_model_function;
633
634 static insn *model_internal;
635 static insn *last_model_internal;
636
637 static insn *model_static;
638 static insn *last_model_static;
639
640 static insn *model_data;
641 static insn *last_model_data;
642
643 static int max_model_fields_len;
644
645 static void
646 insn_table_insert_function(insn_table *table,
647 table_entry *file_entry)
648 {
649 /* create a new function */
650 insn *new_function = ZALLOC(insn);
651 new_function->file_entry = file_entry;
652
653 /* append it to the end of the function list */
654 if (table->last_function)
655 table->last_function->next = new_function;
656 else
657 table->functions = new_function;
658 table->last_function = new_function;
659 }
660
661 static void
662 insn_table_insert_insn(insn_table *table,
663 table_entry *file_entry,
664 insn_fields *fields)
665 {
666 insn **ptr_to_cur_insn = &table->insns;
667 insn *cur_insn = *ptr_to_cur_insn;
668 table_model_entry *insn_model_ptr;
669 model *model_ptr;
670
671 /* create a new instruction */
672 insn *new_insn = ZALLOC(insn);
673 new_insn->file_entry = file_entry;
674 new_insn->fields = fields;
675
676 /* Check out any model information returned to make sure the model
677 is correct. */
678 for(insn_model_ptr = file_entry->model_first; insn_model_ptr; insn_model_ptr = insn_model_ptr->next) {
679 char *name = insn_model_ptr->fields[insn_model_name];
680 int len = strlen (insn_model_ptr->fields[insn_model_fields]);
681
682 while (len > 0 && isspace(*insn_model_ptr->fields[insn_model_fields])) {
683 len--;
684 insn_model_ptr->fields[insn_model_fields]++;
685 }
686
687 if (max_model_fields_len < len)
688 max_model_fields_len = len;
689
690 for(model_ptr = models; model_ptr; model_ptr = model_ptr->next) {
691 if (strcmp(name, model_ptr->printable_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->printable_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 int len;
974
975 /* create a new model */
976 model *new_model = ZALLOC(model);
977
978 new_model->name = file_entry->fields[model_identifer];
979 new_model->printable_name = file_entry->fields[model_name];
980 new_model->insn_default = file_entry->fields[model_default];
981
982 while (*new_model->insn_default && isspace(*new_model->insn_default))
983 new_model->insn_default++;
984
985 len = strlen(new_model->insn_default);
986 if (max_model_fields_len < len)
987 max_model_fields_len = len;
988
989 /* append it to the end of the model list */
990 if (last_model)
991 last_model->next = new_model;
992 else
993 models = new_model;
994 last_model = new_model;
995 }
996
997 static void
998 model_table_insert_specific(insn_table *table,
999 table_entry *file_entry,
1000 insn **start_ptr,
1001 insn **end_ptr)
1002 {
1003 insn *ptr = ZALLOC(insn);
1004 ptr->file_entry = file_entry;
1005 if (*end_ptr)
1006 (*end_ptr)->next = ptr;
1007 else
1008 (*start_ptr) = ptr;
1009 (*end_ptr) = ptr;
1010 }
1011
1012
1013
1014 static insn_table *
1015 insn_table_load_insns(char *file_name)
1016 {
1017 table *file = table_open(file_name, nr_insn_table_fields, nr_insn_model_table_fields);
1018 insn_table *table = ZALLOC(insn_table);
1019 table_entry *file_entry;
1020 table->opcode_rule = opcode_table;
1021
1022 while ((file_entry = table_entry_read(file)) != NULL) {
1023 if (it_is("function", file_entry->fields[insn_flags])
1024 || it_is("internal", file_entry->fields[insn_flags])) {
1025 insn_table_insert_function(table, file_entry);
1026 }
1027 else if (it_is("model", file_entry->fields[insn_flags])) {
1028 model_table_insert(table, file_entry);
1029 }
1030 else if (it_is("model-macro", file_entry->fields[insn_flags])) {
1031 model_table_insert_specific(table, file_entry, &model_macros, &last_model_macro);
1032 }
1033 else if (it_is("model-function", file_entry->fields[insn_flags])) {
1034 model_table_insert_specific(table, file_entry, &model_functions, &last_model_function);
1035 }
1036 else if (it_is("model-internal", file_entry->fields[insn_flags])) {
1037 model_table_insert_specific(table, file_entry, &model_internal, &last_model_internal);
1038 }
1039 else if (it_is("model-static", file_entry->fields[insn_flags])) {
1040 model_table_insert_specific(table, file_entry, &model_static, &last_model_static);
1041 }
1042 else if (it_is("model-data", file_entry->fields[insn_flags])) {
1043 model_table_insert_specific(table, file_entry, &model_data, &last_model_data);
1044 }
1045 else {
1046 insn_fields *fields;
1047 /* skip instructions that aren't relevant to the mode */
1048 filter *filt = filters;
1049 while (filt != NULL) {
1050 if (it_is(filt->flag, file_entry->fields[insn_flags]))
1051 break;
1052 filt = filt->next;
1053 }
1054 if (filt == NULL) {
1055 /* create/insert the new instruction */
1056 fields = parse_insn_format(file_entry,
1057 file_entry->fields[insn_format]);
1058 insn_table_insert_insn(table, file_entry, fields);
1059 }
1060 }
1061 }
1062 return table;
1063 }
1064
1065
1066 static void
1067 dump_insn(insn *entry, int indent, int levels)
1068 {
1069 printf("(insn*)%p\n", entry);
1070
1071 if (levels && entry != NULL) {
1072
1073 dumpf(indent, "(file_entry ");
1074 dump_table_entry(entry->file_entry, indent+1);
1075 dumpf(indent, " )\n");
1076
1077 dumpf(indent, "(fields ");
1078 dump_insn_fields(entry->fields, indent+1);
1079 dumpf(indent, " )\n");
1080
1081 dumpf(indent, "(next ");
1082 dump_insn(entry->next, indent+1, levels-1);
1083 dumpf(indent, " )\n");
1084
1085 }
1086
1087 }
1088
1089
1090 static void
1091 dump_insn_table(insn_table *table,
1092 int indent, int levels)
1093 {
1094
1095 printf("(insn_table*)%p\n", table);
1096
1097 if (levels && table != NULL) {
1098
1099 dumpf(indent, "(opcode_nr %d)\n", table->opcode_nr);
1100
1101 dumpf(indent, "(expanded_bits ");
1102 dump_insn_bits(table->expanded_bits, indent+1, -1);
1103 dumpf(indent, " )\n");
1104
1105 dumpf(indent, "(int nr_insn %d)\n", table->nr_insn);
1106
1107 dumpf(indent, "(insns ");
1108 dump_insn(table->insns, indent+1, table->nr_insn);
1109 dumpf(indent, " )\n");
1110
1111 dumpf(indent, "(opcode_rule ");
1112 dump_opcode_rule(table->opcode_rule, indent+1);
1113 dumpf(indent, " )\n");
1114
1115 dumpf(indent, "(opcode ");
1116 dump_opcode_field(table->opcode, indent+1, 1);
1117 dumpf(indent, " )\n");
1118
1119 dumpf(indent, "(nr_entries %d)\n", table->entries);
1120 dumpf(indent, "(entries ");
1121 dump_insn_table(table->entries, indent+1, table->nr_entries);
1122 dumpf(indent, " )\n");
1123
1124 dumpf(indent, "(sibling ", table->sibling);
1125 dump_insn_table(table->sibling, indent+1, levels-1);
1126 dumpf(indent, " )\n");
1127
1128 dumpf(indent, "(parent ", table->parent);
1129 dump_insn_table(table->parent, indent+1, 0);
1130 dumpf(indent, " )\n");
1131
1132 }
1133 }
1134
1135
1136 /****************************************************************/
1137
1138
1139 static void
1140 lf_print_insn_bits(lf *file, insn_bits *bits)
1141 {
1142 if (bits == NULL)
1143 return;
1144 lf_print_insn_bits(file, bits->last);
1145 lf_putchr(file, '_');
1146 lf_putstr(file, bits->field->val_string);
1147 if (!bits->opcode->is_boolean || bits->value == 0) {
1148 if (bits->opcode->last < bits->field->last)
1149 lf_putint(file, bits->value << (bits->field->last - bits->opcode->last));
1150 else
1151 lf_putint(file, bits->value);
1152 }
1153 }
1154
1155 static void
1156 lf_print_opcodes(lf *file,
1157 insn_table *table)
1158 {
1159 if (table != NULL) {
1160 while (1) {
1161 lf_printf(file, "_%d_%d",
1162 table->opcode->first,
1163 table->opcode->last);
1164 if (table->parent == NULL) break;
1165 lf_printf(file, "__%d", table->opcode_nr);
1166 table = table->parent;
1167 }
1168 }
1169 }
1170
1171 static void
1172 lf_print_table_name(lf *file,
1173 insn_table *table)
1174 {
1175 lf_printf(file, "idecode_table");
1176 lf_print_opcodes(file, table);
1177 }
1178
1179
1180
1181 typedef enum {
1182 function_name_prefix_semantics,
1183 function_name_prefix_idecode,
1184 function_name_prefix_itable,
1185 function_name_prefix_none
1186 } lf_function_name_prefixes;
1187
1188 static void
1189 lf_print_function_name(lf *file,
1190 char *basename,
1191 insn_bits *expanded_bits,
1192 lf_function_name_prefixes prefix)
1193 {
1194
1195 /* the prefix */
1196 switch (prefix) {
1197 case function_name_prefix_semantics:
1198 lf_putstr(file, "semantic_");
1199 break;
1200 case function_name_prefix_idecode:
1201 lf_printf(file, "idecode_");
1202 break;
1203 case function_name_prefix_itable:
1204 lf_putstr(file, "itable_");
1205 break;
1206 default:
1207 break;
1208 }
1209
1210 /* the function name */
1211 {
1212 char *pos;
1213 for (pos = basename;
1214 *pos != '\0';
1215 pos++) {
1216 switch (*pos) {
1217 case '/':
1218 case '-':
1219 break;
1220 case ' ':
1221 lf_putchr(file, '_');
1222 break;
1223 default:
1224 lf_putchr(file, *pos);
1225 break;
1226 }
1227 }
1228 }
1229
1230 /* the suffix */
1231 if (idecode_expand_semantics)
1232 lf_print_insn_bits(file, expanded_bits);
1233 }
1234
1235
1236 static void
1237 lf_print_idecode_table(lf *file,
1238 insn_table *entry)
1239 {
1240 int can_assume_leaf;
1241 opcode_rules *opcode_rule;
1242
1243 /* have a look at the rule table, if all table rules follow all
1244 switch rules, I can assume that all end points are leaves */
1245 opcode_rule = opcode_table;
1246 while (opcode_rule != NULL
1247 && opcode_rule->use_switch)
1248 opcode_rule = opcode_rule->next;
1249 while (opcode_rule != NULL
1250 && opcode_rule->use_switch
1251 && opcode_rule->special_rule)
1252 opcode_rule = opcode_rule->next;
1253 can_assume_leaf = opcode_rule == NULL;
1254
1255 lf_printf(file, "{\n");
1256 lf_indent(file, +2);
1257 {
1258 lf_printf(file, "idecode_table_entry *table = ");
1259 lf_print_table_name(file, entry);
1260 lf_printf(file, ";\n");
1261 lf_printf(file, "int opcode = EXTRACTED32(instruction, %d, %d);\n",
1262 i2target(hi_bit_nr, entry->opcode->first),
1263 i2target(hi_bit_nr, entry->opcode->last));
1264 lf_printf(file, "idecode_table_entry *table_entry = table + opcode;\n");
1265 lf_printf(file, "while (1) {\n");
1266 lf_indent(file, +2);
1267 {
1268 lf_printf(file, "/* nonzero mask -> another table */\n");
1269 lf_printf(file, "while (table_entry->mask != 0) {\n");
1270 lf_indent(file, +2);
1271 {
1272 lf_printf(file, "table = ((idecode_table_entry*)\n");
1273 lf_printf(file, " table_entry->function_or_table);\n");
1274 lf_printf(file, "opcode = ((instruction & table_entry->mask)\n");
1275 lf_printf(file, " >> table_entry->shift);\n");
1276 lf_printf(file, "table_entry = table + opcode;\n");
1277 }
1278 lf_indent(file, -2);
1279 lf_printf(file, "}\n");
1280 lf_printf(file, "ASSERT(table_entry->mask == 0);\n");
1281 if (can_assume_leaf)
1282 lf_printf(file, "ASSERT(table_entry->shift == 0);\n");
1283 else {
1284 lf_printf(file, "if (table_entry->shift == 0)\n");
1285 lf_indent(file, +2);
1286 }
1287 if (idecode_cache) {
1288 lf_printf(file, "return (((idecode_crack*)\n");
1289 lf_printf(file, " table_entry->function_or_table)\n");
1290 lf_printf(file, " (%s));\n", cache_idecode_actual);
1291 }
1292 else {
1293 lf_printf(file, "return (((idecode_semantic*)\n");
1294 lf_printf(file, " table_entry->function_or_table)\n");
1295 lf_printf(file, " (%s));\n", semantic_actual);
1296 }
1297 if (!can_assume_leaf) {
1298 lf_indent(file, -2);
1299 lf_printf(file, "/* must be a boolean */\n");
1300 lf_printf(file, "opcode = (instruction & table_entry->shift) != 0;\n");
1301 lf_printf(file, "table = ((idecode_table_entry*)\n");
1302 lf_printf(file, " table_entry->function_or_table);\n");
1303 lf_printf(file, "table_entry = table + opcode;\n");
1304 }
1305 }
1306 lf_indent(file, -2);
1307 lf_printf(file, "}\n");
1308 }
1309 lf_indent(file, -2);
1310 lf_printf(file, "}\n");
1311 }
1312
1313
1314 static void
1315 lf_print_my_prefix(lf *file,
1316 table_entry *file_entry,
1317 int idecode)
1318 {
1319 lf_printf(file, "const char *const my_prefix = \n");
1320 lf_printf(file, " \"%s:%s:%s:%d\";\n",
1321 filter_filename (file_entry->file_name),
1322 (idecode ? "idecode" : "semantics"),
1323 file_entry->fields[insn_name],
1324 file_entry->line_nr);
1325 lf_printf(file, "const itable_index my_index = ");
1326 lf_print_function_name(file,
1327 file_entry->fields[insn_name],
1328 NULL,
1329 function_name_prefix_itable);
1330 lf_printf(file, ";\n");
1331 }
1332
1333
1334 static void
1335 lf_print_ptrace(lf *file,
1336 int idecode)
1337 {
1338 lf_printf(file, "\n");
1339 lf_printf(file, "ITRACE(trace_%s, (\"\\n\"));\n",
1340 (idecode ? "idecode" : "semantics"));
1341 }
1342
1343
1344 /****************************************************************/
1345
1346 typedef void leaf_handler
1347 (insn_table *entry,
1348 void *data,
1349 int depth);
1350 typedef void padding_handler
1351 (insn_table *table,
1352 void *data,
1353 int depth,
1354 int opcode_nr);
1355
1356
1357 static void
1358 insn_table_traverse_tree(insn_table *table,
1359 void *data,
1360 int depth,
1361 leaf_handler *start,
1362 leaf_handler *leaf,
1363 leaf_handler *end,
1364 padding_handler *padding)
1365 {
1366 insn_table *entry;
1367 int entry_nr;
1368
1369 ASSERT(table != NULL
1370 && table->opcode != NULL
1371 && table->nr_entries > 0
1372 && table->entries != 0);
1373
1374 if (start != NULL && depth >= 0)
1375 start(table, data, depth);
1376
1377 for (entry_nr = 0, entry = table->entries;
1378 entry_nr < (table->opcode->is_boolean
1379 ? 2
1380 : (1 << (table->opcode->last - table->opcode->first + 1)));
1381 entry_nr ++) {
1382 if (entry == NULL
1383 || (!table->opcode->is_boolean
1384 && entry_nr < entry->opcode_nr)) {
1385 if (padding != NULL && depth >= 0)
1386 padding(table, data, depth, entry_nr);
1387 }
1388 else {
1389 ASSERT(entry != NULL && (entry->opcode_nr == entry_nr
1390 || table->opcode->is_boolean));
1391 if (entry->opcode != NULL && depth != 0) {
1392 insn_table_traverse_tree(entry, data, depth+1,
1393 start, leaf, end, padding);
1394 }
1395 else if (depth >= 0) {
1396 if (leaf != NULL)
1397 leaf(entry, data, depth);
1398 }
1399 entry = entry->sibling;
1400 }
1401 }
1402 if (end != NULL && depth >= 0)
1403 end(table, data, depth);
1404 }
1405
1406
1407 typedef void function_handler
1408 (insn_table *table,
1409 void *data,
1410 table_entry *function);
1411
1412 static void
1413 insn_table_traverse_function(insn_table *table,
1414 void *data,
1415 function_handler *leaf)
1416 {
1417 insn *function;
1418 for (function = table->functions;
1419 function != NULL;
1420 function = function->next) {
1421 leaf(table, data, function->file_entry);
1422 }
1423 }
1424
1425
1426 typedef void insn_handler
1427 (insn_table *table,
1428 void *data,
1429 insn *instruction);
1430
1431 static void
1432 insn_table_traverse_insn(insn_table *table,
1433 void *data,
1434 insn_handler *leaf)
1435 {
1436 insn *instruction;
1437 for (instruction = table->insns;
1438 instruction != NULL;
1439 instruction = instruction->next) {
1440 leaf(table, data, instruction);
1441 }
1442 }
1443
1444
1445 static void
1446 update_depth(insn_table *entry,
1447 void *data,
1448 int depth)
1449 {
1450 int *max_depth = (int*)data;
1451 if (*max_depth < depth)
1452 *max_depth = depth;
1453 }
1454
1455
1456 static int
1457 insn_table_depth(insn_table *table)
1458 {
1459 int depth = 0;
1460 insn_table_traverse_tree(table,
1461 &depth,
1462 1,
1463 NULL, /*start*/
1464 update_depth,
1465 NULL, /*end*/
1466 NULL); /*padding*/
1467 return depth;
1468 }
1469
1470
1471 /****************************************************************/
1472
1473 static void
1474 dump_traverse_start(insn_table *table,
1475 void *data,
1476 int depth)
1477 {
1478 dumpf(depth*2, "(%d\n", table->opcode_nr);
1479 }
1480
1481 static void
1482 dump_traverse_leaf(insn_table *entry,
1483 void *data,
1484 int depth)
1485 {
1486 ASSERT(entry->nr_entries == 0
1487 && entry->nr_insn == 1
1488 && entry->opcode == NULL);
1489 dumpf(depth*2, ".%d %s\n", entry->opcode_nr,
1490 entry->insns->file_entry->fields[insn_format]);
1491 }
1492
1493 static void
1494 dump_traverse_end(insn_table *table,
1495 void *data,
1496 int depth)
1497 {
1498 dumpf(depth*2, ")\n");
1499 }
1500
1501 static void
1502 dump_traverse_padding(insn_table *table,
1503 void *data,
1504 int depth,
1505 int opcode_nr)
1506 {
1507 dumpf(depth*2, ".<%d>\n", opcode_nr);
1508 }
1509
1510
1511 static void
1512 dump_traverse(insn_table *table)
1513 {
1514 insn_table_traverse_tree(table, NULL, 1,
1515 dump_traverse_start,
1516 dump_traverse_leaf,
1517 dump_traverse_end,
1518 dump_traverse_padding);
1519 }
1520
1521
1522 /****************************************************************/
1523
1524
1525 static void
1526 lf_print_semantic_function_header(lf *file,
1527 char *basename,
1528 insn_bits *expanded_bits,
1529 int is_function_definition,
1530 int is_inline_function)
1531 {
1532 lf_printf(file, "\n");
1533 lf_printf(file, "STATIC_SEMANTICS unsigned_word ");
1534 lf_print_function_name(file,
1535 basename,
1536 expanded_bits,
1537 function_name_prefix_semantics);
1538 lf_printf(file, "\n(%s)",
1539 (idecode_cache ? cache_semantic_formal : semantic_formal));
1540 if (!is_function_definition)
1541 lf_printf(file, ";");
1542 lf_printf(file, "\n");
1543 }
1544
1545
1546 static void
1547 semantics_h_leaf(insn_table *entry,
1548 void *data,
1549 int depth)
1550 {
1551 lf *file = (lf*)data;
1552 ASSERT(entry->nr_insn == 1);
1553 lf_print_semantic_function_header(file,
1554 entry->insns->file_entry->fields[insn_name],
1555 entry->expanded_bits,
1556 0/* isnt function definition*/,
1557 !idecode_cache && entry->parent->opcode_rule->use_switch);
1558 }
1559
1560 static void
1561 semantics_h_insn(insn_table *entry,
1562 void *data,
1563 insn *instruction)
1564 {
1565 lf *file = (lf*)data;
1566 lf_print_semantic_function_header(file,
1567 instruction->file_entry->fields[insn_name],
1568 NULL,
1569 0/*isnt function definition*/,
1570 0/*isnt inline function*/);
1571 }
1572
1573 static void
1574 semantics_h_function(insn_table *entry,
1575 void *data,
1576 table_entry *function)
1577 {
1578 lf *file = (lf*)data;
1579 if (function->fields[function_type] == NULL
1580 || function->fields[function_type][0] == '\0') {
1581 lf_print_semantic_function_header(file,
1582 function->fields[function_name],
1583 NULL,
1584 0/*isnt function definition*/,
1585 1/*is inline function*/);
1586 }
1587 else {
1588 lf_printf(file, "\n");
1589 lf_printf(file, "INLINE_SEMANTICS %s %s\n(%s);\n",
1590 function->fields[function_type],
1591 function->fields[function_name],
1592 function->fields[function_param]);
1593 }
1594 }
1595
1596
1597 static void
1598 gen_semantics_h(insn_table *table, lf *file)
1599 {
1600
1601 lf_print_copyleft(file);
1602 lf_printf(file, "\n");
1603 lf_printf(file, "#ifndef _SEMANTICS_H_\n");
1604 lf_printf(file, "#define _SEMANTICS_H_\n");
1605 lf_printf(file, "\n");
1606 lf_printf(file, "#ifndef INLINE_SEMANTICS\n");
1607 lf_printf(file, "#define INLINE_SEMANTICS\n");
1608 lf_printf(file, "#endif\n");
1609 lf_printf(file, "\n");
1610 lf_printf(file, "#ifndef STATIC_SEMANTICS\n");
1611 lf_printf(file, "#define STATIC_SEMANTICS\n");
1612 lf_printf(file, "#endif\n");
1613 lf_printf(file, "\n");
1614 lf_printf(file, "\n");
1615
1616 /* output a declaration for all functions */
1617 insn_table_traverse_function(table,
1618 file,
1619 semantics_h_function);
1620
1621 /* output a declaration for all instructions */
1622 if (idecode_expand_semantics)
1623 insn_table_traverse_tree(table,
1624 file,
1625 1,
1626 NULL, /* start */
1627 semantics_h_leaf, /* leaf */
1628 NULL, /* end */
1629 NULL); /* padding */
1630 else
1631 insn_table_traverse_insn(table,
1632 file,
1633 semantics_h_insn);
1634
1635 lf_printf(file, "\n");
1636 lf_printf(file, "#endif /* _SEMANTICS_H_ */\n");
1637
1638 }
1639
1640 /****************************************************************/
1641
1642 typedef struct _icache_tree icache_tree;
1643 struct _icache_tree {
1644 char *name;
1645 icache_tree *next;
1646 icache_tree *children;
1647 };
1648
1649 static icache_tree *
1650 icache_tree_insert(icache_tree *tree,
1651 char *name)
1652 {
1653 icache_tree *new_tree;
1654 /* find it */
1655 icache_tree **ptr_to_cur_tree = &tree->children;
1656 icache_tree *cur_tree = *ptr_to_cur_tree;
1657 while (cur_tree != NULL
1658 && strcmp(cur_tree->name, name) < 0) {
1659 ptr_to_cur_tree = &cur_tree->next;
1660 cur_tree = *ptr_to_cur_tree;
1661 }
1662 ASSERT(cur_tree == NULL
1663 || strcmp(cur_tree->name, name) >= 0);
1664 /* already in the tree */
1665 if (cur_tree != NULL
1666 && strcmp(cur_tree->name, name) == 0)
1667 return cur_tree;
1668 /* missing, insert it */
1669 ASSERT(cur_tree == NULL
1670 || strcmp(cur_tree->name, name) > 0);
1671 new_tree = ZALLOC(icache_tree);
1672 new_tree->name = name;
1673 new_tree->next = cur_tree;
1674 *ptr_to_cur_tree = new_tree;
1675 return new_tree;
1676 }
1677
1678
1679 static icache_tree *
1680 insn_table_cache_fields(insn_table *table)
1681 {
1682 icache_tree *tree = ZALLOC(icache_tree);
1683 insn *instruction;
1684 for (instruction = table->insns;
1685 instruction != NULL;
1686 instruction = instruction->next) {
1687 insn_field *field;
1688 icache_tree *form =
1689 icache_tree_insert(tree,
1690 instruction->file_entry->fields[insn_form]);
1691 for (field = instruction->fields->first;
1692 field != NULL;
1693 field = field->next) {
1694 if (field->is_string)
1695 icache_tree_insert(form, field->val_string);
1696 }
1697 }
1698 return tree;
1699 }
1700
1701
1702
1703 static void
1704 gen_icache_h(icache_tree *tree,
1705 lf *file)
1706 {
1707 lf_print_copyleft(file);
1708 lf_printf(file, "\n");
1709 lf_printf(file, "#ifndef _ICACHE_H_\n");
1710 lf_printf(file, "#define _ICACHE_H_\n");
1711 lf_printf(file, "\n");
1712 lf_printf(file, "#ifndef INLINE_ICACHE\n");
1713 lf_printf(file, "#define INLINE_ICACHE\n");
1714 lf_printf(file, "#endif\n");
1715 lf_printf(file, "\n");
1716
1717 lf_printf(file, "#define WITH_IDECODE_CACHE_SIZE %d\n",
1718 idecode_cache);
1719 lf_printf(file, "\n");
1720
1721 /* create an instruction cache if being used */
1722 if (idecode_cache) {
1723 icache_tree *form;
1724 lf_printf(file, "typedef struct _idecode_cache {\n");
1725 lf_printf(file, " unsigned_word address;\n");
1726 lf_printf(file, " void *semantic;\n");
1727 lf_printf(file, " union {\n");
1728 for (form = tree->children;
1729 form != NULL;
1730 form = form->next) {
1731 icache_tree *field;
1732 lf_printf(file, " struct {\n");
1733 for (field = form->children;
1734 field != NULL;
1735 field = field->next) {
1736 cache_rules *cache_rule;
1737 int found_rule = 0;
1738 for (cache_rule = cache_table;
1739 cache_rule != NULL;
1740 cache_rule = cache_rule->next) {
1741 if (strcmp(field->name, cache_rule->old_name) == 0) {
1742 found_rule = 1;
1743 if (cache_rule->new_name != NULL)
1744 lf_printf(file, " %s %s; /* %s */\n",
1745 (cache_rule->type == NULL
1746 ? "unsigned"
1747 : cache_rule->type),
1748 cache_rule->new_name,
1749 cache_rule->old_name);
1750 }
1751 }
1752 if (!found_rule)
1753 lf_printf(file, " unsigned %s;\n", field->name);
1754 }
1755 lf_printf(file, " } %s;\n", form->name);
1756 }
1757 lf_printf(file, " } crack;\n");
1758 lf_printf(file, "} idecode_cache;\n");
1759 }
1760 else {
1761 /* alernativly, since no cache, #define the fields to be
1762 extractions from the instruction variable. Emit a dummy
1763 definition for idecode_cache to allow model_issue to not
1764 be #ifdefed at the call level */
1765 cache_rules *cache_rule;
1766 lf_printf(file, "\n");
1767 lf_printf(file, "typedef void idecode_cache;\n");
1768 lf_printf(file, "\n");
1769 for (cache_rule = cache_table;
1770 cache_rule != NULL;
1771 cache_rule = cache_rule->next) {
1772 if (cache_rule->expression != NULL
1773 && strlen(cache_rule->expression) > 0)
1774 lf_printf(file, "#define %s %s\n",
1775 cache_rule->new_name, cache_rule->expression);
1776 }
1777 }
1778
1779 lf_printf(file, "\n");
1780 lf_printf(file, "#endif /* _ICACHE_H_ */\n");
1781 }
1782
1783
1784
1785
1786 /****************************************************************/
1787
1788
1789 static void
1790 lf_print_c_extraction(lf *file,
1791 insn *instruction,
1792 char *field_name,
1793 char *field_type,
1794 char *field_expression,
1795 insn_field *cur_field,
1796 insn_bits *bits,
1797 int get_value_from_cache,
1798 int put_value_in_cache)
1799 {
1800 ASSERT(field_name != NULL);
1801 if (bits != NULL
1802 && (!bits->opcode->is_boolean || bits->value == 0)
1803 && strcmp(field_name, cur_field->val_string) == 0) {
1804 ASSERT(bits->field == cur_field);
1805 ASSERT(field_type == NULL);
1806 table_entry_lf_c_line_nr(file, instruction->file_entry);
1807 lf_printf(file, "const unsigned %s = ",
1808 field_name);
1809 if (bits->opcode->last < bits->field->last)
1810 lf_printf(file, "%d;\n",
1811 bits->value << (bits->field->last - bits->opcode->last));
1812 else
1813 lf_printf(file, "%d;\n", bits->value);
1814 }
1815 else {
1816 /* put the field in the local variable */
1817 table_entry_lf_c_line_nr(file, instruction->file_entry);
1818 lf_printf(file, "%s const %s = ",
1819 field_type == NULL ? "unsigned" : field_type,
1820 field_name);
1821 /* getting it from the cache */
1822 if (get_value_from_cache || put_value_in_cache) {
1823 lf_printf(file, "cache_entry->crack.%s.%s",
1824 instruction->file_entry->fields[insn_form],
1825 field_name);
1826 if (put_value_in_cache) /* also put it in the cache? */
1827 lf_printf(file, " = ");
1828 }
1829 if (!get_value_from_cache) {
1830 if (strcmp(field_name, cur_field->val_string) == 0)
1831 lf_printf(file, "EXTRACTED32(instruction, %d, %d)",
1832 i2target(hi_bit_nr, cur_field->first),
1833 i2target(hi_bit_nr, cur_field->last));
1834 else if (field_expression != NULL)
1835 lf_printf(file, "%s", field_expression);
1836 else
1837 lf_printf(file, "eval_%s", field_name);
1838 }
1839 lf_printf(file, ";\n");
1840 }
1841 }
1842
1843
1844 static void
1845 lf_print_c_extractions(lf *file,
1846 insn *instruction,
1847 insn_bits *expanded_bits,
1848 int get_value_from_cache,
1849 int put_value_in_cache)
1850 {
1851 insn_field *cur_field;
1852
1853 /* extract instruction fields */
1854 lf_printf(file, "/* extraction: %s */\n",
1855 instruction->file_entry->fields[insn_format]);
1856
1857 for (cur_field = instruction->fields->first;
1858 cur_field->first < insn_size;
1859 cur_field = cur_field->next) {
1860 if (cur_field->is_string) {
1861 insn_bits *bits;
1862 int found_rule = 0;
1863 /* find any corresponding value */
1864 for (bits = expanded_bits;
1865 bits != NULL;
1866 bits = bits->last) {
1867 if (bits->field == cur_field)
1868 break;
1869 }
1870 /* try the cache rule table for what to do */
1871 if (get_value_from_cache || put_value_in_cache) {
1872 cache_rules *cache_rule;
1873 for (cache_rule = cache_table;
1874 cache_rule != NULL;
1875 cache_rule = cache_rule->next) {
1876 if (strcmp(cur_field->val_string, cache_rule->old_name) == 0) {
1877 found_rule = 1;
1878 if (cache_rule->valid > 1 && put_value_in_cache)
1879 lf_print_c_extraction(file,
1880 instruction,
1881 cache_rule->new_name,
1882 cache_rule->type,
1883 cache_rule->expression,
1884 cur_field,
1885 bits,
1886 0,
1887 0);
1888 else if (cache_rule->valid == 1)
1889 lf_print_c_extraction(file,
1890 instruction,
1891 cache_rule->new_name,
1892 cache_rule->type,
1893 cache_rule->expression,
1894 cur_field,
1895 bits,
1896 get_value_from_cache,
1897 put_value_in_cache);
1898 }
1899 }
1900 }
1901 if (found_rule == 0)
1902 lf_print_c_extraction(file,
1903 instruction,
1904 cur_field->val_string,
1905 0,
1906 0,
1907 cur_field,
1908 bits,
1909 get_value_from_cache,
1910 put_value_in_cache);
1911 /* if any (XXX == 0), output a corresponding test */
1912 if (instruction->file_entry->annex != NULL) {
1913 char *field_name = cur_field->val_string;
1914 char *is_0_ptr = instruction->file_entry->annex;
1915 int field_len = strlen(field_name);
1916 if (strlen(is_0_ptr) >= (strlen("_is_0") + field_len)) {
1917 is_0_ptr += field_len;
1918 while ((is_0_ptr = strstr(is_0_ptr, "_is_0")) != NULL) {
1919 if (strncmp(is_0_ptr - field_len, field_name, field_len) == 0
1920 && !isalpha(is_0_ptr[ - field_len - 1])) {
1921 table_entry_lf_c_line_nr(file, instruction->file_entry);
1922 lf_printf(file, "const unsigned %s_is_0 = (", field_name);
1923 if (bits != NULL)
1924 lf_printf(file, "%d", bits->value);
1925 else
1926 lf_printf(file, "%s", field_name);
1927 lf_printf(file, " == 0);\n");
1928 break;
1929 }
1930 is_0_ptr += strlen("_is_0");
1931 }
1932 }
1933 }
1934 /* any thing else ... */
1935 }
1936 }
1937 lf_print_lf_c_line_nr(file);
1938 }
1939
1940
1941 static void
1942 lf_print_idecode_illegal(lf *file)
1943 {
1944 if (idecode_cache)
1945 lf_printf(file, "return idecode_illegal(%s);\n", cache_idecode_actual);
1946 else
1947 lf_printf(file, "return semantic_illegal(%s);\n", semantic_actual);
1948 }
1949
1950
1951 static void
1952 lf_print_idecode_floating_point_unavailable(lf *file)
1953 {
1954 if (idecode_cache)
1955 lf_printf(file, "return idecode_floating_point_unavailable(%s);\n",
1956 cache_idecode_actual);
1957 else
1958 lf_printf(file, "return semantic_floating_point_unavailable(%s);\n",
1959 semantic_actual);
1960 }
1961
1962
1963 /* Output code to do any final checks on the decoded instruction.
1964 This includes things like verifying any on decoded fields have the
1965 correct value and checking that (for floating point) floating point
1966 hardware isn't disabled */
1967
1968 static void
1969 lf_print_c_validate(lf *file,
1970 insn *instruction,
1971 opcode_field *opcodes)
1972 {
1973 /* Validate: unchecked instruction fields
1974
1975 If any constant fields in the instruction were not checked by the
1976 idecode tables, output code to check that they have the correct
1977 value here */
1978 {
1979 unsigned check_mask = 0;
1980 unsigned check_val = 0;
1981 insn_field *field;
1982 opcode_field *opcode;
1983
1984 /* form check_mask/check_val containing what needs to be checked
1985 in the instruction */
1986 for (field = instruction->fields->first;
1987 field->first < insn_size;
1988 field = field->next) {
1989
1990 check_mask <<= field->width;
1991 check_val <<= field->width;
1992
1993 /* is it a constant that could need validating? */
1994 if (!field->is_int && !field->is_slash)
1995 continue;
1996
1997 /* has it been checked by a table? */
1998 for (opcode = opcodes; opcode != NULL; opcode = opcode->parent) {
1999 if (field->first >= opcode->first
2000 && field->last <= opcode->last)
2001 break;
2002 }
2003 if (opcode != NULL)
2004 continue;
2005
2006 check_mask |= (1 << field->width)-1;
2007 check_val |= field->val_int;
2008 }
2009
2010 /* if any bits not checked by opcode tables, output code to check them */
2011 if (check_mask) {
2012 lf_printf(file, "\n");
2013 lf_printf(file, "/* validate: %s */\n",
2014 instruction->file_entry->fields[insn_format]);
2015 lf_printf(file, "if (WITH_RESERVED_BITS && (instruction & 0x%x) != 0x%x)\n",
2016 check_mask, check_val);
2017 lf_indent(file, +2);
2018 lf_print_idecode_illegal(file);
2019 lf_indent(file, -2);
2020 }
2021 }
2022
2023 /* Validate floating point hardware
2024
2025 If the simulator is being built with out floating point hardware
2026 (different to it being disabled in the MSR) then floating point
2027 instructions are invalid */
2028 {
2029 if (it_is("f", instruction->file_entry->fields[insn_flags])) {
2030 lf_printf(file, "\n");
2031 lf_printf(file, "/* Validate: FP hardware exists */\n");
2032 lf_printf(file, "if (CURRENT_FLOATING_POINT != HARD_FLOATING_POINT)\n");
2033 lf_indent(file, +2);
2034 lf_print_idecode_illegal(file);
2035 lf_indent(file, -2);
2036 }
2037 }
2038
2039 /* Validate: Floating Point available
2040
2041 If floating point is not available, we enter a floating point
2042 unavailable interrupt into the cache instead of the instruction
2043 proper.
2044
2045 The PowerPC spec requires a CSI after MSR[FP] is changed and when
2046 ever a CSI occures we flush the instruction cache. */
2047
2048 {
2049 if (it_is("f", instruction->file_entry->fields[insn_flags])) {
2050 lf_printf(file, "\n");
2051 lf_printf(file, "/* Validate: FP available according to MSR[FP] */\n");
2052 lf_printf(file, "if (!IS_FP_AVAILABLE(processor))\n");
2053 lf_indent(file, +2);
2054 lf_print_idecode_floating_point_unavailable(file);
2055 lf_indent(file, -2);
2056 }
2057 }
2058 }
2059
2060
2061 static void
2062 lf_print_c_cracker(lf *file,
2063 insn *instruction,
2064 insn_bits *expanded_bits,
2065 opcode_field *opcodes)
2066 {
2067
2068 /* function header */
2069 lf_printf(file, "{\n");
2070 lf_indent(file, +2);
2071
2072 lf_print_my_prefix(file,
2073 instruction->file_entry,
2074 1/*putting-value-in-cache*/);
2075
2076 lf_print_ptrace(file,
2077 1/*putting-value-in-cache*/);
2078
2079 lf_print_c_validate(file, instruction, opcodes);
2080
2081 lf_printf(file, "\n");
2082 lf_printf(file, "{\n");
2083 lf_indent(file, +2);
2084 lf_print_c_extractions(file,
2085 instruction,
2086 expanded_bits,
2087 0/*get_value_from_cache*/,
2088 1/*put_value_in_cache*/);
2089 lf_indent(file, -2);
2090 lf_printf(file, "}\n");
2091
2092 /* return the function propper (main sorts this one out) */
2093 lf_printf(file, "\n");
2094 lf_printf(file, "/* semantic routine */\n");
2095 table_entry_lf_c_line_nr(file, instruction->file_entry);
2096 lf_printf(file, "return ");
2097 lf_print_function_name(file,
2098 instruction->file_entry->fields[insn_name],
2099 expanded_bits,
2100 function_name_prefix_semantics);
2101 lf_printf(file, ";\n");
2102
2103 lf_print_lf_c_line_nr(file);
2104 lf_indent(file, -2);
2105 lf_printf(file, "}\n");
2106 }
2107
2108
2109 static void
2110 lf_print_c_semantic(lf *file,
2111 insn *instruction,
2112 insn_bits *expanded_bits,
2113 opcode_field *opcodes)
2114 {
2115
2116 lf_printf(file, "{\n");
2117 lf_indent(file, +2);
2118
2119 lf_print_my_prefix(file,
2120 instruction->file_entry,
2121 0/*not putting value in cache*/);
2122 lf_printf(file, "unsigned_word nia = cia + %d;\n", insn_size / 8);
2123
2124 lf_printf(file, "\n");
2125 lf_print_c_extractions(file,
2126 instruction,
2127 expanded_bits,
2128 idecode_cache/*get_value_from_cache*/,
2129 0/*put_value_in_cache*/);
2130
2131 lf_print_ptrace(file,
2132 0/*put_value_in_cache*/);
2133
2134 /* validate the instruction, if a cache this has already been done */
2135 if (!idecode_cache)
2136 lf_print_c_validate(file, instruction, opcodes);
2137
2138 /* generate the profiling call - this is delayed until after the
2139 instruction has been verified */
2140 lf_printf(file, "\n");
2141 lf_printf(file, "if (WITH_MON & MONITOR_INSTRUCTION_ISSUE) {\n");
2142 lf_printf(file, " mon_issue(");
2143 lf_print_function_name(file,
2144 instruction->file_entry->fields[insn_name],
2145 NULL,
2146 function_name_prefix_itable);
2147 lf_printf(file, ", processor, cia);\n");
2148 lf_printf(file, "}\n");
2149 lf_printf(file, "\n");
2150
2151 /* generate the code (or at least something */
2152 if (instruction->file_entry->annex != NULL) {
2153 /* true code */
2154 lf_printf(file, "\n");
2155 table_entry_lf_c_line_nr(file, instruction->file_entry);
2156 lf_printf(file, "{\n");
2157 lf_indent(file, +2);
2158 lf_print_c_code(file, instruction->file_entry->annex);
2159 lf_indent(file, -2);
2160 lf_printf(file, "}\n");
2161 lf_print_lf_c_line_nr(file);
2162 }
2163 else if (it_is("nop", instruction->file_entry->fields[insn_flags])) {
2164 lf_print_lf_c_line_nr(file);
2165 }
2166 else if (it_is("f", instruction->file_entry->fields[insn_flags])) {
2167 /* unimplemented floating point instruction - call for assistance */
2168 lf_printf(file, "\n");
2169 lf_printf(file, "/* unimplemented floating point instruction - call for assistance */\n");
2170 table_entry_lf_c_line_nr(file, instruction->file_entry);
2171 lf_putstr(file, "floating_point_assist_interrupt(processor, cia);\n");
2172 lf_print_lf_c_line_nr(file);
2173 }
2174 else {
2175 /* abort so it is implemented now */
2176 table_entry_lf_c_line_nr(file, instruction->file_entry);
2177 lf_putstr(file, "error(\"%s: unimplemented, cia=0x%x\\n\", my_prefix, cia);\n");
2178 lf_print_lf_c_line_nr(file);
2179 lf_printf(file, "\n");
2180 }
2181
2182 lf_printf(file, "return nia;\n");
2183 lf_indent(file, -2);
2184 lf_printf(file, "}\n");
2185 }
2186
2187 static void
2188 lf_print_c_semantic_function(lf *file,
2189 insn *instruction,
2190 insn_bits *expanded_bits,
2191 opcode_field *opcodes,
2192 int is_inline_function)
2193 {
2194
2195 /* build the semantic routine to execute the instruction */
2196 lf_print_semantic_function_header(file,
2197 instruction->file_entry->fields[insn_name],
2198 expanded_bits,
2199 1/*is-function-definition*/,
2200 is_inline_function);
2201 lf_print_c_semantic(file,
2202 instruction,
2203 expanded_bits,
2204 opcodes);
2205 }
2206
2207
2208 static void
2209 semantics_c_leaf(insn_table *entry,
2210 void *data,
2211 int depth)
2212 {
2213 lf *file = (lf*)data;
2214 ASSERT(entry->nr_insn == 1
2215 && entry->opcode == NULL
2216 && entry->parent != NULL
2217 && entry->parent->opcode != NULL);
2218 lf_print_c_semantic_function(file,
2219 entry->insns,
2220 entry->expanded_bits,
2221 entry->parent->opcode,
2222 !idecode_cache && entry->parent->opcode_rule->use_switch);
2223 }
2224
2225 static void
2226 semantics_c_insn(insn_table *table,
2227 void *data,
2228 insn *instruction)
2229 {
2230 lf *file = (lf*)data;
2231 lf_print_c_semantic_function(file, instruction,
2232 NULL, NULL,
2233 0/*isnt_inline_function*/);
2234 }
2235
2236 static void
2237 semantics_c_function(insn_table *table,
2238 void *data,
2239 table_entry *function)
2240 {
2241 lf *file = (lf*)data;
2242 if (function->fields[function_type] == NULL
2243 || function->fields[function_type][0] == '\0') {
2244 lf_print_semantic_function_header(file,
2245 function->fields[function_name],
2246 NULL,
2247 1/*is function definition*/,
2248 1/*is inline function*/);
2249 }
2250 else {
2251 lf_printf(file, "\n");
2252 lf_printf(file, "INLINE_SEMANTICS %s\n%s(%s)\n",
2253 function->fields[function_type],
2254 function->fields[function_name],
2255 function->fields[function_param]);
2256 }
2257 table_entry_lf_c_line_nr(file, function);
2258 lf_printf(file, "{\n");
2259 lf_indent(file, +2);
2260 lf_print_c_code(file, function->annex);
2261 lf_indent(file, -2);
2262 lf_printf(file, "}\n");
2263 lf_print_lf_c_line_nr(file);
2264 }
2265
2266
2267
2268 static void
2269 gen_semantics_c(insn_table *table, lf *file)
2270 {
2271 lf_print_copyleft(file);
2272 lf_printf(file, "\n");
2273 lf_printf(file, "#ifndef _SEMANTICS_C_\n");
2274 lf_printf(file, "#define _SEMANTICS_C_\n");
2275 lf_printf(file, "\n");
2276 lf_printf(file, "#ifndef STATIC_INLINE_SEMANTICS\n");
2277 lf_printf(file, "#define STATIC_INLINE_SEMANTICS STATIC_INLINE\n");
2278 lf_printf(file, "#endif\n");
2279 lf_printf(file, "\n");
2280 lf_printf(file, "#include \"cpu.h\"\n");
2281 lf_printf(file, "#include \"idecode.h\"\n");
2282 lf_printf(file, "#include \"semantics.h\"\n");
2283 lf_printf(file, "\n");
2284
2285 /* output a definition (c-code) for all functions */
2286 insn_table_traverse_function(table,
2287 file,
2288 semantics_c_function);
2289
2290 /* output a definition (c-code) for all instructions */
2291 if (idecode_expand_semantics)
2292 insn_table_traverse_tree(table,
2293 file,
2294 1,
2295 NULL, /* start */
2296 semantics_c_leaf,
2297 NULL, /* end */
2298 NULL); /* padding */
2299 else
2300 insn_table_traverse_insn(table,
2301 file,
2302 semantics_c_insn);
2303
2304 lf_printf(file, "\n");
2305 lf_printf(file, "#endif /* _SEMANTICS_C_ */\n");
2306 }
2307
2308
2309 /****************************************************************/
2310
2311 static void
2312 gen_idecode_h(insn_table *table, lf *file)
2313 {
2314 lf_print_copyleft(file);
2315 lf_printf(file, "\n");
2316 lf_printf(file, "#ifndef _IDECODE_H_\n");
2317 lf_printf(file, "#define _IDECODE_H_\n");
2318 lf_printf(file, "\n");
2319 lf_printf(file, "#ifndef INLINE_IDECODE\n");
2320 lf_printf(file, "#define INLINE_IDECODE\n");
2321 lf_printf(file, "#endif\n");
2322 lf_printf(file, "\n");
2323 lf_printf(file, "#include \"idecode_expression.h\"\n");
2324 lf_printf(file, "#include \"idecode_fields.h\"\n");
2325 lf_printf(file, "#include \"idecode_branch.h\"\n");
2326 lf_printf(file, "\n");
2327 lf_printf(file, "#include \"icache.h\"\n");
2328 lf_printf(file, "\n");
2329 lf_printf(file, "typedef unsigned_word idecode_semantic\n(%s);\n",
2330 (idecode_cache ? cache_semantic_formal : semantic_formal));
2331 lf_printf(file, "\n");
2332 if (idecode_cache)
2333 lf_printf(file, "INLINE_IDECODE idecode_semantic *idecode\n(%s);\n",
2334 cache_idecode_formal);
2335 else
2336 lf_printf(file, "INLINE_IDECODE unsigned_word idecode_issue\n(%s);\n",
2337 semantic_formal);
2338 lf_printf(file, "\n");
2339 lf_printf(file, "#endif /* _IDECODE_H_ */\n");
2340 }
2341
2342
2343 /****************************************************************/
2344
2345
2346 static void
2347 idecode_table_start(insn_table *table,
2348 void *data,
2349 int depth)
2350 {
2351 lf *file = (lf*)data;
2352 ASSERT(depth == 0);
2353 /* start of the table */
2354 if (!table->opcode_rule->use_switch) {
2355 lf_printf(file, "\n");
2356 lf_printf(file, "static idecode_table_entry ");
2357 lf_print_table_name(file, table);
2358 lf_printf(file, "[] = {\n");
2359 }
2360 }
2361
2362 static void
2363 idecode_table_leaf(insn_table *entry,
2364 void *data,
2365 int depth)
2366 {
2367 lf *file = (lf*)data;
2368 ASSERT(entry->parent != NULL);
2369 ASSERT(depth == 0);
2370
2371 /* add an entry to the table */
2372 if (!entry->parent->opcode_rule->use_switch) {
2373 if (entry->opcode == NULL) {
2374 /* table leaf entry */
2375 lf_printf(file, " /*%d*/ { 0, 0, ", entry->opcode_nr);
2376 lf_print_function_name(file,
2377 entry->insns->file_entry->fields[insn_name],
2378 entry->expanded_bits,
2379 (idecode_cache
2380 ? function_name_prefix_idecode
2381 : function_name_prefix_semantics));
2382 lf_printf(file, " },\n");
2383 }
2384 else if (entry->opcode_rule->use_switch) {
2385 /* table calling switch statement */
2386 lf_printf(file, " /*%d*/ { 0, 0, ",
2387 entry->opcode_nr);
2388 lf_print_table_name(file, entry);
2389 lf_printf(file, " },\n");
2390 }
2391 else {
2392 /* table `calling' another table */
2393 lf_printf(file, " /*%d*/ { ", entry->opcode_nr);
2394 if (entry->opcode->is_boolean)
2395 lf_printf(file, "MASK32(%d,%d), 0, ",
2396 i2target(hi_bit_nr, entry->opcode->first),
2397 i2target(hi_bit_nr, entry->opcode->last));
2398 else
2399 lf_printf(file, "%d, MASK32(%d,%d), ",
2400 insn_size - entry->opcode->last - 1,
2401 i2target(hi_bit_nr, entry->opcode->first),
2402 i2target(hi_bit_nr, entry->opcode->last));
2403 lf_print_table_name(file, entry);
2404 lf_printf(file, " },\n");
2405 }
2406 }
2407 }
2408
2409 static void
2410 idecode_table_end(insn_table *table,
2411 void *data,
2412 int depth)
2413 {
2414 lf *file = (lf*)data;
2415 ASSERT(depth == 0);
2416
2417 if (!table->opcode_rule->use_switch) {
2418 lf_printf(file, "};\n");
2419 }
2420 }
2421
2422 static void
2423 idecode_table_padding(insn_table *table,
2424 void *data,
2425 int depth,
2426 int opcode_nr)
2427 {
2428 lf *file = (lf*)data;
2429 ASSERT(depth == 0);
2430
2431 if (!table->opcode_rule->use_switch) {
2432 lf_printf(file, " /*%d*/ { 0, 0, %s_illegal },\n",
2433 opcode_nr, (idecode_cache ? "idecode" : "semantic"));
2434 }
2435 }
2436
2437
2438 /****************************************************************/
2439
2440
2441 void lf_print_idecode_switch
2442 (lf *file,
2443 insn_table *table);
2444
2445
2446 static void
2447 idecode_switch_start(insn_table *table,
2448 void *data,
2449 int depth)
2450 {
2451 lf *file = (lf*)data;
2452 ASSERT(depth == 0);
2453 ASSERT(table->opcode_rule->use_switch);
2454
2455 lf_printf(file, "switch (EXTRACTED32(instruction, %d, %d)) {\n",
2456 i2target(hi_bit_nr, table->opcode->first),
2457 i2target(hi_bit_nr, table->opcode->last));
2458 }
2459
2460
2461 static void
2462 idecode_switch_leaf(insn_table *entry,
2463 void *data,
2464 int depth)
2465 {
2466 lf *file = (lf*)data;
2467 ASSERT(entry->parent != NULL);
2468 ASSERT(depth == 0);
2469 ASSERT(entry->parent->opcode_rule->use_switch);
2470 ASSERT(entry->parent->opcode);
2471
2472 if (!entry->parent->opcode->is_boolean
2473 || entry->opcode_nr == 0)
2474 lf_printf(file, "case %d:\n", entry->opcode_nr);
2475 else
2476 lf_printf(file, "default:\n");
2477 lf_indent(file, +2);
2478 {
2479 if (entry->opcode == NULL) {
2480 /* switch calling leaf */
2481 lf_printf(file, "return ");
2482 lf_print_function_name(file,
2483 entry->insns->file_entry->fields[insn_name],
2484 entry->expanded_bits,
2485 (idecode_cache
2486 ? function_name_prefix_idecode
2487 : function_name_prefix_semantics));
2488 if (idecode_cache)
2489 lf_printf(file, "(%s);\n", cache_idecode_actual);
2490 else
2491 lf_printf(file, "(%s);\n", semantic_actual);
2492 }
2493 else if (entry->opcode_rule->use_switch) {
2494 /* switch calling switch */
2495 lf_print_idecode_switch(file, entry);
2496 }
2497 else {
2498 /* switch looking up a table */
2499 lf_print_idecode_table(file, entry);
2500 }
2501 lf_printf(file, "break;\n");
2502 }
2503 lf_indent(file, -2);
2504 }
2505
2506
2507 static void
2508 lf_print_idecode_switch_illegal(lf *file)
2509 {
2510 lf_indent(file, +2);
2511 lf_print_idecode_illegal(file);
2512 lf_printf(file, "break;\n");
2513 lf_indent(file, -2);
2514 }
2515
2516 static void
2517 idecode_switch_end(insn_table *table,
2518 void *data,
2519 int depth)
2520 {
2521 lf *file = (lf*)data;
2522 ASSERT(depth == 0);
2523 ASSERT(table->opcode_rule->use_switch);
2524 ASSERT(table->opcode);
2525
2526 if (table->opcode_rule->use_switch == 1
2527 && !table->opcode->is_boolean) {
2528 lf_printf(file, "default:\n");
2529 lf_print_idecode_switch_illegal(file);
2530 }
2531 lf_printf(file, "}\n");
2532 }
2533
2534 static void
2535 idecode_switch_padding(insn_table *table,
2536 void *data,
2537 int depth,
2538 int opcode_nr)
2539 {
2540 lf *file = (lf*)data;
2541
2542 ASSERT(depth == 0);
2543 ASSERT(table->opcode_rule->use_switch);
2544
2545 if (table->opcode_rule->use_switch > 1) {
2546 lf_printf(file, "case %d:\n", opcode_nr);
2547 lf_print_idecode_switch_illegal(file);
2548 }
2549 }
2550
2551
2552 void
2553 lf_print_idecode_switch(lf *file,
2554 insn_table *table)
2555 {
2556 insn_table_traverse_tree(table,
2557 file,
2558 0,
2559 idecode_switch_start,
2560 idecode_switch_leaf,
2561 idecode_switch_end,
2562 idecode_switch_padding);
2563 }
2564
2565
2566 static void
2567 lf_print_idecode_switch_function_header(lf *file,
2568 insn_table *table,
2569 int is_function_definition)
2570 {
2571 lf_printf(file, "\n");
2572 lf_printf(file, "static ");
2573 if (idecode_cache)
2574 lf_printf(file, "idecode_semantic *");
2575 else
2576 lf_printf(file, "unsigned_word");
2577 if (is_function_definition)
2578 lf_printf(file, "\n");
2579 else
2580 lf_printf(file, " ");
2581 lf_print_table_name(file, table);
2582 lf_printf(file, "\n(%s)",
2583 (idecode_cache ? cache_idecode_formal : semantic_formal));
2584 if (!is_function_definition)
2585 lf_printf(file, ";");
2586 lf_printf(file, "\n");
2587 }
2588
2589
2590 static void
2591 idecode_declare_if_switch(insn_table *table,
2592 void *data,
2593 int depth)
2594 {
2595 lf *file = (lf*)data;
2596
2597 if (table->opcode_rule->use_switch
2598 && table->parent != NULL /* don't declare the top one yet */
2599 && !table->parent->opcode_rule->use_switch) {
2600 lf_print_idecode_switch_function_header(file,
2601 table,
2602 0/*isnt function definition*/);
2603 }
2604 }
2605
2606
2607 static void
2608 idecode_expand_if_switch(insn_table *table,
2609 void *data,
2610 int depth)
2611 {
2612 lf *file = (lf*)data;
2613
2614 if (table->opcode_rule->use_switch
2615 && table->parent != NULL /* don't expand the top one yet */
2616 && !table->parent->opcode_rule->use_switch) {
2617 lf_print_idecode_switch_function_header(file,
2618 table,
2619 1/*is function definition*/);
2620 lf_printf(file, "{\n");
2621 {
2622 lf_indent(file, +2);
2623 lf_print_idecode_switch(file, table);
2624 lf_indent(file, -2);
2625 }
2626 lf_printf(file, "}\n");
2627 }
2628 }
2629
2630
2631 static void
2632 lf_print_c_cracker_function(lf *file,
2633 insn *instruction,
2634 insn_bits *expanded_bits,
2635 opcode_field *opcodes,
2636 int is_inline_function)
2637 {
2638 /* if needed, generate code to enter this routine into a cache */
2639 lf_printf(file, "\n");
2640 lf_printf(file, "STATIC_IDECODE idecode_semantic *\n");
2641 lf_print_function_name(file,
2642 instruction->file_entry->fields[insn_name],
2643 expanded_bits,
2644 function_name_prefix_idecode);
2645 lf_printf(file, "\n(%s)\n", cache_idecode_formal);
2646
2647 lf_print_c_cracker(file,
2648 instruction,
2649 expanded_bits,
2650 opcodes);
2651 }
2652
2653 static void
2654 idecode_crack_leaf(insn_table *entry,
2655 void *data,
2656 int depth)
2657 {
2658 lf *file = (lf*)data;
2659 ASSERT(entry->nr_insn == 1
2660 && entry->opcode == NULL
2661 && entry->parent != NULL
2662 && entry->parent->opcode != NULL
2663 && entry->parent->opcode_rule != NULL);
2664 lf_print_c_cracker_function(file,
2665 entry->insns,
2666 entry->expanded_bits,
2667 entry->opcode,
2668 entry->parent->opcode_rule->use_switch);
2669 }
2670
2671 static void
2672 idecode_crack_insn(insn_table *entry,
2673 void *data,
2674 insn *instruction)
2675 {
2676 lf *file = (lf*)data;
2677 lf_print_c_cracker_function(file,
2678 instruction,
2679 NULL,
2680 NULL,
2681 0/*isnt inline function*/);
2682 }
2683
2684 static void
2685 idecode_c_internal_function(insn_table *table,
2686 void *data,
2687 table_entry *function)
2688 {
2689 lf *file = (lf*)data;
2690 ASSERT(idecode_cache != 0);
2691 if (it_is("internal", function->fields[insn_flags])) {
2692 lf_printf(file, "\n");
2693 lf_printf(file, "STATIC_INLINE_IDECODE idecode_semantic *\n");
2694 lf_print_function_name(file,
2695 function->fields[insn_name],
2696 NULL,
2697 function_name_prefix_idecode);
2698 lf_printf(file, "\n(%s)\n", cache_idecode_formal);
2699 lf_printf(file, "{\n");
2700 lf_indent(file, +2);
2701 lf_printf(file, "/* semantic routine */\n");
2702 table_entry_lf_c_line_nr(file, function);
2703 lf_printf(file, "return ");
2704 lf_print_function_name(file,
2705 function->fields[insn_name],
2706 NULL,
2707 function_name_prefix_semantics);
2708 lf_printf(file, ";\n");
2709
2710 lf_print_lf_c_line_nr(file);
2711 lf_indent(file, -2);
2712 lf_printf(file, "}\n");
2713 }
2714 }
2715
2716
2717 /****************************************************************/
2718
2719 static void
2720 gen_idecode_c(insn_table *table, lf *file)
2721 {
2722 int depth;
2723
2724 /* the intro */
2725 lf_print_copyleft(file);
2726 lf_printf(file, "\n");
2727 lf_printf(file, "\n");
2728 lf_printf(file, "#ifndef _IDECODE_C_\n");
2729 lf_printf(file, "#define _IDECODE_C_\n");
2730 lf_printf(file, "\n");
2731 lf_printf(file, "#ifndef STATIC_INLINE_IDECODE\n");
2732 lf_printf(file, "#define STATIC_INLINE_IDECODE STATIC_INLINE\n");
2733 lf_printf(file, "#endif\n");
2734 lf_printf(file, "\n");
2735 lf_printf(file, "#ifndef STATIC_IDECODE\n");
2736 lf_printf(file, "#define STATIC_IDECODE\n");
2737 lf_printf(file, "#endif\n");
2738 lf_printf(file, "\n");
2739 lf_printf(file, "#include \"cpu.h\"\n");
2740 lf_printf(file, "#include \"idecode.h\"\n");
2741 lf_printf(file, "#include \"semantics.h\"\n");
2742 lf_printf(file, "\n");
2743 lf_printf(file, "\n");
2744 lf_printf(file, "typedef idecode_semantic *idecode_crack\n(%s);\n",
2745 (idecode_cache ? cache_idecode_formal : semantic_formal));
2746 lf_printf(file, "\n");
2747 lf_printf(file, "typedef struct _idecode_table_entry {\n");
2748 lf_printf(file, " unsigned shift;\n");
2749 lf_printf(file, " unsigned mask;\n");
2750 lf_printf(file, " void *function_or_table;\n");
2751 lf_printf(file, "} idecode_table_entry;\n");
2752 lf_printf(file, "\n");
2753 lf_printf(file, "\n");
2754
2755 /* output `internal' invalid/floating-point unavailable functions
2756 where needed */
2757 if (idecode_cache) {
2758 insn_table_traverse_function(table,
2759 file,
2760 idecode_c_internal_function);
2761 }
2762
2763 /* output cracking functions where needed */
2764 if (idecode_cache) {
2765 if (idecode_expand_semantics)
2766 insn_table_traverse_tree(table,
2767 file,
2768 1,
2769 NULL,
2770 idecode_crack_leaf,
2771 NULL,
2772 NULL);
2773 else
2774 insn_table_traverse_insn(table,
2775 file,
2776 idecode_crack_insn);
2777 }
2778
2779 /* output switch function declarations where needed by tables */
2780 insn_table_traverse_tree(table,
2781 file,
2782 1,
2783 idecode_declare_if_switch, /* START */
2784 NULL, NULL, NULL);
2785
2786 /* output tables where needed */
2787 for (depth = insn_table_depth(table);
2788 depth > 0;
2789 depth--) {
2790 insn_table_traverse_tree(table,
2791 file,
2792 1-depth,
2793 idecode_table_start,
2794 idecode_table_leaf,
2795 idecode_table_end,
2796 idecode_table_padding);
2797 }
2798
2799 /* output switch functions where needed */
2800 insn_table_traverse_tree(table,
2801 file,
2802 1,
2803 idecode_expand_if_switch, /* START */
2804 NULL, NULL, NULL);
2805
2806 /* output the main idecode routine */
2807 lf_printf(file, "\n");
2808 if (idecode_cache)
2809 lf_printf(file, "INLINE_IDECODE idecode_semantic *\nidecode\n(%s)\n",
2810 cache_idecode_formal);
2811 else
2812 lf_printf(file, "INLINE_IDECODE unsigned_word\nidecode_issue\n(%s)\n",
2813 semantic_formal);
2814 lf_printf(file, "{\n");
2815 lf_indent(file, +2);
2816 if (table->opcode_rule->use_switch)
2817 lf_print_idecode_switch(file, table);
2818 else
2819 lf_print_idecode_table(file, table);
2820 lf_indent(file, -2);
2821 lf_printf(file, "}\n");
2822 lf_printf(file, "\n");
2823 lf_printf(file, "#endif /* _IDECODE_C_ */\n");
2824 }
2825
2826
2827 /****************************************************************/
2828
2829 static void
2830 itable_h_insn(insn_table *entry,
2831 void *data,
2832 insn *instruction)
2833 {
2834 lf *file = (lf*)data;
2835 lf_printf(file, " ");
2836 lf_print_function_name(file,
2837 instruction->file_entry->fields[insn_name],
2838 NULL,
2839 function_name_prefix_itable);
2840 lf_printf(file, ",\n");
2841 }
2842
2843
2844 static void
2845 gen_itable_h(insn_table *table, lf *file)
2846 {
2847
2848 lf_print_copyleft(file);
2849 lf_printf(file, "\n");
2850 lf_printf(file, "#ifndef _ITABLE_H_\n");
2851 lf_printf(file, "#define _ITABLE_H_\n");
2852 lf_printf(file, "\n");
2853 lf_printf(file, "#ifndef INLINE_ITABLE\n");
2854 lf_printf(file, "#define INLINE_ITABLE\n");
2855 lf_printf(file, "#endif\n");
2856 lf_printf(file, "\n");
2857 lf_printf(file, "\n");
2858
2859 /* output an enumerated type for each instruction */
2860 lf_printf(file, "typedef enum {\n");
2861 insn_table_traverse_insn(table,
2862 file,
2863 itable_h_insn);
2864 lf_printf(file, " nr_itable_entries,\n");
2865 lf_printf(file, "} itable_index;\n");
2866 lf_printf(file, "\n");
2867
2868 /* output the table that contains the actual instruction info */
2869 lf_printf(file, "typedef struct _itable_instruction_info {\n");
2870 lf_printf(file, " itable_index nr;\n");
2871 lf_printf(file, " char *format;\n");
2872 lf_printf(file, " char *form;\n");
2873 lf_printf(file, " char *flags;\n");
2874 lf_printf(file, " char *mnemonic;\n");
2875 lf_printf(file, " char *name;\n");
2876 lf_printf(file, "} itable_info;\n");
2877 lf_printf(file, "\n");
2878 lf_printf(file, "extern itable_info itable[nr_itable_entries];\n");
2879
2880 lf_printf(file, "\n");
2881 lf_printf(file, "#endif /* _ITABLE_C_ */\n");
2882
2883 }
2884
2885 /****************************************************************/
2886
2887 static void
2888 itable_c_insn(insn_table *entry,
2889 void *data,
2890 insn *instruction)
2891 {
2892 lf *file = (lf*)data;
2893 char **fields = instruction->file_entry->fields;
2894 lf_printf(file, " { ");
2895 lf_print_function_name(file,
2896 instruction->file_entry->fields[insn_name],
2897 NULL,
2898 function_name_prefix_itable);
2899 lf_printf(file, ",\n");
2900 lf_printf(file, " \"%s\",\n", fields[insn_format]);
2901 lf_printf(file, " \"%s\",\n", fields[insn_form]);
2902 lf_printf(file, " \"%s\",\n", fields[insn_flags]);
2903 lf_printf(file, " \"%s\",\n", fields[insn_mnemonic]);
2904 lf_printf(file, " \"%s\",\n", fields[insn_name]);
2905 lf_printf(file, " },\n");
2906 }
2907
2908
2909 static void
2910 gen_itable_c(insn_table *table, lf *file)
2911 {
2912
2913 lf_print_copyleft(file);
2914 lf_printf(file, "\n");
2915 lf_printf(file, "#ifndef _ITABLE_C_\n");
2916 lf_printf(file, "#define _ITABLE_C_\n");
2917 lf_printf(file, "\n");
2918 lf_printf(file, "#ifndef STATIC_INLINE_ITABLE\n");
2919 lf_printf(file, "#define STATIC_INLINE_ITABLE STATIC_INLINE\n");
2920 lf_printf(file, "#endif\n");
2921 lf_printf(file, "\n");
2922 lf_printf(file, "#include \"itable.h\"\n");
2923 lf_printf(file, "\n");
2924
2925 /* output the table that contains the actual instruction info */
2926 lf_printf(file, "itable_info itable[nr_itable_entries] = {\n");
2927 insn_table_traverse_insn(table,
2928 file,
2929 itable_c_insn);
2930 lf_printf(file, "};\n");
2931 lf_printf(file, "\n");
2932
2933 lf_printf(file, "\n");
2934 lf_printf(file, "#endif /* _ITABLE_C_ */\n");
2935 }
2936
2937 /****************************************************************/
2938
2939 static void
2940 model_c_or_h_data(insn_table *table,
2941 lf *file,
2942 table_entry *data)
2943 {
2944 if (data->annex) {
2945 table_entry_lf_c_line_nr(file, data);
2946 lf_print_c_code(file, data->annex);
2947 lf_print_lf_c_line_nr(file);
2948 lf_printf(file, "\n");
2949 }
2950 }
2951
2952 static void
2953 model_c_or_h_function(insn_table *entry,
2954 lf *file,
2955 table_entry *function,
2956 char *prefix)
2957 {
2958 if (function->fields[function_type] == NULL
2959 || function->fields[function_type][0] == '\0') {
2960 error("Model function type not specified for %s", function->fields[function_name]);
2961 }
2962 else {
2963 lf_printf(file, "\n");
2964 lf_printf(file, "%s %s %s\n(%s);\n",
2965 prefix,
2966 function->fields[function_type],
2967 function->fields[function_name],
2968 function->fields[function_param]);
2969 }
2970 lf_printf(file, "\n");
2971 }
2972
2973 static void
2974 gen_model_h(insn_table *table, lf *file)
2975 {
2976 insn *insn_ptr;
2977 model *model_ptr;
2978 insn *macro;
2979 char *name;
2980 int model_create_p = 0;
2981 int model_init_p = 0;
2982 int model_halt_p = 0;
2983 int model_mon_info_p = 0;
2984 int model_mon_info_free_p = 0;
2985
2986 lf_print_copyleft(file);
2987 lf_printf(file, "\n");
2988 lf_printf(file, "#ifndef _MODEL_H_\n");
2989 lf_printf(file, "#define _MODEL_H_\n");
2990 lf_printf(file, "\n");
2991
2992 for(macro = model_macros; macro; macro = macro->next) {
2993 model_c_or_h_data(table, file, macro->file_entry);
2994 }
2995
2996 lf_printf(file, "#ifndef INLINE_MODEL\n");
2997 lf_printf(file, "#define INLINE_MODEL\n");
2998 lf_printf(file, "#endif\n");
2999 lf_printf(file, "#ifndef STATIC_INLINE_MODEL\n");
3000 lf_printf(file, "#define STATIC_INLINE_MODEL STATIC_INLINE\n");
3001 lf_printf(file, "#endif\n");
3002 lf_printf(file, "\n");
3003 lf_printf(file, "#ifndef STATIC_MODEL\n");
3004 lf_printf(file, "#define STATIC_MODEL\n");
3005 lf_printf(file, "#endif\n");
3006 lf_printf(file, "\n");
3007 lf_printf(file, "#ifndef EXTERN_MODEL\n");
3008 lf_printf(file, "#define EXTERN_MODEL extern\n");
3009 lf_printf(file, "#endif\n");
3010 lf_printf(file, "\n");
3011
3012 lf_printf(file, "typedef enum _model_enum {\n");
3013 lf_printf(file, " MODEL_NONE,\n");
3014 for (model_ptr = models; model_ptr; model_ptr = model_ptr->next) {
3015 lf_printf(file, " MODEL_%s,\n", model_ptr->name);
3016 }
3017 lf_printf(file, " nr_models\n");
3018 lf_printf(file, "} model_enum;\n");
3019 lf_printf(file, "\n");
3020
3021 lf_printf(file, "#define DEFAULT_MODEL MODEL_%s\n", (models) ? models->name : "NONE");
3022 lf_printf(file, "\n");
3023
3024 lf_printf(file, "typedef struct _model_data model_data;\n");
3025 lf_printf(file, "typedef struct _model_time model_time;\n");
3026 lf_printf(file, "\n");
3027
3028 lf_printf(file, "extern model_enum current_model;\n");
3029 lf_printf(file, "EXTERN_MODEL const char *model_name[ (int)nr_models ];\n");
3030 lf_printf(file, "EXTERN_MODEL const char *const *const model_func_unit_name[ (int)nr_models ];\n");
3031 lf_printf(file, "EXTERN_MODEL const model_time *const model_time_mapping[ (int)nr_models ];\n");
3032 lf_printf(file, "\n");
3033
3034 for(insn_ptr = model_functions; insn_ptr; insn_ptr = insn_ptr->next) {
3035 model_c_or_h_function(table, file, insn_ptr->file_entry, "INLINE_MODEL");
3036 name = insn_ptr->file_entry->fields[function_name];
3037 if (strcmp (name, "model_create") == 0)
3038 model_create_p = 1;
3039 else if (strcmp (name, "model_init") == 0)
3040 model_init_p = 1;
3041 else if (strcmp (name, "model_halt") == 0)
3042 model_halt_p = 1;
3043 else if (strcmp (name, "model_mon_info") == 0)
3044 model_mon_info_p = 1;
3045 else if (strcmp (name, "model_mon_info_free") == 0)
3046 model_mon_info_free_p = 1;
3047 }
3048
3049 if (!model_create_p) {
3050 lf_printf(file, "INLINE_MODEL model_data *model_create\n");
3051 lf_printf(file, "(cpu *processor);\n");
3052 lf_printf(file, "\n");
3053 }
3054
3055 if (!model_init_p) {
3056 lf_printf(file, "INLINE_MODEL void model_init\n");
3057 lf_printf(file, "(model_data *model_ptr);\n");
3058 lf_printf(file, "\n");
3059 }
3060
3061 if (!model_halt_p) {
3062 lf_printf(file, "INLINE_MODEL void model_halt\n");
3063 lf_printf(file, "(model_data *model_ptr);\n");
3064 lf_printf(file, "\n");
3065 }
3066
3067 if (!model_mon_info_p) {
3068 lf_printf(file, "INLINE_MODEL model_print *model_mon_info\n");
3069 lf_printf(file, "(model_data *model_ptr);\n");
3070 lf_printf(file, "\n");
3071 }
3072
3073 if (!model_mon_info_free_p) {
3074 lf_printf(file, "INLINE_MODEL void model_mon_info_free\n");
3075 lf_printf(file, "(model_data *model_ptr,\n");
3076 lf_printf(file, " model_print *info_ptr);\n");
3077 lf_printf(file, "\n");
3078 }
3079
3080 lf_printf(file, "INLINE_MODEL void model_set\n");
3081 lf_printf(file, "(const char *name);\n");
3082 lf_printf(file, "\n");
3083 lf_printf(file, "#endif /* _MODEL_H_ */\n");
3084 }
3085
3086 /****************************************************************/
3087
3088 typedef struct _model_c_passed_data model_c_passed_data;
3089 struct _model_c_passed_data {
3090 lf *file;
3091 model *model_ptr;
3092 };
3093
3094 static void
3095 model_c_insn(insn_table *entry,
3096 void *data,
3097 insn *instruction)
3098 {
3099 model_c_passed_data *data_ptr = (model_c_passed_data *)data;
3100 lf *file = data_ptr->file;
3101 char *current_name = data_ptr->model_ptr->printable_name;
3102 table_model_entry *model_ptr = instruction->file_entry->model_first;
3103
3104 while (model_ptr) {
3105 if (model_ptr->fields[insn_model_name] == current_name) {
3106 lf_printf(file, " { %-*s }, /* %s */\n",
3107 max_model_fields_len,
3108 model_ptr->fields[insn_model_fields],
3109 instruction->file_entry->fields[insn_name]);
3110 return;
3111 }
3112
3113 model_ptr = model_ptr->next;
3114 }
3115
3116 lf_printf(file, " { %-*s }, /* %s */\n",
3117 max_model_fields_len,
3118 data_ptr->model_ptr->insn_default,
3119 instruction->file_entry->fields[insn_name]);
3120 }
3121
3122 static void
3123 model_c_function(insn_table *table,
3124 lf *file,
3125 table_entry *function,
3126 const char *prefix)
3127 {
3128 if (function->fields[function_type] == NULL
3129 || function->fields[function_type][0] == '\0') {
3130 error("Model function return type not specified for %s", function->fields[function_name]);
3131 }
3132 else {
3133 lf_printf(file, "\n");
3134 lf_printf(file, "%s %s\n%s(%s)\n",
3135 prefix,
3136 function->fields[function_type],
3137 function->fields[function_name],
3138 function->fields[function_param]);
3139 }
3140 table_entry_lf_c_line_nr(file, function);
3141 lf_printf(file, "{\n");
3142 if (function->annex) {
3143 lf_indent(file, +2);
3144 lf_print_c_code(file, function->annex);
3145 lf_indent(file, -2);
3146 }
3147 lf_printf(file, "}\n");
3148 lf_print_lf_c_line_nr(file);
3149 lf_printf(file, "\n");
3150 }
3151
3152 static void
3153 gen_model_c(insn_table *table, lf *file)
3154 {
3155 insn *insn_ptr;
3156 model *model_ptr;
3157 char *name;
3158 int model_create_p = 0;
3159 int model_init_p = 0;
3160 int model_halt_p = 0;
3161 int model_mon_info_p = 0;
3162 int model_mon_info_free_p = 0;
3163
3164 lf_print_copyleft(file);
3165 lf_printf(file, "\n");
3166 lf_printf(file, "#ifndef _MODEL_C_\n");
3167 lf_printf(file, "#define _MODEL_C_\n");
3168 lf_printf(file, "\n");
3169 lf_printf(file, "#include \"cpu.h\"\n");
3170 lf_printf(file, "#include \"mon.h\"\n");
3171 lf_printf(file, "\n");
3172 lf_printf(file, "#ifdef HAVE_STDLIB_H\n");
3173 lf_printf(file, "#include <stdlib.h>\n");
3174 lf_printf(file, "#endif\n");
3175 lf_printf(file, "\n");
3176
3177 for(insn_ptr = model_data; insn_ptr; insn_ptr = insn_ptr->next) {
3178 model_c_or_h_data(table, file, insn_ptr->file_entry);
3179 }
3180
3181 for(insn_ptr = model_static; insn_ptr; insn_ptr = insn_ptr->next) {
3182 model_c_or_h_function(table, file, insn_ptr->file_entry, "STATIC_MODEL");
3183 }
3184
3185 for(insn_ptr = model_internal; insn_ptr; insn_ptr = insn_ptr->next) {
3186 model_c_or_h_function(table, file, insn_ptr->file_entry, "STATIC_INLINE_MODEL");
3187 }
3188
3189 for(insn_ptr = model_static; insn_ptr; insn_ptr = insn_ptr->next) {
3190 model_c_function(table, file, insn_ptr->file_entry, "STATIC_MODEL");
3191 }
3192
3193 for(insn_ptr = model_internal; insn_ptr; insn_ptr = insn_ptr->next) {
3194 model_c_function(table, file, insn_ptr->file_entry, "STATIC_INLINE_MODEL");
3195 }
3196
3197 for(insn_ptr = model_functions; insn_ptr; insn_ptr = insn_ptr->next) {
3198 model_c_function(table, file, insn_ptr->file_entry, "INLINE_MODEL");
3199 name = insn_ptr->file_entry->fields[function_name];
3200 if (strcmp (name, "model_create") == 0)
3201 model_create_p = 1;
3202 else if (strcmp (name, "model_init") == 0)
3203 model_init_p = 1;
3204 else if (strcmp (name, "model_halt") == 0)
3205 model_halt_p = 1;
3206 else if (strcmp (name, "model_mon_info") == 0)
3207 model_mon_info_p = 1;
3208 else if (strcmp (name, "model_mon_info_free") == 0)
3209 model_mon_info_free_p = 1;
3210 }
3211
3212 if (!model_create_p) {
3213 lf_printf(file, "INLINE_MODEL model_data *model_create(cpu *processor)\n");
3214 lf_printf(file, "{\n");
3215 lf_printf(file, " return (model_data *)0;\n");
3216 lf_printf(file, "}\n");
3217 lf_printf(file, "\n");
3218 }
3219
3220 if (!model_init_p) {
3221 lf_printf(file, "INLINE_MODEL void model_init(model_data *model_ptr)\n");
3222 lf_printf(file, "{\n");
3223 lf_printf(file, "}\n");
3224 lf_printf(file, "\n");
3225 }
3226
3227 if (!model_halt_p) {
3228 lf_printf(file, "INLINE_MODEL void model_halt(model_data *model_ptr)\n");
3229 lf_printf(file, "{\n");
3230 lf_printf(file, "}\n");
3231 lf_printf(file, "\n");
3232 }
3233
3234 if (!model_mon_info_p) {
3235 lf_printf(file, "INLINE_MODEL model_print *model_mon_info(model_data *model_ptr)\n");
3236 lf_printf(file, "{\n");
3237 lf_printf(file, " return (model_print *)0;\n");
3238 lf_printf(file, "}\n");
3239 lf_printf(file, "\n");
3240 }
3241
3242 if (!model_mon_info_free_p) {
3243 lf_printf(file, "INLINE_MODEL void model_mon_info_free(model_data *model_ptr,\n");
3244 lf_printf(file, " model_print *info_ptr)\n");
3245 lf_printf(file, "{\n");
3246 lf_printf(file, "}\n");
3247 lf_printf(file, "\n");
3248 }
3249
3250 lf_printf(file, "/* Insn functional unit info */\n");
3251 for(model_ptr = models; model_ptr; model_ptr = model_ptr->next) {
3252 model_c_passed_data data;
3253
3254 lf_printf(file, "static const model_time model_time_%s[] = {\n", model_ptr->name);
3255 data.file = file;
3256 data.model_ptr = model_ptr;
3257 insn_table_traverse_insn(table,
3258 (void *)&data,
3259 model_c_insn);
3260
3261 lf_printf(file, "};\n");
3262 lf_printf(file, "\n");
3263 lf_printf(file, "\f\n");
3264 }
3265
3266 lf_printf(file, "STATIC_MODEL const model_time *const model_time_mapping[ (int)nr_models ] = {\n");
3267 lf_printf(file, " (const model_time *const)0,\n");
3268 for(model_ptr = models; model_ptr; model_ptr = model_ptr->next) {
3269 lf_printf(file, " model_time_%s,\n", model_ptr->name);
3270 }
3271 lf_printf(file, "};\n");
3272 lf_printf(file, "\n");
3273
3274 lf_printf(file, "\f\n");
3275 lf_printf(file, "/* map model enumeration into printable string */\n");
3276 lf_printf(file, "STATIC_MODEL const char *model_name[ (int)nr_models ] = {\n");
3277 lf_printf(file, " \"NONE\",\n");
3278 for (model_ptr = models; model_ptr; model_ptr = model_ptr->next) {
3279 lf_printf(file, " \"%s\",\n", model_ptr->printable_name);
3280 }
3281 lf_printf(file, "};\n");
3282 lf_printf(file, "\n");
3283
3284 lf_printf(file, "INLINE_MODEL void\n");
3285 lf_printf(file, "model_set(const char *name)\n");
3286 lf_printf(file, "{\n");
3287 if (models) {
3288 lf_printf(file, " model_enum model;\n");
3289 lf_printf(file, " for(model = MODEL_%s; model < nr_models; model++) {\n", models->name);
3290 lf_printf(file, " if(strcmp(name, model_name[model]) == 0) {\n");
3291 lf_printf(file, " current_model = model;\n");
3292 lf_printf(file, " return;\n");
3293 lf_printf(file, " }\n");
3294 lf_printf(file, " }\n");
3295 lf_printf(file, "\n");
3296 lf_printf(file, " error(\"Unknown model '%%s', Models which are known are:%%s\n\",\n");
3297 lf_printf(file, " name,\n");
3298 lf_printf(file, " \"");
3299 for(model_ptr = models; model_ptr; model_ptr = model_ptr->next) {
3300 lf_printf(file, "\\n\\t%s", model_ptr->printable_name);
3301 }
3302 lf_printf(file, "\");\n");
3303 } else {
3304 lf_printf(file, " error(\"No models are currently known about\");\n");
3305 }
3306
3307 lf_printf(file, "}\n");
3308 lf_printf(file, "\n");
3309
3310 lf_printf(file, "#endif /* _MODEL_C_ */\n");
3311
3312 }
3313
3314 /****************************************************************/
3315
3316
3317 int
3318 main(int argc,
3319 char **argv,
3320 char **envp)
3321 {
3322 insn_table *instructions = NULL;
3323 icache_tree *cache_fields = NULL;
3324 char *real_file_name = NULL;
3325 int ch;
3326
3327 if (argc == 1) {
3328 printf("Usage:\n");
3329 printf(" igen <config-opts> ... <input-opts>... <output-opts>...\n");
3330 printf("Config options:\n");
3331 printf(" -f <filter-out-flag> eg -f 64 to skip 64bit instructions\n");
3332 printf(" -e Expand (duplicate) semantic functions\n");
3333 printf(" -r <icache-size> Generate cracking cache version\n");
3334 printf(" -l Supress line numbering in output files\n");
3335 printf(" -b <bit-size> Set the number of bits in an instruction\n");
3336 printf(" -h <high-bit> Set the nr of the high (msb bit)\n");
3337 printf("Input options (ucase version also dumps loaded table):\n");
3338 printf(" -[Oo] <opcode-rules>\n");
3339 printf(" -[Kk] <cache-rules>\n");
3340 printf(" -[Ii] <instruction-table>\n");
3341 printf("Output options:\n");
3342 printf(" -[Cc] <output-file> output icache.h(C) invalid(c)\n");
3343 printf(" -[Dd] <output-file> output idecode.h(D) idecode.c(d)\n");
3344 printf(" -[Mm] <output-file> output model.h(M) model.c(M)\n");
3345 printf(" -[Ss] <output-file> output schematic.h(S) schematic.c(s)\n");
3346 printf(" -[Tt] <table> output itable.h(T) itable.c(t)\n");
3347 }
3348
3349 while ((ch = getopt(argc, argv,
3350 "leb:h:r:f:I:i:O:o:K:k:M:m:n:S:s:D:d:T:t:C:")) != -1) {
3351 fprintf(stderr, "\t-%c %s\n", ch, (optarg ? optarg : ""));
3352 switch(ch) {
3353 case 'l':
3354 number_lines = 0;
3355 break;
3356 case 'e':
3357 idecode_expand_semantics = 1;
3358 break;
3359 case 'r':
3360 idecode_cache = a2i(optarg);
3361 break;
3362 case 'b':
3363 insn_size = a2i(optarg);
3364 ASSERT(insn_size > 0 && insn_size <= max_insn_size
3365 && (hi_bit_nr == insn_size-1 || hi_bit_nr == 0));
3366 break;
3367 case 'h':
3368 hi_bit_nr = a2i(optarg);
3369 ASSERT(hi_bit_nr == insn_size-1 || hi_bit_nr == 0);
3370 break;
3371 case 'f':
3372 {
3373 filter *new_filter = ZALLOC(filter);
3374 new_filter->flag = strdup(optarg);
3375 new_filter->next = filters;
3376 filters = new_filter;
3377 break;
3378 }
3379 case 'I':
3380 case 'i':
3381 ASSERT(opcode_table != NULL);
3382 ASSERT(cache_table != NULL);
3383 instructions = insn_table_load_insns(optarg);
3384 fprintf(stderr, "\texpanding ...\n");
3385 insn_table_expand_insns(instructions);
3386 fprintf(stderr, "\tcache fields ...\n");
3387 cache_fields = insn_table_cache_fields(instructions);
3388 if (ch == 'I') {
3389 dump_traverse(instructions);
3390 dump_insn_table(instructions, 0, 1);
3391 }
3392 break;
3393 case 'O':
3394 case 'o':
3395 opcode_table = load_opcode_rules(optarg);
3396 if (ch == 'O')
3397 dump_opcode_rules(opcode_table, 0);
3398 break;
3399 case 'K':
3400 case 'k':
3401 cache_table = load_cache_rules(optarg);
3402 if (ch == 'K')
3403 dump_cache_rules(cache_table, 0);
3404 break;
3405 case 'n':
3406 real_file_name = strdup(optarg);
3407 break;
3408 case 'S':
3409 case 's':
3410 case 'D':
3411 case 'd':
3412 case 'M':
3413 case 'm':
3414 case 'T':
3415 case 't':
3416 case 'C':
3417 {
3418 lf *file = lf_open(optarg, real_file_name, number_lines);
3419 ASSERT(instructions != NULL);
3420 switch (ch) {
3421 case 'S':
3422 gen_semantics_h(instructions, file);
3423 break;
3424 case 's':
3425 gen_semantics_c(instructions, file);
3426 break;
3427 case 'D':
3428 gen_idecode_h(instructions, file);
3429 break;
3430 case 'd':
3431 gen_idecode_c(instructions, file);
3432 break;
3433 case 'M':
3434 gen_model_h(instructions, file);
3435 break;
3436 case 'm':
3437 gen_model_c(instructions, file);
3438 break;
3439 case 'T':
3440 gen_itable_h(instructions, file);
3441 break;
3442 case 't':
3443 gen_itable_c(instructions, file);
3444 break;
3445 case 'C':
3446 gen_icache_h(cache_fields, file);
3447 break;
3448 }
3449 lf_close(file);
3450 }
3451 real_file_name = NULL;
3452 break;
3453 default:
3454 error("unknown option\n");
3455 }
3456 }
3457 return 0;
3458 }