Initial entry

This commit is contained in:
dick 1988-06-22 16:22:00 +00:00
parent ec40d28c25
commit d49fb42d47
3 changed files with 411 additions and 0 deletions

34
util/int/switch/Makefile Normal file
View file

@ -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

88
util/int/switch/READ_ME Normal file
View file

@ -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.

289
util/int/switch/mkswitch.c Normal file
View file

@ -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);
}