Initial entry
authordick <none@none>
Wed, 22 Jun 1988 16:22:00 +0000 (16:22 +0000)
committerdick <none@none>
Wed, 22 Jun 1988 16:22:00 +0000 (16:22 +0000)
util/int/switch/Makefile [new file with mode: 0644]
util/int/switch/READ_ME [new file with mode: 0644]
util/int/switch/mkswitch.c [new file with mode: 0644]

diff --git a/util/int/switch/Makefile b/util/int/switch/Makefile
new file mode 100644 (file)
index 0000000..252b90c
--- /dev/null
@@ -0,0 +1,34 @@
+# $Header$
+
+IP_SPEC =      /usr/em/etc/ip_spec.t
+
+SRC =          mkswitch.c
+OBJ =          mkswitch.o
+
+mkswitch:      $(OBJ)
+       $(CC) -o mkswitch $(OBJ)
+
+DoCases:       mkswitch $(IP_SPEC)
+       mkswitch Do $(IP_SPEC) DoCases
+       wc DoCases
+
+PrCases:       mkswitch $(IP_SPEC)
+       mkswitch Pr $(IP_SPEC) PrCases
+       wc PrCases
+
+lint:
+       lint $(SRC)
+
+.distr:                Makefile
+       echo READ_ME Makefile $(SRC) | tr ' ' '\012' >.distr
+
+.SUFFIXES:     .o
+.c.o:
+       $(CC) $(CFLAGS) -c $<
+
+clean:                                         # NOT the cases files !
+       /bin/rm -f a.out core $(OBJ) mkswitch
+
+bare:          clean
+       /bin/rm -f DoCases PrCases
+
diff --git a/util/int/switch/READ_ME b/util/int/switch/READ_ME
new file mode 100644 (file)
index 0000000..7aa1f94
--- /dev/null
@@ -0,0 +1,88 @@
+# $Header$
+
+This directory contains two programs:
+
+mkswitch:
+       C program, necessary for regenerating the giant switches
+       which are part of the INT project.
+
+mkfuncs:
+       shell script that can be used to generate new function
+       files, if a new implementation is needed.
+
+The first program reads an input file which holds the interpreter
+opcode table (as shown in the [IR-81] report appendix B),
+and creates an output file which contains an enormous switch
+file.  This switch has entries for each possible opcode.  It's
+possible to supply a third filename, which is the name of file
+where all functions will be stored.  This is necessary if a new
+function implementation is needed.
+
+The first argument to mkswitch is the prefix to be used in the
+generated function names.  For the interpreter proper this prefix
+is  Do.
+
+The input file contains lines in the following format:
+
+       Mnemonic Flags Count First-number
+
+The created switch file will contain a switch, with each case
+having one of the following formats (? is the opcode):
+
+       1) case ?: DoAz();
+       2) case ?: DoBm(val);
+       3) case ?: DoCs(hob, wsize);
+       4) case ?: DoDXY(wsize);
+
+Ad 1)  This format shows that the corresponding opcode does not
+       have an argument.  Often the operand is popped from the
+       stack.
+
+       e.g. DoNOPz(), this performs the NOP instruction.
+
+Ad 2)  This is the format for a mini.  There is one implicit
+       argument (I) .
+
+       e.g. DoLOCm(1), this is the LOC 1 instruction.
+
+Ad 3)  This format corresponds with a shortie.  There is an implicit
+       argument (high order byte), and a one byte text argument
+       (low order byte).  W equals 'wsize' (if a word multiple),
+       otherwise it equals '1'.  H is the value of the high
+       order byte.
+
+       e.g. DoLOEs(2, wsize), these are all LOE instructions,
+       with all addresses in the range:
+               (512 * wordsize) . . (767 * wordsize).
+       
+Ad 4)  This format is used for opcodes with 2 or more text arguments,
+       and no implicit arguments.  There are 6 types:
+
+       XY = l2: two byte negative or positive text argument.
+       XY = n2: two byte negative text argument.
+       XY = p2: two byte positive text argument.
+       XY = l4: four byte negative or positive text argument.
+       XY = n4: four byte negative text argument.
+       XY = p4: four byte positive text argument.
+
+       W equals 'wsize' (if a word multiple), otherwise it equals 1.
+
+       e.g. DoLDLp2(wsize), these are all LDL instructions, with
+       negative local offsets, which are word multiples.
+
+
+When two file arguments are given to mkswitch (input file and output file),
+only the switch is generated.  If an additional third file name is
+given (another output file), this file is filled with all function
+calls in such a manner that mkfuncs will generate new function files.
+
+Mkfuncs expects two arguments, an input file generated by
+mkswitch and the name of a directory where the new function
+files are stored.  These files (15) each represent one group (as
+proposed in [IR-81] sec 11.3) of instructions.  Each file will
+contain all functions needed to implement that specific group
+of instructions.  The functions will only contain a logging
+message, and a call to newPC() which is necessary to skip the
+arguments.  The names of the generated files are: do_XXX.c, where
+XXX is the name of the corresponding instruction group.
+
diff --git a/util/int/switch/mkswitch.c b/util/int/switch/mkswitch.c
new file mode 100644 (file)
index 0000000..720755f
--- /dev/null
@@ -0,0 +1,289 @@
+/*
+       Generates contents of opcode switch from ip_spec.t
+       Call is:
+               mkswitch prefix ip_spec.t cases [ functions ]
+
+       Note:
+       The u flag has been implemented by just copying and adjusting the
+       code for 2, which is almost identical to that for 4.  When this has
+       stabilized, combine.
+*/
+
+/* $Header$ */
+
+#include <stdio.h>
+
+extern char *sprintf();
+extern FILE *popen();
+
+char *progname;
+
+FILE   *ifp;                   /* Input File Pointer */
+FILE   *ofp;                   /* Output File Pointer */
+FILE   *ffp = 0;               /* Function File Pointer */
+char   *Prefix;                /* Prefix for function name */
+
+main(argc, argv)
+       int argc;
+       char **argv;
+{
+       char    mnem[8];                /* Mnemonic */
+       char    flgs[8];                /* Flags */
+       char    command[32];
+
+       progname = argv[0];
+
+       if (argc < 4 || argc >5) {
+               fatal("usage is: %s prefix ip_spec.t cases [ functions ]\n",
+                       argv[0]);
+       }
+
+       Prefix = argv[1];
+
+       if ((ifp = fopen(argv[2], "r")) == 0) {
+               fatal("cannot open '%s' for reading\n", argv[2]);
+       }
+
+       if ((ofp = fopen(argv[3], "w")) == 0) {
+               fatal("cannot open '%s' for writing\n", argv[3]);
+       }
+
+       if (argc == 5) {        /* Need to store functions */
+               sprintf(command, "sort | uniq > %s", argv[4]);
+               if ((ffp = popen(command, "w")) == 0) {
+                       fatal("cannot popen '%s'\n", command);
+               }
+       }
+
+       /* Start reading the input file */
+       while (fscanf(ifp, "%s %s", mnem, flgs) >= 0) {
+               int i;
+               char *p;
+               char *base;
+               int cnt, first;
+
+               /* check flags */
+               for (p = flgs; *p; p++) {
+                       if (!in("-ms2u4eNPwo", *p)) {
+                               fatal("bad flags ip_spec: %s\n", flgs);
+                       }
+               }
+
+               if (    in(flgs, '-')
+               +       in(flgs, 'm')
+               +       in(flgs, 's')
+               +       in(flgs, '2')
+               +       in(flgs, 'u')
+               +       in(flgs, '4')
+               !=      1
+               ) {
+                       fatal("duplicate or missing opcode flag ip_spec: %s\n",
+                                       flgs);
+               }
+
+               if (    in(flgs, 'N')
+               +       in(flgs, 'P')
+               >       1
+               ) {
+                       fatal("duplicate restriction flags ip_spec: %s\n", flgs);
+               }
+
+               /* capitalize mnemonic */
+               for (p = mnem; *p; p++) {
+                       *p += ('A' - 'a');
+               }
+
+               /* scan rest of line */
+               if (    in(flgs, '-')
+               ||      in(flgs, '2')
+               ||      in(flgs, 'u')
+               ||      in(flgs, '4')
+               ) {
+                       fscanf(ifp, " %d \n", &first);
+               }
+               else {
+                       fscanf(ifp, " %d %d \n", &cnt, &first);
+               }
+
+               /* determine base */
+               if (in(flgs, 'e'))      /* Escaped (secondary) opcode */
+                       base = "SEC_BASE";
+               else
+               if (in(flgs, '4'))      /* Escaped (tertiary) opcode */
+                       base = "TERT_BASE";
+               else
+                       base = "PRIM_BASE";
+
+               /* analyse the opcode */
+               if (in(flgs, '-')) {    /* No arguments */
+                       NoArgs(base, first, mnem);
+               } else if (in(flgs, 'm')) {     /* Mini */
+                       for (i = 0; i<cnt; i++) {
+                               Mini(i, flgs, base, first, mnem);
+                       }
+               } else if (in(flgs, 's')) {     /* Shortie */
+                       for (i = 0; i<cnt; i++) {
+                               Shortie(i, flgs, base, first, mnem);
+                       }
+               } else if (in(flgs, '2')) {     /* Two byte signed */
+                       TwoSgn(flgs, base, first, mnem);
+               } else if (in(flgs, 'u')) {     /* Two byte unsigned */
+                       TwoUns(flgs, base, first, mnem);
+               } else if (in(flgs, '4')) {     /* Four byte signed */
+                       FourSgn(flgs, base, first, mnem);
+               } else {
+                       fatal("no opcode flag in ip_spec %s\n", flgs);
+               }
+       }
+       exit(0);
+}
+
+NoArgs(base, first, mnem)
+       char *base;
+       int first;
+       char *mnem;
+{
+       fprintf(ofp, "\t\tcase %s+%d:\t%s%sz(); break;\n",
+               base, first, Prefix, mnem);
+       if (ffp) {
+               fprintf(ffp, "%s%sz() {", Prefix, mnem);
+               fprintf(ffp, "LOG((\"@ %s%sz()\"));}\n", Prefix, mnem);
+       }
+}
+
+Mini(i, flgs, base, first, mnem)
+       int i;
+       char *flgs;
+       char *base;
+       int first;
+       char *mnem;
+{
+       char arg[16];
+       int newi = in(flgs, 'N') ? (-i-1) : in(flgs, 'o') ? (i+1) : i;
+
+       switch (newi) {
+       case -1:
+               sprintf(arg, "%s",
+                       in(flgs, 'w') ? "-wsize" : "-1L");
+               break;
+       case 0:
+               sprintf(arg, "0L");
+               break;
+       case 1:
+               sprintf(arg, "%s",
+                       in(flgs, 'w') ? "wsize" : "1L");
+               break;
+       default:
+               sprintf(arg, "%dL%s",
+                       newi, in(flgs, 'w') ? "*wsize" : "");
+               break;
+       }
+       fprintf(ofp, "\t\tcase %s+%d:\t%s%sm(%s); break;\n",
+               base, first+i, Prefix, mnem, arg);
+       if (ffp) {
+               fprintf(ffp, "%s%sm(arg) long arg; {",
+                               Prefix, mnem);
+               fprintf(ffp, "LOG((\"@ %s%sm(%%d)\", arg));}\n",
+                               Prefix, mnem);
+       }
+}
+
+Shortie(i, flgs, base, first, mnem)
+       int i;
+       char *flgs;
+       char *base;
+       int first;
+       char *mnem;
+{
+       char arg[16];
+       int newi = in(flgs, 'N') ? (-i-1) : in(flgs, 'o') ? (i+1) : i;
+
+       sprintf(arg, "%dL, %s", newi, (in(flgs, 'w') ? "wsize" : "1L"));
+       fprintf(ofp, "\t\tcase %s+%d:\t%s%ss(%s); break;\n",
+               base, first+i, Prefix, mnem, arg);
+       if (ffp) {
+               fprintf(ffp, "%s%ss(hob, wfac) long hob; size wfac; {",
+                               Prefix, mnem);
+               fprintf(ffp, "LOG((\"@ %s%ss(%%d)\", hob, wfac));",
+                               Prefix, mnem);
+               fprintf(ffp, " newPC(PC+1);}\n");
+       }
+}
+
+TwoSgn(flgs, base, first, mnem)
+       char *flgs;
+       char *base;
+       int first;
+       char *mnem;
+{
+       char *xy = in(flgs, 'P') ? "p2" : in(flgs, 'N') ? "n2" : "l2";
+
+       fprintf(ofp, "\t\tcase %s+%d:\t%s%s%s(%s); break;\n",
+                       base, first, Prefix, mnem, xy,
+                       in(flgs, 'w') ? "wsize" : "1L");
+       if (ffp) {
+               fprintf(ffp, "%s%s%s(arg) long arg; {", Prefix, mnem, xy);
+               fprintf(ffp, "LOG((\"@ %s%s%s(%%d)\", arg));",
+                               Prefix, mnem, xy);
+               fprintf(ffp, " newPC(PC+2);}\n");
+       }
+}
+
+TwoUns(flgs, base, first, mnem)
+       char *flgs;
+       char *base;
+       int first;
+       char *mnem;
+{
+       char *xy = "u";
+
+       fprintf(ofp, "\t\tcase %s+%d:\t%s%s%s(%s); break;\n",
+                       base, first, Prefix, mnem, xy,
+                       in(flgs, 'w') ? "wsize" : "1L");
+       if (ffp) {
+               fprintf(ffp, "%s%s%s(arg) long arg; {", Prefix, mnem, xy);
+               fprintf(ffp, "LOG((\"@ %s%s%s(%%d)\", arg));",
+                               Prefix, mnem, xy);
+               fprintf(ffp, " newPC(PC+2);}\n");
+       }
+}
+
+FourSgn(flgs, base, first, mnem)
+       char *flgs;
+       char *base;
+       int first;
+       char *mnem;
+{
+       char *xy = in(flgs, 'P') ? "p4" : in(flgs, 'N') ? "n4" : "l4";
+
+       fprintf(ofp, "\t\tcase %s+%d:\t%s%s%s(%s); break;\n",
+                       base, first, Prefix, mnem, xy,
+                       in(flgs, 'w') ? "wsize" : "1L");
+       if (ffp) {
+               fprintf(ffp, "%s%s%s(arg) long arg; {", Prefix, mnem, xy);
+               fprintf(ffp, "LOG((\"@ %s%s%s(%%d)\", arg));",
+                               Prefix, mnem, xy);
+               fprintf(ffp, " newPC(PC+4);}\n");
+       }
+}
+
+int
+in(flgs, c)
+       char *flgs;
+       char c;
+{
+       while (*flgs)
+               if (c == *flgs++)
+                       return 1;
+       return 0;
+}
+
+fatal(fmt, str)
+       char *fmt;
+       char *str;
+{
+       fprintf(stderr, "%s, (fatal error): ", progname);
+       fprintf(stderr, fmt, str);
+       fprintf(stderr, "\n");
+       exit(1);
+}