From d49fb42d476af819cde72338b0fc70ffcf474c20 Mon Sep 17 00:00:00 2001 From: dick Date: Wed, 22 Jun 1988 16:22:00 +0000 Subject: [PATCH] Initial entry --- util/int/switch/Makefile | 34 +++++ util/int/switch/READ_ME | 88 +++++++++++ util/int/switch/mkswitch.c | 289 +++++++++++++++++++++++++++++++++++++ 3 files changed, 411 insertions(+) create mode 100644 util/int/switch/Makefile create mode 100644 util/int/switch/READ_ME create mode 100644 util/int/switch/mkswitch.c diff --git a/util/int/switch/Makefile b/util/int/switch/Makefile new file mode 100644 index 000000000..252b90c3d --- /dev/null +++ b/util/int/switch/Makefile @@ -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 index 000000000..7aa1f946d --- /dev/null +++ b/util/int/switch/READ_ME @@ -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 index 000000000..720755f3b --- /dev/null +++ b/util/int/switch/mkswitch.c @@ -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 + +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