home *** CD-ROM | disk | FTP | other *** search
/ CP/M / CPM_CDROM.iso / mbug / mbug103.arc / CMIT.C < prev    next >
Text File  |  1979-12-31  |  9KB  |  280 lines

  1. /*
  2. ** CMIT.C -- Machine Instruction Table Compiler
  3. **
  4. **             Small-Mac Assembler Configuration Utility
  5. **
  6. **                   Copyright 1985 J. E. Hendrix
  7. **
  8. ** Usage: CMIT [-C] [-L] [table] [mac] 
  9. **
  10. ** -C     Configure the executable assembler (MAC.COM) with the indicated,
  11. **        or default, machine instructin table.
  12. **
  13. ** -L     List the compiled machine instruction table.
  14. **
  15. ** table  The name of the machine instruction table file in source
  16. **        format (default 8080.MIT).  The default and only allowed
  17. **        filename extension is MIT.  A drive specifier is allowed.
  18. **
  19. ** mac    Assembler COM file (default MAC.COM).  Must have COM extension
  20. **        to be recognized as such.  Need specify only if not on the
  21. **        default drive or has a different name.
  22. **
  23. **        NOTE: if no switches are given, -L is assumed.  If any switches
  24. **        are given, only those actions so specified are taken.
  25. **
  26. **        NOTE: After compiling and linking a new MAC.COM, it must be
  27. **        configured by running this program before it may be executed.
  28. **        A previously configured MAC.COM may be reconfigured at any time.
  29. */
  30. #include <stdio.h>
  31. #include "mac.h"    /* must be included first */
  32. #include "mit.h"
  33. #include "notice.h"
  34.  
  35. #define COMEXT  ".COM"
  36. #define MITEXT  ".MIT"
  37.  
  38. char
  39.   macfn[MAXFN] = "MAC.COM",    /* default assembler filename */
  40.   mitfn[MAXFN] = "8080.MIT";    /* default mit filename */
  41. int
  42.   con,            /* configure? */
  43.   list,            /* list? */
  44.   looks;        /* number of looks to find it */
  45.  
  46. main(argc, argv) int argc, *argv; {
  47.   char str[MAXFN];
  48.   fputs("Small-Mac MIT Compiler, ", stderr); fputs(VERSION, stderr);
  49.   fputs(CRIGHT1, stderr);
  50.   getsw(argc, argv);        /* fetch and remember switches, etc. */
  51.   load();
  52.   if(list) print();
  53.   if(con) config();
  54.   }
  55.  
  56. /*
  57. ** configure assembler with machine instruction table
  58. */
  59. extern int Uchrpos[];
  60. config() {
  61.   int fd, sz;
  62.   fd = open(macfn, "r+");        /* must exist */
  63.   Uchrpos[fd] = 3;            /* seek to mitable word */
  64.   read(fd, &sz, INTSZ);            /* read table size */
  65.   if(sz != mitable) {
  66.     printf("%s MIT is %u Bytes but Should be %u\n", macfn, sz, mitable);
  67.     abort(7);
  68.     }
  69.   write(fd, &mitable + 1, mitable);
  70.   if(ferror(fd)) error2(macfn, " - Write Error");
  71.   close(fd);
  72.   }
  73.  
  74. /*
  75. ** get switches from command line
  76. */
  77. getsw(argc, argv) int argc, *argv; {
  78.   char arg[MAXFN];
  79.   int i, b, len;
  80.   i = 0;
  81.   while(getarg(++i, arg, MAXFN, argc, argv) != EOF) {
  82.     if(arg[0] == '-') {
  83.       if(toupper(arg[1]) == 'C')      con = YES;
  84.       else if(toupper(arg[1]) == 'L') list = YES;
  85.       else usage();
  86.       }
  87.     else {
  88.       if(extend(arg, MITEXT, COMEXT)) 
  89.            strcpy(macfn, arg);
  90.       else strcpy(mitfn, arg);
  91.       }
  92.     }
  93.   if(!con) list = YES;
  94.   }
  95.  
  96. /*
  97. ** load table from diskette
  98. */
  99. load() {
  100.   char str[MAXLINE], *mitend, *vptr, *last, *ptr, *cp;
  101.   int fd, top, bits, byte, ilen, h, i, j,
  102.       opnd[MIOPNDS], opnds, et, *fptr;
  103.   fd = open(mitfn, "r");
  104.   ptr = mitbuf;
  105.   mitend = mitbuf + (MIBUFSZ - MAXLINE);
  106.   opnds = 0;
  107.   while(fgets(str, MAXLINE, fd)) {        /* load operand fields */
  108.     poll(YES);
  109.     cp = skip(3, str);                /* skip to operand field */
  110.     if(!isgraph(*cp)) continue;            /* no operand to load */
  111.     for(j = 0; j < opnds; ++j)            /* already have it? */
  112.       if(sameopnd(cp, opnd[j])) break;
  113.     if(j < opnds) continue;
  114.     if(ptr > mitend) goto mitovr1;
  115.     opnd[opnds++] = ptr;            /* temp operand ptr */
  116.     if(opnds == MIOPNDS) error2(str, "- MIT Operand Overflow");
  117.     while(isgraph(*ptr = *cp++)) ++ptr;        /* copy operand field */
  118.     *ptr++ = NULL;
  119.     }
  120.   if(rewind(fd)) error("- Can't Rewind MIT File");/* 2nd pass */
  121.   last = ptr; *last = NULL;
  122.   top = 0;
  123.   while(fgets(str, MAXLINE, fd)) {        /* load mnemonics, etc. */
  124.     poll(YES);
  125.     if(ptr > mitend)   {mitovr1: error2(str, "- MIT Buffer Overflow");}
  126.     if(top >= MICOUNT) error("- MIT Mnemonic Overflow");
  127.     cp = skip(2, str);                /* skip to mnemonic field */
  128.     if(fldcmp(cp, last)) {            /* new mnemonic */
  129.       *ptr++ = 0;                /* terminate prior instr */
  130.       mitptr[top++] = last = ptr;        /* mnemonic ptr */
  131.       while(isgraph(*ptr = *cp++)) ++ptr;    /* copy mnemonic field */
  132.       *ptr++ = NULL;
  133.       }
  134.     vptr = ptr++; *vptr = 2*INTSZ;        /* vlen field */
  135.     cp = skip(3, str);                /* locate operand */
  136.     if(isgraph(*cp)) {                /* has an operand field */
  137.       for(j = 0; j < opnds; ++j)
  138.         if(sameopnd(cp, opnd[j])) break;
  139.       if(j == opnds) error2(str, "- Can't Find Operand");
  140.       putint(ptr, opnd[j]);
  141.       }
  142.     else putint(ptr, 0);            /* has no operand */
  143.     ptr += INTSZ;
  144.     fptr = ptr; ptr += INTSZ; *fptr = 0;    /* fmt field */
  145.     bits = 13;
  146.     ilen = -1;
  147.     cp = skip(1, str);                /* code field */
  148.     while(isgraph(*cp)) {
  149.       if(islower(*cp)) {            /* x1, x2, etc. */
  150.         et = *cp++;                /* expr type */
  151.         bits -= 3; *fptr = ((*fptr >> 3) & 8191) + 8192;
  152.         switch(*cp) {
  153.            default: error2(str, "- Bad Expression Specifier");
  154.           case '2': *fptr += 32768; ilen += 2; break;
  155.           case '1': ++ilen;
  156.           }
  157.         if(et == 'p') *fptr += 16384;        /* pc relative expr */
  158.         ++cp;
  159.         continue;
  160.         }
  161.       if(isxdigit(*cp)) {
  162.         if((j = xtoi(cp, &byte)) > 2) error2(str, "- Bad Hex Byte");
  163.         cp += j;
  164.         *ptr++ = byte; *vptr += 1;
  165.         --bits; *fptr = ((*fptr >> 1) & 32767);
  166.         ++ilen;
  167.         continue;
  168.         }
  169.       ++cp;                /* bump past field separator */
  170.       }
  171.     *fptr >>= bits;            /* right adjust format byte */
  172.     *fptr |= ilen & 7;            /* and insert instr length */
  173.     }
  174.   *ptr++ = 0;                /* terminate prior instr */
  175.   printf("  Operation Codes %5u\n", top);
  176.   printf("Buffer Space Used %5u\n", ptr - mitbuf);
  177.   for(i = 0; i < MICOUNT; ++i)        /* init hash indices */
  178.     mitndx[i] = mitnxt[i] = EOF;
  179.   for(i = 0; i < top; ++i) {        /* create hash indices - pass 1 */
  180.     poll(YES);
  181.     h = hash(mitptr[i], MICOUNT);
  182.     if(mitndx[h] == EOF) {
  183.       mitndx[h] = i;
  184.       }
  185.     }
  186.   for(i = j = 0; i < top; ++i) {    /* create hash indices - pass 2 */
  187.     poll(YES);
  188.     h = hash(mitptr[i], MICOUNT);
  189.     if(mitndx[h] != i) {
  190.       while(mitndx[j] != EOF) ++j;    /* must be empty slot */
  191.       mitndx[j] = i;
  192.       while(mitnxt[h] != EOF) h = mitnxt[h];
  193.       mitnxt[h] = j;
  194.       }
  195.     }
  196.   close(fd);
  197.   }
  198.  
  199. /*
  200. ** print compiled machine instruction table
  201. */
  202. print() {
  203.   int i ,k, bak, fd, fmt, len, opcode, holding;
  204.   char lin[MAXLINE], inst[MAXLINE], *ptr, *vptr, *cp;
  205.   fd = open(mitfn, "r");
  206.   while(fgets(lin, MAXLINE, fd)) {
  207.     poll(YES);
  208.     i = 0; cp = skip(2, lin);
  209.     while(isgraph(inst[i++] = *cp++)) ;
  210.     if(inst[i-1] == '\n') inst[i-1] = ' ';
  211.     bak = i;
  212.     cp = skip(3, lin);
  213.     do {
  214.       i = bak;  
  215.       while(isgraph(*cp) && *cp != ANOTHER) inst[i++] = *cp++;
  216.       inst[i] = 0;
  217.       if(*cp == ANOTHER) ++cp;
  218.       printf("%-15s ", inst);        /* mnemonic */
  219.       if(!(ptr = find(inst)))
  220.         error("- Can't Find Instruction in MIT");
  221.       printf(" (%2u looks) ", looks);
  222.       ptr += INTSZ;
  223.       fmt = getint(ptr);        /* ptr -> first code byte */
  224.       ptr += INTSZ;
  225.       len = (fmt & 7) + 1;
  226.       fmt >>= 3;
  227.       holding = NO;
  228.       while(len-- > 0) {        /* for each byte of code */
  229.         if(fmt & 1) {            /* expression */
  230.           if(holding) {
  231.             opcode += opadj;
  232.             opadj = 0;
  233.             holding = NO;
  234.             printf(" %2x", opcode);
  235.             }
  236.           fmt >>= 1;
  237.           switch(fmt & 3) {
  238.             case 0: printf(" x1"); break;        /* 1-byte */
  239.             case 1: printf(" p1"); break;        /* 1-byte pc rel */
  240.             case 2: printf(" x2"); --len; break;    /* 2-byte */
  241.             case 3: printf(" p2"); --len; break;    /* 2-byte pc rel */
  242.             }
  243.           fmt >>= 1;
  244.           }
  245.         else {                    /* code byte */
  246.           if(holding) printf(" %2x", opcode);
  247.           opcode = *ptr++ & 255;
  248.           holding = YES;
  249.           }
  250.         fmt >>= 1;
  251.         }
  252.       if(holding) {
  253.         opcode += opadj;
  254.         printf(" %2x", opcode);
  255.         }
  256.       puts("");
  257.       } while(*cp > ' ');
  258.     }
  259.   close(fd);
  260.   }
  261.  
  262. /*
  263. ** same operand fields? (case sensitive)
  264. */
  265. sameopnd(opnd1, opnd2) char *opnd1, *opnd2; {
  266.   while(!atend(*opnd1) && *opnd1 == *opnd2) {    /* only opnd1 has \n */
  267.     ++opnd1;
  268.     ++opnd2;
  269.     }
  270.   if(atend(*opnd1) && atend(*opnd2)) return (YES);
  271.   return (NO);
  272.   }
  273.  
  274. /*
  275. ** abort with a usage message
  276. */
  277. usage() {
  278.   error("Usage: CMIT [-C] [-L] [table] [mac]");
  279.   }
  280.