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