Model 3 (intelligent calls) implemented

This commit is contained in:
ceriel 1990-06-21 12:11:50 +00:00
parent 472ee0cea4
commit c7c79e9b42
3 changed files with 305 additions and 14 deletions

View file

@ -1,15 +1,20 @@
# $Header$
IP_SPEC = ../../../etc/ip_spec.t
EM = ../../..
IP_SPEC = $(EM)/etc/ip_spec.t
CFLAGS = -I$(EM)
SRC = mkswitch.c
OBJ = mkswitch.o
SRC = mkiswitch.c mkswitch.c
OBJ = mkiswitch.o mkswitch.o
mkswitch: $(OBJ)
$(CC) -o mkswitch $(OBJ)
mkiswitch: mkiswitch.o
$(CC) -o mkiswitch mkiswitch.o $(EM)/lib/em_data.a
DoCases: mkswitch $(IP_SPEC)
mkswitch Do $(IP_SPEC) DoCases
mkswitch: mkswitch.o
$(CC) -o mkswitch mkswitch.o
DoCases: mkiswitch $(IP_SPEC)
mkiswitch Do $(IP_SPEC) DoCases
wc DoCases
PrCases: mkswitch $(IP_SPEC)
@ -29,10 +34,10 @@ distr: .distr
$(CC) $(CFLAGS) -c $<
clean: # NOT the cases files !
/bin/rm -f a.out core $(OBJ) mkswitch
rm -f a.out core $(OBJ) mkswitch mkiswitch
bare: clean
/bin/rm -f DoCases PrCases
rm -f DoCases PrCases
all: mkswitch

View file

@ -3,12 +3,20 @@
This directory contains two programs:
mkswitch:
C program, necessary for regenerating the giant switches
which are part of the INT project.
C program, necessary for regenerating the giant switch
needed for the disassembly function of the interpreter,
which (still) works with Operand access method 2
(Intelligent Routines) as described in "The EM
interpreter".
mkfuncs:
shell script that can be used to generate new function
files, if a new implementation is needed.
mkiswitch:
C program, necessary for regenerating the giant switch
needed for finding the correct instruction handling routine
for each opcode. It works with Operand access method 3
(Intelligent Calls) as described in "The EM interpreter".
It constructs the operand of the instruction and passes
it to the appropriate routine with the operand as
argument.
The first program reads an input file which holds the interpreter
opcode table (as shown in the [IR-81] report appendix B),
@ -86,3 +94,5 @@ 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.
(Note: these remarks about mkfuncs are probably outdated now,
since mkfuncs has disappeared. -rbf)

276
util/int/switch/mkiswitch.c Normal file
View file

@ -0,0 +1,276 @@
/*
Generates contents of opcode switch from ip_spec.t,
and parameter descriptions of em_flag.h.
Call is:
mkiswitch prefix ip_spec.t cases
*/
/* $Header$ */
#include <stdio.h>
extern char *sprintf();
extern FILE *popen();
#include <util/ass/ip_spec.h>
#include <h/em_spec.h>
#include <h/em_flag.h>
extern char em_mnem[][4] ;
extern char em_flag[] ;
char *progname;
FILE *ifp; /* Input File Pointer */
FILE *ofp; /* Output File Pointer */
char *Prefix; /* Prefix for function name */
main(argc, argv)
int argc;
char **argv;
{
char mnem[8]; /* Mnemonic */
char flgs[8]; /* Flags */
char argstr[256]; /* To build argument */
progname = argv[0];
if (argc != 4 ) {
fatal("usage is: %s prefix ip_spec.t cases\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]);
}
/* Start reading the input file */
while (fscanf(ifp, "%s %s", mnem, flgs) >= 0) {
int i;
char *p;
char *base;
int cnt, first;
int mnemcode;
/* 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);
}
mnemcode = getmnem(mnem);
/* 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, '-')) {
if ((em_flag[mnemcode] & EM_PAR) == PAR_W) {
/* Implicit argument on stack */
ImplicitArg(argstr);
OutCase(mnem, base, first, 0, argstr);
} else {
/* No arguments */
NoArgs(argstr);
OutCase(mnem, base, first, 0, argstr);
}
} else if (in(flgs, 'm')) { /* Mini */
for (i = 0; i<cnt; i++) {
Mini(argstr, i, flgs);
OutCase(mnem, base, first, i, argstr);
}
} else if (in(flgs, 's')) { /* Shortie */
for (i = 0; i<cnt; i++) {
Shortie(argstr, i, flgs);
OutCase(mnem, base, first, i, argstr);
}
} else if (in(flgs, '2')) { /* Two byte signed */
TwoSgn(argstr, flgs);
OutCase(mnem, base, first, 0, argstr);
} else if (in(flgs, 'u')) { /* Two byte unsigned */
TwoUns(argstr, flgs);
OutCase(mnem, base, first, 0, argstr);
} else if (in(flgs, '4')) { /* Four byte signed */
FourSgn(argstr, flgs);
OutCase(mnem, base, first, 0, argstr);
} else {
fatal("no opcode flag in ip_spec %s\n", flgs);
}
}
exit(0);
}
OutCase(mnem, base, first, i, argstr)
char *mnem;
char *base;
int first;
int i;
char *argstr;
{
/* Output a case in the switch statement */
fprintf(ofp, "\t\tcase %s+%d:\t%s%s(%s); break;\n",
base, first+i, Prefix, mnem, argstr);
}
ImplicitArg(argstr)
char *argstr;
{
sprintf(argstr, "uwpop()");
}
NoArgs(argstr)
char *argstr;
{
sprintf(argstr, "");
}
Mini(argstr, i, flgs)
char *argstr;
int i;
char *flgs;
{
int newi = in(flgs, 'N') ? (-i-1) : in(flgs, 'o') ? (i+1) : i;
switch (newi) {
case -1:
sprintf(argstr, "%s",
in(flgs, 'w') ? "-wsize" : "-1L");
break;
case 0:
sprintf(argstr, "0L");
break;
case 1:
sprintf(argstr, "%s",
in(flgs, 'w') ? "wsize" : "1L");
break;
default:
sprintf(argstr, "%dL%s",
newi, in(flgs, 'w') ? "*wsize" : "");
break;
}
}
Shortie(argstr, i, flgs)
char *argstr;
int i;
char *flgs;
{
int newi = in(flgs, 'N') ? (-i-1) : in(flgs, 'o') ? (i+1) : i;
sprintf(argstr, "S_arg(%d)*%s",
newi, in(flgs, 'w') ? "wsize" : "1L");
}
TwoSgn(argstr, flgs)
char *argstr;
char *flgs;
{
sprintf(argstr, "%s*%s", in(flgs, 'P') ? "P_arg_2()" : in(flgs, 'N') ? "N_arg_2()" : "L_arg_2()",
in(flgs, 'w') ? "wsize" : "1L");
}
TwoUns(argstr, flgs)
char *argstr;
char *flgs;
{
sprintf(argstr, "%s*%s", "U_arg()",
in(flgs, 'w') ? "wsize" : "((unsigned long) 1)");
}
FourSgn(argstr, flgs)
char *argstr;
char *flgs;
{
sprintf(argstr, "%s*%s", in(flgs, 'P') ? "P_arg_4()" : in(flgs, 'N') ? "N_arg_4()" : "L_arg_4()",
in(flgs, 'w') ? "wsize" : "1L");
}
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);
}
int getmnem(str) char *str ; {
char (*ptr)[4] ;
for ( ptr = em_mnem ; *ptr<= &em_mnem[sp_lmnem][0] ; ptr++ ) {
if ( strcmp(*ptr,str)==0 ) return (ptr-em_mnem) ;
}
fatal("Illegal mnemonic") ;
return 0 ;
}