Initial entry
This commit is contained in:
parent
ec40d28c25
commit
d49fb42d47
34
util/int/switch/Makefile
Normal file
34
util/int/switch/Makefile
Normal 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
88
util/int/switch/READ_ME
Normal 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
289
util/int/switch/mkswitch.c
Normal 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);
|
||||
}
|
Loading…
Reference in a new issue