/* ** 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 instruction 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 #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(fldcmp(cp, opnd[j]) == 0) 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(fldcmp(cp, opnd[j]) == 0) 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); } /* ** abort with usage message */ usage() { error("Usage: CMIT [-C] [-L] ]table] [mac]"); }