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