Bläddra i källkod

Model 3 (intelligent calls) implemented

ceriel 34 år sedan
förälder
incheckning
c7c79e9b42
3 ändrade filer med 306 tillägg och 15 borttagningar
  1. 14 9
      util/int/switch/Makefile
  2. 16 6
      util/int/switch/READ_ME
  3. 276 0
      util/int/switch/mkiswitch.c

+ 14 - 9
util/int/switch/Makefile

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

+ 16 - 6
util/int/switch/READ_ME

@@ -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.
-
-mkfuncs:
-	shell script that can be used to generate new function
-	files, if a new implementation is needed.
+	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".
+
+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 - 0
util/int/switch/mkiswitch.c

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