diff options
-rw-r--r-- | sim/igen/ChangeLog | 31 | ||||
-rw-r--r-- | sim/igen/igen.c | 292 | ||||
-rw-r--r-- | sim/igen/table.c | 385 | ||||
-rw-r--r-- | sim/igen/table.h | 70 |
4 files changed, 740 insertions, 38 deletions
diff --git a/sim/igen/ChangeLog b/sim/igen/ChangeLog index b9835de..808f861 100644 --- a/sim/igen/ChangeLog +++ b/sim/igen/ChangeLog @@ -1,3 +1,34 @@ +Thu May 29 10:29:57 1997 Andrew Cagney <cagney@b1.cygnus.com> + + * lf.c (lf_write): New function write an N character buffer to the + file. + + * igen.c (print_itrace): When available, use the assembler to + print the insn-trace. + (print_itrace_prefix): New function, print first part of call to + print_one_insn. + (print_itrace_format): New function, print fmt argument for + print_one_insn. + + * table.c (table_entry_read): Save any assembler lines instead of + discarding them. + +Wed May 28 09:55:29 1997 Andrew Cagney <cagney@b1.cygnus.com> + + * gen-icache.c (print_icache_body): Process immeds. + + * gen-semantics.c (print_semantic_body): When computing NIA, skip + any immed words that follow the instruction word. + + * ld-insn.c (parse_insn_format): Parse immeds appended to an + instruction. + + * igen.c (main): Allow any register to be specified as the zero + register. + (semantic_zero_reg): Global, index to zero register. + + * gen-semantics.c (print_semantic_body): Zero selected register. + Tue May 27 14:12:32 1997 Andrew Cagney <cagney@b1.cygnus.com> * igen.h: Stop options and code gen type bit masks overlaping. diff --git a/sim/igen/igen.c b/sim/igen/igen.c index a8475ed..2354d61 100644 --- a/sim/igen/igen.c +++ b/sim/igen/igen.c @@ -47,6 +47,7 @@ int insn_bit_size = default_insn_bit_size; int insn_specifying_widths = 0; const char *global_name_prefix = ""; const char *global_uname_prefix = ""; +int semantic_zero_reg_nr = 0; int code = generate_calls; @@ -216,54 +217,264 @@ print_function_name(lf *file, void -print_my_defines(lf *file, - insn_bits *expanded_bits, - table_entry *file_entry) +print_my_defines (lf *file, + insn_bits *expanded_bits, + table_entry *file_entry) { /* #define MY_INDEX xxxxx */ - lf_indent_suppress(file); - lf_printf(file, "#undef MY_INDEX\n"); - lf_indent_suppress(file); - lf_printf(file, "#define MY_INDEX "); - print_function_name(file, - file_entry->fields[insn_name], - NULL, - function_name_prefix_itable); - lf_printf(file, "\n"); + lf_indent_suppress (file); + lf_printf (file, "#undef MY_INDEX\n"); + lf_indent_suppress (file); + lf_printf (file, "#define MY_INDEX "); + print_function_name (file, + file_entry->fields[insn_name], + NULL, + function_name_prefix_itable); + lf_printf (file, "\n"); /* #define MY_PREFIX xxxxxx */ - lf_indent_suppress(file); - lf_printf(file, "#undef MY_PREFIX\n"); - lf_indent_suppress(file); - lf_printf(file, "#define MY_PREFIX "); - print_function_name(file, - file_entry->fields[insn_name], - expanded_bits, - function_name_prefix_none); - lf_printf(file, "\n"); + lf_indent_suppress (file); + lf_printf (file, "#undef MY_PREFIX\n"); + lf_indent_suppress (file); + lf_printf (file, "#define MY_PREFIX "); + print_function_name (file, + file_entry->fields[insn_name], + expanded_bits, + function_name_prefix_none); + lf_printf (file, "\n"); +} + + +static int +print_itrace_prefix (lf *file, + table_entry *file_entry, + const char *phase_lc) +{ + const char *prefix = "trace_one_insn ("; + int indent = strlen (prefix); + lf_printf (file, "%sSD, CPU, %s, TRACE_LINENUM_P (CPU),\n", + prefix, (code & generate_with_semantic_delayed_branch) ? "cia.ip" : "cia"); + lf_indent (file, +indent); + lf_printf (file, "itable[MY_INDEX].file,\n"); + lf_printf (file, "itable[MY_INDEX].line_nr,\n"); + lf_printf (file, "\"%s\",\n", phase_lc); + return indent; +} + + +static void +print_itrace_format (lf *file, + table_assembler_entry *assembler) +{ + /* pass=1 is fmt string; pass=2 is is arguments */ + int pass; + const char *chp; + /* print the format string */ + for (pass = 1; pass <= 2; pass++) + { + const char *chp = assembler->format; + chp++; /* skip the leading quote */ + /* prefix the format with the insn `name' */ + if (pass == 1) + { + lf_printf (file, "\"%%s - %%s - "); + } + else + { + lf_printf (file, ",\n"); + lf_printf (file, "itable[MY_INDEX].name"); + lf_printf (file, ",\n"); + lf_printf (file, "XSTRING(MY_PREFIX)"); + } + /* write out the format/args */ + while (*chp != '\0') + { + if (chp[0] == '\\' && (chp[1] == '<' || chp[1] == '>')) + { + if (pass == 1) + lf_putchr (file, chp[1]); + chp += 2; + } + else if (chp[0] == '<' || chp[0] == '%') + { + /* parse [ "%" ... ] "<" [ func "#" ] param ">" */ + const char *fmt; + const char *func; + int strlen_func; + const char *param; + int strlen_param; + /* the "%" ... "<" format */ + fmt = chp; + while (chp[0] != '<' && chp[0] != '\0') + chp++; + if (chp[0] != '<') + error ("%s:%d: Missing `<' after `%%'", + assembler->file_name, + assembler->line_nr); + chp++; + /* [ "func" # ] OR "param" */ + func = chp; + param = chp; + while (chp[0] != '>' && chp[0] != '#' && chp[0] != '\0') + chp++; + strlen_func = chp - func; + if (chp[0] == '#') + { + chp++; + param = chp; + while (chp[0] != '>' && chp[0] != '\0') + chp++; + } + strlen_param = chp - param; + if (chp[0] != '>') + error ("%s:%d: Missing closing `>' in assembler string", + assembler->file_name, + assembler->line_nr); + chp++; + /* now process it */ + if (pass == 2) + lf_printf (file, ",\n"); + if (strncmp (fmt, "<", 1) == 0) + /* implicit long int format */ + { + if (pass == 1) + lf_printf (file, "%%ld"); + else + { + lf_printf (file, "(long) "); + lf_write (file, param, strlen_param); + } + } + else if (strncmp (fmt, "%<", 2) == 0) + /* explicit format */ + { + if (pass == 1) + lf_printf (file, "%%"); + else + lf_write (file, param, strlen_param); + } + else if (strncmp (fmt, "%s<", 3) == 0) + /* string format */ + { + if (pass == 1) + lf_printf (file, "%%s"); + else + { + lf_printf (file, "%sstr_", global_name_prefix); + lf_write (file, func, strlen_func); + lf_printf (file, " (_SD, "); + lf_write (file, param, strlen_param); + lf_printf (file, ")"); + } + } + else if (strncmp (fmt, "%lx<", 4) == 0) + /* simple hex */ + { + if (pass == 1) + lf_printf (file, "%%lx"); + else + { + lf_printf (file, "(unsigned long) "); + lf_write (file, param, strlen_param); + } + } + else if (strncmp (fmt, "%08lx<", 6) == 0) + /* simple hex */ + { + if (pass == 1) + lf_printf (file, "%%08lx"); + else + { + lf_printf (file, "(unsigned long) "); + lf_write (file, param, strlen_param); + } + } + else + error ("%s:%d: Unknown assembler string format", + assembler->file_name, + assembler->line_nr); + } + else + { + if (pass == 1) + lf_putchr (file, chp[0]); + chp += 1; + } + } + } + lf_printf (file, ");\n"); } void -print_itrace(lf *file, - table_entry *file_entry, - int idecode) +print_itrace (lf *file, + table_entry *file_entry, + int idecode) { const char *phase = (idecode) ? "DECODE" : "INSN"; const char *phase_lc = (idecode) ? "decode" : "insn"; - lf_printf(file, "\n"); - lf_indent_suppress(file); - lf_printf(file, "#if defined(WITH_TRACE)\n"); - lf_printf(file, "/* trace the instructions execution if enabled */\n"); - lf_printf(file, "if (TRACE_%s_P (CPU)) {\n", phase); - lf_printf(file, " trace_one_insn (SD, CPU, %s, TRACE_LINENUM_P (CPU),\n", - (code & generate_with_semantic_delayed_branch) ? "cia.ip" : "cia"); - - lf_printf(file, " itable[MY_INDEX].file, itable[MY_INDEX].line_nr,\n"); - lf_printf(file, " \"%s\", itable[MY_INDEX].name);\n", phase_lc); - - lf_printf(file, "}\n"); - lf_indent_suppress(file); - lf_printf(file, "#endif\n"); + lf_printf (file, "\n"); + lf_indent_suppress (file); + lf_printf (file, "#if defined (WITH_TRACE)\n"); + lf_printf (file, "/* trace the instructions execution if enabled */\n"); + lf_printf (file, "if (TRACE_%s_P (CPU)) {\n", phase); + lf_indent (file, +2); + if (file_entry->assembler != NULL) + { + table_assembler_entry *assembler = file_entry->assembler; + int is_first = 1; + do + { + if (assembler->condition != NULL) + { + int indent; + lf_printf (file, "%sif (%s)\n", + is_first ? "" : "else ", + assembler->condition); + lf_indent (file, +2); + indent = print_itrace_prefix (file, file_entry, phase_lc); + print_itrace_format (file, assembler); + lf_indent (file, -indent); + lf_indent (file, -2); + if (assembler->next == NULL) + error ("%s:%d: Missing final unconditional assembler", + assembler->file_name, + assembler->line_nr); + } + else + { + int indent; + if (!is_first) + { + lf_printf (file, "else\n"); + lf_indent (file, +2); + } + indent = print_itrace_prefix (file, file_entry, phase_lc); + print_itrace_format (file, assembler); + lf_indent (file, -indent); + if (!is_first) + lf_indent (file, -2); + if (assembler->next != NULL) + error ("%s:%d: Unconditional assembler is not last", + assembler->file_name, + assembler->line_nr); + } + is_first = 0; + assembler = assembler->next; + } + while (assembler != NULL); + } + else + { + int indent = print_itrace_prefix (file, file_entry, phase_lc); + lf_printf (file, "\"%%s - %%s - ?\",\n"); + lf_printf (file, "itable[MY_INDEX].name,\n"); + lf_printf (file, "XSTRING(MY_PREFIX));\n"); + lf_indent (file, -indent); + } + lf_indent (file, -2); + lf_printf (file, "}\n"); + lf_indent_suppress (file); + lf_printf (file, "#endif\n"); } @@ -453,6 +664,7 @@ main(int argc, printf(" insn-in-icache - save original instruction when cracking\n"); printf(" default-nia-minus-one - instead of cia + insn-size\n"); printf(" delayed-branch - instead of cia + insn-size\n"); + printf(" zero-r<N> - arch assumes GPR(<N>) == 0, keep it that way\n"); printf(" conditional-issue - conditionally issue each instruction\n"); printf(" validate-slot - perform slot verification as part of decode\n"); printf("\n"); @@ -560,6 +772,10 @@ main(int argc, else if (strcmp(optarg, "conditional-issue") == 0) { code |= generate_with_semantic_conditional_issue; } + else if (strncmp (optarg, "zero-r", strlen ("zero-r")) == 0) { + code |= generate_with_semantic_zero_reg; + semantic_zero_reg_nr = atoi (optarg + strlen ("zero-r")); + } else if (strcmp(optarg, "verify-slot") == 0) { code |= generate_with_idecode_slot_verification; } diff --git a/sim/igen/table.c b/sim/igen/table.c new file mode 100644 index 0000000..461a632 --- /dev/null +++ b/sim/igen/table.c @@ -0,0 +1,385 @@ +/* This file is part of the program psim. + + Copyright (C) 1994-1995,1997 Andrew Cagney <cagney@highland.com.au> + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + + */ + + +#include <sys/types.h> +#include <sys/stat.h> +#include <stdio.h> +#include <fcntl.h> +#include <ctype.h> + +#include "config.h" +#include "misc.h" +#include "lf.h" +#include "table.h" + +#ifdef HAVE_UNISTD_H +#include <unistd.h> +#endif + +#ifdef HAVE_STDLIB_H +#include <stdlib.h> +#endif + +struct _table { + size_t size; + char *buffer; + char *pos; + int nr_fields; + int nr_model_fields; + int line_nr; + char *file_name; + int current_file_line_offset; + char *current_file_name; +}; + +extern table * +table_open(const char *file_name, + int nr_fields, + int nr_model_fields) +{ + int fd; + struct stat stat_buf; + table *file; + + /* create a file descriptor */ + file = ZALLOC(table); + ASSERT(file != NULL); + file->nr_fields = nr_fields; + file->nr_model_fields = nr_model_fields; + + /* save the file name */ + file->file_name = (char*)zalloc(strlen(file_name) + 1); + ASSERT(file->file_name != NULL); + strcpy(file->file_name, file_name); + file->current_file_name = file->file_name; + + /* open the file */ + fd = open(file->file_name, O_RDONLY, 0); + if (fd < 0) { + perror(file->file_name); + exit (1); + } + + /* determine the size */ + if (fstat(fd, &stat_buf) < 0) { + perror("table_open.fstat"); + exit(1); + } + file->size = stat_buf.st_size; + + /* allocate this much memory */ + file->buffer = (char*)zalloc(file->size+1); + ASSERT(file->buffer != NULL); + file->pos = file->buffer; + + /* read it in */ + if (read(fd, file->buffer, file->size) < file->size) { + perror(file->file_name); + exit(1); + } + file->buffer[file->size] = '\0'; + + /* set the initial line numbering */ + file->line_nr = 0; + file->current_file_line_offset = 0; + + /* done */ + close(fd); + return file; +} + + +extern table_entry * +table_entry_read(table *file) +{ + int field; + table_entry *entry; + + /* skip comments/blanks */ + while(1) { + /* leading white space */ + while (*file->pos != '\0' + && *file->pos != '\n' + && isspace(*file->pos)) + file->pos++; + /* cpp line nr directive - # <line-nr> "<file>" */ + if (file->pos[0] == '#' + && file->pos[1] == ' ' + && isdigit(file->pos[2])) { + file->pos += strlen("# "); + /* parse the number */ + file->current_file_line_offset = atoi(file->pos) - file->line_nr - 2; + /* skip to the file name */ + while (file->pos[0] != '0' + && file->pos[0] != '"' + && file->pos[0] != '\0') + file->pos++; + if (file->pos[0] != '"') { + error("%s:%d: Missing opening quote", + file->file_name, + file->line_nr); + } + /* parse the file name */ + file->pos++; + file->current_file_name = file->pos; + while (file->pos[0] != '"' + && file->pos[0] != '\0') + file->pos++; + if (file->pos[0] != '"') { + error("%s:%d: Missing closing quote", + file->file_name, + file->line_nr); + } + file->pos[0] = '\0'; + file->pos ++; + while (file->pos[0] != '\0' + && file->pos[0] != '\n') + file->pos[0]++; + if (file->pos[0] != '\n') + error("%s:%d: Missing newline", + file->file_name, + file->line_nr); + } + /* comment - leading // or # - skip */ + else if ((file->pos[0] == '/' && file->pos[1] == '/') + || (file->pos[0] == '#')) { + do { + file->pos++; + } while (*file->pos != '\0' && *file->pos != '\n'); + } + /* end of line? */ + if (*file->pos == '\n') { + file->pos++; + file->line_nr++; + } + else + break; + } + if (*file->pos == '\0') + return NULL; + + /* create this new entry */ + entry = (table_entry*)zalloc(sizeof(table_entry) + + (file->nr_fields + 1) * sizeof(char*)); + ASSERT(entry != NULL); + entry->file_name = file->current_file_name; + entry->nr_fields = file->nr_fields; + + /* break the line into its colon delimitered fields */ + for (field = 0; field < file->nr_fields-1; field++) { + entry->fields[field] = file->pos; + while(*file->pos && *file->pos != ':' && *file->pos != '\n') + file->pos++; + if (*file->pos == ':') { + *file->pos = '\0'; + file->pos++; + } + } + + /* any trailing stuff not the last field */ + ASSERT(field == file->nr_fields-1); + entry->fields[field] = file->pos; + while (*file->pos && *file->pos != '\n') { + file->pos++; + } + if (*file->pos == '\n') { + *file->pos = '\0'; + file->pos++; + } + file->line_nr++; + + /* If following lines being with a double quote ("), add them to the + list of assembler lines */ + { + table_assembler_entry **current = &entry->assembler; + while (*file->pos == '"') { + char *tmpchp; + const char *format; + int strlen_format; + const char *condition; + int strlen_condition; + + /* skip over the format string */ + format = file->pos; + strlen_format = 0; + do { + if (file->pos[0] == '\\' && file->pos[1] == '"') + file->pos += 2; + else + file->pos += 1; + } while (*file->pos != '\0' && *file->pos != '\n' && *file->pos != '"'); + if (*file->pos != '"') + error ("%s:%d: Missing closing quote in assembler line", + file->file_name, + file->line_nr); + file->pos++; + strlen_format = file->pos - format; + + /* skip over the boolean condition */ + condition = NULL; + strlen_condition = 0; + if (*file->pos == ':') + { + file->pos++; + while (isspace(*file->pos) && *file->pos != '\0' && *file->pos != '\n') + file->pos++; + condition = file->pos; + while (*file->pos != '\0' && *file->pos != '\n') + file->pos++; + strlen_condition = file->pos - condition; + } + + /* create the new assembler entry */ + *current = ZALLOC (table_assembler_entry); + tmpchp = zalloc (strlen_format + 1); + strncpy (tmpchp, format, strlen_format); + (*current)->format = tmpchp; + (*current)->file_name = file->file_name; + (*current)->line_nr = file->line_nr; + if (condition != NULL && strlen_condition > 0) + { + tmpchp = zalloc (strlen_condition + 1); + strncpy (tmpchp, condition, strlen_condition); + (*current)->condition = tmpchp; + } + current = &(*current)->next; + + /* end of line? */ + if (*file->pos != '\n') + error ("%s:%d: Missing eoln in assembler line", + file->file_name, + file->line_nr); + file->pos++; + file->line_nr++; + } + } + + /* if following lines begin with a star, add them to the model + section. */ + while ((file->nr_model_fields > 0) && (*file->pos == '*')) { + table_model_entry *model = (table_model_entry*)zalloc(sizeof(table_model_entry) + + (file->nr_model_fields + 1) * sizeof(char*)); + if (entry->model_last) + entry->model_last->next = model; + else + entry->model_first = model; + entry->model_last = model; + + /* break the line into its colon delimitered fields */ + file->pos++; + for (field = 0; field < file->nr_model_fields-1; field++) { + model->fields[field] = file->pos; + while(*file->pos && *file->pos != ':' && *file->pos != '\n') + file->pos++; + if (*file->pos == ':') { + *file->pos = '\0'; + file->pos++; + } + } + + /* any trailing stuff not the last field */ + ASSERT(field == file->nr_model_fields-1); + model->fields[field] = file->pos; + while (*file->pos && *file->pos != '\n') { + file->pos++; + } + if (*file->pos == '\n') { + *file->pos = '\0'; + file->pos++; + } + + file->line_nr++; + model->line_nr = file->current_file_line_offset + file->line_nr; + } + + entry->line_nr = file->current_file_line_offset + file->line_nr; + + /* if following lines are tab indented, put in the annex */ + if (*file->pos == '\t') { + entry->annex = file->pos; + do { + do { + file->pos++; + } while (*file->pos != '\0' && *file->pos != '\n'); + if (*file->pos == '\n') { + char *save_pos = ++file->pos; + int extra_lines = 0; + file->line_nr++; + /* Allow tab indented to have blank lines */ + while (*save_pos == '\n') { + save_pos++; + extra_lines++; + } + if (*save_pos == '\t') { + file->pos = save_pos; + file->line_nr += extra_lines; + } + } + } while (*file->pos != '\0' && *file->pos == '\t'); + if (file->pos[-1] == '\n') + file->pos[-1] = '\0'; + } + else + entry->annex = NULL; + + /* return it */ + return entry; + +} + + +extern void +dump_table_entry(table_entry *entry, + int indent) +{ + printf("(table_entry*)%p\n", entry); + + if (entry != NULL) { + int field; + char sep; + + sep = ' '; + dumpf(indent, "(fields"); + for (field = 0; field < entry->nr_fields; field++) { + printf("%c%s", sep, entry->fields[field]); + sep = ':'; + } + printf(")\n"); + + dumpf(indent, "(line_nr %d)\n", entry->line_nr); + + dumpf(indent, "(file_name %s)\n", entry->file_name); + + dumpf(indent, "(annex\n%s\n", entry->annex); + dumpf(indent, " )\n"); + + } +} + + +extern void +table_entry_print_cpp_line_nr(lf *file, + table_entry *entry) +{ + lf_print__external_reference(file, entry->line_nr, entry->file_name); +} + + diff --git a/sim/igen/table.h b/sim/igen/table.h new file mode 100644 index 0000000..6b3f6e7 --- /dev/null +++ b/sim/igen/table.h @@ -0,0 +1,70 @@ +/* This file is part of the program psim. + + Copyright (C) 1994-1995, Andrew Cagney <cagney@highland.com.au> + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + + */ + + +/* load a table into memory */ + +typedef struct _table table; + +typedef struct _table_model_entry table_model_entry; +struct _table_model_entry { + table_model_entry *next; + int line_nr; + int nr_fields; + char *fields[0]; /* User defined */ +}; + +typedef struct _table_assembler_entry table_assembler_entry; +struct _table_assembler_entry { + const char *format; + const char *condition; + const char *file_name; + int line_nr; + table_assembler_entry *next; +}; + +typedef struct _table_entry table_entry; +struct _table_entry { + int line_nr; + int nr_fields; + char *file_name; + table_assembler_entry *assembler; + table_model_entry *model_first; + table_model_entry *model_last; + char *annex; + char *fields[0]; /* User defined */ +}; + + +extern table *table_open +(const char *file_name, + int max_nr_fields, + int max_nr_model_fields); + +extern table_entry *table_entry_read +(table *file); + +extern void dump_table_entry +(table_entry *entry, + int indent); + +extern void table_entry_print_cpp_line_nr +(lf *file, + table_entry *entry); |