home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
CP/M
/
CPM_CDROM.iso
/
mbug
/
mbug103.arc
/
CMIT.C
< prev
next >
Wrap
Text File
|
1979-12-31
|
9KB
|
280 lines
/*
** CMIT.C -- Machine Instruction Table Compiler
**
** Small-Mac Assembler Configuration Utility
**
** Copyright 1985 J. E. Hendrix
**
** Usage: CMIT [-C] [-L] [table] [mac]
**
** -C Configure the executable assembler (MAC.COM) with the indicated,
** or default, machine instructin table.
**
** -L List the compiled machine instruction table.
**
** table The name of the machine instruction table file in source
** format (default 8080.MIT). The default and only allowed
** filename extension is MIT. A drive specifier is allowed.
**
** mac Assembler COM file (default MAC.COM). Must have COM extension
** to be recognized as such. Need specify only if not on the
** default drive or has a different name.
**
** NOTE: if no switches are given, -L is assumed. If any switches
** are given, only those actions so specified are taken.
**
** NOTE: After compiling and linking a new MAC.COM, it must be
** configured by running this program before it may be executed.
** A previously configured MAC.COM may be reconfigured at any time.
*/
#include <stdio.h>
#include "mac.h" /* must be included first */
#include "mit.h"
#include "notice.h"
#define COMEXT ".COM"
#define MITEXT ".MIT"
char
macfn[MAXFN] = "MAC.COM", /* default assembler filename */
mitfn[MAXFN] = "8080.MIT"; /* default mit filename */
int
con, /* configure? */
list, /* list? */
looks; /* number of looks to find it */
main(argc, argv) int argc, *argv; {
char str[MAXFN];
fputs("Small-Mac MIT Compiler, ", stderr); fputs(VERSION, stderr);
fputs(CRIGHT1, stderr);
getsw(argc, argv); /* fetch and remember switches, etc. */
load();
if(list) print();
if(con) config();
}
/*
** configure assembler with machine instruction table
*/
extern int Uchrpos[];
config() {
int fd, sz;
fd = open(macfn, "r+"); /* must exist */
Uchrpos[fd] = 3; /* seek to mitable word */
read(fd, &sz, INTSZ); /* read table size */
if(sz != mitable) {
printf("%s MIT is %u Bytes but Should be %u\n", macfn, sz, mitable);
abort(7);
}
write(fd, &mitable + 1, mitable);
if(ferror(fd)) error2(macfn, " - Write Error");
close(fd);
}
/*
** get switches from command line
*/
getsw(argc, argv) int argc, *argv; {
char arg[MAXFN];
int i, b, len;
i = 0;
while(getarg(++i, arg, MAXFN, argc, argv) != EOF) {
if(arg[0] == '-') {
if(toupper(arg[1]) == 'C') con = YES;
else if(toupper(arg[1]) == 'L') list = YES;
else usage();
}
else {
if(extend(arg, MITEXT, COMEXT))
strcpy(macfn, arg);
else strcpy(mitfn, arg);
}
}
if(!con) list = YES;
}
/*
** load table from diskette
*/
load() {
char str[MAXLINE], *mitend, *vptr, *last, *ptr, *cp;
int fd, top, bits, byte, ilen, h, i, j,
opnd[MIOPNDS], opnds, et, *fptr;
fd = open(mitfn, "r");
ptr = mitbuf;
mitend = mitbuf + (MIBUFSZ - MAXLINE);
opnds = 0;
while(fgets(str, MAXLINE, fd)) { /* load operand fields */
poll(YES);
cp = skip(3, str); /* skip to operand field */
if(!isgraph(*cp)) continue; /* no operand to load */
for(j = 0; j < opnds; ++j) /* already have it? */
if(sameopnd(cp, opnd[j])) break;
if(j < opnds) continue;
if(ptr > mitend) goto mitovr1;
opnd[opnds++] = ptr; /* temp operand ptr */
if(opnds == MIOPNDS) error2(str, "- MIT Operand Overflow");
while(isgraph(*ptr = *cp++)) ++ptr; /* copy operand field */
*ptr++ = NULL;
}
if(rewind(fd)) error("- Can't Rewind MIT File");/* 2nd pass */
last = ptr; *last = NULL;
top = 0;
while(fgets(str, MAXLINE, fd)) { /* load mnemonics, etc. */
poll(YES);
if(ptr > mitend) {mitovr1: error2(str, "- MIT Buffer Overflow");}
if(top >= MICOUNT) error("- MIT Mnemonic Overflow");
cp = skip(2, str); /* skip to mnemonic field */
if(fldcmp(cp, last)) { /* new mnemonic */
*ptr++ = 0; /* terminate prior instr */
mitptr[top++] = last = ptr; /* mnemonic ptr */
while(isgraph(*ptr = *cp++)) ++ptr; /* copy mnemonic field */
*ptr++ = NULL;
}
vptr = ptr++; *vptr = 2*INTSZ; /* vlen field */
cp = skip(3, str); /* locate operand */
if(isgraph(*cp)) { /* has an operand field */
for(j = 0; j < opnds; ++j)
if(sameopnd(cp, opnd[j])) break;
if(j == opnds) error2(str, "- Can't Find Operand");
putint(ptr, opnd[j]);
}
else putint(ptr, 0); /* has no operand */
ptr += INTSZ;
fptr = ptr; ptr += INTSZ; *fptr = 0; /* fmt field */
bits = 13;
ilen = -1;
cp = skip(1, str); /* code field */
while(isgraph(*cp)) {
if(islower(*cp)) { /* x1, x2, etc. */
et = *cp++; /* expr type */
bits -= 3; *fptr = ((*fptr >> 3) & 8191) + 8192;
switch(*cp) {
default: error2(str, "- Bad Expression Specifier");
case '2': *fptr += 32768; ilen += 2; break;
case '1': ++ilen;
}
if(et == 'p') *fptr += 16384; /* pc relative expr */
++cp;
continue;
}
if(isxdigit(*cp)) {
if((j = xtoi(cp, &byte)) > 2) error2(str, "- Bad Hex Byte");
cp += j;
*ptr++ = byte; *vptr += 1;
--bits; *fptr = ((*fptr >> 1) & 32767);
++ilen;
continue;
}
++cp; /* bump past field separator */
}
*fptr >>= bits; /* right adjust format byte */
*fptr |= ilen & 7; /* and insert instr length */
}
*ptr++ = 0; /* terminate prior instr */
printf(" Operation Codes %5u\n", top);
printf("Buffer Space Used %5u\n", ptr - mitbuf);
for(i = 0; i < MICOUNT; ++i) /* init hash indices */
mitndx[i] = mitnxt[i] = EOF;
for(i = 0; i < top; ++i) { /* create hash indices - pass 1 */
poll(YES);
h = hash(mitptr[i], MICOUNT);
if(mitndx[h] == EOF) {
mitndx[h] = i;
}
}
for(i = j = 0; i < top; ++i) { /* create hash indices - pass 2 */
poll(YES);
h = hash(mitptr[i], MICOUNT);
if(mitndx[h] != i) {
while(mitndx[j] != EOF) ++j; /* must be empty slot */
mitndx[j] = i;
while(mitnxt[h] != EOF) h = mitnxt[h];
mitnxt[h] = j;
}
}
close(fd);
}
/*
** print compiled machine instruction table
*/
print() {
int i ,k, bak, fd, fmt, len, opcode, holding;
char lin[MAXLINE], inst[MAXLINE], *ptr, *vptr, *cp;
fd = open(mitfn, "r");
while(fgets(lin, MAXLINE, fd)) {
poll(YES);
i = 0; cp = skip(2, lin);
while(isgraph(inst[i++] = *cp++)) ;
if(inst[i-1] == '\n') inst[i-1] = ' ';
bak = i;
cp = skip(3, lin);
do {
i = bak;
while(isgraph(*cp) && *cp != ANOTHER) inst[i++] = *cp++;
inst[i] = 0;
if(*cp == ANOTHER) ++cp;
printf("%-15s ", inst); /* mnemonic */
if(!(ptr = find(inst)))
error("- Can't Find Instruction in MIT");
printf(" (%2u looks) ", looks);
ptr += INTSZ;
fmt = getint(ptr); /* ptr -> first code byte */
ptr += INTSZ;
len = (fmt & 7) + 1;
fmt >>= 3;
holding = NO;
while(len-- > 0) { /* for each byte of code */
if(fmt & 1) { /* expression */
if(holding) {
opcode += opadj;
opadj = 0;
holding = NO;
printf(" %2x", opcode);
}
fmt >>= 1;
switch(fmt & 3) {
case 0: printf(" x1"); break; /* 1-byte */
case 1: printf(" p1"); break; /* 1-byte pc rel */
case 2: printf(" x2"); --len; break; /* 2-byte */
case 3: printf(" p2"); --len; break; /* 2-byte pc rel */
}
fmt >>= 1;
}
else { /* code byte */
if(holding) printf(" %2x", opcode);
opcode = *ptr++ & 255;
holding = YES;
}
fmt >>= 1;
}
if(holding) {
opcode += opadj;
printf(" %2x", opcode);
}
puts("");
} while(*cp > ' ');
}
close(fd);
}
/*
** same operand fields? (case sensitive)
*/
sameopnd(opnd1, opnd2) char *opnd1, *opnd2; {
while(!atend(*opnd1) && *opnd1 == *opnd2) { /* only opnd1 has \n */
++opnd1;
++opnd2;
}
if(atend(*opnd1) && atend(*opnd2)) return (YES);
return (NO);
}
/*
** abort with a usage message
*/
usage() {
error("Usage: CMIT [-C] [-L] [table] [mac]");
}