home *** CD-ROM | disk | FTP | other *** search
/ Power-Programmierung / CD1.mdf / magazine / drdobbs / 1986 / 12 / rodman.dec < prev    next >
Text File  |  1986-12-31  |  43KB  |  1,607 lines

  1. /* A32000.C - Series 32000 assembler
  2.    850903 rr fix addr ext, scaled index, acp, cxp 0.10
  3.    850902 rr add scaled index logic 0.09
  4.    850828 rr fix enter, setcfg, lpr/spr, index 0.08
  5.    850809 rr add equate logic 0.07
  6.    850730 rr add binary search in lookup 0.06
  7.    850729 rr symbol table mods, reglist 0.05
  8.  
  9. Still need:
  10.    --- register names for lpr/spr
  11.    --- linkable modules
  12.  
  13. Note: While 68000 is hilo (high-bytes at lower memory
  14.    addresses), 32000 is lohi (low-bytes at lower memory
  15.    addresses, like the Z80).
  16.  
  17.    This is a 3-pass assembler; 3 passes to make
  18.    sure that relative branches are computed correctly. */
  19.  
  20. #define EOF -1
  21.  
  22. #define SYMSIZ 1024     /* symbol table size */
  23.  
  24. char inpbuf[ 256 ];     /* input buffer */
  25. int inpcnt, inpptr;     /* input counter, pointer */
  26.  
  27. char word_buffer[ 128 ];     /* buff for current word */
  28. char ambig_buffer[ 128 ];    /* ambiguous refs here */
  29.  
  30. char listline[ 81 ];    /* line of listing output */
  31. int listop, listcp;     /* pointers for list output */
  32.  
  33. int paren = 0;          /* used in gchar() */
  34. int brack = 0;
  35. int quote = 0;
  36.  
  37. int iwparen = 0;        /* used in inword() */
  38.  
  39. int errors = 0;         /* count of errors */
  40.  
  41. char *word;             /* pointer to current word */
  42. char *ambig[ 10 ];      /* filled in by match */
  43. int ambcnt = 0;         /* count of pointers in ambig[] */
  44.  
  45. int pass;               /* pass = 1, 2 or 3 */
  46. long int asmadr, codadr; /* assembly addr, code addr */
  47. char filename[ 30 ];
  48.  
  49. int fasm, fobj;         /* file numbers */
  50.  
  51. char objbuf[ 64 ];      /* object byte buffer */
  52. long int objadr;        /* addr of first byte of buf */
  53. int objcnt = 0;         /* count of bytes in buffer */
  54.  
  55. struct {                /* Symbol table */
  56.    char *snam;          /* symbol name */
  57.    long int sval;       /* value */
  58. } symbol[ SYMSIZ ];
  59.  
  60. int symcnt;             /* count of symbols */
  61.  
  62. char hexchr[ 17 ] = "0123456789abcdef";
  63.  
  64. /* --- 32000 opcodes --- */
  65.  
  66. /* Note: Shortest form of opcode must be listed first. */
  67.  
  68. #define MAXOP 149
  69.  
  70. /* the opcode binary value should be a string of bits,
  71.    e.g. 0111xxxxx000b the opcode opopt character is used
  72.    to specify special operands, etc. */
  73.  
  74. /* opopts used here for the 32000 are:
  75.    blank      nothing special
  76.    a    gen
  77.    b    gen short
  78.    c    gen gen
  79.    d    00000 short
  80.    e    gen gen reg
  81.    f    reglist save/enter
  82.    g    reglist restore/exit
  83.    h    00000 gen (sfsr)
  84.    i    inss/exts
  85.    j    movs/skps/cmps
  86.    k    setcfg
  87.    l    procreg, gen for lpr/spr
  88.    m    index (operand order)
  89.    n    ret/rett - postbyte
  90.    o    movm
  91.    p    cxp (disp after instruction) */
  92.  
  93. struct {
  94.    char *onam;  /* opcode name */
  95.    int ocnt;    /* operand count, negative if PC-rel */
  96.    char *obin;  /* opcode binary value */
  97.    char oopt;   /* opcode opopt char */
  98. } opcode[ MAXOP ] = {
  99.  
  100. /* Format 1 ops (16) */
  101.  
  102.    "bsr",      -1,  "02h",   ' ',
  103.    "ret",      1,   "12h",   'n',
  104.    "cxp",      1,   "22h",   'p',
  105.    "rxp",      1,   "32h",   'n',
  106.    "rett",     1,   "42h",   'n',
  107.    "reti",     0,   "52h",   ' ',
  108.    "save",     1,   "62h",   'f',
  109.    "restore",  1,   "72h",   'g',
  110.    "enter",    2,   "82h",   'f',
  111.    "exit",     1,   "92h",   'g',
  112.    "nop",      0,   "0a2h",  ' ',
  113.    "wait",     0,   "0b2h",  ' ',
  114.    "dia",      0,   "0c2h",  ' ',
  115.    "flag",     0,   "0d2h",  ' ',
  116.    "svc",      0,   "0e2h",  ' ',
  117.    "bpt",      0,   "0f2h",  ' ',
  118.  
  119. /* Conditional branches (15) */
  120.  
  121.    "beq",      -1,   "0ah",   'b',
  122.    "bne",      -1,   "1ah",   'b',
  123.    "bcs",      -1,   "2ah",   'b',
  124.    "bcc",      -1,   "3ah",   'b',
  125.    "bhi",      -1,   "4ah",   'b',
  126.    "bls",      -1,   "5ah",   'b',
  127.    "bgt",      -1,   "6ah",   'b',
  128.    "ble",      -1,   "7ah",   'b',
  129.    "bfs",      -1,   "8ah",   'b',
  130.    "bfc",      -1,   "9ah",   'b',
  131.    "blo",      -1,   "0aah",  'b',
  132.    "bhs",      -1,   "0bah",  'b',
  133.    "blt",      -1,   "0cah",  'b',
  134.    "bge",      -1,   "0dah",  'b',
  135.    "br",       -1,   "0eah",  'b',
  136.  
  137. /* Format 2 ops (7) */
  138.  
  139.    "addq?",     2,   "xxxxxxxxx00011iib",   'e',
  140.    "cmpq?",     2,   "xxxxxxxxx00111iib",   'e',
  141.    "spr?",      2,   "xxxxxxxxx01011iib",   'l',
  142.    "lpr?",      2,   "xxxxxxxxx11011iib",   'l',
  143.  
  144.    "seq?",      1,   "xxxxx000001111iib",   'a',
  145.    "sne?",      1,   "xxxxx000101111iib",   'a',
  146.    "scs?",      1,   "xxxxx001001111iib",   'a',
  147.    "scc?",      1,   "xxxxx001101111iib",   'a',
  148.    "shi?",      1,   "xxxxx010001111iib",   'a',
  149.    "sls?",      1,   "xxxxx010101111iib",   'a',
  150.    "sgt?",      1,   "xxxxx011001111iib",   'a',
  151.    "sle?",      1,   "xxxxx011101111iib",   'a',
  152.    "sfs?",      1,   "xxxxx100001111iib",   'a',
  153.    "sfc?",      1,   "xxxxx100101111iib",   'a',
  154.    "slo?",      1,   "xxxxx101001111iib",   'a',
  155.    "shs?",      1,   "xxxxx101101111iib",   'a',
  156.    "slt?",      1,   "xxxxx110001111iib",   'a',
  157.    "sge?",      1,   "xxxxx110101111iib",   'a',
  158.    "st?",       1,   "xxxxx111001111iib",   'a',
  159.    "sf?",       1,   "xxxxx111101111iib",   'a',
  160.  
  161. /* The acb instruction 3rd operand is a relative jump */
  162.  
  163.    "acb?",      -3,   "xxxxxxxxx10011iib",   'e',
  164.    "movq?",     2,   "xxxxxxxxx10111iib",   'e',
  165.  
  166. /* Format 3 instructions (7) */
  167.  
  168.    "cxpd",      1,   "xxxxx00001111111b",   'a',
  169.    "bicpsr?",   1,   "xxxxx001011111iib",   'a',
  170.    "jump",      1,   "xxxxx01001111111b",   'a',
  171.    "bispsr?",   1,   "xxxxx011011111iib",   'a',
  172.    "adjsp?",    1,   "xxxxx101011111iib",   'a',
  173.    "jsr",       1,   "xxxxx11001111111b",   'a',
  174.    "case?",     1,   "xxxxx111011111iib",   'a',
  175.  
  176. /* Format 11 ops (16) - 
  177.    moved here so wildcards won't interfere */
  178.  
  179.    "addf",      2,   "xxxxxxxxxx00000110111110b",   'c',
  180.    "addl",      2,   "xxxxxxxxxx00000010111110b",   'c',
  181.    "movf",      2,   "xxxxxxxxxx00010110111110b",   'c',
  182.    "movl",      2,   "xxxxxxxxxx00010010111110b",   'c',
  183.    "cmpf",      2,   "xxxxxxxxxx00100110111110b",   'c',
  184.    "cmpl",      2,   "xxxxxxxxxx00100010111110b",   'c',
  185.    "subf",      2,   "xxxxxxxxxx01000110111110b",   'c',
  186.    "subl",      2,   "xxxxxxxxxx01000010111110b",   'c',
  187.    "negf",      2,   "xxxxxxxxxx01010110111110b",   'c',
  188.    "negl",      2,   "xxxxxxxxxx01010010111110b",   'c',
  189.    "divf",      2,   "xxxxxxxxxx10000110111110b",   'c',
  190.    "divl",      2,   "xxxxxxxxxx10000010111110b",   'c',
  191.    "mulf",      2,   "xxxxxxxxxx11000110111110b",   'c',
  192.    "mull",      2,   "xxxxxxxxxx11000010111110b",   'c',
  193.    "absf",      2,   "xxxxxxxxxx11010110111110b",   'c',
  194.    "absl",      2,   "xxxxxxxxxx11010010111110b",   'c',
  195.  
  196. /* Format 4 instructions (12) */
  197.  
  198.    "add?",      2,   "xxxxxxxxxx0000iib",   'c',
  199.    "cmp?",      2,   "xxxxxxxxxx0001iib",   'c',
  200.    "bic?",      2,   "xxxxxxxxxx0010iib",   'c',
  201.    "addc?",     2,   "xxxxxxxxxx0100iib",   'c',
  202.    "mov?",      2,   "xxxxxxxxxx0101iib",   'c',
  203.    "or?",       2,   "xxxxxxxxxx0110iib",   'c',
  204.    "sub?",      2,   "xxxxxxxxxx1000iib",   'c',
  205.    "addr",      2,   "xxxxxxxxxx100111b",   'c',
  206.    "lxpd",      2,   "xxxxxxxxxx100111b",   'c',
  207.    "and?",      2,   "xxxxxxxxxx1010iib",   'c',
  208.    "subc?",     2,   "xxxxxxxxxx1100iib",   'c',
  209.    "tbit?",     2,   "xxxxxxxxxx1101iib",   'c',
  210.    "xor?",      2,   "xxxxxxxxxx1110iib",   'c',
  211.  
  212. /* Format 5 instructions (4) */
  213.  
  214.    "movst",     1,   "00000xxx100000ii00001110b",   'j',
  215.    "movs?",     1,   "00000xxx000000ii00001110b",   'j',
  216.    "cmpst",     1,   "00000xxx100001ii00001110b",   'j',
  217.    "cmps?",     1,   "00000xxx000001ii00001110b",   'j',
  218.    "skpst",     1,   "00000xxx100011ii00001110b",   'j',
  219.    "skps?",     1,   "00000xxx000011ii00001110b",   'j',
  220.  
  221.    "setcfg",    1,   "00000xxxx000101100001110b",   'k',
  222.  
  223. /* Format 6 ops (14) */
  224.  
  225.    "rot?",      2,   "xxxxxxxxxx0000ii01001110b",   'c',
  226.    "ash?",      2,   "xxxxxxxxxx0001ii01001110b",   'c',
  227.    "cbit?",     2,   "xxxxxxxxxx0010ii01001110b",   'c',
  228.    "cbiti?",    2,   "xxxxxxxxxx0011ii01001110b",   'c',
  229.    "lsh?",      2,   "xxxxxxxxxx0101ii01001110b",   'c',
  230.    "sbit?",     2,   "xxxxxxxxxx0110ii01001110b",   'c',
  231.    "sbiti?",    2,   "xxxxxxxxxx0111ii01001110b",   'c',
  232.    "neg?",      2,   "xxxxxxxxxx1000ii01001110b",   'c',
  233.    "not?",      2,   "xxxxxxxxxx1001ii01001110b",   'c',
  234.    "subp?",     2,   "xxxxxxxxxx1011ii01001110b",   'c',
  235.    "abs?",      2,   "xxxxxxxxxx1100ii01001110b",   'c',
  236.    "com?",      2,   "xxxxxxxxxx1101ii01001110b",   'c',
  237.    "ibit?",     2,   "xxxxxxxxxx1110ii01001110b",   'c',
  238.    "addp?",     2,   "xxxxxxxxxx1111ii01001110b",   'c',
  239.  
  240. /* Format 7 ops (15) */
  241.  
  242.    "movm?",     3,   "xxxxxxxxxx0000ii11001110b",   'o',
  243.    "cmpm?",     2,   "xxxxxxxxxx0001ii11001110b",   'c',
  244.    "inss?",     4,   "xxxxxxxxxx0010ii11001110b",   'i',
  245.    "exts?",     4,   "xxxxxxxxxx0011ii11001110b",   'i',
  246.    "movxbw?",   2,   "xxxxxxxxxx0100ii11001110b",   'c',
  247.    "movzbw?",   2,   "xxxxxxxxxx0101ii11001110b",   'c',
  248.    "movz?d",    2,   "xxxxxxxxxx0110ii11001110b",   'c',
  249.    "movx?d",    2,   "xxxxxxxxxx0111ii11001110b",   'c',
  250.    "mul?",      2,   "xxxxxxxxxx1000ii11001110b",   'c',
  251.    "mei?",      2,   "xxxxxxxxxx1001ii11001110b",   'c',
  252.    "dei?",      2,   "xxxxxxxxxx1011ii11001110b",   'c',
  253.    "quo?",      2,   "xxxxxxxxxx1100ii11001110b",   'c',
  254.    "rem?",      2,   "xxxxxxxxxx1101ii11001110b",   'c',
  255.    "mod?",      2,   "xxxxxxxxxx1110ii11001110b",   'c',
  256.    "div?",      2,   "xxxxxxxxxx1111ii11001110b",   'c',
  257.  
  258. /* Format 8 ops (8) */
  259.  
  260.    "ext?",      4,   "xxxxxxxxxxxxx0ii00101110b",   'm',
  261.    "cvtp",      3,   "xxxxxxxxxxxxx01101101110b",   'm',
  262.    "ins?",      4,   "xxxxxxxxxxxxx0ii10101110b",   'm',
  263.    "check?",    3,   "xxxxxxxxxxxxx0ii11101110b",   'm',
  264.    "index?",    3,   "xxxxxxxxxxxxx1ii00101110b",   'm',
  265.    "ffs?",      2,   "xxxxxxxxxx0001ii01101110b",   'c',
  266.    "movsu?",    2,   "xxxxxxxxxx0011ii10101110b",   'c',
  267.    "movus?",    2,   "xxxxxxxxxx0111ii10101110b",   'c',
  268.  
  269. /* Format 9 ops (12) */
  270.  
  271.    "movlf",     2,   "xxxxxxxxxx0101ii00111110b",   'c',
  272.    "movfl",     2,   "xxxxxxxxxx0111ii00111110b",   'c',
  273.    "mov?f",     2,   "xxxxxxxxxx0001ii00111110b",   'c',
  274.    "mov?l",     2,   "xxxxxxxxxx0000ii00111110b",   'c',
  275.    "lfsr",      1,   "xxxxx0000000111100111110b",   'a',
  276.    "sfsr",      1,   "00000xxxxx11011100111110b",   'h',
  277.    "roundf?",   2,   "xxxxxxxxxx1001ii00111110b",   'c',
  278.    "roundl?",   2,   "xxxxxxxxxx1000ii00111110b",   'c',
  279.    "truncf?",   2,   "xxxxxxxxxx1011ii00111110b",   'c',
  280.    "truncl?",   2,   "xxxxxxxxxx1010ii00111110b",   'c',
  281.    "floorf?",   2,   "xxxxxxxxxx1111ii00111110b",   'c',
  282.    "floorl?",   2,   "xxxxxxxxxx1110ii00111110b",   'c',
  283.  
  284. /* Format 14 instructions (4) */
  285.  
  286.    "rdval",     1,   "xxxxxxxxx000001100011110b",   'a',
  287.    "wrval",     1,   "xxxxxxxxx000011100011110b",   'a',
  288.    "lmr",       2,   "xxxxxxxxx000101100011110b",   'e',
  289.    "smr",       2,   "xxxxxxxxx000111100011110b",   'e'
  290. };
  291.  
  292.    /* Address Mode Table */
  293.  
  294. #define MAXAM 42
  295.  
  296. struct {
  297.    char *mstr;  /* mode match string */
  298.    char *gstr;  /* output string to insert (gen) */
  299.    int mcnt;    /* count of ambigs to be put into
  300.                extension bytes */
  301.    char mopt;   /* mode option */
  302. } admode[ MAXAM ] = {
  303.  
  304. /* Scaled index modes */
  305.  
  306.    "*[r?:b]",   "11100",   1,   's',
  307.    "*[r?:w]",   "11101",   1,   's',
  308.    "*[r?:d]",   "11110",   1,   's',
  309.    "*[r?:q]",   "11111",   1,   's',
  310.  
  311. /* Simple register modes */
  312.  
  313.    "r0",   "00000",   0,   ' ',   /* main registers */
  314.    "r1",   "00001",   0,   ' ',
  315.    "r2",   "00010",   0,   ' ',
  316.    "r3",   "00011",   0,   ' ',
  317.    "r4",   "00100",   0,   ' ',
  318.    "r5",   "00101",   0,   ' ',
  319.    "r6",   "00110",   0,   ' ',
  320.    "r7",   "00111",   0,   ' ',
  321.  
  322.    "f0",   "00000",   0,   ' ',   /* floating point */
  323.    "f1",   "00001",   0,   ' ',
  324.    "f2",   "00010",   0,   ' ',
  325.    "f3",   "00011",   0,   ' ',
  326.    "f4",   "00100",   0,   ' ',
  327.    "f5",   "00101",   0,   ' ',
  328.    "f6",   "00110",   0,   ' ',
  329.    "f7",   "00111",   0,   ' ',
  330.  
  331. /* Indexed addressing modes */
  332.  
  333.    "*(r0)",   "01000",   1,   ' ',   /* indexed */
  334.    "*(r1)",   "01001",   1,   ' ',
  335.    "*(r2)",   "01010",   1,   ' ',
  336.    "*(r3)",   "01011",   1,   ' ',
  337.    "*(r4)",   "01100",   1,   ' ',
  338.    "*(r5)",   "01101",   1,   ' ',
  339.    "*(r6)",   "01110",   1,   ' ',
  340.    "*(r7)",   "01111",   1,   ' ',
  341.  
  342.    "*(*(fp))",  "10000",   2,   'r',   /* frame ptr */
  343.    "*(*(sp))",  "10001",   2,   'r',   /* stack mem */
  344.    "*(*(sb))",  "10010",   2,   'r',   /* static mem */
  345.  
  346.    "#*",        "10100",   1,   ' ',   /* immediate */
  347.    "@*",        "10101",   1,   ' ',   /* absolute */
  348.    "ext(*)+*",  "10110",   2,   ' ',   /* external */
  349.    "tos",       "10111",   0,   ' ',   /* top of stack */
  350.  
  351.    "*(fp)",     "11000",   1,   ' ',   /* frame mem */
  352.    "*(sp)",     "11001",   1,   ' ',   /* stack mem */
  353.    "*(sb)",     "11010",   1,   ' ',   /* static mem */
  354.  
  355.    ".+*",       "11011",   1,   ' ',   /* program mem */
  356.  
  357.    "[*]",       "",   0,   'l',   /* register list */
  358.  
  359. /* catch-all */
  360.  
  361.    "*",   "",   1,   'w' /* fits no pattern */
  362. };
  363.  
  364. /*---MAIN PROGRAM---*/
  365.  
  366. main( argc, argv )
  367. int argc;
  368. char *argv[];
  369. {
  370.    int i;
  371.  
  372.    puts( "\nA32000 v0.10" );
  373.  
  374.    if( argc < 2 ) {
  375.       puts( "\n?No file name specified" );
  376.       exit( 1 );
  377.    }
  378.  
  379.    symcnt = 0;
  380.  
  381.    for( pass = 1; pass <= 3; ++pass ) {
  382.  
  383.       makename( argv[ 1 ], ".s" );
  384.       fasm = fopen( filename, "r" );
  385.  
  386.       if( fasm == 0 ) {
  387.          puts( "\n?Unable to open source file" );
  388.          exit( 1 );
  389.       }
  390.  
  391.       if( pass == 3 ) {
  392.          makename( argv[ 1 ], ".hex" );
  393.          fobj = fopen( filename, "w" );
  394.          if( ! fobj ) {
  395.             puts( "\n?No directory space" );
  396.             exit( 1 );
  397.          }
  398.       }
  399.  
  400.       puts( "\nPass " );
  401.       putchar( pass + '0' );
  402.  
  403.       asmadr = 0;
  404.       codadr = 0;
  405.  
  406.       if( pass == 3 ) {
  407.          objflush();
  408.          listnl();
  409.       }
  410.       inpload();
  411.  
  412.       while( gword() ) {
  413.  
  414.          if( match( word, "end" )) break;
  415.  
  416. /* Each word is processed by the following nested if
  417.    statement, which attempts to identify what it is.
  418.    Note that any successful identification stops the
  419.    process of the statement. */
  420.  
  421.          if( ! islabel( word ))
  422.             if( ! ispseudo( word ))
  423.                if( ! isopcode( word ))
  424.                   if( ! isequate( word ))
  425.                      error( '?', word );
  426.       }
  427.  
  428.       fclose( fasm );
  429.  
  430. /* Sort symbols after pass 1. */
  431.  
  432.       if( pass == 1 ) sortsyms();
  433.  
  434.       if( pass == 3 )   {
  435.          objflush();
  436.  
  437.          putc( ':', fobj );     /* write eof record */
  438.          for( i = 0; i < 10; ++i ) putc( '0', fobj );
  439.          putc( '\n', fobj );
  440.  
  441.          fclose( fobj );
  442.       }
  443.    }
  444.  
  445.    listpr();
  446.    puts( "\n\n" );
  447.    dumpsyms();
  448.  
  449.    if( errors )
  450.       puts( "\n---Fix errors and reassemble---" );
  451. }
  452.  
  453. /* Construct a filename from two strings. */
  454.  
  455. makename( p, q )
  456. char *p, *q;
  457. {
  458.    char *r;
  459.    r = &filename[ 0 ];
  460.    while( *p ) *r++ = *p++;
  461.    while( *q ) *r++ = *q++;
  462.    *r = '\0';
  463. }
  464.  
  465. /* Check to see if the word is a label, and if it is, add
  466.    its value to the symbol table */
  467.  
  468. int islabel( w )
  469. char *w;
  470. {
  471.    while( *w ) ++w;
  472.    if( *--w != ':' ) return 0;
  473.    *w = '\0';   /* take off the colon */
  474.  
  475.    addsymbol( word, codadr );
  476.    return 1;
  477. }
  478.  
  479. /* Check the word to see if it is a pseudo-op. */
  480.  
  481. int ispseudo( w )
  482. char *w;
  483. {
  484.    long int getarg(), temp;
  485.  
  486.    if( match( w, "org" )) {
  487.       asmadr = getarg();
  488.       codadr = asmadr;
  489.       if( pass == 3 ) objflush();
  490.       return 1;
  491.    }
  492.  
  493.    if( match( w, "db" )) {      /* Note: Allow msgs? */
  494.       temp = getarg();          /* get argument */
  495.       objout( temp & 0xFF );    /* output byte */
  496.       return 1;
  497.    }
  498.  
  499.    if( match( w, "dw" )) {
  500.       temp = getarg();          /* get argument */
  501.       objout( temp & 0xFF );    /* output lsb */
  502.       objout(( temp >> 8 ) & 0xFF );    /* output msb */
  503.       return 1;
  504.    }
  505.  
  506.    if( match( w, "dd" )) {
  507.       temp = getarg();          /* get argument */
  508.       objout( temp & 0xFF );    /* output lsb */
  509.       objout(( temp >> 8 ) & 0xFF );
  510.       objout(( temp >> 16 ) & 0xFF );
  511.       objout(( temp >> 24 ) & 0xFF );   /* output msb */
  512.       return 1;
  513.    }
  514.  
  515.    if( match( w, "even" ) && ( codadr & 1 )) {
  516.       objout( 0 ); /* send 1 byte to go to word bndry */
  517.       return 1;
  518.    }
  519.  
  520.    return 0;
  521. }
  522.  
  523. /* Check to see if the word is an opcode, and if it is,
  524.    get any operands required and generate code. */
  525.  
  526. int isopcode( w )
  527. char *w;
  528. {
  529.    long int value(), bitbin(), decbin(), o, ocodadr;
  530.    char opbuf[ 33 ], bytbuf[ 33 ], extbuf[ 128 ];
  531.    char opopt, modopt, opsiz, opcnt;
  532.    int i, j, k, l;
  533.    char *p, *q, *cpystr(), *regbits();
  534.  
  535.    /* postbytes & scaled indexes */
  536.    int opexbt[ 4 ], opexct;
  537.  
  538.    int adexct, adexln[ 8 ];
  539.    char *adexpt[ 8 ], *eoadex; /* addressing extensions */
  540.  
  541.    ocodadr = codadr;    /* save addr of begin of instr */
  542.  
  543.    opexct = 0;          /* no postbytes as yet */
  544.    adexct = 0;          /* no extensions as yet */
  545.    eoadex = &extbuf[ 0 ]; /* point to begin of extbuf */
  546.  
  547.    for( i = 0; i < MAXOP; ++i )
  548.       if( match( w, opcode[ i ].onam )) {
  549.  
  550.       opopt = opcode[ i ].oopt;
  551.  
  552.       if( opopt == 'x' ) {
  553.          error( 'x', w ); /* unimplemented instruction */
  554.          return 1;
  555.       }
  556.  
  557.       p = cpystr( opcode[ i ].obin, &opbuf[ 0 ] );
  558.  
  559. /* see if length modifier */
  560.  
  561.       if( ambcnt > 0 ) {
  562.          p = &opbuf[ 0 ];
  563.          opsiz = *ambig[ 0 ];
  564.  
  565.          while( *p && *p != 'i' ) ++p;
  566.  
  567.          if( ! *p ) error( 'l', w );
  568.             else {
  569.             switch( opsiz ) {
  570.  
  571.             case 'b' : *p++ = '0';
  572.                *p++ = '0';
  573.                break;
  574.  
  575.             case 'w' : *p++ = '0';
  576.                *p++ = '1';
  577.                break;
  578.  
  579.             case 'd' : *p++ = '1';
  580.                *p++ = '1';
  581.             }
  582.          }
  583.       }
  584.  
  585. /* now parse operands */
  586.  
  587. /* get count of operands.
  588.    Take abs value (neg = PC-relative) */
  589.  
  590.       opcnt = opcode[ i ].ocnt;
  591.       if( opcnt < 0 ) opcnt = 0 - opcnt;
  592.  
  593.       p = &opbuf[ 0 ];  /* modified parts start at beg. */
  594.  
  595.       for( j = 0; j < opcnt; ++j ) {
  596.          gword();       /* get operand */
  597.  
  598. /* find addr mode */
  599.  
  600.          k = 0;
  601.          while(( k < MAXAM )
  602.             && ! match( word, admode[ k ].mstr )) ++k;
  603.  
  604.          modopt = admode[ k ].mopt;
  605.  
  606. /* move bit string into place */
  607.  
  608.          q = admode[ k ].gstr;
  609.  
  610. /* if opopt h, sfsr, skip 5 bits */
  611.  
  612.          if( opopt == 'h' ) p += 5;
  613.  
  614. /* for most opopts, move the bits in */
  615.  
  616.          if(( opopt == ' ' )
  617.             || ( opopt == 'a' )
  618.             || ( opopt == 'c' )
  619.             || ( opopt == 'e' && j == 1 )
  620.             || ( opopt == 'h' )
  621.             || ( opopt == 'i' && j < 2 )
  622.             || ( opopt == 'l' && j == 1 )
  623.             || ( opopt == 'm' && j > 0 && j < 3 )
  624.             || ( opopt == 'o' && j < 2 ))
  625.             while( *q ) *p++ = *q++;
  626.  
  627. /* Double the effort for scaled index mode.  create an
  628.    extension postbyte opexbt[] with basemode as upper
  629.    5 bits, reg as lower 3 bits. */
  630.  
  631.          if( admode[ k ].mopt == 's' ) {
  632.             l = ( *ambig[ 1 ] ) & 7;
  633.             q = cpystr( ambig[ 0 ], &bytbuf[ 0 ] );
  634.  
  635. /* find basemode */
  636.  
  637.             k = 0;
  638.             while(( k < MAXAM )
  639.                && ! match( &bytbuf[ 0 ],
  640.                admode[ k ].mstr )) ++k;
  641.  
  642.             modopt = admode[ k ].mopt;
  643.  
  644. /* move bit string into postbyte.  use bitbin, because
  645.    value() destroys ambig[] array which we still need. */
  646.  
  647.             q = cpystr( admode[ k ].gstr,
  648.                &bytbuf[ 0 ] );
  649.             --q;                /* back up to null */
  650.             *q++ = '0' + (( l >> 2 ) & 1 );
  651.             *q++ = '0' + (( l >> 1 ) & 1 );
  652.             *q++ = '0' + ( l & 1 );
  653.             *q = '\0';
  654.  
  655.             opexbt[ opexct++ ] = bitbin( &bytbuf[ 0 ] );
  656.             q = admode[ k ].gstr;
  657.          }
  658.  
  659. /* funny handling of reg: index operation (opopt 'm') */
  660.  
  661.          if( opopt == 'm' && j == 0 ) {
  662.             p = &opbuf[ 10 ];   /* off to reg */
  663.             q += 2;             /* skip 0 bits */
  664.             while( *q ) *p++ = *q++;
  665.             p = &opbuf[ 0 ];    /* reset */
  666.          }
  667.  
  668. /* move ambigs into extension bytes. set length to
  669.    variable (0). For some addressing modes, the
  670.    extensions go in in reverse order */
  671.  
  672.          if( modopt == 'r' )
  673.             for( l = admode[ k ].mcnt - 1; l >= 0;
  674.                --l ) {
  675.                adexpt[ adexct ] = eoadex;
  676.                adexln[ adexct ] = 0;
  677.                ++adexct;
  678.                eoadex = cpystr( ambig[ l ], \
  679.                   eoadex );
  680.          } else for( l = 0; l < admode[ k ].mcnt; ++l ) {
  681.                adexpt[ adexct ] = eoadex;
  682.                adexln[ adexct ] = 0;
  683.                ++adexct;
  684.                eoadex = cpystr( ambig[ l ], \
  685.                   eoadex );
  686.          }
  687.  
  688. /* special logic for register list for "enter", "save",
  689.    "restore", "exit" */
  690.  
  691.          if(( j == 0 && opopt == 'f' ) || opopt == 'g' ) {
  692.             adexpt[ adexct ] = eoadex;
  693.             adexln[ adexct ] = 1;
  694.             ++adexct;
  695.             eoadex = regbits( word, eoadex, opopt );
  696.          }
  697.  
  698. /* shorten extension to 1 byte for enter, return */
  699.  
  700.          if(( j == 1 && opopt == 'f' ) || opopt == 'n' ) {
  701.             if( adexct > 0 ) adexln[ adexct - 1 ] = 1;
  702.                else error( 'e', w );
  703.          }
  704.  
  705. /* opopts 'e' or 'd': immed data becomes 4 bit value */
  706.  
  707.          if(( j == 0 && opopt == 'e' ) || opopt == 'd' ) {
  708.             if( ! adexct ) error( 'e', w );
  709.                else {
  710.                l = value( adexpt[ --adexct ] );
  711.                p = &opbuf[ 5 ];
  712.                *p++ = '0' + (( l >> 3 ) & 1 );
  713.                *p++ = '0' + (( l >> 2 ) & 1 );
  714.                *p++ = '0' + (( l >> 1 ) & 1 );
  715.                *p = '0' + ( l & 1 );
  716.                p = &opbuf[ 0 ];
  717.             }
  718.          }
  719.  
  720. /* opopt 'i': combine last two ambigs into one postbyte.
  721.    Put it in bytbuf and set length to 1 */
  722.  
  723.          if( opopt == 'i' && j == 3 ) {
  724.             if( adexct < 2 ) error( 'e', w );
  725.             else {
  726.                l = ( value( adexpt[ --adexct ] ) - 1 )
  727.                   & 31;
  728.                l += ( value( adexpt[ --adexct ] )
  729.                   & 7 ) << 5;
  730.                bytbuf[ 0 ] = '0' +
  731.                   (( l / 100 ) % 10 );
  732.                bytbuf[ 1 ] = '0' +
  733.                   (( l / 10 ) % 10 );
  734.                bytbuf[ 2 ] = '0' + ( l % 10 );
  735.                bytbuf[ 3 ] = '\0';
  736.                adexpt[ adexct ] = &bytbuf[ 0 ];
  737.                adexln[ adexct++ ] = 1;
  738.             }
  739.          }
  740.  
  741. /* opopt 'j': uwb bits for movs, cmps, skps */
  742.  
  743.          if( opopt == 'j' ) {
  744.             p += 5;
  745.             uwbbits( word, p );
  746.             adexct = 0;         /* in case no paren */
  747.          }
  748.  
  749. /* opopt 'k': config bits for setcfg */
  750.  
  751.          if( opopt == 'k' ) {
  752.             p += 5;
  753.             cfgbits( word, p );
  754.          }
  755.  
  756. /* opopt 'l': operand 1 becomes 4 bit value */
  757.  
  758.          if( opopt == 'l' && j == 0 ) {
  759.             adexct = 0;         /* unjunk extensions */
  760.             l = -1;
  761.             if( strcmp( word, "upsr" ) == 0 ) l = 0;
  762.             if( strcmp( word, "fp" ) == 0 ) l = 8;
  763.             if( strcmp( word, "sp" ) == 0 ) l = 9;
  764.             if( strcmp( word, "sb" ) == 0 ) l = 10;
  765.             if( strcmp( word, "psr" ) == 0 ) l = 13;
  766.             if( strcmp( word, "intbase" ) == 0 ) l = 14;
  767.             if( strcmp( word, "mod" ) == 0 ) l = 15;
  768.             if( l == -1 ) error( 'p', word );
  769.                else {
  770.                p = &opbuf[ 5 ];
  771.                *p++ = '0' + (( l >> 3 ) & 1 );
  772.                *p++ = '0' + (( l >> 2 ) & 1 );
  773.                *p++ = '0' + (( l >> 1 ) & 1 );
  774.                *p = '0' + ( l & 1 );
  775.                p = &opbuf[ 0 ];
  776.             }
  777.          }
  778.  
  779. /* odd length extension for movm, opopt 'o' */
  780.  
  781.          if( j == 2 && opopt == 'o' ) {
  782.             if( adexct > 0 ) adexln[ --adexct ] = 1;
  783.                else error( 'e', w );
  784.             l = value( adexpt[ adexct ] ) - 1;
  785.             switch( opsiz ) {
  786.             case 'd' : l *= 4; break;
  787.             case 'w' : l *= 2; break;
  788.             }
  789.             bytbuf[ 0 ] = '0' + (( l / 100 ) % 10 );
  790.             bytbuf[ 1 ] = '0' + (( l / 10 ) % 10 );
  791.             bytbuf[ 2 ] = '0' + ( l % 10 );
  792.             bytbuf[ 3 ] = '\0';
  793.             adexpt[ adexct++ ] = &bytbuf[ 0 ];
  794.          }
  795.  
  796.       }         /* done operands */
  797.  
  798.       o = value( &opbuf[ 0 ] );
  799.  
  800.       l = strlen( opbuf );
  801.  
  802. /* Send as many opcode bytes as necessary */
  803.  
  804.       objout( o % 256 );
  805.       if( l > 9 ) objout(( o / 256 ) % 256 );
  806.       if( l > 17 ) objout( o / 65536 );
  807.  
  808. /* Send postbytes for scaled index mode */
  809.  
  810.       for( l = 0; l < opexct; ++l )
  811.          objout( opexbt[ l ] );
  812.  
  813. /* Send addressing extensions.
  814.    adexln = length of extension word in bytes if +.
  815.    If 0, it is a variable-length signed displacement.
  816.    If -1, indicates code-relative */
  817.  
  818. /* If opcode ocnt was negative, last address extension is
  819.    code relative. */
  820.  
  821.       if( opcode[ i ].ocnt < 0 )
  822.          adexln[ adexct - 1 ] = -1;
  823.  
  824. /* send extension words */
  825.  
  826.       for( j = 0; j < adexct; ++j ) {
  827.  
  828.          o = value( adexpt[ j ] );
  829.  
  830. /* if adexln[] negative, operand(s) code-relative.
  831.    Note: on the 32000 you don't correct by adding 2 to
  832.    codadr first */
  833.  
  834.          if( adexln[ j ] < 0 ) o -= ocodadr;
  835.  
  836. /* Compute variable-length signed displacement */
  837.  
  838.          if( adexln[ j ] <= 0 ) {
  839.             if( o < 63 && o > -64 ) {
  840.                o = ( o & 0x7F );
  841.                l = 1;           /* one-byte */
  842.             } else if( o < 8191 && o > -8192 ) {
  843.                o = ( o & 0x3FFF ) + 0x8000;
  844.                l = 2;
  845.             } else {
  846.                o = ( o & 0x3FFFFFFF )
  847.                   + 0xC0000000;
  848.                l = 4;
  849.             }
  850.          } else l = adexln[ j ];
  851.  
  852. /* address extensions are sent in lohi order */
  853.  
  854.          if( l > 3 ) objout(( o >> 24 ) & 0xFF );
  855.          if( l > 2 ) objout(( o >> 16 ) & 0xFF );
  856.          if( l > 1 ) objout(( o >> 8 ) & 0xFF );
  857.          objout( o % 256 );
  858.       }
  859.       return 1;
  860.    }
  861.    return 0;
  862. }
  863.  
  864. /* Special to create extension word for register list */
  865.  
  866. /* Regbits may look like "r0" or may look like "[r0,r2]"
  867.    or like "[r0-r7]". */
  868.  
  869. char *regbits( src, dst, flg )
  870. char *src, *dst, flg;
  871. {
  872.    int bits, reg, loreg, hireg;
  873.  
  874.    bits = 0;
  875.  
  876.    if( *src == '[' ) ++src;     /* strip parens */
  877.       else error( '[', src );
  878.  
  879.    while( *src ) {
  880.       if( *src++ != 'r' ) error( 'r', src );
  881.       reg = ( *src++ ) - '0';
  882.       bits = bits | ( 1 << reg );
  883.       if( *src++ == '-' ) {
  884.          loreg = reg;
  885.          if( *src++ != 'r' ) error( 'r', src );
  886.          hireg = ( *src++ ) - '0';
  887.          if( hireg < loreg ) {
  888.             reg = hireg;
  889.             hireg = loreg;
  890.             loreg = reg;
  891.          }              /* swap if out of order */
  892.          for( reg = loreg; reg <= hireg; ++reg )
  893.             bits = bits | ( 1 << reg );
  894.          ++src;         /* skip over the comma */
  895.       }
  896.       if( *src == ']' ) break;
  897.    }
  898.  
  899. /* if flg = 'f', save/enter, need to swap bit
  900.    significance. The routine above constructed it in
  901.    reversed order in the first place, because of the
  902.    routine below */
  903.  
  904.    if( flg == 'f' ) {
  905.       hireg = 0;
  906.       for( reg = 0; reg < 8; ++reg ) {
  907.          hireg = ( hireg << 1 ) + ( bits & 1 );
  908.          bits = ( bits >> 1 );
  909.       }
  910.       bits = hireg;
  911.    }
  912.  
  913. /* now create a binary string for the extension.
  914.    Note that bit significance becomes reversed again */
  915.  
  916.    for( reg = 0; reg < 8; ++reg ) {
  917.       *dst++ = '0' + ( bits & 1 );
  918.       bits = ( bits >> 1 );
  919.    }
  920.  
  921.    *dst++ = 'b';        /* add b for binary */
  922.    *dst++ = '\0';       /* terminate */
  923.  
  924.    return dst;
  925. }
  926.  
  927. /* put config bits into instruction */
  928.  
  929. cfgbits( src, dst )
  930. char *src, *dst;
  931. {
  932.    char b[ 4 ];
  933.  
  934.    b[ 0 ] = '0';
  935.    b[ 1 ] = '0';
  936.    b[ 2 ] = '0';
  937.    b[ 3 ] = '0';
  938.  
  939.    if( *src == '[' ) ++src;     /* strip parens */
  940.       else error( '[', src );
  941.  
  942.    while( *src ) {
  943.       switch( *src++ ) {
  944.  
  945.       case 'c' : b[ 0 ] = '1';
  946.             break;
  947.  
  948.       case 'm' : b[ 1 ] = '1';
  949.             break;
  950.  
  951.       case 'f' : b[ 2 ] = '1';
  952.             break;
  953.  
  954.       case 'i' : b[ 3 ] = '1';
  955.       }
  956.  
  957.       if( *src++ == ']' ) break;
  958.    }
  959.    *dst++ = b[ 0 ];
  960.    *dst++ = b[ 1 ];
  961.    *dst++ = b[ 2 ];
  962.    *dst = b[ 3 ];
  963. }
  964.  
  965. /* put uwb bits into instruction */
  966.  
  967. uwbbits( src, dst )
  968. char *src, *dst;
  969. {
  970.    char b[ 3 ];
  971.  
  972.    b[ 0 ] = '0';        /* default = forward */
  973.    b[ 1 ] = '0';        /* default = neither */
  974.    b[ 2 ] = '0';
  975.  
  976.    while( *src ) {
  977.       switch( *src++ ) {
  978.  
  979.       case 'b' : b[ 2 ] = '1';  /* backward */
  980.             break;
  981.  
  982.       case 'u' : b[ 0 ] = '1';  /* until match */
  983.             b[ 1 ] = '1';
  984.             break;
  985.  
  986.       case 'w' : b[ 0 ] = '0';  /* while match */
  987.             b[ 1 ] = '1';
  988.       }
  989.    }
  990.    *dst++ = b[ 0 ];
  991.    *dst++ = b[ 1 ];
  992.    *dst = b[ 2 ];
  993. }
  994.  
  995. /* Check to see if the word begins an equate, and if it
  996.    does, add the symbol to the symbol table. */
  997.  
  998. int isequate( w )
  999. char *w;
  1000. {
  1001.    char tempword[ 128 ];
  1002.    char *q, *cpystr();
  1003.    long int l, getarg();
  1004.  
  1005.    q = cpystr( w, &tempword[ 0 ] );
  1006.  
  1007.    gword();             /* get next word */
  1008.  
  1009.    if( strcmp( word, "equ" ) == 0 ||
  1010.       strcmp( word, "=" ) == 0 ) {
  1011.       l = getarg();     /* get argument */
  1012.  
  1013.       addsymbol( &tempword[ 0 ], l );
  1014.       
  1015.       return 1;         /* it was an equate */
  1016.    }
  1017.  
  1018.    return 0;            /* we lost a word */
  1019. }
  1020.  
  1021. /* Get an argument value (for use above). */
  1022.  
  1023. long int getarg()
  1024. {
  1025.    long int value();
  1026.  
  1027.    gword();             /* get next word */
  1028.    return value( word );
  1029. }
  1030.  
  1031. /* copy string and return new ending address */
  1032.  
  1033. char *cpystr( src, dst )
  1034. char *src, *dst;
  1035. {
  1036.    while( *src ) *dst++ = *src++;
  1037.    *dst++ = '\0';       /* terminate copied string */
  1038.    return dst;          /* return next address */
  1039. }
  1040.  
  1041. /* Calculate the value of a word.  It may be a symbol, a
  1042.    constant, or a computed value (must be enclosed in
  1043.    parentheses.) */
  1044.  
  1045. long int value( w )
  1046. char *w;
  1047. {
  1048.    long int hexbin(), octbin(), bitbin(), decbin(), v;
  1049.    int lookup(), i, negate;
  1050.  
  1051.    char *q;
  1052.  
  1053.    char *wp[ 16 ];
  1054.    int wpcnt;
  1055.  
  1056.    negate = 0;
  1057.  
  1058.    if( *w == '-' ) {    /* Unary negation */
  1059.       negate = 1;
  1060.       ++w;
  1061.    }
  1062.  
  1063.    if( strcmp( w, "." ) == 0 )
  1064.       return codadr; /* . = code address */
  1065.    if( strcmp( w, ".." ) == 0 )
  1066.       return asmadr; /* .. = assembly address */
  1067.  
  1068.    if( isdigit( *w )) {
  1069.       if( match( w, "*h" )) v = hexbin( w );
  1070.          else if( match( w, "*q" )) v = octbin( w );
  1071.             else if( match( w, "*b" ))
  1072.                v = bitbin( w );
  1073.                else v = decbin( w );
  1074.    } else {
  1075.  
  1076.       if( *w == '(' ) {         /* --- FORMULA --- */
  1077.          ++w;                   /* skip ( */
  1078.          q = w;
  1079.          while( *q ) ++q;       /* find end of string */
  1080.          --q;
  1081.          if( *q != ')' ) error( ')', q );
  1082.             else *q = '\0';     /* zap ) */
  1083.  
  1084.          iwparen = 0;           /* no parens now */
  1085.  
  1086.          wpcnt = 0;
  1087.  
  1088.          while( 1 ) {           /* find beg of word */
  1089.             while( inword( *w )) ++w;
  1090.  
  1091.             if( ! *w ) break;
  1092.  
  1093.             wp[ wpcnt++ ] = w;  /* ptr to value */
  1094.  
  1095.             iwparen = 0;        /* find end of word */
  1096.             while( *w && ! inword( *w )) ++w;
  1097.             if( ! *w ) break;
  1098.             *w++ = '\0';        /* terminate it */
  1099.  
  1100.             if( wpcnt == 16 ) {
  1101.                error( 'l', w ); /* too long */
  1102.                break;
  1103.             }
  1104.          }
  1105.  
  1106.          if(( wpcnt % 2 ) == 0 ) {
  1107.             error( 'v', w );    /* must be odd */
  1108.             --wpcnt;
  1109.          }
  1110.  
  1111.          v = value( wp[ 0 ] );
  1112.  
  1113.          for( i = 1; i < wpcnt; i += 2 ) {
  1114.             if( strcmp( wp[ i ], "+" ) == 0 ) {
  1115.                v += value( wp[ i + 1 ] );
  1116.                goto opdone;
  1117.             }
  1118.             if( strcmp( wp[ i ], "-" ) == 0 ) {
  1119.                v -= value( wp[ i + 1 ] );
  1120.                goto opdone;
  1121.             }
  1122.             if( strcmp( wp[ i ], "*" ) == 0 ) {
  1123.                v *= value( wp[ i + 1 ] );
  1124.                goto opdone;
  1125.             }
  1126.             if( strcmp( wp[ i ], "/" ) == 0 ) {
  1127.                v /= value( wp[ i + 1 ] );
  1128.                goto opdone;
  1129.             }
  1130.             error( 'o', wp[ i ] );      /* unknown op */
  1131. opdone:
  1132.             i = i;              /* get around c/80 bug */
  1133.          }
  1134.  
  1135.       } else {                  /* --- PLAIN VALUE --- */
  1136.  
  1137.          i = lookup( w );       /* look up symbol */
  1138.          if( i < 0 ) return 0;  /* unknown symbol */
  1139.          v = symbol[ i ].sval;  /* return sym value */
  1140.       }
  1141.    }
  1142.  
  1143.    if( negate ) v = 0 - v;
  1144.  
  1145.    return v;
  1146. }
  1147.  
  1148. /* function for value() */
  1149.  
  1150. int inword( c )
  1151. char c;
  1152. {
  1153.    if( c == '(' ) ++iwparen;    /* special var for this */
  1154.    if( c == ')' ) --iwparen;    /* function */
  1155.  
  1156.    if( iwparen ) return 0;
  1157.  
  1158.    if( c == ' ' ) return 1;     /* is space */
  1159.  
  1160.    return 0;
  1161. }
  1162.  
  1163. /* --- SYMBOL TABLE LOGIC --- */
  1164.  
  1165. /* add new symbol to symbol table */
  1166.  
  1167. addsymbol( p, v )
  1168. char *p;
  1169. long int v;
  1170. {
  1171.    char *w, *cpystr(), *alloc();
  1172.    int i, lookup();
  1173.  
  1174.    i = lookup( p );     /* see if already known */
  1175.  
  1176.    if( i < 0 ) {        /* new symbol */
  1177.       i = symcnt;
  1178.       ++symcnt;         /* count a new symbol */
  1179.  
  1180.       symbol[ i ].snam = alloc( strlen( p ) + 1 );
  1181.       w = cpystr( p, symbol[ i ].snam );
  1182.    }
  1183.  
  1184.    symbol[ i ].sval = v; /* update value in table */
  1185. }
  1186.  
  1187. /* lookup - returns symbol number or -1 if not found */
  1188.  
  1189. int lookup( p )
  1190. char *p;
  1191. {
  1192.    char *w;
  1193.    int i, j, k, found;
  1194.  
  1195.    found = 0;           /* not found yet */
  1196.  
  1197. /* pass 1 - use linear search */
  1198.  
  1199.    if( pass == 1 ) {
  1200.       for( i = 0; i < symcnt && ! found; ++i ) {
  1201.          w = symbol[ i ].snam;
  1202.          found = ( strcmp( p, w ) == 0 );
  1203.       }
  1204.    } else {
  1205.  
  1206. /* passes 2 and 3 - use binary search */
  1207.  
  1208.       j = ( symcnt + 1 ) / 4;   /* step to use */
  1209.       i = symcnt / 2;           /* starting point */
  1210.       k = j + 1;                /* one-step count */
  1211.  
  1212.       while( 1 ) {
  1213.          w = symbol[ i ].snam;
  1214.          found = strcmp( p, w );
  1215.          if( found == 0 ) {
  1216.             found = 1;
  1217.             break;
  1218.          } else if( found < 0 ) i -= j;
  1219.             else i += j;
  1220.  
  1221.          if( i < 0 ) i = 0;
  1222.          if( i >= symcnt ) i = symcnt - 1;
  1223.  
  1224.          j /= 2;                /* halve step */
  1225.  
  1226.          if( j == 0 ) {
  1227.             if( k-- == 0 ) {
  1228.                found = 0;       /* not found */
  1229.                break;
  1230.             }
  1231.             j = 1;
  1232.          }
  1233.       }
  1234.    }
  1235.  
  1236.    if( ! found ) {
  1237.       if( pass != 1 ) error( 'u', w );
  1238.       return -1;
  1239.    }
  1240.  
  1241.    return i;
  1242. }
  1243.  
  1244. /* display error code */
  1245.  
  1246. error( c, p )
  1247. char c;
  1248. char *p;
  1249. {
  1250.    puts( "\n>>---> Error " );
  1251.    putchar( c );
  1252.    puts( " at " );
  1253.    puts( p );
  1254.  
  1255.    ++errors;
  1256. }
  1257.  
  1258. /* sort symbols by shell sort */
  1259.  
  1260. sortsyms()
  1261. {
  1262.    int jump, done, k, l;
  1263.    char *n;
  1264.    long int v;
  1265.  
  1266.    jump = symcnt;       /* set jmp to cnt of elements */
  1267.  
  1268.    while( jump > 0 ) {
  1269.       jump = jump / 2;
  1270.  
  1271.       while( 1 ) {
  1272.          done = 1;
  1273.          for( k = 0; k < ( symcnt - jump ); ++k ) {
  1274.             l = k + jump;
  1275.             if( strcmp( symbol[ k ].snam,
  1276.                symbol[ l ].snam ) > 0 ) {
  1277.                n = symbol[ k ].snam;
  1278.                v = symbol[ k ].sval;
  1279.                symbol[ k ].snam = symbol[ l ].snam;
  1280.                symbol[ k ].sval = symbol[ l ].sval;
  1281.                symbol[ l ].snam = n;
  1282.                symbol[ l ].sval = v;
  1283.                done = 0;
  1284.             }
  1285.          }
  1286.          if( done ) break;
  1287.       }
  1288.    }
  1289. }
  1290.  
  1291. /* dump symbol table */
  1292.  
  1293. dumpsyms()
  1294. {
  1295.    char *w;
  1296.    int i;
  1297.    long int v;
  1298.  
  1299.    puts( "\nSymbol and Value\n" );
  1300.  
  1301.    for( i = 0; i < symcnt; ++i ) {
  1302.       puts( symbol[ i ].snam );
  1303.       puts( " = " );
  1304.       v = symbol[ i ].sval;
  1305.       puthex( v >> 24, 0 );
  1306.       puthex(( v >> 16 ) & 0xFF, 0 );
  1307.       puthex(( v >> 8 ) & 0xFF, 0 );
  1308.       puthex( v & 0xFF, 0 );    /* print value */
  1309.       putchar( '\n' );
  1310.    }
  1311. }
  1312.  
  1313. /* Match string.  If match, returns 1; else returns 0.
  1314.    Ambiguous values from the matches are saved and
  1315.    pointed to by the array of char pointers ambig[], so
  1316.    they can be checked later. */
  1317.  
  1318. int match( w1, w2 )
  1319. char *w1, *w2;
  1320. {
  1321.    char c;
  1322.    char *next_ambig;
  1323.  
  1324.    next_ambig = &ambig_buffer[ 0 ]; /* init ambig buff */
  1325.    ambcnt = 0;                      /* ambigs so far */
  1326.  
  1327.    while( *w1 ) {
  1328.       c = *w2++;
  1329.       if( c == '*' ) {
  1330.          ambig[ ambcnt++ ] = next_ambig;
  1331.          while( *w1 && *w1 != *w2 )
  1332.             *next_ambig++ = *w1++;
  1333.          if( ! *w1 && *w2 ) return 0;
  1334.          *next_ambig++ = '\0';  /* terminate this ambig */
  1335.       } else if( c == '?' ) {
  1336.             ambig[ ambcnt++ ] = next_ambig;
  1337.             *next_ambig++ = *w1++;      /* 1-char ambig */
  1338.             *next_ambig++ = '\0';       /* terminate it */
  1339.          } else if( c != *w1++ ) return 0;
  1340.    }
  1341.    return 1;
  1342. }
  1343.  
  1344. int gword()
  1345. {
  1346.    char *p, *q;
  1347.    char c, gchar();
  1348.  
  1349.    p = &word_buffer[ 0 ];
  1350.  
  1351.    c = ' ';
  1352.  
  1353.    while( isdelim( c )) c = gchar();
  1354.  
  1355.    while( ! isdelim( c )) {
  1356.       *p++ = tolower( c );
  1357.       c = gchar();
  1358.    }
  1359.  
  1360.    *p = '\0';   /* terminate word */
  1361.  
  1362.    word = &word_buffer[ 0 ];
  1363.  
  1364.    return 1;
  1365. }
  1366.  
  1367. /* is the character a delimeter? */
  1368.  
  1369. isdelim( c )
  1370. char c;
  1371. {
  1372.    if( paren || quote || brack )
  1373.       return 0; /* not a delim */
  1374.  
  1375.    if( c == ' ' || c == ',' || c == ';' || c == '\n' \
  1376.       || c == '\r' || c == '\t' )
  1377.       return 1;
  1378.    return 0;
  1379. }
  1380.  
  1381. /* get next char from source file */
  1382.  
  1383. char gchar()
  1384. {
  1385.    char c, getch();
  1386.  
  1387.    c = getch();          /* get char from file */
  1388.  
  1389.    if( c == '\'' ) quote = ! quote;
  1390.    if( c == '"' ) quote = ! quote;
  1391.    if( c == '(' ) ++paren;
  1392.    if( c == ')' ) --paren;
  1393.    if( c == '[' ) ++brack;
  1394.    if( c == ']' ) --brack;
  1395.  
  1396.    if( ! quote && ! paren && ! brack ) {
  1397.  
  1398.       while( c == ';' ) {       /* ;comment\n */
  1399.          while( getch() != '\n' ) ;
  1400.          c = getch();
  1401.       }
  1402.    }
  1403.  
  1404.    return c;
  1405. }
  1406.  
  1407. puts( p )
  1408. char *p;
  1409. {
  1410.    while( *p ) putchar( *p++ );
  1411. }
  1412.  
  1413. /* --- source file routines --- */
  1414.  
  1415. char getch()
  1416. {
  1417.    while( inpcnt == 0 ) {       /* if input buf empty, */
  1418.       listpr();         /* print listing line */
  1419.       inpload();        /* reload input buffer */
  1420.    }
  1421.  
  1422.    --inpcnt;
  1423.    return( inpbuf[ inpptr++ ] );
  1424. }
  1425.  
  1426. inpload()
  1427. {
  1428.    char c, getc();
  1429.  
  1430.    inpcnt = 0;
  1431.    inpptr = 0;
  1432.  
  1433.    while((( c = getc( fasm )) != '\n' ) && ( c != EOF )) {
  1434.       inpbuf[ inpcnt++ ] = c;
  1435.       if( listcp < 81 ) listline[ listcp++ ] = c;
  1436.    }
  1437.  
  1438.    inpbuf[ inpcnt++ ] = '\n';
  1439. }
  1440.  
  1441. /* --- listing file routines --- */
  1442.  
  1443. listnl()        /* list new line */
  1444. {
  1445.    int i;
  1446.  
  1447.    if( pass != 3 ) return;
  1448.  
  1449.    for( i = 0; i < 26; ++i ) listline[ i ] = ' ';
  1450.    for( i = 26; i < 81; ++i ) listline[ i ] = '\0';
  1451.  
  1452.    listop = 0;  /* flag to cause addr output */
  1453.    listcp = 26;
  1454. }
  1455.  
  1456. lbyt( b )       /* put object byte in list file */
  1457. unsigned int b;
  1458. {
  1459.    char c;
  1460.  
  1461.    if( pass != 3 ) return;
  1462.  
  1463.    c = (( b / 16 ) % 16 ) + '0';
  1464.    if( c > '9' ) c += ( 'a' - ':' );
  1465.    listline[ listop++ ] = c;
  1466.  
  1467.    c = ( b % 16 ) + '0';
  1468.    if( c > '9' ) c += ( 'a' - ':' );
  1469.    listline[ listop++ ] = c;
  1470.  
  1471.    if( listop > 24 ) listpr();  /* print list line */
  1472. }
  1473.  
  1474. listpr()        /* print list line */
  1475. {
  1476.    if( pass != 3 ) return;
  1477.  
  1478.    putchar( '\n' );
  1479.    puts( listline );
  1480.    listnl();
  1481. }
  1482.  
  1483. /* --- object file routines --- */
  1484.  
  1485. objout( c )
  1486. char c;
  1487. {
  1488.    asmadr++;    /* incr asmadr, codadr. DON'T incr*/
  1489.    codadr++;    /* objadr, it is addr of 1st byte */
  1490.    if( pass != 3 ) return;   /* skip if not last pass */
  1491.    objbuf[ objcnt++ ] = c;   /* put new byte in buffer */
  1492.    if( objcnt == 32 ) objflush();
  1493.  
  1494.    if( listop == 0 ) {          /* print address? */
  1495.       lbyt( asmadr / 16777216 );
  1496.       lbyt(( asmadr / 65536 ) % 256 );
  1497.       lbyt(( asmadr / 256 ) % 256 );
  1498.       lbyt( asmadr % 256 );
  1499.       listop = 9;
  1500.    }
  1501.    lbyt( c );           /* send byte to listing too */
  1502. }
  1503.  
  1504. objflush()
  1505. {
  1506.    int i, cksum;
  1507.  
  1508.    if( pass != 3 ) return; /* just in case we get here */
  1509.  
  1510.    cksum = 0;
  1511.  
  1512.    if( objcnt > 0 ) {
  1513.       putc( ':', fobj );
  1514.       puthex( objcnt, fobj );
  1515.       puthex( objadr / 256, fobj );
  1516.       puthex( objadr % 256, fobj );
  1517.       puthex( 0, fobj );
  1518.       cksum =
  1519.          objcnt + ( objadr / 256 ) + ( objadr % 256 );
  1520.       for( i = 0; i < objcnt; ++i ) {
  1521.          puthex( objbuf[ i ], fobj );
  1522.          cksum += objbuf[ i ];
  1523.       }
  1524.       puthex( 0 - cksum, fobj );
  1525.       putc( '\n', fobj );
  1526.    }
  1527.  
  1528.    objadr = asmadr;
  1529.    objcnt = 0;}
  1530.  
  1531. puthex( b, c )
  1532. int b, c;
  1533. {
  1534.    int v;
  1535.  
  1536.    v = ( b & 0x00F0 ) >> 4;
  1537.    if( v > 9 ) v += 'A' - 10; else v += '0';
  1538.    putc( v, c );
  1539.    v = ( b & 0x000F );
  1540.    if( v > 9 ) v += 'A' - 10; else v += '0';
  1541.    putc( v, c );
  1542. }
  1543.  
  1544. long int hexbin( p )
  1545. char *p;
  1546. {
  1547.    long int v;
  1548.  
  1549.    v = 0;
  1550.  
  1551.    while( *p ) {
  1552.       if( isdigit( *p )) v = ( 16 * v ) + *p++ - '0';
  1553.          else if( *p >= 'a' && *p <= 'f' )
  1554.             v = ( 16 * v ) + *p++ - 'a' + 10;
  1555.             else ++p;
  1556.    }
  1557.  
  1558.    return v;
  1559. }
  1560.  
  1561. long int octbin( p )
  1562. char *p;
  1563. {
  1564.    long int v;
  1565.  
  1566.    v = 0;
  1567.  
  1568.    while( *p ) {
  1569.       if( *p >= '0' && *p <= '7' )
  1570.          v = ( 8 * v ) + *p++ - '0';
  1571.          else ++p;
  1572.    }
  1573.    return v;
  1574. }
  1575.  
  1576. long int bitbin( p )
  1577. char *p;
  1578. {
  1579.    long int v;
  1580.  
  1581.    v = 0;
  1582.  
  1583.    while( *p ) {
  1584.       if( *p == '0' || *p == '1' )
  1585.          v = ( 2 * v ) + *p++ - '0';
  1586.          else ++p;
  1587.    }
  1588.    return v;
  1589. }
  1590.  
  1591. long int decbin( p )
  1592. char *p;
  1593. {
  1594.    long int v;
  1595.  
  1596.    v = 0;
  1597.  
  1598.    while( *p ) {
  1599.       if( isdigit( *p )) v = ( 10 * v ) + *p++ - '0';
  1600.          else ++p;
  1601.    }
  1602.    return v;
  1603. }
  1604.  
  1605. #include "stdlib.c"
  1606.  
  1607.