home *** CD-ROM | disk | FTP | other *** search
/ io Programmo 23 / IOPROG_23.ISO / SOFT / ASM / DEBUG095.ZIP / mktables.c < prev    next >
Encoding:
C/C++ Source or Header  |  1997-08-07  |  27.2 KB  |  1,182 lines

  1. /*
  2.  *    This program reads in the various data files, performs some checks,
  3.  *    and spits out the tables needed for assembly and disassembly.
  4.  *
  5.  *    The input files are:
  6.  *        instr.set    Instruction set
  7.  *        instr.key    Translation from one- or two-character keys to
  8.  *                operand list types
  9.  *        instr.ord    Ordering relations to enforce on the operands
  10.  *
  11.  *    The output tables are merged into the debug source file debug.a86.
  12.  */
  13.  
  14. #ifndef    DOS
  15. #ifdef    __MSDOS__
  16. #define    DOS    1
  17. #else
  18. #define    DOS    0
  19. #endif
  20. #endif
  21.  
  22. #include <stdlib.h>
  23. #if    ! DOS
  24. #include <unistd.h>
  25. #endif
  26. #include <stdio.h>
  27. #include <stdarg.h>
  28. #include <string.h>
  29. #include <ctype.h>
  30. #include <errno.h>
  31.  
  32. #if    DOS
  33. #define    CRLF    "\n"
  34. #define    bzero(a, b)    memset(a, 0, b)
  35. #else
  36. #define    CRLF    "\r\n"
  37. #define    cdecl
  38. #endif
  39.  
  40. #define    MARKLINE1    ";-@@-@@-@@-Do not edit these tables!  " \
  41.     "They have been automatically generated." CRLF
  42. #define    MARKLINE2    ";-@@-@@-@@-End of auto-generated tables.  " \
  43.     "You may edit below this point." CRLF
  44.  
  45. #define    MAX_OL_TYPES    80
  46. #define    MAX_N_ORDS    30
  47. #define    LINELEN        132
  48. #define    MAX_ASM_TAB    2048
  49. #define    MAX_MNRECS    400
  50. #define    MAX_SAVED_MNEMS    10
  51. #define    MAX_SLASH_ENTRIES 20
  52. #define    MAX_STAR_ENTRIES 15
  53. #define    MAX_LOCKTAB_ENTRIES 50
  54. #define    MAX_AGROUP_ENTRIES 14
  55. #define    MSHIFT        12    /* number of bits below machine type */
  56.  
  57. typedef    char    Boolean;
  58. #define    True    1
  59. #define    False    0
  60.  
  61. #define    NUMBER(x)    (sizeof(x) / sizeof(*x))
  62.  
  63. char        line[LINELEN];
  64. const char    *filename;
  65. int        lineno;
  66.  
  67. int    n_keys        = 0;
  68. struct keytab {
  69.     short    key;
  70.     short    value;
  71.     short    width;
  72. };
  73.  
  74. int    n_ol_types    = 0;
  75. struct keytab    olkeydict[MAX_OL_TYPES];
  76. char        *olnames[MAX_OL_TYPES];
  77. int        oloffset[MAX_OL_TYPES];
  78.  
  79. int    n_ords        = 0;
  80. struct keytab    *keyord1[MAX_N_ORDS];
  81. struct keytab    *keyord2[MAX_N_ORDS];
  82. Boolean        ordsmall[MAX_OL_TYPES];
  83.  
  84. /*
  85.  *    Equates for the assembler table.
  86.  *    These should be the same as in debug.asm.
  87.  */
  88.  
  89. #define    ASM_END        0xff
  90. #define    ASM_DB        0xfe
  91. #define    ASM_DW        0xfd
  92. #define    ASM_DD        0xfc
  93. #define    ASM_ORG        0xfb
  94. #define    ASM_WAIT     0xfa
  95. #define    ASM_D32        0xf9
  96. #define    ASM_AAX        0xf8
  97. #define    ASM_SEG        0xf7
  98. #define    ASM_LOCKREP    0xf6
  99. #define    ASM_LOCKABLE    0xf5
  100. #define    ASM_MACH6    0xf4
  101. #define    ASM_MACH0    0xee
  102.  
  103. int    n_asm_tab    = 0;
  104. unsigned char    asmtab[MAX_ASM_TAB];
  105.  
  106. struct mnrec {
  107.     struct mnrec    *next;
  108.     char        *string;
  109.     short        len;
  110.     short        offset;
  111.     short        asmoffset;
  112. };
  113.  
  114. int        num_mnrecs;
  115. struct mnrec    mnlist[MAX_MNRECS];
  116. struct mnrec    *mnhead;
  117.  
  118. int    n_saved_mnems        = 0;
  119. int    saved_mnem[MAX_SAVED_MNEMS];
  120.  
  121. int    n_slash_entries;
  122. int    slashtab_seq[MAX_SLASH_ENTRIES];
  123. int    slashtab_mn[MAX_SLASH_ENTRIES];
  124.  
  125. int    n_star_entries;
  126. int    startab_seq[MAX_STAR_ENTRIES];
  127. int    startab_mn[MAX_STAR_ENTRIES];
  128.  
  129. int    n_locktab;
  130. int    locktab[MAX_LOCKTAB_ENTRIES];
  131.  
  132. int    n_agroups;
  133. int    agroup_i[MAX_AGROUP_ENTRIES];
  134. int    agroup_inf[MAX_AGROUP_ENTRIES];
  135.  
  136. volatile void
  137. fail(const char *message, ...)
  138. {
  139.     va_list    args;
  140.  
  141.     va_start(args, message);
  142.     vfprintf(stderr, message, args);
  143.     va_end(args);
  144.     putc('\n', stderr);
  145.     exit(1);
  146. }
  147.  
  148. FILE *
  149. openread(const char *path)
  150. {
  151.     FILE    *f;
  152.  
  153.     f = fopen(path, "r");
  154.     if (f == NULL) {
  155.         perror(path);
  156.         exit(1);
  157.     }
  158.     filename = path;
  159.     lineno = 0;
  160.     return f;
  161. }
  162.  
  163. volatile void
  164. linenofail(const char *message, ...)
  165. {
  166.     va_list args;
  167.  
  168.     fprintf(stderr, "Line %d of `%s':  ", lineno, filename);
  169.     va_start(args, message);
  170.     vfprintf(stderr, message, args);
  171.     va_end(args);
  172.     putc('\n', stderr);
  173.     exit(1);
  174. }
  175.  
  176. void *
  177. xmalloc(unsigned int len, const char *why)
  178. {
  179.     void    *ptr    = malloc(len);
  180.  
  181.     if (ptr == NULL) fail("Cannot allocate %u bytes for %s", len, why);
  182.     return ptr;
  183. }
  184.  
  185. Boolean
  186. getline(FILE *ff)
  187. {
  188.     int    n;
  189.  
  190.     for (;;) {
  191.         if (fgets(line, LINELEN, ff) == NULL) return False;
  192.         ++lineno;
  193.         if (line[0] == '#') continue;
  194.         n = strlen(line) - 1;
  195.         if (n < 0 || line[n] != '\n')
  196.         linenofail("too long.");
  197.         if (n > 0 && line[n-1] == '\r') --n;
  198.         if (n == 0) continue;
  199.         line[n] = '\0';
  200.         return True;
  201.     }
  202. }
  203.  
  204. short
  205. getkey(char **pp)
  206. {
  207.     short    key;
  208.     char    *p    = *pp;
  209.  
  210.     if (*p == ' ' || *p == '\t' || *p == ';' || *p == '\0')
  211.         linenofail("key expected");
  212.     key = *p++;
  213.     if (*p != ' ' && *p != '\t' && *p != ';' && *p != '\0') {
  214.         key = (key << 8) | *p++;
  215.         if (*p != ' ' && *p != '\t' && *p != ';' && *p != '\0')
  216.         linenofail("key too long");
  217.     }
  218.     *pp = p;
  219.     return key;
  220. }
  221.  
  222. /*
  223.  *    Mark the given key pointer as small, as well as anything smaller than
  224.  *    it (according to instr.ord).
  225.  */
  226.  
  227. void
  228. marksmall(struct keytab *kp)
  229. {
  230.     int    i;
  231.  
  232.     ordsmall[kp - olkeydict] = True;
  233.     for (i = 0; i < n_ords; ++i)
  234.         if (keyord2[i] == kp)
  235.         marksmall(keyord1[i]);
  236. }
  237.  
  238. /*
  239.  *    Add a byte to the assembler table (asmtab).
  240.  *    The format of this table is described in a long comment in debug.asm,
  241.  *    somewhere within the mini-assembler.
  242.  */
  243.  
  244. void
  245. add_to_asmtab(unsigned char byte)
  246. {
  247.     if (n_asm_tab >= MAX_ASM_TAB)
  248.         linenofail("Assembler table overflow.");
  249.     asmtab[n_asm_tab++] = byte;
  250. }
  251.  
  252.  
  253. unsigned char
  254. getmachine(char **pp)
  255. {
  256.     char        *p    = *pp;
  257.     unsigned char    value;
  258.  
  259.     if (*p != ';') return 0;
  260.     ++p;
  261.     if (*p < '0' || *p > '6')
  262.         linenofail("bad machine type");
  263.     value = *p++ - '0';
  264.     add_to_asmtab(ASM_MACH0 + value);
  265.     *pp = p;
  266.     return value;
  267. }
  268.  
  269. struct keytab *
  270. lookupkey(short key)
  271. {
  272.     struct keytab *kp;
  273.  
  274.     for (kp = olkeydict; kp < olkeydict + NUMBER(olkeydict); ++kp)
  275.         if (key == kp->key) return kp;
  276.     linenofail("can't find key");
  277. }
  278.  
  279. char *
  280. skipwhite(char *p)
  281. {
  282.     while (*p == ' ' || *p == '\t') ++p;
  283.     return p;
  284. }
  285.  
  286. /*
  287.  *    Data and setup stuff for the disassembler processing.
  288.  */
  289.  
  290. /*    Data on coprocessor groups */
  291.  
  292. unsigned int    fpgrouptab[]    = {0xd9e8, 0xd9f0, 0xd9f8};
  293.  
  294. #define    NGROUPS        9
  295.  
  296. #define    GROUP(i)    (256 + 8 * ((i) - 1))
  297. #define    COPR(i)        (256 + 8 * NGROUPS + 16 * (i))
  298. #define    FPGROUP(i)    (256 + 8 * NGROUPS + 16 * 8 + 8 * (i))
  299. #define    SPARSE_BASE    (256 + 8 * NGROUPS + 16 * 8 \
  300.                 + 8 * NUMBER(fpgrouptab))
  301.  
  302. /* #define OPILLEGAL    0 */
  303. #define    OPTWOBYTE    2
  304. #define    OPGROUP        4
  305. #define    OPCOPR        6
  306. #define    OPFPGROUP    8
  307. #define    OPPREFIX    10
  308. #define    OPSIMPLE    12
  309. #define    OPTYPES        12    /* op types start here (includes simple ops) */
  310.  
  311. #define    PRESEG        1    /* these should be the same as in debug.asm */
  312. #define    PREREP        2
  313. #define    PRELOCK        4
  314. #define    PRE32D        8
  315. #define    PRE32A        0x10
  316.  
  317. /*
  318.  *    For sparsely filled parts of the opcode map, we have counterparts
  319.  *    to the above, which are compressed in a simple way.
  320.  */
  321.  
  322. /*    Sparse coprocessor groups */
  323.  
  324. unsigned int    sp_fpgrouptab[]    = {0xd9d0, 0xd9e0, 0xdae8, 0xdbe0, 
  325.                    0xded8, 0xdfe0};
  326.  
  327. #define    NSGROUPS    5
  328.  
  329. #define    SGROUP(i)    (SPARSE_BASE + 256 + 8 * ((i) - 1))
  330. #define    SFPGROUP(i)    (SPARSE_BASE + 256 + 8 * NSGROUPS + 8 * (i))
  331. #define    NOPS        (SPARSE_BASE + 256 + 8 * NSGROUPS \
  332.             + 8 * NUMBER(sp_fpgrouptab))
  333.  
  334. int        optype[NOPS];
  335. int        opinfo[NOPS];
  336. unsigned char    opmach[NOPS];
  337.  
  338. /*
  339.  *    Here are the tables for the main processor groups.
  340.  */
  341.  
  342. struct {
  343.     int    seq;    /* sequence number of the group */
  344.     int    info;    /* which group number it is */
  345. }
  346.     grouptab[]    = {
  347.         {0x80, GROUP(1)},    /* Intel group 1 */
  348.         {0x81, GROUP(1)},
  349.         {0x83, GROUP(2)},
  350.         {0xd0, GROUP(3)},    /* Intel group 2 */
  351.         {0xd1, GROUP(3)},
  352.         {0xd2, GROUP(4)},
  353.         {0xd3, GROUP(4)},
  354.         {0xc0, GROUP(5)},    /* Intel group 2a */
  355.         {0xc1, GROUP(5)},
  356.         {0xf6, GROUP(6)},    /* Intel group 3 */
  357.         {0xf7, GROUP(6)},
  358.         {0xff, GROUP(7)},    /* Intel group 5 */
  359.         {SPARSE_BASE + 0x00, GROUP(8)},        /* Intel group 6 */
  360.         {SPARSE_BASE + 0x01, GROUP(9)}};    /* Intel group 7 */
  361.  
  362. /* #define    NGROUPS    9 (this was done above) */
  363.  
  364. struct {    /* sparse groups */
  365.     int    seq;    /* sequence number of the group */
  366.     int    info;    /* which group number it is */
  367. }
  368.     sp_grouptab[]    = {
  369.         {0xfe, SGROUP(1)},        /* Intel group 4 */
  370.         {SPARSE_BASE+0xba, SGROUP(2)},    /* Intel group 8 */
  371.         {SPARSE_BASE+0xc7, SGROUP(3)},    /* Intel group 9 */
  372.         {0x8f, SGROUP(4)},        /* Not an Intel group */
  373.         {0xc6, SGROUP(5)},        /* Not an Intel group */
  374.         {0xc7, SGROUP(5)}};
  375.  
  376. /* #define    NSGROUPS    5 (this was done above) */
  377.  
  378. /*
  379.  *    Creates an entry in the disassembler lookup table
  380.  */
  381.  
  382. void
  383. entertable(int i, int type, int info)
  384. {
  385.     if (optype[i] != 0)
  386.         linenofail("Duplicate information for index %d", i);
  387.     optype[i] = type;
  388.     opinfo[i] = info;
  389. }
  390.  
  391. /*
  392.  *    Get a hex nybble from the input line or fail.
  393.  */
  394.  
  395. int
  396. getnybble(char c)
  397. {
  398.     if (c >= '0' && c <= '9') return c - '0';
  399.     if (c >= 'a' && c <= 'f') return c - 'a' + 10;
  400.     linenofail("Hex digit expected instead of `%c'", c);
  401. }
  402.  
  403. /*
  404.  *    Get a hex byte from the input line and update the pointer accordingly.
  405.  */
  406.  
  407. int
  408. getbyte(char **pp)
  409. {
  410.     char    *p = *pp;
  411.     int    answer;
  412.  
  413.     answer = getnybble(*p++);
  414.     answer = (answer << 4) | getnybble(*p++);
  415.     *pp = p;
  416.     return answer;
  417. }
  418.  
  419. /*
  420.  *    Get a `/r' descriptor from the input line and update the pointer
  421.  *    accordingly.
  422.  */
  423.  
  424. int
  425. getslash(char **pp)
  426. {
  427.     char    *p = *pp;
  428.     int    answer;
  429.  
  430.     if (*p != '/') linenofail("`/' expected");
  431.     ++p;
  432.     if (*p < '0' || *p > '7') linenofail("Octal digit expected");
  433.     answer = *p - '0';
  434.     ++p;
  435.     *pp = p;
  436.     return answer;
  437. }
  438.  
  439. int
  440. entermn(char *str, char *str_end)
  441. {
  442.     char    *p;
  443.  
  444.     if (num_mnrecs >= MAX_MNRECS)
  445.         linenofail("Too many mnemonics");
  446.  
  447.     if (*str == '+') {
  448.         if (n_saved_mnems >= MAX_SAVED_MNEMS)
  449.         linenofail("Too many mnemonics to save");
  450.         saved_mnem[n_saved_mnems++] = num_mnrecs;
  451.         ++str;
  452.     }
  453.  
  454.     p = xmalloc(str_end - str + 1, "mnemonic name");
  455.     mnlist[num_mnrecs].string = p;
  456.     mnlist[num_mnrecs].len = str_end - str;
  457.     while (str < str_end) *p++ = toupper(*str++);
  458.     *p = '\0';
  459.     mnlist[num_mnrecs].asmoffset = n_asm_tab;
  460.     return num_mnrecs++;
  461. }
  462.  
  463. /*
  464.  *    Merge sort the indicated range of mnemonic records.
  465.  */
  466.  
  467. struct mnrec *
  468. mn_sort(struct mnrec *start, int len)
  469. {
  470.     struct mnrec    *p1, *p2, *answer;
  471.     struct mnrec    **headpp;
  472.     int        i;
  473.  
  474.     i = len / 2;
  475.     if (i == 0)
  476.         return start;
  477.  
  478.     p1 = mn_sort(start, i);
  479.     p2 = mn_sort(start + i, len - i);
  480.     headpp = &answer;
  481.     for (;;)
  482.         if (strcmp(p1->string, p2->string) < 0) {
  483.         *headpp = p1;
  484.         headpp = &p1->next;
  485.         p1 = *headpp;
  486.         if (p1 == NULL) {
  487.             *headpp = p2;
  488.             break;
  489.         }
  490.         }
  491.         else {
  492.         *headpp = p2;
  493.         headpp = &p2->next;
  494.         p2 = *headpp;
  495.         if (p2 == NULL) {
  496.             *headpp = p1;
  497.             break;
  498.         }
  499.         }
  500.  
  501.     return answer;
  502. }
  503.  
  504. /*
  505.  *    This reads the main file, "instr.set".
  506.  */
  507.  
  508. void
  509. read_is(FILE *f1)
  510. {
  511.     int    i;
  512.  
  513.     entertable(0x0f, OPTWOBYTE, SPARSE_BASE);
  514.     entertable(0x26, OPPREFIX, PRESEG | (0 << 8));    /* seg es */
  515.     entertable(0x2e, OPPREFIX, PRESEG | (1 << 8));    /* seg cs */
  516.     entertable(0x36, OPPREFIX, PRESEG | (2 << 8));    /* seg ss */
  517.     entertable(0x3e, OPPREFIX, PRESEG | (3 << 8));    /* seg ds */
  518.     entertable(0x64, OPPREFIX, PRESEG | (4 << 8));    /* seg fs */
  519.     entertable(0x65, OPPREFIX, PRESEG | (5 << 8));    /* seg gs */
  520.     entertable(0xf2, OPPREFIX, PREREP);        /* other prefixes */
  521.     entertable(0xf3, OPPREFIX, PREREP);
  522.     entertable(0xf0, OPPREFIX, PRELOCK);
  523.     entertable(0x66, OPPREFIX, PRE32D);
  524.     entertable(0x67, OPPREFIX, PRE32A);
  525.     opmach[0x64] = opmach[0x65] = opmach[0x66] = opmach[0x67] = 3;
  526.     
  527.     for (i = 0; i < NUMBER(grouptab); ++i)
  528.         entertable(grouptab[i].seq, OPGROUP, grouptab[i].info);
  529.     for (i = 0; i < NUMBER(sp_grouptab); ++i)
  530.         entertable(sp_grouptab[i].seq, OPGROUP, sp_grouptab[i].info);
  531.     for (i = 0; i < 8; ++i)
  532.         entertable(0xd8 + i, OPCOPR, COPR(i));
  533.     for (i = 0; i < NUMBER(fpgrouptab); ++i) {
  534.         unsigned int j = fpgrouptab[i];
  535.         unsigned int k = (j >> 8) - 0xd8;
  536.  
  537.         if (k > 8 || (j & 0xff) < 0xc0)
  538.         fail("Bad value for fpgrouptab[%d]", i);
  539.         entertable(COPR(k) + 8 + (((j & 0xff) - 0xc0) >> 3),
  540.         OPFPGROUP, FPGROUP(i));
  541.     }
  542.     for (i = 0; i < NUMBER(sp_fpgrouptab); ++i) {
  543.         unsigned int j = sp_fpgrouptab[i];
  544.         unsigned int k = (j >> 8) - 0xd8;
  545.  
  546.         if (k > 8 || (j & 0xff) < 0xc0)
  547.         fail("Bad value for sp_fpgrouptab[%d]", i);
  548.         entertable(COPR(k) + 8 + (((j & 0xff) - 0xc0) >> 3),
  549.         OPFPGROUP, SFPGROUP(i));
  550.     }
  551.     while (getline(f1)) {    /* loop over lines in the file */
  552.         int mnem;
  553.         int mn_alt;
  554.         char *p, *p0, *pslash, *pstar;
  555.         Boolean asm_only_line;
  556.         unsigned char atab_addendum;
  557.  
  558.         asm_only_line = False;
  559.         p0 = line;
  560.         if (line[0] == '_') {
  561.         asm_only_line = True;
  562.         ++p0;
  563.         }
  564.         atab_addendum = '\0';
  565.         if (*p0 == '^') {
  566.         static    const    unsigned char    uptab[]    =
  567.                     {ASM_AAX, ASM_DB, ASM_DW,
  568.                      ASM_DD, ASM_ORG, ASM_D32};
  569.  
  570.         ++p0;
  571.         atab_addendum = uptab[*p0++ - '0'];
  572.         }
  573.         p = strchr(p0, ' ');
  574.         if (p == NULL) p = p0 + strlen(p0);
  575.         pslash = memchr(p0, '/', p - p0);
  576.         if (pslash != NULL) {
  577.         mnem = entermn(p0, pslash);
  578.         ++mnlist[mnem].asmoffset;    /* this one isn't 32 bit */
  579.         ++pslash;
  580.         mn_alt = entermn(pslash, p);
  581.         add_to_asmtab(ASM_D32);
  582.         }
  583.         else {
  584.         pstar = memchr(p0, '*', p - p0);
  585.         if (pstar != NULL) {
  586.             mn_alt = entermn(p0, pstar);    /* note the reversal */
  587.             ++pstar;
  588.             add_to_asmtab(ASM_WAIT);
  589.             mnem = entermn(pstar, p);
  590.         }
  591.         else
  592.             mnem = entermn(p0, p);
  593.         }
  594.         if (atab_addendum != '\0') add_to_asmtab(atab_addendum);
  595.  
  596.         atab_addendum = ASM_END;
  597.         bzero(ordsmall, n_keys * sizeof(Boolean));
  598.         while (*p == ' ') {        /* loop over instruction variants */
  599.         Boolean        lockable;
  600.         Boolean        asm_only;
  601.         Boolean        dis_only;
  602.         unsigned char    machine;
  603.         unsigned long    atab_inf;
  604.         unsigned short    atab_key;
  605.         unsigned char    atab_xtra    = 0;
  606.  
  607.         while (*p == ' ') ++p;
  608.         asm_only = asm_only_line;
  609.         dis_only = False;
  610.         if (*p == '_') {    /* if assembler only */
  611.             ++p;
  612.             asm_only = True;
  613.         }
  614.         else if (*p == 'D') {    /* if disassembler only */
  615.             ++p;
  616.             dis_only = True;
  617.         }
  618.         lockable = False;
  619.         if (*p == 'L') {
  620.             ++p;
  621.             lockable = True;
  622.             add_to_asmtab(ASM_LOCKABLE);
  623.         }
  624.         atab_inf = i = getbyte(&p);
  625.         if (i == 0x0f) {
  626.             i = getbyte(&p);
  627.             atab_inf = 256 + i;
  628.             i += SPARSE_BASE;
  629.         }
  630.         if (optype[i] == OPGROUP) {
  631.             int j = getslash(&p);
  632.             int k;
  633.  
  634.             for (k = 0;; ++k) {
  635.             if (k >= n_agroups) {
  636.                 if (++n_agroups > MAX_AGROUP_ENTRIES)
  637.                 linenofail("Too many agroup entries");
  638.                 agroup_i[k] = i;
  639.                 agroup_inf[k] = atab_inf;
  640.                 break;
  641.             }
  642.             if (agroup_i[k] == i)
  643.                 break;
  644.             }
  645.             atab_inf = 256 + 256 + 64 + 8 * k + j;
  646.             i = opinfo[i] + j;
  647.         }
  648.         if (optype[i] == OPCOPR) {
  649.             if (*p == '/') {
  650.             int    j    = getslash(&p);
  651.  
  652.             atab_inf = 256 + 256 + j * 8 + (i - 0xd8);
  653.             i = opinfo[i] + j;
  654.             }
  655.             else {
  656.             atab_xtra = getbyte(&p);
  657.             if (atab_xtra < 0xc0)
  658.                 linenofail("Bad second escape byte");
  659.             i = opinfo[i] + 8 + ((atab_xtra - 0xc0) >> 3);
  660.             if (optype[i] == OPFPGROUP)
  661.                 i = opinfo[i] + (atab_xtra & 7);
  662.             }
  663.         }
  664.         switch (*p++) {
  665.             case '.':
  666.             machine = getmachine(&p);
  667.             if (!asm_only) {
  668.                 entertable(i, OPSIMPLE, mnem);
  669.                 opmach[i] = machine;
  670.             }
  671.             atab_key = 0;
  672.             /* none of these are lockable */
  673.             break;
  674.             case '*':    /* lock or rep... prefix */
  675.             add_to_asmtab(ASM_LOCKREP);
  676.             add_to_asmtab(atab_inf);    /* special case */
  677.             atab_addendum = '\0';
  678.             break;
  679.             case '&':    /* segment prefix */
  680.             add_to_asmtab(ASM_SEG);
  681.             add_to_asmtab(atab_inf);    /* special case */
  682.             atab_addendum = '\0';
  683.             break;
  684.             case ':': {
  685.                 struct keytab *kp = lookupkey(getkey(&p));
  686.                 int width = kp->width;
  687.                 int j;
  688.  
  689.                 machine = getmachine(&p);
  690.                 if (dis_only)
  691.                 atab_addendum = '\0';
  692.                 else {
  693.                 if (ordsmall[kp - olkeydict])
  694.                     linenofail("Variants out of order.");
  695.                 marksmall(kp);
  696.                 }
  697.                 atab_key = kp->value + 1;
  698.                 if ((i >= 256 && i < SPARSE_BASE)
  699.                     || i >= SPARSE_BASE + 256) {
  700.                 if (width > 2)
  701.                     linenofail("width failure");
  702.                 width = 1;
  703.                 }
  704.                 if (i & (width - 1))
  705.                 linenofail("width alignment failure");
  706.                 if (!asm_only)
  707.                 for (j = (i == 0x90); j < width; ++j) {
  708.                     /*    ^^^^^^^^^  kludge for NOP instr. */
  709.                     entertable(i|j, oloffset[kp->value], mnem);
  710.                     opmach[i | j] = machine;
  711.                     if (lockable) {
  712.                     if (n_locktab >= MAX_LOCKTAB_ENTRIES)
  713.                         linenofail("Too many lockable "
  714.                           "instructions");
  715.                     locktab[n_locktab] = i | j;
  716.                     ++n_locktab;
  717.                     }
  718.                 }
  719.             }
  720.             break;
  721.             default:
  722.             linenofail("Syntax error.");
  723.         }
  724.         if (atab_addendum != '\0') {
  725.             atab_inf = atab_inf * (unsigned short) (n_ol_types + 1)
  726.               + atab_key;
  727.             add_to_asmtab(atab_inf >> 8);
  728.             if ((atab_inf >> 8) >= ASM_MACH0)
  729.             fail("Assembler table is too busy");
  730.             add_to_asmtab(atab_inf);
  731.             if (atab_xtra != 0)
  732.             add_to_asmtab(atab_xtra);
  733.         }
  734.         if (pslash != NULL) {
  735.             if (n_slash_entries >= MAX_SLASH_ENTRIES)
  736.             linenofail("Too many slash entries");
  737.             slashtab_seq[n_slash_entries] = i;
  738.             slashtab_mn[n_slash_entries] = mn_alt;
  739.             ++n_slash_entries;
  740.         }
  741.         else if (pstar != NULL) {
  742.             if (n_star_entries >= MAX_STAR_ENTRIES)
  743.             linenofail("Too many star entries");
  744.             startab_seq[n_star_entries] = i;
  745.             startab_mn[n_star_entries] = mn_alt;
  746.             ++n_star_entries;
  747.         }
  748.         }
  749.         if (*p != '\0')
  750.         linenofail("Syntax error.");
  751.         if (atab_addendum != '\0')
  752.         add_to_asmtab(atab_addendum);    /* ASM_END, if applicable */
  753.     }
  754. }
  755.  
  756. /*
  757.  *    Print everything onto the file.
  758.  */
  759.  
  760. struct inforec {    /* strings to put into comment fields */
  761.     int    seqno;
  762.     char    *string;
  763. }
  764.     tblcomments[] = {
  765.         {0, "main opcode part"},
  766.         {GROUP(1), "Intel group 1"},
  767.         {GROUP(3), "Intel group 2"},
  768.         {GROUP(5), "Intel group 2a"},
  769.         {GROUP(6), "Intel group 3"},
  770.         {GROUP(7), "Intel group 5"},
  771.         {GROUP(8), "Intel group 6"},
  772.         {GROUP(9), "Intel group 7"},
  773.         {COPR(0), "Coprocessor d8"},
  774.         {COPR(1), "Coprocessor d9"},
  775.         {COPR(2), "Coprocessor da"},
  776.         {COPR(3), "Coprocessor db"},
  777.         {COPR(4), "Coprocessor dc"},
  778.         {COPR(5), "Coprocessor dd"},
  779.         {COPR(6), "Coprocessor de"},
  780.         {COPR(7), "Coprocessor df"},
  781.         {FPGROUP(0), "Coprocessor groups"},
  782.         {-1, NULL}};
  783.  
  784. void
  785. put_dw(FILE *f2, const char *label, int *datap, int n)
  786. {
  787.     const char    *initstr;
  788.     int        i;
  789.  
  790.     fputs(label,f2);
  791.     while (n > 0) {
  792.         initstr = "\tdw\t";
  793.         for (i = (n <= 8 ? n : 8); i > 0; --i) {
  794.         fputs(initstr, f2);
  795.         initstr = ",";
  796.         fprintf(f2, "%5d", *datap++);
  797.         }
  798.         fputs(CRLF, f2);
  799.         n -= 8;
  800.     }
  801. }
  802.  
  803. void
  804. dumptables(FILE *f2)
  805. {
  806.     int        offset;
  807.     struct mnrec    *mnp;
  808.     int        colsleft;
  809.     char        *auxstr;
  810.     struct inforec    *tblptr;
  811.     int        i;
  812.     int        j;
  813.     int        k;
  814.  
  815.     /*
  816.      * Dump out asmtab.
  817.      */
  818.  
  819.     auxstr = CRLF ";\tMain data table for the assembler." CRLF CRLF
  820.       "asmtab\tdb\t";
  821.     colsleft = 16;
  822.     for (i = 0; i < n_asm_tab; ++i) {
  823.         fprintf(f2, "%s%d", auxstr, asmtab[i]);
  824.         auxstr = ",";
  825.         if (--colsleft <= 0) {
  826.         auxstr = CRLF "\tdb\t";
  827.         colsleft = 16;
  828.         }
  829.     }
  830.  
  831.     /*
  832.      * Dump out agroup_inf.
  833.      */
  834.  
  835.     auxstr = CRLF CRLF ";\tData on groups (for the assembler)." CRLF CRLF
  836.       "agroups\tdw\t";
  837.     for (i = 0; i < n_agroups; ++i) {
  838.         fprintf(f2, "%s%d", auxstr, agroup_inf[i]);
  839.         auxstr = ",";
  840.     }
  841.  
  842.     /*
  843.      * Sort the mnemonics alphabetically, compute their offsets,
  844.      * and print out the table.
  845.      */
  846.  
  847.     if (num_mnrecs == 0)
  848.         fail("No assembler mnemonics!");
  849.     mnhead = mn_sort(mnlist, num_mnrecs);
  850.     offset = 0;
  851.     auxstr = CRLF CRLF ";\tThis is the list of assembler mnemonics." CRLF
  852.       CRLF "mnlist\tdb\t";
  853.     colsleft = 80 - 15;
  854.     for (mnp = mnhead; mnp != NULL; mnp = mnp->next) {
  855.         mnp->offset = offset + 2;
  856.         offset += mnp->len + 3;
  857.         if (colsleft < mnp->len + 13) {
  858.         auxstr = CRLF "\tdb\t";
  859.         colsleft = 80 - 15;
  860.         }
  861.         colsleft -= mnp->len + 13;
  862.         fprintf(f2, "%s%d,%d,\"%s\",0", auxstr, mnp->asmoffset / 255 + 1,
  863.         mnp->asmoffset % 255 + 1, mnp->string);
  864.         auxstr = ",";
  865.     }
  866.     fputs(CRLF "end_mnlist db" CRLF, f2);
  867.     if (offset >= (1 << MSHIFT)) {
  868.         fprintf(stderr, "%d bytes of mnemonics.  That's too many.\n",
  869.         offset);
  870.         exit(1);
  871.     }
  872.  
  873.     /*
  874.      * Print out mnemonics we want to refer to.
  875.      */
  876.  
  877.     fputs(CRLF ";\tThese are equates to refer to the above mnemonics."
  878.         CRLF CRLF, f2);
  879.     for (i = 0; i < n_saved_mnems; ++i) {
  880.         mnp = mnlist + saved_mnem[i];
  881.         fprintf(f2, "MNEM_%s\tEQU\t%d" CRLF, mnp->string, mnp->offset);
  882.     }
  883.  
  884.     /*
  885.      * Print out ASMMOD and the opindex array.
  886.      */
  887.  
  888.     fprintf(f2, CRLF ";\tNumber of entries in the following array." CRLF
  889.       CRLF "ASMMOD\tEQU\t%d" CRLF, n_ol_types + 1);
  890.  
  891.     auxstr = CRLF ";\tThis is an array of indices into the oplists array "
  892.       "(below)." CRLF
  893.       ";\tIt is used by the assembler to save space." CRLF CRLF
  894.       "opindex\tdb\t0,";
  895.     colsleft = 16;
  896.     for (i = 0; i < n_ol_types; ++i) {
  897.         fprintf(f2, "%s%d", auxstr, oloffset[i] - OPTYPES);
  898.         auxstr = ",";
  899.         if (--colsleft <= 0) {
  900.         auxstr = CRLF "\tdb\t";
  901.         colsleft = 16;
  902.         }
  903.     }
  904.  
  905.     /*
  906.      * Print out oplists[]
  907.      */
  908.  
  909.     fputs(CRLF CRLF ";\tThese are the lists of operands "
  910.         "for the various instruction types." CRLF CRLF
  911.         "oplists\tdb\t0\t;simple instruction" CRLF, f2);
  912.     for (i = 0; i < n_ol_types; ++i)
  913.         fprintf(f2, "\tdb\t%s, 0" CRLF, olnames[i]);
  914.     fprintf(f2, CRLF "OPTYPES_BASE\tEQU\t%d" CRLF, OPTYPES);
  915.     fprintf(f2, CRLF "OPLIST_Z\tEQU\t%d" CRLF,
  916.         oloffset[lookupkey('z')->value]);
  917.     fprintf(f2, "OPLIST_ES\tEQU\t%d" CRLF,
  918.         oloffset[lookupkey(('E' << 8) | 'S')->value]);
  919.  
  920.     /*
  921.      * Print out optype[]
  922.      */
  923.  
  924.     auxstr = CRLF ";\tHere is the compressed table of the opcode types."
  925.         CRLF CRLF "optypes\tdb\t";
  926.     tblptr = tblcomments;
  927.  
  928.     for (i = 0; i < SPARSE_BASE; i += 8) {
  929.         for (j = 0; j < 8; ++j) {
  930.         fputs(auxstr, f2);
  931.         fprintf(f2, "%3d", optype[i + j]);
  932.         auxstr = ",";
  933.         }
  934.         fprintf(f2, "\t; %02x - %02x", i, i + 7);
  935.         if (i == tblptr->seqno)
  936.         fprintf(f2, " (%s)", (tblptr++)->string);
  937.         auxstr = CRLF "\tdb\t";
  938.     }
  939.     auxstr = CRLF ";\tThe rest of these are squeezed." CRLF "\tdb\t 0,";
  940.     colsleft = 7;
  941.     for (i = SPARSE_BASE; i < NOPS; ++i)
  942.         if ((j = optype[i]) != 0) {
  943.         if (--colsleft < 0) {
  944.             colsleft = 7;
  945.             auxstr = CRLF "\tdb\t";
  946.         }
  947.         fputs(auxstr, f2);
  948.         fprintf(f2, "%3d", j);
  949.         auxstr = ",";
  950.         }
  951.     fputs(CRLF, f2);
  952.  
  953.     /*
  954.      * Print out opinfo[]
  955.      */
  956.  
  957.     fputs(CRLF ";\tAnd here is the compressed table of additional "
  958.         "information." CRLF CRLF "opinfo", f2);
  959.  
  960.     for (i = 0; i < SPARSE_BASE; i += 8) {
  961.         auxstr = "\tdw\t";
  962.         for (j = 0; j < 8; ++j) {
  963.         fputs(auxstr, f2);
  964.         k = opinfo[i + j];
  965.         if (optype[i + j] >= OPTYPES)
  966.             k = mnlist[k].offset;
  967.         fprintf(f2, "0%04xh", k | (opmach[i + j] << MSHIFT));
  968.         auxstr = ",";
  969.         }
  970.         fprintf(f2, "\t; %02x" CRLF, i);
  971.     }
  972.     auxstr = ";\tThe rest of these are squeezed." CRLF "\tdw\t     0,";
  973.     colsleft = 7;
  974.     for (i = SPARSE_BASE; i < NOPS; ++i)
  975.         if ((j = optype[i]) != 0) {
  976.         if (--colsleft < 0) {
  977.             colsleft = 7;
  978.             auxstr = CRLF "\tdw\t";
  979.         }
  980.         fputs(auxstr, f2);
  981.         k = opinfo[i];
  982.         if (j >= OPTYPES) k = mnlist[k].offset;
  983.         fprintf(f2, "0%04xh", k | (opmach[i] << MSHIFT));
  984.         auxstr = ",";
  985.         }
  986.     fputs(CRLF, f2);
  987.  
  988.     /*
  989.      * Print out sqztab
  990.      */
  991.  
  992.     fputs(CRLF ";\tThis table converts unsqueezed numbers to squeezed."
  993.         CRLF CRLF "sqztab", f2);
  994.  
  995.     k = 0;
  996.     for (i = SPARSE_BASE; i < NOPS; i += 8) {
  997.         auxstr = "\tdb\t";
  998.         for (j = 0; j < 8; ++j) {
  999.         fprintf(f2, "%s%3d", auxstr, optype[i + j] == 0 ? 0 : ++k);
  1000.         auxstr = ",";
  1001.         }
  1002.         fputs(CRLF, f2);
  1003.     }
  1004.  
  1005.     /*
  1006.      * Print out the cleanup tables.
  1007.      */
  1008.  
  1009.     fputs(CRLF ";\tThis is the table of mnemonics that change in the "
  1010.         "presence of a WAIT" CRLF ";\tinstruction." CRLF CRLF, f2);
  1011.     put_dw(f2, "wtab1", startab_seq, n_star_entries);
  1012.     for (i = 0; i < n_star_entries; ++i)
  1013.         startab_mn[i] = mnlist[startab_mn[i]].offset;
  1014.     put_dw(f2, "wtab2", startab_mn, n_star_entries);
  1015.     fprintf(f2, "N_WTAB\tequ\t%d" CRLF, n_star_entries);
  1016.  
  1017.     fputs(CRLF ";\tThis is the table for operands which have a different "
  1018.         "mnemonic for" CRLF ";\ttheir 32 bit versions." CRLF CRLF, f2);
  1019.     put_dw(f2, "ltab1", slashtab_seq, n_slash_entries);
  1020.     for (i = 0; i < n_slash_entries; ++i)
  1021.         slashtab_mn[i] = mnlist[slashtab_mn[i]].offset;
  1022.     put_dw(f2, "ltab2", slashtab_mn, n_slash_entries);
  1023.     fprintf(f2, "N_LTAB\tequ\t%d" CRLF, n_slash_entries);
  1024.  
  1025.     fputs(CRLF ";\tThis is the table of lockable instructions" CRLF CRLF,
  1026.         f2);
  1027.     put_dw(f2, "locktab", locktab, n_locktab);
  1028.     fprintf(f2, "N_LOCK\tequ\t%d" CRLF, n_locktab);
  1029.  
  1030.     /*
  1031.      * Print out miscellaneous equates.
  1032.      */
  1033.  
  1034.     fprintf(f2, CRLF ";\tEquates used in the assembly-language code." CRLF
  1035.         CRLF "SPARSE_BASE\tequ\t%d" CRLF
  1036.         CRLF "SFPGROUP3\tequ\t%d" CRLF CRLF, SPARSE_BASE, SFPGROUP(3));
  1037. }
  1038.  
  1039. int cdecl
  1040. main() {
  1041.     FILE    *f1;
  1042.     FILE    *f2;
  1043.     int    offset;
  1044.  
  1045.     /*
  1046.      * Read in the key dictionary.
  1047.      */
  1048.  
  1049.     f1 = openread("instr.key");
  1050.     offset = OPTYPES + 1;
  1051.     while (getline(f1)) {
  1052.         char *p = line;
  1053.         int i;
  1054.  
  1055.         if (n_keys >= MAX_OL_TYPES)
  1056.         fail("Too many keys.");
  1057.         olkeydict[n_keys].key = getkey(&p);
  1058.         p = skipwhite(p);
  1059.         for (i = 0;; ++i) {
  1060.         if (i >= n_ol_types) {
  1061.             char *q = xmalloc(strlen(p) + 1, "operand type name");
  1062.  
  1063.             strcpy(q, p);
  1064.             if (n_ol_types >= MAX_OL_TYPES)
  1065.             fail("Too many operand list types.");
  1066.             olnames[n_ol_types] = q;
  1067.             oloffset[n_ol_types] = offset;
  1068.             for (;;) {
  1069.             ++offset;
  1070.             q = strchr(q, ',');
  1071.             if (q == NULL) break;
  1072.             ++q;
  1073.             }
  1074.             ++offset;
  1075.             ++n_ol_types;
  1076.         }
  1077.         if (strcmp(p, olnames[i]) == 0)
  1078.             break;
  1079.         }
  1080.         olkeydict[n_keys].value = i;
  1081.         olkeydict[n_keys].width = 1;
  1082.         if (strstr(p, "OP_ALL") != NULL)
  1083.         olkeydict[n_keys].width = 2;
  1084.         else if (strstr(p, "OP_R_ADD") != NULL)
  1085.         olkeydict[n_keys].width = 8;
  1086.         ++n_keys;
  1087.     }
  1088.     fclose(f1);
  1089.     if (offset >= 256) {
  1090.         fprintf(stderr, "%d bytes of operand lists.  That's too many.\n",
  1091.         offset);
  1092.         exit(1);
  1093.     }
  1094.  
  1095.     /*
  1096.      * Read in the ordering relations.
  1097.      */
  1098.  
  1099.     f1 = openread("instr.ord");
  1100.     while (getline(f1)) {
  1101.         char *p = line;
  1102.  
  1103.         if (n_ords >= MAX_N_ORDS)
  1104.         fail ("Too many ordering restrictions.");
  1105.         keyord1[n_ords] = lookupkey(getkey(&p));
  1106.         p = skipwhite(p);
  1107.         keyord2[n_ords] = lookupkey(getkey(&p));
  1108.         if (*p != '\0')
  1109.         fail("Syntax error in ordering file.");
  1110.         ++n_ords;
  1111.     }
  1112.     fclose(f1);
  1113.  
  1114.     /*
  1115.      * Do the main processing.
  1116.      */
  1117.  
  1118.     f1 = openread("instr.set");
  1119.     read_is(f1);
  1120.     fclose(f1);
  1121.  
  1122.     /*
  1123.      * Write the file.
  1124.      */
  1125.  
  1126.     f1 = openread("debug.a86");
  1127.     f2 = fopen("debug.tmp", "w");
  1128.     if (f2 == NULL) {
  1129.         perror("debug.tmp");
  1130.         exit(1);
  1131.     }
  1132.  
  1133.     do {
  1134.         if (fgets(line, LINELEN, f1) == NULL) {
  1135.         fputs("Couldn't find beginning marker line\n", stderr);
  1136.         exit(1);
  1137.         }
  1138.         fputs(line, f2);
  1139.     }
  1140.     while (strcmp(line, MARKLINE1) != 0);
  1141.  
  1142.     dumptables(f2);
  1143.  
  1144.     do {
  1145.         if (fgets(line, LINELEN, f1) == NULL) {
  1146.         fputs("Couldn't find ending marker line\n", stderr);
  1147.         exit(1);
  1148.         }
  1149.     }
  1150.     while (strcmp(line, MARKLINE2) != 0);
  1151.  
  1152.     do
  1153.         fputs(line, f2);
  1154.     while (fgets(line, LINELEN, f1) != NULL);
  1155.  
  1156.     fclose(f1);    
  1157.     fclose(f2);
  1158.  
  1159.     /*
  1160.      * Move the file to its original position.
  1161.      */
  1162.  
  1163. #if    DOS
  1164.     if (unlink("debug.old") == -1 && errno != ENOFILE) {
  1165.         perror("delete debug.old");
  1166.         return 1;
  1167.     }
  1168. #endif
  1169.     if (rename("debug.a86", "debug.old") == -1) {
  1170.         perror("rename debug.a86 -> debug.old");
  1171.         return 1;
  1172.     }
  1173.     if (rename("debug.tmp", "debug.a86") == -1) {
  1174.         perror("rename debug.tmp -> debug.a86");
  1175.         return 1;
  1176.     }
  1177.  
  1178.     puts("Done.");
  1179.  
  1180.     return 0;
  1181. }
  1182.