1 /* This file is part of the program psim.
3 Copyright (C) 1994-1995, Andrew Cagney <cagney@highland.com.au>
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.
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.
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.
24 Instead of using/abusing macro's the semantic code should be parsed
25 and each `cachable' expression replaced with the corresponding
28 If not expanding fields, invalid_insn has call to its self this is
29 a little fatal when semantic_invalid() is being called because an
30 instruction is invalid */
33 #include <sys/types.h>
45 #include "ppc-config.h"
53 /****************************************************************/
56 error (char *msg
, ...)
68 void *memory
= malloc(size
);
70 error("zmalloc failed\n");
76 dumpf (int indent
, char *msg
, ...)
79 for (; indent
> 0; indent
--)
87 /****************************************************************/
89 int idecode_expand_semantics
= WITH_IDECODE_EXPAND_SEMANTICS
;
90 int idecode_cache
= WITH_IDECODE_CACHE
;
91 int spreg_lookup_table
= WITH_SPREG_LOOKUP_TABLE
;
93 /****************************************************************/
103 extraction_rules cachable_values
[] = WITH_IDECODE_CACHE_RULES
;
105 /****************************************************************/
107 typedef struct _opcode_rules
{
114 char *force_expansion
;
116 unsigned special_mask
;
117 unsigned special_value
;
118 unsigned special_rule
;
121 /* FIXME - this should be loaded from a file */
122 opcode_rules opcode_table
[] = WITH_IDECODE_OPCODE_RULES
;
124 dump_opcode_rule(opcode_rules
*rule
,
127 printf("(opcode_rules*)0x%x\n", rule
);
128 dumpf(indent
, "(valid %d)\n", rule
->valid
);
129 ASSERT(rule
!= NULL
);
131 dumpf(indent
, "(first %d)\n", rule
->first
);
132 dumpf(indent
, "(last %d)\n", rule
->last
);
133 dumpf(indent
, "(force_first %d)\n", rule
->force_first
);
134 dumpf(indent
, "(force_last %d)\n", rule
->force_last
);
135 dumpf(indent
, "(force_slash %d)\n", rule
->force_slash
);
136 dumpf(indent
, "(force_expansion %s)\n", rule
->force_expansion
);
141 /****************************************************************/
148 char cache_idecode_formal
[] = "cpu *processor,\n instruction_word instruction,\n unsigned_word cia,\n idecode_cache *cache_entry";
149 char cache_idecode_actual
[] = "processor, instruction, cia, cache_entry";
150 char cache_insn_formal
[] = "cpu *processor,\n idecode_cache *cache_entry,\n unsigned_word cia";
151 char cache_insn_actual
[] = "processor, entry, cia";
153 char insn_formal
[] = "cpu *processor,\n instruction_word instruction,\n unsigned_word cia";
154 char insn_actual
[] = "processor, instruction, cia";
156 char insn_local
[] = "unsigned_word nia = cia + 4;";
159 /****************************************************************/
162 bin2i(char *bin
, int width
)
165 while (*bin
!= '\0' && width
!= 0) {
166 i
= (i
<< 1) + (*bin
- '0');
178 int flag_len
= strlen(flag
);
179 while (*flags
!= '\0') {
180 if (!strncmp(flags
, flag
, flag_len
)
181 && (flags
[flag_len
] == ',' || flags
[flag_len
] == '\0'))
183 while (*flags
!= ',') {
194 /****************************************************************/
196 typedef struct _lf lf
;
199 int line_nr
; /* nr complete lines written, curr line is line_nr+1 */
209 /* create a file object */
210 lf
*new_lf
= zmalloc(sizeof(lf
));
211 ASSERT(new_lf
!= NULL
);
212 new_lf
->file_name
= name
;
214 /* attach to stdout if pipe */
215 if (!strcmp(name
, "-")) {
216 new_lf
->stream
= stdout
;
219 /* create a new file */
220 new_lf
->stream
= fopen(name
, "w");
221 ASSERT(new_lf
->stream
!= NULL
);
230 if (file
->stream
!= stdout
) {
231 if (fclose(file
->stream
)) {
232 perror("lf_close.fclose");
246 file
->line_blank
= 1;
248 else if (file
->line_blank
) {
250 for (pad
= file
->indent
; pad
> 0; pad
--)
251 putc(' ', file
->stream
);
252 file
->line_blank
= 0;
254 putc(chr
, file
->stream
);
258 lf_indent_suppress(lf
*file
)
260 file
->line_blank
= 0;
269 if (string
!= NULL
) {
270 for (chp
= string
; *chp
!= '\0'; chp
++) {
271 lf_putchr(file
, *chp
);
277 do_lf_putunsigned(lf
*file
,
281 do_lf_putunsigned(file
, u
/ 10);
282 lf_putchr(file
, (u
% 10) + '0');
292 lf_putchr(file
, '0');
293 else if (decimal
< 0) {
294 lf_putchr(file
, '-');
295 do_lf_putunsigned(file
, -decimal
);
297 else if (decimal
> 0) {
298 do_lf_putunsigned(file
, decimal
);
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
);
322 lf_print_file_line_nr(lf
*file
)
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");
334 lf_indent(lf
*file
, int delta
)
336 file
->indent
+= delta
;
340 /****************************************************************/
342 /* read entries from ppc.instructions */
345 file_table_max_fields
= 6,
348 typedef struct _file_table file_table
;
357 typedef struct _file_table_entry file_table_entry
;
358 struct _file_table_entry
{
359 char *fields
[file_table_max_fields
];
367 file_table_open(char *file_name
)
370 struct stat stat_buf
;
373 /* create a file descriptor */
374 file
= (file_table
*)zmalloc(sizeof(file_table
));
375 ASSERT(file
!= NULL
);
377 /* save the file name */
378 file
->file_name
= (char*)zmalloc(strlen(file_name
) + 1);
379 ASSERT(file
->file_name
!= NULL
);
380 strcpy(file
->file_name
, file_name
);
383 fd
= open(file
->file_name
, O_RDONLY
, 0);
386 /* determine the size */
387 if (fstat(fd
, &stat_buf
) < 0) {
388 perror("file_table_open.fstat");
391 file
->size
= stat_buf
.st_size
;
393 /* allocate this much memory */
394 file
->buffer
= (char*)zmalloc(file
->size
+1);
395 if(file
->buffer
== NULL
) {
396 perror("file_table_open.calloc.file->size+1");
399 file
->pos
= file
->buffer
;
402 if (read(fd
, file
->buffer
, file
->size
) < file
->size
) {
403 perror("file_table_open.read");
406 file
->buffer
[file
->size
] = '\0';
415 file_table_read(file_table
*file
)
418 file_table_entry
*entry
;
420 /* skip comments/blanks */
422 /* leading white space */
423 while (*file
->pos
!= '\0'
424 && *file
->pos
!= '\n'
425 && isspace(*file
->pos
))
428 if (*file
->pos
== '#') {
431 } while (*file
->pos
!= '\0' && *file
->pos
!= '\n');
434 if (*file
->pos
== '\n') {
441 if (*file
->pos
== '\0')
444 /* create this new entry */
445 entry
= (file_table_entry
*)zmalloc(sizeof(file_table_entry
));
446 ASSERT(entry
!= NULL
);
447 entry
->file_name
= file
->file_name
;
449 /* break the line into its colon delimitered fields */
450 for (field
= 0; field
< file_table_max_fields
-1; field
++) {
451 entry
->fields
[field
] = file
->pos
;
452 while(*file
->pos
&& *file
->pos
!= ':' && *file
->pos
!= '\n')
454 if (*file
->pos
== ':') {
460 /* any trailing stuff not the last field */
461 ASSERT(field
== file_table_max_fields
-1);
462 entry
->fields
[field
] = file
->pos
;
463 while (*file
->pos
&& *file
->pos
!= '\n') {
466 if (*file
->pos
== '\n') {
471 entry
->line_nr
= file
->line_nr
;
473 /* if following lines tab indented, put in the annex */
474 if (*file
->pos
== '\t') {
475 entry
->annex
= file
->pos
;
479 } while (*file
->pos
!= '\0' && *file
->pos
!= '\n');
480 if (*file
->pos
== '\n') {
484 } while (*file
->pos
!= '\0' && *file
->pos
== '\t');
485 if (file
->pos
[-1] == '\n')
486 file
->pos
[-1] = '\0';
498 dump_file_table_entry(file_table_entry
*entry
,
501 printf("(file_table_entry*)0x%x\n", entry
);
508 dumpf(indent
, "(fields");
509 for (field
= 0; field
< file_table_max_fields
; field
++) {
510 printf("%c%s", sep
, entry
->fields
[field
]);
515 dumpf(indent
, "(line_nr %d)\n", entry
->line_nr
);
517 dumpf(indent
, "(file_name %s)\n", entry
->file_name
);
519 dumpf(indent
, "(annex\n%s\n", entry
->annex
);
520 dumpf(indent
, " )\n");
526 /****************************************************************/
528 typedef struct _insn_field insn_field
;
543 typedef struct _insn_fields insn_fields
;
544 struct _insn_fields
{
545 insn_field
*bits
[insn_size
];
554 insn_field
*new_field
= (insn_field
*)zmalloc(sizeof(insn_field
));
555 ASSERT(new_field
!= NULL
);
562 insn_fields
*new_fields
= (insn_fields
*)zmalloc(sizeof(insn_fields
));
563 ASSERT(new_fields
!= NULL
);
569 parse_insn_format(file_table_entry
*entry
,
573 insn_fields
*fields
= insn_fields_new();
575 /* create a leading sentinal */
576 fields
->first
= insn_field_new();
577 fields
->first
->first
= -1;
578 fields
->first
->last
= -1;
579 fields
->first
->width
= 0;
581 /* and a trailing sentinal */
582 fields
->last
= insn_field_new();
583 fields
->last
->first
= insn_size
;
584 fields
->last
->last
= insn_size
;
585 fields
->last
->width
= 0;
587 /* link them together */
588 fields
->first
->next
= fields
->last
;
589 fields
->last
->prev
= fields
->first
;
591 /* now work through the formats */
594 while (*chp
!= '\0') {
599 insn_field
*new_field
;
602 if (!isdigit(*chp
)) {
603 fprintf(stderr
, "%s:%d: missing position field at %s\n",
604 entry
->file_name
, entry
->line_nr
, chp
);
608 /* break out the bit position */
610 while (isdigit(*chp
))
612 strlen_pos
= chp
- start_pos
;
613 if (*chp
== '.' && strlen_pos
> 0)
616 fprintf(stderr
, "%s:%d: missing field value at %s\n",
617 entry
->file_name
, entry
->line_nr
, chp
);
621 /* break out the value */
623 while (*start_val
== '/' && *chp
== '/'
624 || isdigit(*start_val
) && isdigit(*chp
)
625 || isalpha(*start_val
) && (isalnum(*chp
) || *chp
== '_'))
627 strlen_val
= chp
- start_val
;
630 else if (*chp
!= '\0' || strlen_val
== 0) {
631 fprintf(stderr
, "%s:%d: missing field terminator at %s\n",
632 entry
->file_name
, entry
->line_nr
, chp
);
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
;
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;
650 else if (new_field
->val_string
[0] == '/') {
651 new_field
->is_slash
= 1;
654 new_field
->is_string
= 1;
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*/
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
;
673 /* now go over this again, pointing each bit position at a field
678 field
= fields
->first
;
679 for (i
= 0; i
< insn_size
; i
++) {
680 while (field
->last
< i
)
682 fields
->bits
[i
] = field
;
686 /* go over each of the fields, and compute a `value' for the insn */
690 for (field
= fields
->first
;
691 field
->last
< insn_size
;
692 field
= field
->next
) {
693 fields
->value
<<= field
->width
;
695 fields
->value
|= field
->val_int
;
703 field_constant_int
= 1,
704 field_constant_slash
= 2,
705 field_constant_string
= 3
706 } constant_field_types
;
710 insn_field_is_constant(insn_field
*field
,
713 /* field is an integer */
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') {
724 char *end
= strchr(forced_fields
, ',');
726 field_len
= strlen(forced_fields
);
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
== ',')
742 dump_insn_field(insn_field
*field
,
746 printf("(insn_field*)0x%x\n", field
);
748 dumpf(indent
, "(first %d)\n", field
->first
);
750 dumpf(indent
, "(last %d)\n", field
->last
);
752 dumpf(indent
, "(width %d)\n", field
->width
);
755 dumpf(indent
, "(is_int %d)\n", field
->val_int
);
758 dumpf(indent
, "(is_slash)\n");
760 if (field
->is_string
)
761 dumpf(indent
, "(is_string `%s')\n", field
->val_string
);
763 dumpf(indent
, "(next 0x%x)\n", field
->next
);
765 dumpf(indent
, "(prev 0x%x)\n", field
->prev
);
771 dump_insn_fields(insn_fields
*fields
,
777 printf("(insn_fields*)0x%x\n", fields
);
779 dumpf(indent
, "(first 0x%x)\n", fields
->first
);
780 dumpf(indent
, "(last 0x%x)\n", fields
->last
);
782 dumpf(indent
, "(value 0x%x)\n", fields
->value
);
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");
793 /****************************************************************/
795 typedef struct _opcode_field opcode_field
;
796 struct _opcode_field
{
800 opcode_field
*parent
;
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;
814 dump_opcode_field(opcode_field
*field
, int indent
, int levels
)
816 printf("(opcode_field*)0x%x\n", field
);
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);
827 /****************************************************************/
829 typedef struct _insn_bits insn_bits
;
834 opcode_field
*opcode
;
841 insn_bits
*new_bits
= (insn_bits
*)zmalloc(sizeof(insn_bits
));
848 dump_insn_bits(insn_bits
*bits
, int indent
, int levels
)
850 printf("(insn_bits*)0x%x\n", bits
);
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);
866 /****************************************************************/
876 nr_insn_table_fields
= file_table_max_fields
878 char *insn_field_name
[] = {
879 "format", "form", "flags", "nmemonic", "name", "comments"
882 typedef struct _insn insn
;
884 file_table_entry
*file_entry
;
889 typedef struct _insn_table insn_table
;
892 insn_bits
*expanded_bits
;
895 opcode_rules
*opcode_rule
;
896 opcode_field
*opcode
;
908 insn
*new_entry
= ((insn
*) zmalloc(sizeof(insn
)));
909 ASSERT(new_entry
!= NULL
);
916 insn_table
*new_table
= (insn_table
*)zmalloc(sizeof(insn_table
));
917 ASSERT(new_table
!= NULL
);
923 insn_table_insert_insn(insn_table
*table
,
924 file_table_entry
*file_entry
,
927 insn
**ptr_to_cur_insn
= &table
->insns
;
928 insn
*cur_insn
= *ptr_to_cur_insn
;
930 /* create a new instruction */
931 insn
*new_insn
= insn_new();
932 new_insn
->file_entry
= file_entry
;
933 new_insn
->fields
= fields
;
935 /* insert it according to the order of the fields */
936 while (cur_insn
!= NULL
937 && new_insn
->fields
->value
>= cur_insn
->fields
->value
) {
938 ptr_to_cur_insn
= &cur_insn
->next
;
939 cur_insn
= *ptr_to_cur_insn
;
942 new_insn
->next
= cur_insn
;
943 *ptr_to_cur_insn
= new_insn
;
950 insn_table_find_opcode_field(insn
*insns
,
954 opcode_field
*curr_opcode
= opcode_field_new();
959 for (entry
= insns
; entry
!= NULL
; entry
= entry
->next
) {
960 insn_fields
*fields
= entry
->fields
;
961 opcode_field new_opcode
;
963 /* find a start point for the opcode field */
964 new_opcode
.first
= rule
->first
;
965 while (new_opcode
.first
<= rule
->last
967 || insn_field_is_constant(fields
->bits
[new_opcode
.first
],
968 rule
) != field_constant_string
)
970 || !insn_field_is_constant(fields
->bits
[new_opcode
.first
],
972 new_opcode
.first
= fields
->bits
[new_opcode
.first
]->last
+ 1;
973 ASSERT(new_opcode
.first
> rule
->last
975 && insn_field_is_constant(fields
->bits
[new_opcode
.first
],
976 rule
) == field_constant_string
)
978 && insn_field_is_constant(fields
->bits
[new_opcode
.first
],
981 /* find the end point for the opcode field */
982 new_opcode
.last
= rule
->last
;
983 while (new_opcode
.last
>= rule
->first
985 || insn_field_is_constant(fields
->bits
[new_opcode
.last
],
986 rule
) != field_constant_string
)
988 || !insn_field_is_constant(fields
->bits
[new_opcode
.last
],
990 new_opcode
.last
= fields
->bits
[new_opcode
.last
]->first
- 1;
991 ASSERT(new_opcode
.last
< rule
->first
993 && insn_field_is_constant(fields
->bits
[new_opcode
.last
],
994 rule
) == field_constant_string
)
996 && insn_field_is_constant(fields
->bits
[new_opcode
.last
],
999 /* now see if our current opcode needs expanding */
1000 if (new_opcode
.first
<= rule
->last
1001 && curr_opcode
->first
> new_opcode
.first
)
1002 curr_opcode
->first
= new_opcode
.first
;
1003 if (new_opcode
.last
>= rule
->first
1004 && curr_opcode
->last
< new_opcode
.last
)
1005 curr_opcode
->last
= new_opcode
.last
;
1009 /* was any thing interesting found? */
1010 if (curr_opcode
->first
> rule
->last
) {
1011 ASSERT(curr_opcode
->last
< rule
->first
);
1015 ASSERT(curr_opcode
->last
>= rule
->first
);
1016 ASSERT(curr_opcode
->first
<= rule
->last
);
1018 /* if something was found, check it includes the forced field range */
1020 && curr_opcode
->first
> rule
->force_first
) {
1021 curr_opcode
->first
= rule
->force_first
;
1024 && curr_opcode
->last
< rule
->force_last
) {
1025 curr_opcode
->last
= rule
->force_last
;
1027 /* handle special case elminating any need to do shift after mask */
1029 && rule
->force_last
== insn_size
-1) {
1030 curr_opcode
->last
= insn_size
-1;
1033 /* handle any special cases */
1034 switch (rule
->special_rule
) {
1035 case 0: /* let the above apply */
1037 case 1: /* expand a limited nr of bits, ignoring the rest */
1038 curr_opcode
->first
= rule
->force_first
;
1039 curr_opcode
->last
= rule
->force_last
;
1041 case 2: /* boolean field */
1042 curr_opcode
->is_boolean
= 1;
1051 insn_table_insert_expanded(insn_table
*table
,
1054 insn_bits
*new_bits
)
1056 insn_table
**ptr_to_cur_entry
= &table
->entries
;
1057 insn_table
*cur_entry
= *ptr_to_cur_entry
;
1059 /* find the new table for this entry */
1060 while (cur_entry
!= NULL
1061 && cur_entry
->opcode_nr
< new_opcode_nr
) {
1062 ptr_to_cur_entry
= &cur_entry
->sibling
;
1063 cur_entry
= *ptr_to_cur_entry
;
1066 if (cur_entry
== NULL
|| cur_entry
->opcode_nr
!= new_opcode_nr
) {
1067 insn_table
*new_entry
= insn_table_new();
1068 new_entry
->opcode_nr
= new_opcode_nr
;
1069 new_entry
->expanded_bits
= new_bits
;
1070 new_entry
->opcode_rule
= table
->opcode_rule
+1;
1071 new_entry
->sibling
= cur_entry
;
1072 new_entry
->parent
= table
;
1073 *ptr_to_cur_entry
= new_entry
;
1074 cur_entry
= new_entry
;
1075 table
->nr_entries
++;
1077 /* ASSERT new_bits == cur_entry bits */
1078 ASSERT(cur_entry
!= NULL
&& cur_entry
->opcode_nr
== new_opcode_nr
);
1079 insn_table_insert_insn(cur_entry
,
1080 old_insn
->file_entry
,
1085 insn_table_expand_opcode(insn_table
*table
,
1092 if (field_nr
> table
->opcode
->last
) {
1093 insn_table_insert_expanded(table
, instruction
, opcode_nr
, bits
);
1096 insn_field
*field
= instruction
->fields
->bits
[field_nr
];
1097 if (field
->is_int
|| field
->is_slash
) {
1098 ASSERT(field
->first
>= table
->opcode
->first
1099 && field
->last
<= table
->opcode
->last
);
1100 insn_table_expand_opcode(table
, instruction
, field
->last
+1,
1101 ((opcode_nr
<< field
->width
) + field
->val_int
),
1106 int last_pos
= ((field
->last
< table
->opcode
->last
)
1107 ? field
->last
: table
->opcode
->last
);
1108 int first_pos
= ((field
->first
> table
->opcode
->first
)
1109 ? field
->first
: table
->opcode
->first
);
1110 int width
= last_pos
- first_pos
+ 1;
1111 int last_val
= (table
->opcode
->is_boolean
1112 ? 2 : (1 << width
));
1113 for (val
= 0; val
< last_val
; val
++) {
1114 insn_bits
*new_bits
= insn_bits_new();
1115 new_bits
->field
= field
;
1116 new_bits
->value
= val
;
1117 new_bits
->last
= bits
;
1118 new_bits
->opcode
= table
->opcode
;
1119 insn_table_expand_opcode(table
, instruction
, last_pos
+1,
1120 ((opcode_nr
<< width
) | val
),
1127 insn_table_insert_expanding(insn_table
*table
,
1130 insn_table_expand_opcode(table
,
1132 table
->opcode
->first
,
1134 table
->expanded_bits
);
1139 insn_table_expand_insns(insn_table
*table
)
1142 ASSERT(table
->nr_insn
>= 1);
1144 /* determine a valid opcode */
1145 while (table
->opcode_rule
->valid
) {
1146 /* specials only for single instructions */
1147 if ((table
->nr_insn
> 1
1148 && table
->opcode_rule
->special_mask
== 0
1149 && table
->opcode_rule
->special_rule
== 0)
1150 || (table
->nr_insn
== 1
1151 && table
->opcode_rule
->special_mask
!= 0
1152 && ((table
->insns
->fields
->value
1153 & table
->opcode_rule
->special_mask
)
1154 == table
->opcode_rule
->special_value
))
1155 || (idecode_expand_semantics
1156 && table
->opcode_rule
->special_mask
== 0
1157 && table
->opcode_rule
->special_rule
== 0))
1159 insn_table_find_opcode_field(table
->insns
,
1161 table
->nr_insn
== 1/*string*/
1163 if (table
->opcode
!= NULL
)
1165 table
->opcode_rule
++;
1168 /* did we find anything */
1169 if (table
->opcode
== NULL
) {
1172 ASSERT(table
->opcode
!= NULL
);
1174 /* back link what we found to its parent */
1175 if (table
->parent
!= NULL
) {
1176 ASSERT(table
->parent
->opcode
!= NULL
);
1177 table
->opcode
->parent
= table
->parent
->opcode
;
1180 /* expand the raw instructions according to the opcode */
1183 for (entry
= table
->insns
; entry
!= NULL
; entry
= entry
->next
) {
1184 insn_table_insert_expanding(table
, entry
);
1188 /* and do the same for the sub entries */
1191 for (entry
= table
->entries
; entry
!= NULL
; entry
= entry
->sibling
) {
1192 insn_table_expand_insns(entry
);
1200 insn_table_load_insns(char *file_name
)
1202 file_table
*file
= file_table_open(file_name
);
1203 insn_table
*table
= insn_table_new();
1204 file_table_entry
*file_entry
;
1205 table
->opcode_rule
= opcode_table
;
1207 while (file_entry
= file_table_read(file
)) {
1208 insn_fields
*fields
;
1209 /* skip instructions that aren't relevant to the mode */
1210 if (it_is("64", file_entry
->fields
[insn_flags
]) && !WITH_64BIT_TARGET
1211 || it_is("32", file_entry
->fields
[insn_flags
]) && WITH_64BIT_TARGET
)
1213 /* create/insert the new instruction */
1214 fields
= parse_insn_format(file_entry
, file_entry
->fields
[insn_format
]);
1215 insn_table_insert_insn(table
, file_entry
, fields
);
1223 dump_insn(insn
*entry
, int indent
, int levels
)
1225 printf("(insn*)0x%x\n", entry
);
1227 if (levels
&& entry
!= NULL
) {
1229 dumpf(indent
, "(file_entry ");
1230 dump_file_table_entry(entry
->file_entry
, indent
+1);
1231 dumpf(indent
, " )\n");
1233 dumpf(indent
, "(fields ");
1234 dump_insn_fields(entry
->fields
, indent
+1);
1235 dumpf(indent
, " )\n");
1237 dumpf(indent
, "(next ");
1238 dump_insn(entry
->next
, indent
+1, levels
-1);
1239 dumpf(indent
, " )\n");
1247 dump_insn_table(insn_table
*table
,
1248 int indent
, int levels
)
1251 printf("(insn_table*)0x%x\n", table
);
1253 if (levels
&& table
!= NULL
) {
1256 dumpf(indent
, "(opcode_nr %d)\n", table
->opcode_nr
);
1258 dumpf(indent
, "(expanded_bits ");
1259 dump_insn_bits(table
->expanded_bits
, indent
+1, -1);
1260 dumpf(indent
, " )\n");
1262 dumpf(indent
, "(int nr_insn %d)\n", table
->nr_insn
);
1264 dumpf(indent
, "(insns ");
1265 dump_insn(table
->insns
, indent
+1, table
->nr_insn
);
1266 dumpf(indent
, " )\n");
1268 dumpf(indent
, "(opcode_rule ");
1269 dump_opcode_rule(table
->opcode_rule
, indent
+1);
1270 dumpf(indent
, " )\n");
1272 dumpf(indent
, "(opcode ");
1273 dump_opcode_field(table
->opcode
, indent
+1, 1);
1274 dumpf(indent
, " )\n");
1276 dumpf(indent
, "(nr_entries %d)\n", table
->entries
);
1277 dumpf(indent
, "(entries ");
1278 dump_insn_table(table
->entries
, indent
+1, table
->nr_entries
);
1279 dumpf(indent
, " )\n");
1281 dumpf(indent
, "(sibling ", table
->sibling
);
1282 dump_insn_table(table
->sibling
, indent
+1, levels
-1);
1283 dumpf(indent
, " )\n");
1285 dumpf(indent
, "(parent ", table
->parent
);
1286 dump_insn_table(table
->parent
, indent
+1, 0);
1287 dumpf(indent
, " )\n");
1293 /****************************************************************/
1297 lf_print_copyleft(lf
*file
)
1300 /* This file is part of psim (model of the PowerPC(tm) architecture)
1302 Copyright (C) 1994-1995, Andrew Cagney <cagney@highland.com.au>
1304 This library is free software; you can redistribute it and/or
1305 modify it under the terms of the GNU Library General Public License
1306 as published by the Free Software Foundation; either version 2 of
1307 the License, or (at your option) any later version.
1309 This library is distributed in the hope that it will be useful, but
1310 WITHOUT ANY WARRANTY; without even the implied warranty of
1311 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
1312 Library General Public License for more details.
1314 You should have received a copy of the GNU Library General Public
1315 License along with this library; if not, write to the Free Software
1316 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
1320 PowerPC is a trademark of International Business Machines Corporation.
1324 This file was generated by the program gen */
1330 lf_print_c_line_nr(lf
*file
, file_table_entry
*entry
)
1332 #if WITH_LINE_NUMBERS
1333 lf_indent_suppress(file
);
1334 lf_putstr(file
, "#line ");
1335 lf_putint(file
, entry
->line_nr
);
1336 lf_putstr(file
, " \"");
1337 lf_putstr(file
, entry
->file_name
);
1338 lf_putstr(file
, "\"\n");
1344 lf_print_c_code(lf
*file
, char *code
)
1347 int in_bit_field
= 0;
1348 while (*chp
!= '\0') {
1352 lf_indent_suppress(file
);
1353 while (*chp
!= '\0' && *chp
!= '\n') {
1354 if (chp
[0] == '{' && !isspace(chp
[1])) {
1356 lf_putchr(file
, '_');
1358 else if (in_bit_field
&& chp
[0] == ':') {
1359 lf_putchr(file
, '_');
1361 else if (in_bit_field
&& *chp
== '}') {
1362 lf_putchr(file
, '_');
1366 lf_putchr(file
, *chp
);
1371 error("bit field paren miss match some where\n");
1373 lf_putchr(file
, '\n');
1377 lf_putchr(file
, '\n');
1382 lf_print_binary(lf
*file
, int decimal
, int width
)
1387 for (bit
= 1 << (width
-1); bit
!= 0; bit
>>= 1) {
1389 lf_putchr(file
, '1');
1391 lf_putchr(file
, '0');
1398 lf_print_insn_bits(lf
*file
, insn_bits
*bits
)
1402 lf_print_insn_bits(file
, bits
->last
);
1403 lf_putchr(file
, '_');
1404 lf_putstr(file
, bits
->field
->val_string
);
1405 if (!bits
->opcode
->is_boolean
|| bits
->value
== 0) {
1406 if (bits
->opcode
->last
< bits
->field
->last
)
1407 lf_putint(file
, bits
->value
<< (bits
->field
->last
- bits
->opcode
->last
));
1409 lf_putint(file
, bits
->value
);
1414 lf_print_opcodes(lf
*file
,
1417 if (table
!= NULL
) {
1419 lf_printf(file
, "_%d_%d",
1420 table
->opcode
->first
,
1421 table
->opcode
->last
);
1422 if (table
->parent
== NULL
) break;
1423 lf_printf(file
, "__%d", table
->opcode_nr
);
1424 table
= table
->parent
;
1430 lf_print_table_name(lf
*file
,
1433 lf_printf(file
, "idecode_table");
1434 lf_print_opcodes(file
, table
);
1440 function_name_prefix_semantics
,
1441 function_name_prefix_idecode
,
1442 function_name_prefix_none
1443 } lf_function_name_prefixes
;
1446 lf_print_function_name(lf
*file
,
1448 insn_bits
*expanded_bits
,
1449 lf_function_name_prefixes prefix
)
1453 case function_name_prefix_semantics
:
1454 lf_putstr(file
, "semantic_");
1456 case function_name_prefix_idecode
:
1457 lf_printf(file
, "idecode_");
1463 /* the function name */
1466 for (pos
= instruction
->file_entry
->fields
[insn_name
];
1474 lf_putchr(file
, '_');
1477 lf_putchr(file
, *pos
);
1484 if (idecode_expand_semantics
)
1485 lf_print_insn_bits(file
, expanded_bits
);
1490 lf_print_idecode_table(lf
*file
,
1493 int can_assume_leaf
;
1496 /* have a look at the rule table, if all table rules follow all
1497 switch rules, I can assume that all end points are leaves */
1499 while (opcode_table
[rule
].valid
1500 && opcode_table
[rule
].use_switch
)
1502 while (opcode_table
[rule
].valid
1503 && !opcode_table
[rule
].use_switch
1504 && !opcode_table
[rule
].special_rule
)
1506 can_assume_leaf
= !opcode_table
[rule
].valid
;
1508 lf_printf(file
, "{\n");
1509 lf_indent(file
, +2);
1511 lf_printf(file
, "idecode_table_entry *table = ");
1512 lf_print_table_name(file
, entry
);
1513 lf_printf(file
, ";\n");
1514 lf_printf(file
, "int opcode = EXTRACTED32(instruction, %d, %d);\n",
1515 entry
->opcode
->first
, entry
->opcode
->last
);
1516 lf_printf(file
, "idecode_table_entry *table_entry = table + opcode;\n");
1517 lf_printf(file
, "while (1) {\n");
1518 lf_indent(file
, +2);
1520 lf_printf(file
, "while (table_entry->mask != 0) {\n");
1521 lf_indent(file
, +2);
1523 lf_printf(file
, "table = ((idecode_table_entry*)\n");
1524 lf_printf(file
, " table_entry->function_or_table);\n");
1525 lf_printf(file
, "opcode = ((instruction & table_entry->mask)\n");
1526 lf_printf(file
, " >> table_entry->shift);\n");
1527 lf_printf(file
, "table_entry = table + opcode;\n");
1529 lf_indent(file
, -2);
1530 lf_printf(file
, "}\n");
1531 if (!idecode_cache
&& can_assume_leaf
) {
1532 lf_printf(file
, "return (((idecode_semantic*)\n");
1533 lf_printf(file
, " table_entry->function_or_table)\n");
1534 lf_printf(file
, " (%s));\n", insn_actual
);
1536 else if (!idecode_cache
&& !can_assume_leaf
) {
1537 lf_printf(file
, "if (table_entry->shift == 0)");
1538 lf_printf(file
, " return (((idecode_semantic*)\n");
1539 lf_printf(file
, " table_entry->function_or_table)\n");
1540 lf_printf(file
, " (%s));\n", insn_actual
);
1542 else if (idecode_cache
== 1 && can_assume_leaf
) {
1543 lf_printf(file
, "ASSERT(!entry->shift);\n");
1544 lf_printf(file
, "return ((idecode_semantic*)\n");
1545 lf_printf(file
, " table_entry->function_or_table);\n");
1547 else if (idecode_cache
== 1 && !can_assume_leaf
) {
1548 lf_printf(file
, "if (table_entry->shift == 0)\n");
1549 lf_printf(file
, " return ((idecode_semantic*)\n");
1550 lf_printf(file
, " table_entry->function_or_table);\n");
1551 lf_printf(file
, "else if (table_entry->shift == -1)\n");
1552 lf_printf(file
, " return (((idecode_crack*)\n");
1553 lf_printf(file
, " table_entry->function_or_table)\n");
1554 lf_printf(file
, " (%s));\n", insn_actual
);
1557 lf_printf(file
, "if (table_entry->shift == 0)\n");
1558 lf_printf(file
, " return (((idecode_crack*)\n");
1559 lf_printf(file
, " table_entry->function_or_table)\n");
1560 lf_printf(file
, " (%s));\n", cache_idecode_actual
);
1562 if (!can_assume_leaf
) {
1563 lf_printf(file
, "opcode = (instruction & table_entry->shift) != 0;\n");
1564 lf_printf(file
, "table = ((idecode_table_entry*)\n");
1565 lf_printf(file
, " table_entry->function_or_table);\n");
1566 lf_printf(file
, "table_entry = table + opcode;\n");
1569 lf_indent(file
, -2);
1570 lf_printf(file
, "}\n");
1572 lf_indent(file
, -2);
1573 lf_printf(file
, "}\n");
1578 lf_print_my_prefix(lf
*file
,
1579 file_table_entry
*file_entry
)
1581 lf_printf(file
, "const char *const my_prefix = \n");
1582 lf_printf(file
, " \"%s:%s:%d:cache\";\n",
1583 file_entry
->file_name
,
1584 file_entry
->fields
[insn_name
],
1585 file_entry
->line_nr
);
1590 lf_print_ptrace(lf
*file
)
1592 lf_printf(file
, "\n");
1593 lf_putstr(file
, "ITRACE(trace_semantics, (\"cia=0x%x\\n\", cia));\n");
1597 /****************************************************************/
1599 typedef void leaf_handler
1603 typedef void padding_handler
1611 insn_table_traverse_tree(insn_table
*table
,
1614 leaf_handler
*start
,
1617 padding_handler
*padding
)
1622 ASSERT(table
!= NULL
1623 && table
->opcode
!= NULL
1624 && table
->nr_entries
> 0
1625 && table
->entries
!= 0);
1627 if (start
!= NULL
&& depth
>= 0)
1628 start(table
, data
, depth
);
1630 for (entry_nr
= 0, entry
= table
->entries
;
1631 entry_nr
< (table
->opcode
->is_boolean
1633 : (1 << (table
->opcode
->last
- table
->opcode
->first
+ 1)));
1636 || (!table
->opcode
->is_boolean
1637 && entry_nr
< entry
->opcode_nr
)) {
1638 if (padding
!= NULL
&& depth
>= 0)
1639 padding(table
, data
, depth
, entry_nr
);
1642 ASSERT(entry
!= NULL
&& (entry
->opcode_nr
== entry_nr
1643 || table
->opcode
->is_boolean
));
1644 if (entry
->opcode
!= NULL
&& depth
!= 0) {
1645 insn_table_traverse_tree(entry
, data
, depth
+1,
1646 start
, leaf
, end
, padding
);
1648 else if (depth
>= 0) {
1650 leaf(entry
, data
, depth
);
1652 entry
= entry
->sibling
;
1655 if (end
!= NULL
&& depth
>= 0)
1656 end(table
, data
, depth
);
1660 typedef void insn_handler
1666 insn_table_traverse_insn(insn_table
*table
,
1671 for (instruction
= table
->insns
;
1672 instruction
!= NULL
;
1673 instruction
= instruction
->next
) {
1674 leaf(table
, data
, instruction
);
1680 update_depth(insn_table
*entry
,
1684 int *max_depth
= (int*)data
;
1685 if (*max_depth
< depth
)
1691 insn_table_depth(insn_table
*table
)
1694 insn_table_traverse_tree(table
,
1705 /****************************************************************/
1708 dump_traverse_start(insn_table
*table
,
1712 dumpf(depth
*2, "(%d\n", table
->opcode_nr
);
1716 dump_traverse_leaf(insn_table
*entry
,
1720 ASSERT(entry
->nr_entries
== 0
1721 && entry
->nr_insn
== 1
1722 && entry
->opcode
== NULL
);
1723 dumpf(depth
*2, ".%d %s\n", entry
->opcode_nr
,
1724 entry
->insns
->file_entry
->fields
[insn_format
]);
1728 dump_traverse_end(insn_table
*table
,
1732 dumpf(depth
*2, ")\n");
1736 dump_traverse_padding(insn_table
*table
,
1741 dumpf(depth
*2, ".<%d>\n", opcode_nr
);
1746 dump_traverse(insn_table
*table
)
1748 insn_table_traverse_tree(table
, NULL
, 1,
1749 dump_traverse_start
,
1752 dump_traverse_padding
);
1756 /****************************************************************/
1760 semantics_h_print_function(lf
*file
,
1762 insn_bits
*expanded_bits
)
1764 lf_printf(file
, "\n");
1765 lf_printf(file
, "INLINE_SEMANTICS unsigned_word ");
1766 lf_print_function_name(file
,
1769 function_name_prefix_semantics
);
1770 lf_printf(file
, "\n(%s);\n",
1771 idecode_cache
> 1 ? cache_insn_formal
: insn_formal
);
1776 semantics_h_leaf(insn_table
*entry
,
1780 lf
*file
= (lf
*)data
;
1781 ASSERT(entry
->nr_insn
== 1);
1782 semantics_h_print_function(file
, entry
->insns
, entry
->expanded_bits
);
1786 semantics_h_insn(insn_table
*entry
,
1790 lf
*file
= (lf
*)data
;
1791 semantics_h_print_function(file
, instruction
, NULL
);
1796 gen_semantics_h(insn_table
*table
, lf
*file
)
1799 lf_print_copyleft(file
);
1800 lf_printf(file
, "\n");
1801 lf_printf(file
, "#ifndef _SEMANTICS_H_\n");
1802 lf_printf(file
, "#define _SEMANTICS_H_\n");
1803 lf_printf(file
, "\n");
1804 lf_printf(file
, "#ifndef INLINE_SEMANTICS\n");
1805 lf_printf(file
, "#define INLINE_SEMANTICS\n");
1806 lf_printf(file
, "#endif\n");
1807 lf_printf(file
, "\n");
1808 lf_printf(file
, "\n");
1810 if (idecode_expand_semantics
)
1811 insn_table_traverse_tree(table
,
1815 semantics_h_leaf
, /* leaf */
1817 NULL
); /* padding */
1819 insn_table_traverse_insn(table
,
1823 lf_printf(file
, "\n");
1824 lf_printf(file
, "#endif /* _SEMANTICS_H_ */\n");
1828 /****************************************************************/
1830 typedef struct _icache_tree icache_tree
;
1831 struct _icache_tree
{
1834 icache_tree
*children
;
1840 icache_tree
*new_tree
= (icache_tree
*)zmalloc(sizeof(icache_tree
));
1841 ASSERT(new_tree
!= NULL
);
1846 icache_tree_insert(icache_tree
*tree
,
1849 icache_tree
*new_tree
;
1851 icache_tree
**ptr_to_cur_tree
= &tree
->children
;
1852 icache_tree
*cur_tree
= *ptr_to_cur_tree
;
1853 while (cur_tree
!= NULL
1854 && strcmp(cur_tree
->name
, name
) < 0) {
1855 ptr_to_cur_tree
= &cur_tree
->next
;
1856 cur_tree
= *ptr_to_cur_tree
;
1858 ASSERT(cur_tree
== NULL
1859 || strcmp(cur_tree
->name
, name
) >= 0);
1860 /* already in the tree */
1861 if (cur_tree
!= NULL
1862 && strcmp(cur_tree
->name
, name
) == 0)
1864 /* missing, insert it */
1865 ASSERT(cur_tree
== NULL
1866 || strcmp(cur_tree
->name
, name
) > 0);
1867 new_tree
= icache_tree_new();
1868 new_tree
->name
= name
;
1869 new_tree
->next
= cur_tree
;
1870 *ptr_to_cur_tree
= new_tree
;
1876 insn_table_cache_fields(insn_table
*table
)
1878 icache_tree
*tree
= icache_tree_new();
1880 for (instruction
= table
->insns
;
1881 instruction
!= NULL
;
1882 instruction
= instruction
->next
) {
1885 icache_tree_insert(tree
,
1886 instruction
->file_entry
->fields
[insn_form
]);
1887 for (field
= instruction
->fields
->first
;
1889 field
= field
->next
) {
1890 if (field
->is_string
)
1891 icache_tree_insert(form
, field
->val_string
);
1900 gen_icache_h(icache_tree
*tree
,
1903 lf_print_copyleft(file
);
1904 lf_printf(file
, "\n");
1905 lf_printf(file
, "#ifndef _ICACHE_H_\n");
1906 lf_printf(file
, "#define _ICACHE_H_\n");
1907 lf_printf(file
, "\n");
1908 lf_printf(file
, "#ifndef INLINE_ICACHE\n");
1909 lf_printf(file
, "#define INLINE_ICACHE\n");
1910 lf_printf(file
, "#endif\n");
1911 lf_printf(file
, "\n");
1912 lf_printf(file
, "\n");
1914 /* create an instruction cache if being used */
1915 if (idecode_cache
) {
1916 lf_printf(file
, "typedef struct _idecode_cache {\n");
1917 lf_printf(file
, " unsigned_word address;\n");
1918 lf_printf(file
, " void *semantic;\n");
1919 if (idecode_cache
== 1) {
1920 lf_printf(file
, " instruction_word instruction;\n");
1924 lf_printf(file
, " union {\n");
1925 for (form
= tree
->children
;
1927 form
= form
->next
) {
1929 lf_printf(file
, " struct {\n");
1930 for (field
= form
->children
;
1932 field
= field
->next
) {
1933 extraction_rules
*rule
;
1935 for (rule
= cachable_values
;
1938 if (strcmp(field
->name
, rule
->old_name
) == 0) {
1940 if (rule
->new_name
!= NULL
)
1941 lf_printf(file
, " %s %s; /* %s */\n",
1942 rule
->type
== NULL
? "unsigned" : rule
->type
,
1943 rule
->new_name
, rule
->old_name
);
1947 lf_printf(file
, " unsigned %s;\n", field
->name
);
1949 lf_printf(file
, " } %s;\n", form
->name
);
1951 lf_printf(file
, " } crack;\n");
1953 lf_printf(file
, "} idecode_cache;\n");
1956 /* define various fields according to the cache */
1957 if (idecode_cache
<= 1) {
1958 extraction_rules
*rule
;
1959 lf_printf(file
, "\n");
1960 for (rule
= cachable_values
;
1963 if (rule
->expression
!= NULL
)
1964 lf_printf(file
, "#define %s %s\n",
1965 rule
->new_name
, rule
->expression
);
1969 lf_printf(file
, "\n");
1970 lf_printf(file
, "#endif /* _ICACHE_H_ */\n");
1976 /****************************************************************/
1980 lf_print_c_extraction(lf
*file
,
1984 char *field_expression
,
1985 insn_field
*cur_field
,
1987 int get_value_from_cache
,
1988 int put_value_in_cache
)
1990 ASSERT(field_name
!= NULL
);
1992 && (!bits
->opcode
->is_boolean
|| bits
->value
== 0)
1993 && strcmp(field_name
, cur_field
->val_string
) == 0) {
1994 ASSERT(bits
->field
== cur_field
);
1995 ASSERT(field_type
== NULL
);
1996 lf_print_c_line_nr(file
, instruction
->file_entry
);
1997 lf_printf(file
, "const unsigned %s = ",
1999 if (bits
->opcode
->last
< bits
->field
->last
)
2000 lf_printf(file
, "%d;\n",
2001 bits
->value
<< (bits
->field
->last
- bits
->opcode
->last
));
2003 lf_printf(file
, "%d;\n", bits
->value
);
2006 /* put the field in the local variable */
2007 lf_print_c_line_nr(file
, instruction
->file_entry
);
2008 lf_printf(file
, "%s const %s = ",
2009 field_type
== NULL
? "unsigned" : field_type
,
2011 /* getting it from the cache */
2012 if (get_value_from_cache
|| put_value_in_cache
) {
2013 lf_printf(file
, "cache_entry->crack.%s.%s",
2014 instruction
->file_entry
->fields
[insn_form
],
2016 if (put_value_in_cache
) /* also put it in the cache? */
2017 lf_printf(file
, " = ");
2019 if (!get_value_from_cache
) {
2020 if (strcmp(field_name
, cur_field
->val_string
) == 0)
2021 lf_printf(file
, "EXTRACTED32(instruction, %d, %d)",
2022 cur_field
->first
, cur_field
->last
);
2023 else if (field_expression
!= NULL
)
2024 lf_printf(file
, "%s", field_expression
);
2026 lf_printf(file
, "eval_%s", field_name
);
2028 lf_printf(file
, ";\n");
2034 lf_print_c_extractions(lf
*file
,
2036 insn_bits
*expanded_bits
,
2037 int get_value_from_cache
,
2038 int put_value_in_cache
)
2040 insn_field
*cur_field
;
2042 /* extract instruction fields */
2043 lf_printf(file
, "/* extraction: %s */\n",
2044 instruction
->file_entry
->fields
[insn_format
]);
2046 for (cur_field
= instruction
->fields
->first
;
2047 cur_field
->first
< insn_size
;
2048 cur_field
= cur_field
->next
) {
2049 if (cur_field
->is_string
) {
2052 /* find any corresponding value */
2053 for (bits
= expanded_bits
;
2055 bits
= bits
->last
) {
2056 if (bits
->field
== cur_field
)
2059 /* try the cache rule table for what to do */
2060 if (get_value_from_cache
|| put_value_in_cache
) {
2061 extraction_rules
*field_rule
;
2062 for (field_rule
= cachable_values
;
2065 if (strcmp(cur_field
->val_string
, field_rule
->old_name
) == 0) {
2067 if (field_rule
->valid
> 1 && put_value_in_cache
)
2068 lf_print_c_extraction(file
,
2070 field_rule
->new_name
,
2072 field_rule
->expression
,
2077 else if (field_rule
->valid
== 1)
2078 lf_print_c_extraction(file
,
2080 field_rule
->new_name
,
2082 field_rule
->expression
,
2085 get_value_from_cache
,
2086 put_value_in_cache
);
2090 if (found_rule
== 0)
2091 lf_print_c_extraction(file
,
2093 cur_field
->val_string
,
2098 get_value_from_cache
,
2099 put_value_in_cache
);
2100 /* if any (XXX == 0), output a corresponding test */
2101 if (instruction
->file_entry
->annex
!= NULL
) {
2102 char *field_name
= cur_field
->val_string
;
2103 char *is_0_ptr
= instruction
->file_entry
->annex
;
2104 int field_len
= strlen(field_name
);
2105 if (strlen(is_0_ptr
) >= (strlen("_is_0") + field_len
)) {
2106 is_0_ptr
+= field_len
;
2107 while ((is_0_ptr
= strstr(is_0_ptr
, "_is_0")) != NULL
) {
2108 if (strncmp(is_0_ptr
- field_len
, field_name
, field_len
) == 0
2109 && !isalpha(is_0_ptr
[ - field_len
- 1])) {
2110 lf_print_c_line_nr(file
, instruction
->file_entry
);
2111 lf_printf(file
, "const unsigned %s_is_0 = (", field_name
);
2113 lf_printf(file
, "%d", bits
->value
);
2115 lf_printf(file
, "%s", field_name
);
2116 lf_printf(file
, " == 0);\n");
2119 is_0_ptr
+= strlen("_is_0");
2123 /* any thing else ... */
2126 lf_print_file_line_nr(file
);
2130 lf_print_c_validate(lf
*file
,
2132 opcode_field
*opcodes
)
2134 unsigned check_mask
= 0;
2135 unsigned check_val
= 0;
2137 opcode_field
*opcode
;
2139 for (field
= instruction
->fields
->first
;
2140 field
->first
< insn_size
;
2141 field
= field
->next
) {
2143 check_mask
<<= field
->width
;
2144 check_val
<<= field
->width
;
2146 /* is it a constant that could need validating? */
2147 if (!field
->is_int
&& !field
->is_slash
)
2150 /* has it been checked by a table? */
2151 for (opcode
= opcodes
; opcode
!= NULL
; opcode
= opcode
->parent
) {
2152 if (field
->first
>= opcode
->first
2153 && field
->last
<= opcode
->last
)
2159 check_mask
|= (1 << field
->width
)-1;
2160 check_val
|= field
->val_int
;
2163 /* if any bits not checked by opcode tables, output code to check them */
2164 if (!it_is("illegal", instruction
->file_entry
->fields
[insn_flags
])
2166 lf_printf(file
, "\n");
2167 lf_printf(file
, "/* validate: %s */\n",
2168 instruction
->file_entry
->fields
[insn_format
]);
2169 lf_printf(file
, "if ((instruction & 0x%x) != 0x%x) {\n",
2170 check_mask
, check_val
);
2171 switch (idecode_cache
) {
2173 lf_printf(file
, " return semantic_illegal(%s);\n", insn_actual
);
2176 lf_printf(file
, " return semantic_illegal;\n");
2179 lf_printf(file
, " return idecode_illegal(%s);\n", cache_idecode_actual
);
2181 lf_printf(file
, "}\n");
2188 lf_print_c_cracker(lf
*file
,
2190 insn_bits
*expanded_bits
,
2191 opcode_field
*opcodes
)
2194 /* function header */
2195 lf_printf(file
, "{\n");
2196 lf_indent(file
, +2);
2198 lf_print_my_prefix(file
,
2199 instruction
->file_entry
);
2201 lf_print_ptrace(file
);
2203 lf_print_c_validate(file
, instruction
, opcodes
);
2205 lf_printf(file
, "\n");
2206 lf_printf(file
, "{\n");
2207 lf_indent(file
, +2);
2208 lf_print_c_extractions(file
,
2211 0/*get_value_from_cache*/,
2212 1/*put_value_in_cache*/);
2213 lf_indent(file
, -2);
2214 lf_printf(file
, "}\n");
2216 /* return the function propper (main sorts this one out) */
2217 lf_printf(file
, "\n");
2218 lf_printf(file
, "/* semantic routine */\n");
2219 lf_print_c_line_nr(file
, instruction
->file_entry
);
2220 lf_printf(file
, "return ");
2221 lf_print_function_name(file
,
2224 function_name_prefix_semantics
);
2225 lf_printf(file
, ";\n");
2227 lf_print_file_line_nr(file
);
2228 lf_indent(file
, -2);
2229 lf_printf(file
, "}\n");
2234 lf_print_c_semantic(lf
*file
,
2236 insn_bits
*expanded_bits
,
2237 opcode_field
*opcodes
)
2240 lf_printf(file
, "{\n");
2241 lf_indent(file
, +2);
2243 lf_print_my_prefix(file
,
2244 instruction
->file_entry
);
2245 lf_putstr(file
, insn_local
);
2246 lf_printf(file
, "\n");
2248 lf_printf(file
, "\n");
2249 lf_print_c_extractions(file
,
2252 idecode_cache
> 1/*get_value_from_cache*/,
2253 0/*put_value_in_cache*/);
2255 lf_print_ptrace(file
);
2257 /* generate code to check previously unchecked fields */
2258 if (idecode_cache
< 2)
2259 lf_print_c_validate(file
, instruction
, opcodes
);
2261 /* if OEA and a floating point generate a check that fp is enabled */
2262 if (it_is("f", instruction
->file_entry
->fields
[insn_flags
])) {
2263 lf_printf(file
, "\n");
2264 lf_printf(file
, "/* verify FP is enabled */\n");
2265 lf_printf(file
, "if (!IS_FP_AVAILABLE(processor))\n");
2266 lf_printf(file
, " floating_point_unavailable_interrupt(processor, cia);\n");
2269 /* generate the code (or at least something */
2270 if (instruction
->file_entry
->annex
!= NULL
) {
2272 lf_printf(file
, "\n");
2273 lf_print_c_line_nr(file
, instruction
->file_entry
);
2274 lf_printf(file
, "{\n");
2275 lf_indent(file
, +2);
2276 lf_print_c_code(file
, instruction
->file_entry
->annex
);
2277 lf_indent(file
, -2);
2278 lf_printf(file
, "}\n");
2279 lf_print_file_line_nr(file
);
2281 else if (it_is("nop", instruction
->file_entry
->fields
[insn_flags
])) {
2282 lf_print_file_line_nr(file
);
2284 else if (it_is("f", instruction
->file_entry
->fields
[insn_flags
])) {
2285 /* unimplemented floating point - call for assistance */
2286 lf_printf(file
, "\n");
2287 lf_print_c_line_nr(file
, instruction
->file_entry
);
2288 lf_putstr(file
, "floating_point_assist_interrupt(processor, cia);\n");
2289 lf_print_file_line_nr(file
);
2292 /* abort so it is implemented now */
2293 lf_print_c_line_nr(file
, instruction
->file_entry
);
2294 lf_putstr(file
, "error(\"%s: unimplemented, cia=0x%x\\n\", my_prefix, cia);\n");
2295 lf_print_file_line_nr(file
);
2296 lf_printf(file
, "\n");
2299 /* the function footer */
2300 lf_printf(file
, "return nia;\n");
2301 lf_indent(file
, -2);
2302 lf_printf(file
, "}\n");
2306 lf_print_c_semantic_function(lf
*file
,
2308 insn_bits
*expanded_bits
,
2309 opcode_field
*opcodes
)
2312 /* build the semantic routine to execute the instruction */
2314 /* function header */
2315 lf_printf(file
, "\n");
2316 lf_printf(file
, "INLINE_SEMANTICS unsigned_word\n");
2317 lf_print_function_name(file
,
2320 function_name_prefix_semantics
);
2321 lf_printf(file
, "\n(%s)\n",
2322 idecode_cache
> 1 ? cache_insn_formal
: insn_formal
);
2324 lf_print_c_semantic(file
,
2333 semantics_c_leaf(insn_table
*entry
,
2337 lf
*file
= (lf
*)data
;
2338 ASSERT(entry
->nr_insn
== 1
2339 && entry
->opcode
== NULL
2340 && entry
->parent
!= NULL
2341 && entry
->parent
->opcode
!= NULL
);
2342 lf_print_c_semantic_function(file
,
2344 entry
->expanded_bits
,
2345 entry
->parent
->opcode
);
2349 semantics_c_insn(insn_table
*table
,
2353 lf
*file
= (lf
*)data
;
2354 lf_print_c_semantic_function(file
, instruction
,
2361 gen_semantics_c(insn_table
*table
, lf
*file
)
2363 lf_print_copyleft(file
);
2364 lf_printf(file
, "\n");
2365 lf_printf(file
, "#ifndef _SEMANTICS_C_\n");
2366 lf_printf(file
, "#define _SEMANTICS_C_\n");
2367 lf_printf(file
, "\n");
2368 lf_printf(file
, "#ifndef STATIC_INLINE_SEMANTICS\n");
2369 lf_printf(file
, "#define STATIC_INLINE_SEMANTICS STATIC_INLINE\n");
2370 lf_printf(file
, "#endif\n");
2371 lf_printf(file
, "\n");
2372 lf_printf(file
, "#include \"cpu.h\"\n");
2373 lf_printf(file
, "#include \"idecode.h\"\n");
2374 lf_printf(file
, "#include \"semantics.h\"\n");
2375 lf_printf(file
, "\n");
2377 if (idecode_expand_semantics
)
2378 insn_table_traverse_tree(table
,
2384 NULL
); /* padding */
2386 insn_table_traverse_insn(table
,
2390 lf_printf(file
, "\n");
2391 lf_printf(file
, "#endif /* _SEMANTICS_C_ */\n");
2395 /****************************************************************/
2398 gen_idecode_h(insn_table
*table
, lf
*file
)
2400 lf_print_copyleft(file
);
2401 lf_printf(file
, "\n");
2402 lf_printf(file
, "#ifndef _IDECODE_H_\n");
2403 lf_printf(file
, "#define _IDECODE_H_\n");
2404 lf_printf(file
, "\n");
2405 lf_printf(file
, "#ifndef INLINE_IDECODE\n");
2406 lf_printf(file
, "#define INLINE_IDECODE\n");
2407 lf_printf(file
, "#endif\n");
2408 lf_printf(file
, "\n");
2409 lf_printf(file
, "#include \"idecode_insn.h\"\n");
2410 lf_printf(file
, "#include \"idecode_expression.h\"\n");
2411 lf_printf(file
, "#include \"idecode_fields.h\"\n");
2412 lf_printf(file
, "#include \"idecode_branch.h\"\n");
2413 lf_printf(file
, "\n");
2414 lf_printf(file
, "#include \"icache.h\"\n");
2415 lf_printf(file
, "\n");
2416 lf_printf(file
, "typedef unsigned_word idecode_semantic\n(%s);\n",
2417 idecode_cache
< 2 ? insn_formal
: cache_insn_formal
);
2418 lf_printf(file
, "\n");
2420 lf_printf(file
, "INLINE_IDECODE unsigned_word idecode_issue\n(%s);\n",
2422 else if (idecode_cache
)
2423 lf_printf(file
, "INLINE_IDECODE idecode_semantic *idecode\n(%s);\n",
2424 idecode_cache
== 1 ? insn_formal
: cache_idecode_formal
);
2425 lf_printf(file
, "\n");
2426 lf_printf(file
, "#endif /* _IDECODE_H_ */\n");
2430 /****************************************************************/
2434 idecode_table_start(insn_table
*table
,
2438 lf
*file
= (lf
*)data
;
2440 /* start of the table */
2441 if (!table
->opcode_rule
->use_switch
) {
2442 lf_printf(file
, "\n");
2443 lf_printf(file
, "static idecode_table_entry ");
2444 lf_print_table_name(file
, table
);
2445 lf_printf(file
, "[] = {\n");
2450 idecode_table_leaf(insn_table
*entry
,
2454 lf
*file
= (lf
*)data
;
2455 ASSERT(entry
->parent
!= NULL
);
2458 /* add an entry to the table */
2459 if (!entry
->parent
->opcode_rule
->use_switch
) {
2460 if (entry
->opcode
== NULL
) {
2461 /* table leaf entry */
2462 lf_printf(file
, " /*%d*/ { 0, 0, ", entry
->opcode_nr
);
2463 lf_print_function_name(file
,
2465 entry
->expanded_bits
,
2467 ? function_name_prefix_semantics
2468 : function_name_prefix_idecode
));
2469 lf_printf(file
, " },\n");
2471 else if (entry
->opcode_rule
->use_switch
) {
2472 /* table calling switch statement */
2473 lf_printf(file
, " /*%d*/ { -1, 0, ",
2475 lf_print_table_name(file
, entry
);
2476 lf_printf(file
, " },\n");
2479 /* table `calling' another table */
2480 lf_printf(file
, " /*%d*/ { ", entry
->opcode_nr
);
2481 if (entry
->opcode
->is_boolean
)
2482 lf_printf(file
, "MASK32(%d,%d), 0, ",
2483 entry
->opcode
->first
, entry
->opcode
->last
);
2485 lf_printf(file
, "%d, MASK32(%d,%d), ",
2486 insn_size
- entry
->opcode
->last
- 1,
2487 entry
->opcode
->first
, entry
->opcode
->last
);
2488 lf_print_table_name(file
, entry
);
2489 lf_printf(file
, " },\n");
2495 idecode_table_end(insn_table
*table
,
2499 lf
*file
= (lf
*)data
;
2502 if (!table
->opcode_rule
->use_switch
) {
2503 lf_printf(file
, "};\n");
2508 idecode_table_padding(insn_table
*table
,
2513 lf
*file
= (lf
*)data
;
2516 if (!table
->opcode_rule
->use_switch
) {
2517 lf_printf(file
, " /*%d*/ { 0, 0, %s_illegal },\n",
2518 opcode_nr
, idecode_cache
> 1 ? "idecode" : "semantic");
2523 /****************************************************************/
2526 void lf_print_idecode_switch
2532 idecode_switch_start(insn_table
*table
,
2536 lf
*file
= (lf
*)data
;
2538 ASSERT(table
->opcode_rule
->use_switch
);
2540 lf_printf(file
, "switch (EXTRACTED32(instruction, %d, %d)) {\n",
2541 table
->opcode
->first
, table
->opcode
->last
);
2546 idecode_switch_leaf(insn_table
*entry
,
2550 lf
*file
= (lf
*)data
;
2551 ASSERT(entry
->parent
!= NULL
);
2553 ASSERT(entry
->parent
->opcode_rule
->use_switch
);
2555 lf_printf(file
, "case %d:\n", entry
->opcode_nr
);
2556 lf_indent(file
, +2);
2558 if (entry
->opcode
== NULL
) {
2559 /* switch calling leaf */
2560 lf_printf(file
, "return ");
2561 lf_print_function_name(file
,
2563 entry
->expanded_bits
,
2565 ? function_name_prefix_semantics
2566 : function_name_prefix_idecode
));
2568 lf_printf(file
, "(%s);\n", insn_actual
);
2569 else if (idecode_cache
== 1)
2570 lf_printf(file
, ";\n");
2572 lf_printf(file
, "(%s);\n", cache_idecode_actual
);
2574 else if (entry
->opcode_rule
->use_switch
) {
2575 /* switch calling switch */
2576 lf_print_idecode_switch(file
, entry
);
2579 /* switch calling table */
2580 lf_printf(file
, "return ");
2581 lf_print_idecode_table(file
, entry
);
2583 lf_printf(file
, "break;\n");
2585 lf_indent(file
, -2);
2588 lf_print_idecode_switch_illegal(lf
*file
)
2590 switch (idecode_cache
) {
2592 lf_printf(file
, " return semantic_illegal(%s);\n", insn_actual
);
2595 lf_printf(file
, " return semantic_illegal;\n");
2598 lf_printf(file
, " return idecode_illegal(%s);\n", cache_idecode_actual
);
2600 lf_printf(file
, " break;\n");
2604 idecode_switch_end(insn_table
*table
,
2608 lf
*file
= (lf
*)data
;
2610 ASSERT(table
->opcode_rule
->use_switch
);
2612 if (table
->opcode_rule
->use_switch
== 1) {
2613 lf_printf(file
, "default:\n");
2614 lf_print_idecode_switch_illegal(file
);
2616 lf_printf(file
, "}\n");
2620 idecode_switch_padding(insn_table
*table
,
2625 lf
*file
= (lf
*)data
;
2628 ASSERT(table
->opcode_rule
->use_switch
);
2630 if (table
->opcode_rule
->use_switch
> 1) {
2631 lf_printf(file
, "case %d:\n", opcode_nr
);
2632 lf_print_idecode_switch_illegal(file
);
2638 lf_print_idecode_switch(lf
*file
,
2641 insn_table_traverse_tree(table
,
2644 idecode_switch_start
,
2645 idecode_switch_leaf
,
2647 idecode_switch_padding
);
2652 idecode_expand_if_switch(insn_table
*table
,
2656 lf
*file
= (lf
*)data
;
2658 if (table
->opcode_rule
->use_switch
2659 && table
->parent
!= NULL
/* don't expand the top one yet */
2660 && !table
->parent
->opcode_rule
->use_switch
) {
2661 lf_printf(file
, "\n");
2662 lf_printf(file
, "STATIC_INLINE_IDECODE void\n");
2663 lf_print_table_name(file
, table
);
2664 lf_printf(file
, "\n(%s)\n",
2665 idecode_cache
? cache_idecode_formal
: insn_formal
);
2666 lf_printf(file
, "{\n");
2668 lf_indent(file
, +2);
2669 lf_print_idecode_switch(file
, table
);
2670 lf_indent(file
, -2);
2672 lf_printf(file
, "}\n");
2677 lf_print_c_cracker_function(lf
*file
,
2679 insn_bits
*expanded_bits
,
2680 opcode_field
*opcodes
)
2682 /* if needed, generate code to enter this routine into a cache */
2683 lf_printf(file
, "\n");
2684 lf_printf(file
, "STATIC_INLINE_IDECODE idecode_semantic *\n");
2685 lf_print_function_name(file
,
2688 function_name_prefix_idecode
);
2689 lf_printf(file
, "\n(%s)\n", cache_idecode_formal
);
2691 lf_print_c_cracker(file
,
2698 idecode_crack_leaf(insn_table
*entry
,
2702 lf
*file
= (lf
*)data
;
2703 ASSERT(entry
->nr_insn
== 1
2704 && entry
->opcode
== NULL
2705 && entry
->parent
!= NULL
2706 && entry
->parent
->opcode
!= NULL
);
2707 lf_print_c_cracker_function(file
,
2709 entry
->expanded_bits
,
2714 idecode_crack_insn(insn_table
*entry
,
2718 lf
*file
= (lf
*)data
;
2719 lf_print_c_cracker_function(file
,
2725 /****************************************************************/
2727 gen_idecode_c(insn_table
*table
, lf
*file
)
2732 lf_print_copyleft(file
);
2733 lf_printf(file
, "\n");
2734 lf_printf(file
, "\n");
2735 lf_printf(file
, "#ifndef _IDECODE_C_\n");
2736 lf_printf(file
, "#define _IDECODE_C_\n");
2737 lf_printf(file
, "\n");
2738 lf_printf(file
, "#ifndef STATIC_INLINE_IDECODE\n");
2739 lf_printf(file
, "#define STATIC_INLINE_IDECODE STATIC_INLINE\n");
2740 lf_printf(file
, "#endif\n");
2741 lf_printf(file
, "\n");
2742 lf_printf(file
, "#include \"cpu.h\"\n");
2743 lf_printf(file
, "#include \"idecode.h\"\n");
2744 lf_printf(file
, "#include \"semantics.h\"\n");
2745 lf_printf(file
, "\n");
2746 lf_printf(file
, "\n");
2747 lf_printf(file
, "typedef idecode_semantic *idecode_crack\n(%s);\n",
2748 idecode_cache
> 1 ? cache_idecode_formal
: insn_formal
);
2749 lf_printf(file
, "\n");
2750 lf_printf(file
, "typedef struct _idecode_table_entry {\n");
2751 lf_printf(file
, " unsigned shift;\n");
2752 lf_printf(file
, " unsigned mask;\n");
2753 lf_printf(file
, " void *function_or_table;\n");
2754 lf_printf(file
, "} idecode_table_entry;\n");
2755 lf_printf(file
, "\n");
2756 lf_printf(file
, "\n");
2758 /* output cracking functions where needed */
2759 if (idecode_cache
> 1) {
2760 if (idecode_expand_semantics
)
2761 insn_table_traverse_tree(table
,
2769 insn_table_traverse_insn(table
,
2771 idecode_crack_insn
);
2775 /* output tables where needed */
2776 for (depth
= insn_table_depth(table
);
2779 insn_table_traverse_tree(table
,
2782 idecode_table_start
,
2785 idecode_table_padding
);
2788 /* output switch functions where needed */
2789 insn_table_traverse_tree(table
,
2792 idecode_expand_if_switch
, /* START */
2795 /* output the main idecode routine */
2796 lf_printf(file
, "\n");
2798 lf_printf(file
, "INLINE_IDECODE unsigned_word\nidecode_issue\n(%s)\n",
2800 else if (idecode_cache
)
2801 lf_printf(file
, "INLINE_IDECODE idecode_semantic *\nidecode\n(%s)\n",
2802 idecode_cache
== 1 ? insn_formal
: cache_idecode_formal
);
2803 lf_printf(file
, "{\n");
2804 lf_indent(file
, +2);
2806 lf_printf(file
, "cpu_increment_number_of_insns (processor);\n");
2807 if (table
->opcode_rule
->use_switch
)
2808 lf_print_idecode_switch(file
, table
);
2810 lf_print_idecode_table(file
, table
);
2811 lf_indent(file
, -2);
2812 lf_printf(file
, "}\n");
2813 lf_printf(file
, "\n");
2814 lf_printf(file
, "#endif\n");
2818 /****************************************************************/
2826 nr_spreg_registers
= file_table_max_fields
2829 typedef struct _spreg_table_entry spreg_table_entry
;
2830 struct _spreg_table_entry
{
2835 file_table_entry
*entry
;
2836 spreg_table_entry
*next
;
2839 typedef struct _spreg_table spreg_table
;
2840 struct _spreg_table
{
2841 spreg_table_entry
*sprs
;
2845 spreg_table_entry_new()
2847 spreg_table_entry
*new_entry
=
2848 (spreg_table_entry
*)zmalloc(sizeof(spreg_table_entry
));
2849 ASSERT(new_entry
!= NULL
);
2856 spreg_table
*new_table
= (spreg_table
*)zmalloc(sizeof(spreg_table
));
2857 ASSERT(new_table
!= NULL
);
2862 spreg_table_insert(spreg_table
*table
, file_table_entry
*entry
)
2864 /* create a new spr entry */
2865 spreg_table_entry
*new_spr
= spreg_table_entry_new();
2866 new_spr
->next
= NULL
;
2867 new_spr
->entry
= entry
;
2868 new_spr
->spreg_nr
= atoi(entry
->fields
[spreg_reg_nr
]);
2869 new_spr
->is_readonly
= (entry
->fields
[spreg_readonly
]
2870 ? atoi(entry
->fields
[spreg_readonly
])
2872 new_spr
->length
= atoi(entry
->fields
[spreg_length
]);
2873 new_spr
->name
= (char*)zmalloc(strlen(entry
->fields
[spreg_name
]) + 1);
2874 ASSERT(new_spr
->name
!= NULL
);
2877 for (i
= 0; entry
->fields
[spreg_name
][i
] != '\0'; i
++) {
2878 if (isupper(entry
->fields
[spreg_name
][i
]))
2879 new_spr
->name
[i
] = tolower(entry
->fields
[spreg_name
][i
]);
2881 new_spr
->name
[i
] = entry
->fields
[spreg_name
][i
];
2885 /* insert, by spreg_nr order */
2887 spreg_table_entry
**ptr_to_spreg_entry
= &table
->sprs
;
2888 spreg_table_entry
*spreg_entry
= *ptr_to_spreg_entry
;
2889 while (spreg_entry
!= NULL
&& spreg_entry
->spreg_nr
< new_spr
->spreg_nr
) {
2890 ptr_to_spreg_entry
= &spreg_entry
->next
;
2891 spreg_entry
= *ptr_to_spreg_entry
;
2893 ASSERT(spreg_entry
== NULL
|| spreg_entry
->spreg_nr
!= new_spr
->spreg_nr
);
2894 *ptr_to_spreg_entry
= new_spr
;
2895 new_spr
->next
= spreg_entry
;
2902 spreg_table_load(char *file_name
)
2904 file_table
*file
= file_table_open(file_name
);
2905 spreg_table
*table
= spreg_table_new();
2908 file_table_entry
*entry
;
2909 while (entry
= file_table_read(file
)) {
2910 spreg_table_insert(table
, entry
);
2918 /****************************************************************/
2920 char *spreg_attributes
[] = {
2930 gen_spreg_h(spreg_table
*table
, lf
*file
)
2932 spreg_table_entry
*entry
;
2935 lf_print_copyleft(file
);
2936 lf_printf(file
, "\n");
2937 lf_printf(file
, "#ifndef _SPREG_H_\n");
2938 lf_printf(file
, "#define _SPREG_H_\n");
2939 lf_printf(file
, "\n");
2940 lf_printf(file
, "#ifndef INLINE_SPREG\n");
2941 lf_printf(file
, "#define INLINE_SPREG\n");
2942 lf_printf(file
, "#endif\n");
2943 lf_printf(file
, "\n");
2944 lf_printf(file
, "typedef unsigned_word spreg;\n");
2945 lf_printf(file
, "\n");
2946 lf_printf(file
, "typedef enum {\n");
2948 for (entry
= table
->sprs
;
2950 entry
= entry
->next
) {
2951 lf_printf(file
, " spr_%s = %d,\n", entry
->name
, entry
->spreg_nr
);
2954 lf_printf(file
, " nr_of_sprs = %d\n", nr_of_sprs
);
2955 lf_printf(file
, "} sprs;\n");
2956 lf_printf(file
, "\n");
2957 for (attribute
= spreg_attributes
;
2960 if (strcmp(*attribute
, "name") == 0)
2961 lf_printf(file
, "INLINE_SPREG char *spr_%s(sprs spr);\n",
2964 lf_printf(file
, "INLINE_SPREG int spr_%s(sprs spr);\n",
2967 lf_printf(file
, "\n");
2968 lf_printf(file
, "#endif /* _SPREG_H_ */\n");
2973 gen_spreg_c(spreg_table
*table
, lf
*file
)
2975 spreg_table_entry
*entry
;
2979 lf_print_copyleft(file
);
2980 lf_printf(file
, "\n");
2981 lf_printf(file
, "#ifndef _SPREG_C_\n");
2982 lf_printf(file
, "#define _SPREG_C_\n");
2983 lf_printf(file
, "\n");
2984 lf_printf(file
, "#include \"words.h\"\n");
2985 lf_printf(file
, "#include \"spreg.h\"\n");
2987 lf_printf(file
, "\n");
2988 lf_printf(file
, "typedef struct _spreg_info {\n");
2989 lf_printf(file
, " char *name;\n");
2990 lf_printf(file
, " int is_valid;\n");
2991 lf_printf(file
, " int length;\n");
2992 lf_printf(file
, " int is_readonly;\n");
2993 lf_printf(file
, " int index;\n");
2994 lf_printf(file
, "} spreg_info;\n");
2995 lf_printf(file
, "\n");
2996 lf_printf(file
, "static spreg_info spr_info[nr_of_sprs+1] = {\n");
2997 entry
= table
->sprs
;
2998 for (spreg_nr
= 0; spreg_nr
< nr_of_sprs
+1; spreg_nr
++) {
2999 if (entry
== NULL
|| spreg_nr
< entry
->spreg_nr
)
3000 lf_printf(file
, " { 0, 0, 0, 0, %d},\n", spreg_nr
);
3002 lf_printf(file
, " { \"%s\", %d, %d, %d, spr_%s /*%d*/ },\n",
3003 entry
->name
, 1, entry
->length
, entry
->is_readonly
,
3004 entry
->name
, entry
->spreg_nr
);
3005 entry
= entry
->next
;
3008 lf_printf(file
, "};\n");
3010 for (attribute
= spreg_attributes
;
3013 lf_printf(file
, "\n");
3014 if (strcmp(*attribute
, "name") == 0)
3015 lf_printf(file
, "INLINE_SPREG char *\n");
3017 lf_printf(file
, "INLINE_SPREG int\n");
3018 lf_printf(file
, "spr_%s(sprs spr)\n", *attribute
);
3019 lf_printf(file
, "{\n");
3020 if (spreg_lookup_table
3021 || strcmp(*attribute
, "name") == 0
3022 || strcmp(*attribute
, "index") == 0)
3023 lf_printf(file
, " return spr_info[spr].%s;\n",
3026 spreg_table_entry
*entry
;
3027 lf_printf(file
, " switch (spr) {\n");
3028 for (entry
= table
->sprs
; entry
!= NULL
; entry
= entry
->next
) {
3029 lf_printf(file
, " case %d:\n", entry
->spreg_nr
);
3030 if (strcmp(*attribute
, "is_valid") == 0)
3031 lf_printf(file
, " return 1;\n");
3032 else if (strcmp(*attribute
, "is_readonly") == 0)
3033 lf_printf(file
, " return %d;\n", entry
->is_readonly
);
3034 else if (strcmp(*attribute
, "length") == 0)
3035 lf_printf(file
, " return %d;\n", entry
->length
);
3039 lf_printf(file
, " default:\n");
3040 lf_printf(file
, " return 0;\n");
3041 lf_printf(file
, " }\n");
3043 lf_printf(file
, "}\n");
3046 lf_printf(file
, "\n");
3047 lf_printf(file
, "#endif /* _SPREG_C_ */\n");
3052 /****************************************************************/
3060 insn_table
*instructions
= NULL
;
3061 spreg_table
*sprs
= NULL
;
3062 icache_tree
*cache_fields
= NULL
;
3065 while ((ch
= getopt(argc
, argv
, "i:I:r:S:s:D:d:P:p:C:")) != -1) {
3066 fprintf(stderr
, "\t-%c %s\n", ch
, optarg
);
3070 instructions
= insn_table_load_insns(optarg
);
3071 fprintf(stderr
, "\texpanding ...\n");
3072 insn_table_expand_insns(instructions
);
3073 fprintf(stderr
, "\tcache fields ...\n");
3074 cache_fields
= insn_table_cache_fields(instructions
);
3076 dump_traverse(instructions
);
3077 dump_insn_table(instructions
, 0, 1);
3081 sprs
= spreg_table_load(optarg
);
3085 lf
*file
= lf_open(optarg
);
3088 gen_semantics_h(instructions
, file
);
3091 gen_semantics_c(instructions
, file
);
3094 gen_spreg_h(sprs
, file
);
3097 gen_spreg_c(sprs
, file
);
3100 gen_idecode_h(instructions
, file
);
3103 gen_idecode_c(instructions
, file
);
3106 gen_icache_h(cache_fields
, file
);