home *** CD-ROM | disk | FTP | other *** search
/ ftp.whtech.com / ftp.whtech.com.7z / ftp.whtech.com / emulators / v9t9 / linux / sources / V9t9 / tools / TIAsm / tiasm.c < prev    next >
Encoding:
C/C++ Source or Header  |  2006-10-19  |  27.7 KB  |  1,540 lines

  1.  
  2. /*    V9t9: the TI Emulator! v6.0 Source 
  3.     Copyright (c) 1996 by Edward Swartz
  4. */
  5.  
  6. /*
  7.     TI-99/4A Assembler
  8.  
  9.  
  10.     For now, file formats are ordinary text/binary files.
  11.  
  12. */
  13.  
  14. extern unsigned int _stklen = 32768;
  15.  
  16. #if defined(__BORLANDC__)
  17. #include <alloc.h>
  18. #else
  19. #include <malloc.h>
  20. #endif
  21. #include <ctype.h>
  22. #include <stdio.h>
  23. #include <stdlib.h>
  24. #include <string.h>
  25.  
  26. #if defined(__GNUC__) || defined(__MWERKS__)
  27. char       *
  28. strupr(char *s)
  29. {
  30.     char       *p = s;
  31.  
  32.     while (*p) {
  33.         if (islower(*p))
  34.             *p = toupper(*p);
  35.         p++;
  36.     }
  37.     return s;
  38.  
  39.  
  40. }
  41. #endif
  42.  
  43. #if defined(__MWERKS__)
  44. void
  45. swab(unsigned char *a, unsigned char *b, int bytes) 
  46. {
  47.     while (bytes > 0) {
  48.         unsigned char t = a[0], u = a[1];
  49.  
  50.         b[0] = u;
  51.         b[1] = t;
  52.         a += 2;
  53.         b += 2;
  54.         bytes -= 2;
  55.     }
  56. }
  57. #endif 
  58.  
  59. #include "expr.h"
  60. //typedef   unsigned int    word;
  61. //typedef unsigned char byte;
  62. // current input filename
  63. char        inname[256];
  64.  
  65. // list file
  66. FILE       *list;
  67.  
  68. int         pass;
  69. int         errors;
  70. int         warnings;
  71.  
  72. #define    DEBUG if (1)
  73.  
  74. struct symbolrec {
  75.     char        name[16];
  76.     int         line;
  77.     int         addr;
  78.  
  79.     struct symbolrec *left, *right;
  80. }          *symtable;
  81.  
  82.  
  83. int         assemble(char *filename);
  84. void        breakup(char *line, char *label, char *inst, char *src,
  85.  
  86.                     char *dest);
  87. char       *skipspaces(char *line);
  88. char       *copychars(char *from, char *to, int max);
  89.  
  90. void        dolisting(word start, word end, char *line,
  91.  
  92.                       struct symbolrec *sym);
  93. int         doaline(char *line, struct symbolrec **sym);
  94.  
  95. int         addsymbol(char *name, int defining, struct symbolrec **nw);
  96.  
  97. int         decode(char **pline, struct symbolrec *label, word orgaddr,
  98.  
  99.                    byte optype);
  100.  
  101. int         getregister(char **pline, word orgaddr, byte start);
  102. int         getjump(char **pline, word orgaddr);
  103. int         getgen(char **pline, word orgaddr, byte tbit, byte bit);
  104. int         getcnt(char **pline, word orgaddr, byte bit, char *type);
  105. int         getbit(char **pline, word orgaddr);
  106.  
  107. int         getnumber(char **pline, word orgaddr, long *ret, byte * neither);
  108. int         getexpr(char **pline, word orgaddr, byte size, long *ret);
  109.  
  110.  
  111.  
  112. word        addr;
  113. byte        memory[0x8000];
  114.  
  115. char        em[256];            // error message
  116.  
  117.  
  118. struct opcoderec {
  119.     char        name[6];
  120.     word        opcode;
  121.     byte        src;
  122.     byte        dst;
  123. };
  124.  
  125. int
  126. opsort(struct opcoderec *a, struct opcoderec *b)
  127. {
  128.     return (strcmp(a->name, b->name));
  129. }
  130.  
  131. static enum { NIL, REG, REGH, REG4, GEN, GENH, JMP, BIT, CNT, CNTH,
  132.     BYT, WRD, DWD, EQU, IMM, XOP, BSS, AORG, INC, NIMM, AGAIN,
  133.     EVEN
  134. };
  135.  
  136. static struct opcoderec
  137.             opcodes[] = {
  138.     {"DB", 0x0000, BYT, AGAIN},
  139.     {"BYTE", 0x0000, BYT, AGAIN},
  140.     {"TEXT", 0x0000, BYT, AGAIN},
  141.     {"DW", 0x0000, WRD, AGAIN},
  142.     {"DATA", 0x0000, WRD, AGAIN},
  143.     {"DD", 0x0000, DWD, AGAIN},
  144.     {"EQU", 0x0000, EQU, NIL},
  145.     {"BSS", 0x0000, BSS, NIL},
  146.     {"AORG", 0x0000, AORG, NIL},
  147.     {"INCL", 0x0000, INC, NIL},
  148.     {"EVEN", 0x0000, EVEN, NIL},
  149.  
  150.     {"LI", 0x0200, REG, IMM},
  151.     {"AI", 0x0220, REG, IMM},
  152.     {"SI", 0x0220, REG, NIMM},
  153.     {"ANDI", 0x0240, REG, IMM},
  154.     {"ORI", 0x0260, REG, IMM},
  155.     {"CI", 0x0280, REG, IMM},
  156.  
  157.     {"STWP", 0x02a0, REG, NIL},
  158.     {"STST", 0x02c0, REG, NIL},
  159.  
  160.     {"LWPI", 0x02e0, IMM, NIL},
  161.  
  162.     {"LIMI", 0x0300, IMM, NIL},
  163.  
  164.     {"IDLE", 0x0340, NIL, NIL},
  165.     {"RSET", 0x0360, NIL, NIL},
  166.     {"RTWP", 0x0380, NIL, NIL},
  167.     {"CKON", 0x03a0, NIL, NIL},
  168.     {"CKOF", 0x03c0, NIL, NIL},
  169.     {"LREX", 0x03e0, NIL, NIL},
  170.  
  171.     {"BLWP", 0x0400, GEN, NIL},
  172.     {"B", 0x0440, GEN, NIL},
  173.     {"RT", 0x045B, NIL, NIL},
  174.     {"X", 0x0480, GEN, NIL},
  175.     {"CLR", 0x04c0, GEN, NIL},
  176.     {"NEG", 0x0500, GEN, NIL},
  177.     {"INV", 0x0540, GEN, NIL},
  178.     {"INC", 0x0580, GEN, NIL},
  179.     {"INCT", 0x05c0, GEN, NIL},
  180.     {"DEC", 0x0600, GEN, NIL},
  181.     {"DECT", 0x0640, GEN, NIL},
  182.     {"BL", 0x0680, GEN, NIL},
  183.     {"SWPB", 0x06c0, GEN, NIL},
  184.     {"SETO", 0x0700, GEN, NIL},
  185.     {"ABS", 0x0740, GEN, NIL},
  186.  
  187.     {"SRA", 0x0800, REG, CNT},
  188.     {"SRL", 0x0900, REG, CNT},
  189.     {"SLA", 0x0a00, REG, CNT},
  190.     {"SRC", 0x0b00, REG, CNT},
  191.  
  192.     // v9t9 internal opcodes
  193.     {"DSR", 0x0c00, NIL, NIL},
  194.     {"KEY", 0x0d80, NIL, NIL},
  195.     {"EMIT", 0x0dc0, NIL, NIL},    // R0 implicit
  196.     {"DBG", 0x0de0, NIL, NIL},
  197.     {"-DBG", 0x0de1, NIL, NIL},
  198.  
  199.     {"JMP", 0x1000, JMP, NIL},
  200.     {"NOP", 0x1000, NIL, NIL},
  201.     {"JLT", 0x1100, JMP, NIL},
  202.     {"JLE", 0x1200, JMP, NIL},
  203.     {"JBE", 0x1200, JMP, NIL},
  204.     {"JEQ", 0x1300, JMP, NIL},
  205.     {"JE", 0x1300, JMP, NIL},
  206.     {"JHE", 0x1400, JMP, NIL},
  207.     {"JAE", 0x1400, JMP, NIL},
  208.     {"JGT", 0x1500, JMP, NIL},
  209.     {"JG", 0x1500, JMP, NIL},
  210.     {"JNE", 0x1600, JMP, NIL},
  211.     {"JNC", 0x1700, JMP, NIL},
  212.     {"JOC", 0x1800, JMP, NIL},
  213.     {"JC", 0x1800, JMP, NIL},
  214.     {"JNO", 0x1900, JMP, NIL},
  215.     {"JL", 0x1A00, JMP, NIL},
  216.     {"JB", 0x1A00, JMP, NIL},
  217.     {"JH", 0x1B00, JMP, NIL},
  218.     {"JA", 0x1B00, JMP, NIL},
  219.     {"JOP", 0x1C00, JMP, NIL},
  220.  
  221.     {"SBO", 0x1d00, BIT, NIL},
  222.     {"SBZ", 0x1e00, BIT, NIL},
  223.     {"TB", 0x1f00, BIT, NIL},
  224.  
  225.     {"COC", 0x2000, GEN, REGH},
  226.     {"CZC", 0x2400, GEN, REGH},
  227.     {"XOR", 0x2800, GEN, REGH},
  228.     {"XOP", 0x2c00, GEN, XOP},
  229.     {"LDCR", 0x3000, GEN, CNTH},
  230.     {"STCR", 0x3400, GEN, CNTH},
  231.     {"MPY", 0x3800, GEN, REGH},
  232.  
  233.     {"MUL", 0x3800, GEN, REGH},
  234.     {"DIV", 0x3c00, GEN, REGH},
  235.  
  236.     {"SZC", 0x4000, GEN, GENH},
  237.     {"SZCB", 0x5000, GEN, GENH},
  238.     {"S", 0x6000, GEN, GENH},
  239.     {"SB", 0x7000, GEN, GENH},
  240.     {"C", 0x8000, GEN, GENH},
  241.     {"CB", 0x9000, GEN, GENH},
  242.     {"A", 0xa000, GEN, GENH},
  243.     {"AB", 0xb000, GEN, GENH},
  244.     {"MOV", 0xc000, GEN, GENH},
  245.     {"MOVB", 0xd000, GEN, GENH},
  246.     {"SOC", 0xe000, GEN, GENH},
  247.     {"SOCB", 0xf000, GEN, GENH},
  248.     {"", 0x0000, NIL, NIL}
  249. };
  250.  
  251. #define    OPCOUNT (sizeof(opcodes)/sizeof(opcodes[0]))
  252.  
  253. typedef int sorter(const void *, const void *);
  254.  
  255. enum {
  256.     A_rom = 1 << (0x0000 / 0x2000),
  257.     A_module = 1 << (0x6000 / 0x2000),
  258.     A_grom = 7 << (0x0000 / 0x2000),
  259.     A_dsr = 1 << (0x4000 / 0x2000)
  260. } addrmask, warnmask;
  261.  
  262. #define BANKUSED(a) (1 << ((a) / 0x2000))
  263. #define INRANGE(a) (addrmask & BANKUSED(a))
  264.  
  265. int
  266. main(int argc, char *argv[])
  267. {
  268.     int         ap;
  269.     char       *romout = 0, *modout = 0, *dsrout = 0, *gromout = 0;
  270.     char       *listout = 0;
  271.  
  272.     if (argc < 3) {
  273.         printf
  274.             ("TIASM <input file> [-r <console ROM output>] [-m <module ROM output>]\n"
  275.              "[-d <DSR ROM output>] [-g <console GROM output>] [<list file>]\n"
  276.              "\n" "-r saves the 8k memory block at >0000.\n"
  277.              "-m saves the 8k memory block at >6000.\n"
  278.              "-d saves the 8k memory block at >4000.\n"
  279.              "-g saves the 24k memory block at >0000.  This can only be used with -m.\n");
  280.         return 1;
  281.     }
  282.  
  283.     addrmask = 0;
  284.     warnmask = 0;
  285.     ap = 1;
  286.     strcpy(inname, argv[ap++]);
  287.  
  288.     while (ap < argc) {
  289.         if (strcmp(argv[ap], "-r") == 0) {
  290.             romout = argv[++ap];
  291.             if (!(addrmask & A_rom))
  292.                 addrmask |= A_rom;
  293.             else {
  294.                 printf("-r specified twice, or -g also specified");
  295.                 return 1;
  296.             }
  297.         } else if (strcmp(argv[ap], "-m") == 0) {
  298.             modout = argv[++ap];
  299.             if (!(addrmask & A_module))
  300.                 addrmask |= A_module;
  301.             else {
  302.                 printf("-m specified twice");
  303.                 return 1;
  304.             }
  305.         } else if (strcmp(argv[ap], "-d") == 0) {
  306.             dsrout = argv[++ap];
  307.             if (!(addrmask & A_dsr))
  308.                 addrmask |= A_dsr;
  309.             else {
  310.                 printf("-d specified twice, or -g also specified");
  311.                 return 1;
  312.             }
  313.         } else if (strcmp(argv[ap], "-g") == 0) {
  314.             gromout = argv[++ap];
  315.             if (!(addrmask & A_grom))
  316.                 addrmask |= A_grom;
  317.             else {
  318.                 printf("-g specified twice, or -r|-d also specified");
  319.                 return 1;
  320.             }
  321.         } else if (argv[ap][0] == '-') {
  322.             printf("Unknown option %s\n", argv[ap]);
  323.             return 1;
  324.         } else
  325.             listout = argv[ap];
  326.         ap++;
  327.     }
  328.  
  329.     qsort((void *) opcodes, OPCOUNT - 1, sizeof(struct opcoderec),
  330.  
  331.           (sorter *) opsort);
  332.  
  333.     if (listout) {
  334.         list = fopen(listout, "w");
  335.         if (list == NULL) {
  336.             printf("Could not open listing file '%s'\n", listout);
  337.             return 1;
  338.         }
  339.     }
  340.  
  341.  
  342.     pass = 0;
  343.     errors = 0;
  344.     strcpy(inname, argv[1]);
  345.     symtable = NULL;
  346.     addr = 0;
  347.     if (assemble(inname) == 0) {
  348.         pass++;
  349.         addr = 0;
  350.         if (assemble(inname) == 0) {
  351.             FILE       *out;
  352.  
  353.             printf("Successful compilation.\n");
  354.             swab(memory, memory, 0x8000);
  355.  
  356.             if (romout) {
  357.                 out = fopen(romout, "wb");
  358.                 if (out == NULL || fwrite(memory, 1, 8192, out) != 8192) {
  359.                     printf("main: couldn't create ROM file %s\n", romout);
  360.                     return 1;
  361.                 }
  362.                 fclose(out);
  363.             }
  364.             if (dsrout) {
  365.                 out = fopen(dsrout, "wb");
  366.                 if (out == NULL ||
  367.                     fwrite(memory + 0x4000, 1, 8192, out) != 8192) {
  368.                     printf("main: couldn't create DSR file %s\n", romout);
  369.                     return 1;
  370.                 }
  371.                 fclose(out);
  372.             }
  373.             if (modout) {
  374.                 out = fopen(modout, "wb");
  375.                 if (out == NULL ||
  376.                     fwrite(memory + 0x6000, 1, 8192, out) != 8192) {
  377.                     printf("main: couldn't create module file %s\n", romout);
  378.                     return 1;
  379.                 }
  380.                 fclose(out);
  381.             }
  382.             if (gromout) {
  383.                 out = fopen(gromout, "wb");
  384.                 if (out == NULL || fwrite(memory, 1, 24576, out) != 24576) {
  385.                     printf("main: couldn't create GROM file %s\n", gromout);
  386.                     return 1;
  387.                 }
  388.                 fclose(out);
  389.             }
  390.         } else
  391.             printf("PASS 2:  %d errors.\n", errors);
  392.     } else {
  393.         printf("PASS 1:  %d errors.\n", errors);
  394.     }
  395.  
  396.     if (list)
  397.         fclose(list);
  398.  
  399.     return errors != 0;
  400. }
  401.  
  402.  
  403.  
  404.  
  405. #define    WARNING(s) {    \
  406.             fprintf(stderr,"Warning:  %s (%d): %s\n",inname,linenum,s); \
  407.             if (list) \
  408.             fprintf(list,"Warning:  %s (%d): %s\n",inname,linenum,s); \
  409.             warnings++; \
  410.            }
  411.  
  412. #define    ERROR(s,v,r) {    \
  413.             sprintf(em,s,v); \
  414.             fprintf(stderr,"Error:  %s (%d): %s\n",inname,linenum,em); \
  415.             if (list) \
  416.             fprintf(list,"Error:  %s (%d): %s\n",inname,linenum,em); \
  417.             errors++; \
  418.             return r; \
  419.            }
  420.  
  421.  
  422.  
  423. #define    FATAL(s) {    \
  424.             fprintf(stderr,"Fatal:  %s (%d): %s\n",inname,linenum,s); \
  425.             if (list) \
  426.             fprintf(list,"Fatal:  %s (%d): %s\n",inname,linenum,s); \
  427.             exit(1); \
  428.          }
  429.  
  430.  
  431. #define    FIXADDR addr=(addr+1)&0xfffe
  432. #define    WORD(a) (*(word *)(memory+(a)))
  433. #define    BYTE(a) (memory[(a)^1])
  434.  
  435.  
  436. int         linenum;
  437.  
  438.  
  439. int
  440. assemble(char *filename)
  441. {
  442.     FILE       *in;
  443.     char        line[256];
  444.     char        orgline[256];
  445.     int         err;
  446.     word        orgaddr;
  447.     struct symbolrec *sym;
  448.     int         oldline;
  449.     char        oldname[256];
  450.  
  451.     int         last = 0;
  452.  
  453.  
  454.     in = fopen(filename, "r");
  455.     if (in == NULL) {
  456.         printf("parse: couldn't open input file %s\n", filename);
  457.         return 1;
  458.     }
  459.  
  460.     oldline = linenum;
  461.     strcpy(oldname, inname);
  462.  
  463.     linenum = 1;
  464.     strcpy(inname, filename);
  465.  
  466.     while (!feof(in) && !last) {
  467.         sym = NULL;
  468.         em[0] = 0;
  469.         if (fgets(line, 256, in) != NULL) {
  470.             if (line[strlen(line) - 1] != '\n')
  471.                 last = 1;        // buggy fgets
  472.             strcpy(orgline, line);
  473.  
  474.             orgaddr = addr;
  475.             err = doaline(line, &sym);
  476.  
  477.             if (pass && list)
  478.                 dolisting(orgaddr, addr, orgline, sym);
  479.  
  480.             if (err)
  481.                 break;
  482.             linenum++;
  483.         } else
  484.             last = 1;
  485.     }
  486.     fclose(in);
  487.     if (pass && list)
  488.         fprintf(list, "\n");
  489.  
  490.     linenum = oldline;
  491.     strcpy(inname, oldname);
  492.  
  493.     err |= errors;
  494.  
  495.     return err;
  496. }
  497.  
  498.  
  499.  
  500.  
  501. void
  502. dolisting(word start, word end, char *line, struct symbolrec *sym)
  503. {
  504.     int         first, printed;
  505.     int         trailing;
  506.  
  507.     if (start == end || !INRANGE(start))
  508.         if (sym == NULL)
  509.             fprintf(list, "%05d                          \t%s", linenum, line);
  510.         else if (sym->addr == start)
  511.             fprintf(list, "%05d >%04X                    \t%s", linenum,
  512.                     sym->addr, line);
  513.         else
  514.             fprintf(list, "%05d       >%04X              \t%s", linenum,
  515.                     sym->addr, line);
  516.     else {
  517.         first = 1;
  518.         trailing = 0;
  519.         while (start < end && trailing < 5) {
  520.             printed = 0;
  521.             if (first)
  522.                 fprintf(list, "%05d >%04X=", linenum, start);
  523.             else {
  524.                 fprintf(list, "            ");
  525.                 trailing++;
  526.             }
  527.  
  528.             while (printed < 3 && start < end) {
  529.                 if (start & 1) {
  530.                     fprintf(list, "  >%02X ", BYTE(start));
  531.                     start++;
  532.                 } else {
  533.                     fprintf(list, ">%04X ", WORD(start));
  534.                     start += 2;
  535.                 }
  536.                 printed++;
  537.             }
  538.  
  539.             while (printed < 3) {
  540.                 fprintf(list, "      ");
  541.                 printed++;
  542.             }
  543.  
  544.             if (first) {
  545.                 fprintf(list, " \t%s", line);
  546.                 first = 0;
  547.             } else
  548.                 fprintf(list, "\n");
  549.         }
  550.     }
  551. }
  552.  
  553.  
  554.  
  555. char       *
  556. skipspaces(char *line)
  557. {
  558.     while (isspace(*line))
  559.         line++;
  560.     return line;
  561. }
  562.  
  563. char       *
  564. copychars(char *from, char *to, int max)
  565. {
  566.     while ((!isspace(*from)) && *from)
  567.         if (max) {
  568.             *to++ = *from++;
  569.             max--;
  570.         } else if (*from)
  571.             from++;
  572.     *to++ = 0;
  573.     return from;
  574. }
  575.  
  576.  
  577.  
  578.  
  579.  
  580. void
  581. losecomments(char *line)
  582. {
  583.     char        temp[256];
  584.     char        ch;
  585.     char       *tp;
  586.  
  587. //  char    *lst,*fst;
  588.  
  589.     strcpy(temp, line);
  590.     tp = temp;
  591. //  fst=line;
  592.     while (*tp) {
  593.         ch = *tp++;
  594.         if (ch == '\n' || ch == ';')
  595.             break;
  596.         *line++ = ch;
  597.     }
  598.  
  599. /*    lst=line-1;
  600.     while (lst>fst && (*lst==' ' || *lst=='\t'))
  601.         lst--;
  602.     line=lst;*/
  603.  
  604.     *line++ = 0;
  605.     *line++ = 0;
  606. }
  607.  
  608.  
  609. int
  610. skipcommas(char **pline, int must)
  611. {
  612.     char       *line = *pline;
  613.  
  614.     line = skipspaces(line);
  615.     if (*line++ != ',')
  616.         if (must)
  617.             ERROR("Comma expected", "", 1)
  618.                 else
  619.         {
  620.             *pline = line;
  621.             return 1;
  622.         }
  623.  
  624.  
  625.     line = skipspaces(line);
  626.     *pline = line;
  627.     return 0;
  628. }
  629.  
  630. int
  631. pushw(word w)
  632. {
  633. //  FIXADDR;
  634.  
  635.     if (!INRANGE(addr)) {
  636.         if (!(warnmask & BANKUSED(addr))) {
  637.             WARNING("PUSHW:  Writing to non-stored memory bank");
  638.             warnmask |= BANKUSED(addr);
  639.         }
  640.     }
  641.  
  642.     if (addr >= sizeof(memory))
  643.         FATAL("Address larger than memory\n");
  644.  
  645.     WORD((addr + 1) & 0xfffe) = w;
  646.  
  647. //DEBUG fprintf(stderr,"pushw: @>%04X := >%04X\n",addr,w);
  648.  
  649.     addr += 2;
  650.     return 0;
  651. }
  652.  
  653. int
  654. pushb(byte b)
  655. {
  656.     if (!INRANGE(addr)) {
  657.         if (!(warnmask & BANKUSED(addr))) {
  658.             WARNING("PUSHB:  Writing to non-stored memory bank");
  659.             warnmask |= BANKUSED(addr);
  660.         }
  661.     }
  662.  
  663.     if (addr >= sizeof(memory))
  664.         FATAL("Address larger than memory\n");
  665.  
  666.     BYTE(addr) = b;
  667.  
  668. //DEBUG fprintf(stderr,"pushb: @>%04X := >%02X\n",addr,b);
  669.  
  670.     addr++;
  671.     return 0;
  672. }
  673.  
  674.  
  675. #if defined(__BORLANDC__)
  676. int
  677. swap(int a)
  678. {
  679.     asm {
  680.     mov         ax, a ror ax, 8} return _AX;
  681. }
  682.  
  683. #else
  684. word swap(word a)
  685. {
  686.     return ((a & 0xff) << 8) | ((a & 0xff00) >> 8);
  687. }
  688.  
  689. #endif
  690.  
  691. int         quoting, quotesize;
  692. char        quoted[256];
  693.  
  694.  
  695.  
  696.  
  697. int
  698. doaline(char *line, struct symbolrec **sym)
  699. {
  700.  
  701.  
  702.  
  703. //  struct instrec inst;
  704. //  struct symbolrec *sym;
  705.  
  706.     char        ch;
  707.     char        labelname[17];
  708.     char        opcode[6];
  709.  
  710.     struct opcoderec *om;
  711.     byte        optype;
  712.     word        orgaddr;
  713.  
  714.  
  715.     orgaddr = addr;
  716.     quoting = 0;
  717.  
  718.     ch = *line;
  719.  
  720.     losecomments(line);
  721.  
  722. //DEBUG fprintf (stderr,"(%d) %s\n",linenum,line);
  723.  
  724.     //  Get a label
  725.  
  726.     if (*line == 0)
  727.         return 0;
  728.  
  729.     *sym = NULL;
  730.     if (!isspace(ch)) {
  731.         memset(labelname, 0, 16);
  732.         line = copychars(line, labelname, 16);
  733.  
  734.         if (labelname[strlen(labelname) - 1] == ':')
  735.             labelname[strlen(labelname) - 1] = 0;
  736.  
  737.         if (labelname[15]) {
  738.             WARNING("Label name truncated");
  739.             labelname[15] = 0;
  740.         }
  741.  
  742.         strupr(labelname);
  743.         if (addsymbol(labelname, 1, sym))
  744.             return 0;
  745.     } else
  746.         *labelname = 0;
  747.  
  748.     line = skipspaces(line);
  749.     if (*line) {
  750.         line = copychars(line, opcode, 5);
  751.         line = skipspaces(line);
  752.         strupr(opcode);
  753.  
  754.  
  755.         om = (struct opcoderec *)
  756.             bsearch(opcode, opcodes, OPCOUNT - 1, sizeof(struct opcoderec),
  757.                     (sorter *) opsort);
  758.  
  759.         if (om != NULL) {
  760.             orgaddr = addr;
  761.             if (om->opcode)
  762.                 pushw(om->opcode);
  763.             optype = om->src;
  764.             if (optype == NIL || decode(&line, *sym, orgaddr, optype));
  765.             else
  766.                 do {
  767.                     if (om->dst == NIL)
  768.                         break;
  769.  
  770.                     if (om->dst != AGAIN) {
  771.                         optype = om->dst;
  772.                         if (skipcommas(&line, 1))
  773.                             return 0;
  774.                         if (decode(&line, *sym, orgaddr, optype))
  775.                             return 0;
  776.                     } else {
  777.                         if (skipcommas(&line, 0))
  778.                             break;
  779.                         if (decode(&line, *sym, orgaddr, om->src))
  780.                             return 0;
  781.                     }
  782.  
  783.                 } while (om->dst == AGAIN && *line);
  784.         } else
  785.             ERROR("Invalid mnemonic '%s'", opcode, 0);
  786.     }
  787.  
  788.     return 0;
  789. }
  790.  
  791. /////////////////////////////////////////////////////////////////////////
  792.  
  793.  
  794.  
  795. int
  796. findsymbol(char *buffer, struct symbolrec **ret)
  797. {
  798.     struct symbolrec *s;
  799.     char        name[16];
  800.     int         cmp;
  801.  
  802.     s = symtable;
  803.     while (s != NULL) {
  804.         strcpy(name, s->name);
  805.         name[0] &= 0x7f;
  806.         if ((cmp = strcmp(name, buffer)) == 0) {
  807.             *ret = s;
  808.             return 0;
  809.         }
  810.         if (cmp < 0)
  811.             s = s->right;
  812.         else
  813.             s = s->left;
  814.     }
  815.  
  816.     *ret = NULL;
  817.  
  818.     return 1;
  819. }
  820.  
  821.  
  822. /*
  823.     Add a symbol to the symbol table.
  824.  
  825.     Returns FATAL error if memory full,
  826.         ERROR if multiple symbols.
  827.  
  828.     Uppercases the symbol.
  829.  
  830. */
  831.  
  832.  
  833. int
  834. addsymbol(char *name, int defining, struct symbolrec **nw)
  835. {
  836.     struct symbolrec *s, *n, *m, **l;
  837.     int         cmp;
  838.     char        compare[18];
  839.  
  840.     n = malloc(sizeof(struct symbolrec));
  841.  
  842.     if (n == NULL) {
  843.         FATAL("Memory full!");
  844.     } else {
  845.         strcpy(n->name, name);
  846.         strupr(n->name);
  847.  
  848.         if ((strchr("0123456789>$", n->name[0]) != NULL) ||
  849.             (strpbrk(n->name, "+-=, ;*/<>") != NULL))
  850.             ERROR("Illegal character(s) in label '%s'", n->name, 1);
  851.  
  852.         if (!defining) {
  853.             n->name[0] |= 0x80;    // not defined yet
  854.         }
  855.  
  856.         n->addr = addr;
  857.         n->line = linenum;
  858.         n->left = n->right = NULL;
  859.  
  860. //DEBUG     fprintf(stderr,"Adding symbol '%s' on line %d at >%04X\n",name,linenum,addr);
  861.     }
  862.  
  863.     if (symtable == NULL)
  864.         symtable = s = n;
  865.     else {
  866.         if (defining) {
  867.             if (findsymbol(n->name, &m) == 0) {    // found alreddy
  868.                 if (!(m->name[0] & 0x80) && !pass)    // redefine?
  869.                 {
  870.                     ERROR("Multiple definition of '%s'", n->name, 1);
  871.                 }
  872.                 m->name[0] &= 0x7f;
  873.                 m->addr = addr;
  874.                 free(n);
  875.                 *nw = m;
  876.                 return 0;
  877.             }
  878.         }
  879.  
  880.         s = symtable;
  881.         while (s != NULL) {
  882.             strcpy(compare, s->name);
  883.             compare[0] &= 0x7f;
  884.             cmp = strcmp(compare, n->name);
  885.             if (!pass && cmp == 0)
  886.                 ERROR("Multiple symbol '%s'", n->name, 0);
  887.             if (cmp < 0) {
  888.                 l = &s->right;
  889.                 s = s->right;
  890.             } else {
  891.                 l = &s->left;
  892.                 s = s->left;
  893.             }
  894.  
  895.         }
  896.  
  897.         *l = n;
  898.     }
  899.  
  900.     *nw = n;
  901.     return 0;
  902. }
  903.  
  904.  
  905. /*
  906.     This routine will return address of the name.
  907.  
  908.     If the symbol not found, a blank entry will be added to the
  909.         symbol table and zero returned.
  910.     If it's undefined, a new link will be made using record->addr
  911.         and the address of the last link returned.
  912.  
  913.     The special symbol "$" is handled here.
  914.  
  915. */
  916. int
  917. getsymboladdress(word orgaddr, char *name, int *ret)
  918. {
  919.     struct symbolrec *s;
  920.  
  921.  
  922.     if (strcmp(name, "$") == 0) {
  923.         *ret = orgaddr;
  924.         return 0;
  925.     }
  926.  
  927.     if (findsymbol(name, &s) == 0)    // found, defined
  928.     {
  929.         if (pass == 0) {
  930.             *ret = 0;
  931.             return 0;
  932.         } else if (s->name[0] & 0x80)
  933.             ERROR("Unresolved symbol '%s'", name, 1)
  934.                 else
  935.         {
  936.             *ret = s->addr;        // return defined addr
  937.             return 0;
  938.         }
  939.     } else if (pass)
  940.         ERROR("Undefined symbol '%s'", name, 1)
  941.             else
  942.     {
  943.         if (addsymbol(name, 0, &s) == 0)    // adding, undefined
  944.         {
  945.             *ret = 0;
  946.             return 0;
  947.         } else
  948.             return 1;            // ouch!
  949.     }
  950. }
  951.  
  952.  
  953. //////////////////////////////////////////////////////////////////////
  954.  
  955. /*
  956.     GETNUMBER will decode a number or an address as a long.
  957.  
  958.     *pline is non-null
  959. */
  960.  
  961. int
  962. getnumber(char **pline, word orgaddr, long *ret, byte * neither)
  963. {
  964.     static char *abasestr = "0123456789ABCDEF";
  965.     char        basestr[18];
  966.     char        name[18];
  967.     char       *line = *pline;
  968.     char       *start;
  969.     char       *where;
  970.     long        val;
  971.     int         base;
  972.     byte        dig;
  973.     byte        not;
  974.     byte        smt;
  975.     char        ch;
  976.     char       *format;
  977.     int         err;
  978.     struct symbolrec *s;
  979.     int         addr;
  980.  
  981.     ch = *line;
  982.  
  983.     not = (ch == '~');
  984.     if (not)
  985.         line++;
  986.  
  987.  
  988.     if (ch == '>') {
  989.         base = 16;
  990.         line++;
  991.     } else
  992.         base = 10;
  993.  
  994.     start = line;
  995.  
  996.     memcpy(basestr, abasestr, base);
  997.     basestr[base] = 0;
  998.  
  999.     val = 0;
  1000.     err = 0;
  1001.     smt = 0;
  1002.     while (!err) {
  1003.         where = strchr(basestr, toupper(*line));
  1004.         if (where == NULL || *where == 0) {
  1005.             if (!smt)
  1006.                 err = 1;
  1007.             else if (not)
  1008.                 val = ~val;
  1009.             break;
  1010.         }
  1011.  
  1012.         dig = where - basestr;
  1013.         val = (val * base) + dig;
  1014.         line++;
  1015.         smt = 1;
  1016.         *neither = 0;
  1017.     }
  1018.  
  1019.     if (err) {
  1020.         line = start;
  1021.         dig = 0;
  1022.         while (strchr(", \t\n+-*/()&|[]^", *line) == NULL) {
  1023.             if (dig < 15)
  1024.                 name[dig++] = (*line++);
  1025.             else
  1026.                 line++;
  1027.         }
  1028.         name[dig] = 0;
  1029.  
  1030.         if (dig) {
  1031.             *neither = 0;
  1032.             strupr(name);
  1033.             if (getsymboladdress(orgaddr, name, &addr) == 0)
  1034.                 val = addr;
  1035.             else
  1036.                 return 1;
  1037.         } else {
  1038.             *neither = 1;
  1039.             return 1;
  1040.         }
  1041.     }
  1042.  
  1043.     *pline = line;
  1044.     *ret = val;
  1045.     return 0;
  1046. }
  1047.  
  1048.  
  1049. /*
  1050.     GETEXPR will decode an expression as a long.
  1051. */
  1052. int
  1053. getexpr(char **pline, word orgaddr, byte size, long *ret)
  1054. {
  1055. #define    STMAX    32
  1056.     static long stack[STMAX];
  1057.     int         sp = 0;
  1058.     char       *line;
  1059.     long        val;
  1060.     char        name[16];
  1061.     byte        neither;
  1062.  
  1063.     line = *pline;
  1064.     line = skipspaces(line);
  1065.  
  1066.     if (*line == 0 && !quoting) {
  1067.         ERROR("Missing argument", "", 1);
  1068.     }
  1069.  
  1070.     do {
  1071.         if (sp >= STMAX)
  1072.             ERROR("Expression stack overflow!", "", 1);
  1073.         if (*line == '"') {
  1074.             quoting = 0;
  1075.             do                    // copy into quoted
  1076.                 quoted[quoting++] = *line++;
  1077.             while (*line != '"' && *line);
  1078.             if (!*line)
  1079.                 ERROR("Unterminated string", "", 1);
  1080.             line++;                // skip last quote
  1081.             while ((quoting - 1) % size)
  1082.                 quoted[quoting++] = 0;
  1083.             quotesize = quoting;
  1084.             quoting = 1;
  1085.         }
  1086.  
  1087.         if (quoting)            // quoting?
  1088.         {
  1089.             if (size == 1)
  1090.                 stack[sp++] = quoted[quoting] & 255;
  1091.             else if (size == 2)
  1092.                 stack[sp++] = ((quoted[quoting] & 255) << 8) +
  1093.                     (quoted[quoting + 1] & 255);
  1094.             else if (size == 4)
  1095.                 stack[sp++] = ((quoted[quoting] & 255) << 24) +
  1096.                     ((quoted[quoting + 1] & 255) << 16) +
  1097.                     ((quoted[quoting + 2] & 255) << 8) +
  1098.                     (quoted[quoting + 3] & 255);
  1099.             else
  1100.                 ERROR("Invalid size passed to getexpr (%hd)!", size, 1);
  1101.             quoting += size;
  1102.  
  1103.             if (quoting >= quotesize)
  1104.                 quoting = 0;
  1105.         } else if (getnumber(&line, orgaddr, &val, &neither) == 0) {
  1106.             if (sp >= 32)
  1107.                 ERROR("Expression stack overflow at '%s'", line, 1)
  1108.                     else
  1109.                 stack[sp++] = val;
  1110.         } else if (!neither)
  1111.             return 1;
  1112.         else if (strchr("+-*/%|&^[]", *line) == NULL)
  1113.             break;
  1114.         else if (sp > 1)
  1115.             switch (*line) {
  1116.             case '+':
  1117.                 sp--;
  1118.                 line++;
  1119.                 stack[sp - 1] += stack[sp];
  1120.                 break;
  1121.             case '-':
  1122.                 sp--;
  1123.                 line++;
  1124.                 stack[sp - 1] -= stack[sp];
  1125.                 break;
  1126.             case '*':
  1127.                 sp--;
  1128.                 line++;
  1129.                 stack[sp - 1] *= stack[sp];
  1130.                 break;
  1131.             case '/':
  1132.                 sp--;
  1133.                 line++;
  1134.                 if (stack[sp])
  1135.                     stack[sp - 1] /= stack[sp];
  1136.                 else if (pass)
  1137.                     ERROR("Divide by zero", "", 1);
  1138.                 break;
  1139.             case '%':
  1140.                 sp--;
  1141.                 line++;
  1142.                 stack[sp - 1] %= stack[sp];
  1143.                 break;
  1144.             case '|':
  1145.                 sp--;
  1146.                 line++;
  1147.                 stack[sp - 1] |= stack[sp];
  1148.                 break;
  1149.             case '&':
  1150.                 sp--;
  1151.                 line++;
  1152.                 stack[sp - 1] &= stack[sp];
  1153.                 break;
  1154.             case '^':
  1155.                 sp--;
  1156.                 line++;
  1157.                 stack[sp - 1] ^= stack[sp];
  1158.                 break;
  1159.             case ']':
  1160.                 sp--;
  1161.                 line++;
  1162.                 stack[sp - 1] >>= stack[sp];
  1163.                 break;
  1164.             case '[':
  1165.                 sp--;
  1166.                 line++;
  1167.                 stack[sp - 1] <<= stack[sp];
  1168.                 break;
  1169.             default:
  1170.                 ERROR("Illegal operator '%c'", *line, 1);
  1171.         } else
  1172.             ERROR("Stack underflow at '%s'", line, 1);
  1173.  
  1174.         line = skipspaces(line);
  1175.     } while (*line && *line != ',');
  1176.  
  1177.     if (sp > 1)
  1178.         ERROR("Unterminated expression", "", 1);
  1179.  
  1180.  
  1181.     *ret = stack[0];
  1182.     *pline = line;
  1183.     return 0;
  1184. }
  1185.  
  1186.  
  1187. /////////////////////////////////////////////////////////
  1188.  
  1189. /*
  1190.     Decode will encode one operand of an instruction.
  1191.  
  1192.     The optype will be used to limit the type.
  1193.  
  1194.     All operands are separated by commas.
  1195.  
  1196.     When all parameters are read, return *line==0
  1197. */
  1198.  
  1199. int
  1200. decode(char **pline, struct symbolrec *label, word orgaddr, byte optype)
  1201. {
  1202.     char       *line;
  1203.     long        val;
  1204.     long        val1, val2, val3, val4;
  1205.     byte        reg, ts, td;
  1206.     word        s, d, sa, da;
  1207.  
  1208.     line = *pline;
  1209.     if (*line == 0 && optype != EVEN)
  1210.         ERROR("Missing argument", "", 1);
  1211.  
  1212.     if (optype != BYT && optype != BSS) {
  1213.         FIXADDR;
  1214.         if (label && (label->addr & 1)) {
  1215.             label->addr = (label->addr + 1) & 0xfffe;
  1216. //      DEBUG   fprintf(stderr,"decode:bumping label addr to %04X\n",label->addr);
  1217.         }
  1218.     }
  1219.  
  1220.     switch (optype) {
  1221.     case WRD:
  1222.         do {
  1223.             if (getexpr(&line, orgaddr, 2, &val))
  1224.                 return 1;
  1225.  
  1226.             if (val < -32768 || val > 65535)
  1227.                 ERROR("Integer out of range (%ld)", val, 1);
  1228.             if (pushw(val))
  1229.                 return 1;
  1230.         } while (quoting);
  1231.         break;
  1232.  
  1233.     case BYT:
  1234.         do {
  1235.             if (getexpr(&line, orgaddr, 1, &val) == 0) {
  1236.                 if (val < -128 || val > 255)
  1237.                     ERROR("Byte out of range (%ld)", val, 1);
  1238.                 if (pushb(val))
  1239.                     return 1;
  1240.             } else
  1241.                 return 1;
  1242.         } while (quoting);
  1243.         break;
  1244.  
  1245.     case DWD:
  1246.         do {
  1247.             if (getexpr(&line, orgaddr, 4, &val) == 0) {
  1248.                 if (pushw(val >> 16) || pushw(val & 0xffff))
  1249.                     return 1;
  1250.             } else
  1251.                 return 1;
  1252.         } while (quoting);
  1253.         break;
  1254.  
  1255.     case EQU:
  1256.         if (getexpr(&line, orgaddr, 2, &val) == 0) {
  1257.             if (label != NULL)
  1258.                 if (val >= -32768 && val < 65535)
  1259.                     label->addr = val;
  1260.                 else
  1261.                     ERROR("Equate too large (%ld)", val, 1);
  1262.         } else
  1263.             return 1;
  1264.         break;
  1265.  
  1266.     case AORG:
  1267.         if (getexpr(&line, orgaddr, 2, &val) == 0)
  1268.             addr = val;
  1269.         else
  1270.             return 1;
  1271.         break;
  1272.  
  1273.     case BSS:
  1274.         if (getexpr(&line, orgaddr, 2, &val) == 0)
  1275.             addr += val;
  1276.         else
  1277.             return 1;
  1278.         break;
  1279.  
  1280.     case INC:
  1281.         line = skipspaces(line);
  1282.         return assemble(line);
  1283.  
  1284.     case EVEN:
  1285.         addr = (addr + 1) & 0xfffe;
  1286.         break;
  1287.  
  1288. ////////////////////////////////////////////////////////////////////
  1289.  
  1290.     case IMM:
  1291.         if (getexpr(&line, orgaddr, 2, &val))
  1292.             return 1;
  1293.  
  1294.         if (val < -32768 || val > 65535)
  1295.             ERROR("Integer out of range (%ld)", val, 1);
  1296.         if (pushw(val))
  1297.             return 1;
  1298.         break;
  1299.  
  1300.     case NIMM:
  1301.         if (getexpr(&line, orgaddr, 2, &val))
  1302.             return 1;
  1303.  
  1304.         if (val < -32768 || val > 65535)
  1305.             ERROR("Integer out of range (%ld)", val, 1);
  1306.         if (pushw(-val))
  1307.             return 1;
  1308.         break;
  1309.  
  1310.     case REG:
  1311.         if (getregister(&line, orgaddr, 0))
  1312.             return 1;
  1313.         break;
  1314.  
  1315.     case REGH:
  1316.         if (getregister(&line, orgaddr, 6))
  1317.             return 1;
  1318.         break;
  1319.  
  1320.     case REG4:
  1321.         if (getregister(&line, orgaddr, 4))
  1322.             return 1;
  1323.         break;
  1324.  
  1325.     case JMP:
  1326.         if (getjump(&line, orgaddr))
  1327.             return 1;
  1328.         break;
  1329.  
  1330.     case BIT:
  1331.         if (getbit(&line, orgaddr))
  1332.             return 1;
  1333.         break;
  1334.  
  1335.     case CNT:
  1336.         if (getcnt(&line, orgaddr, 4, "Shift count"))
  1337.             return 1;
  1338.         break;
  1339.  
  1340.     case CNTH:
  1341.         if (getcnt(&line, orgaddr, 6, "bit count"))
  1342.             return 1;
  1343.         break;
  1344.  
  1345.     case XOP:
  1346.         if (getcnt(&line, orgaddr, 6, "XOP vector"))
  1347.             return 1;
  1348.         break;
  1349.  
  1350.     case GEN:
  1351.         if (getgen(&line, orgaddr, 4, 0))
  1352.             return 1;
  1353.         break;
  1354.  
  1355.     case GENH:
  1356.         if (getgen(&line, orgaddr, 10, 6))
  1357.             return 1;
  1358.         break;
  1359.  
  1360.     default:
  1361.         FATAL("Operand type not implemented!");
  1362.     }
  1363.  
  1364.     *pline = line;
  1365.     return 0;
  1366. }
  1367.  
  1368.  
  1369.  
  1370.  
  1371.  
  1372. /////////////////////////////////////////////////////////////////////
  1373.  
  1374. /*
  1375.     Get a register at pline and change the word at start.
  1376. */
  1377. int
  1378. getregister(char **pline, word orgaddr, byte start)
  1379. {
  1380.     byte        neither;
  1381.     long        regval;
  1382.  
  1383.     if (getexpr(pline, orgaddr, 1, ®val) == 0)
  1384.         if (regval >= 0 && regval < 16) {
  1385.             WORD(orgaddr) |= (regval << start);
  1386.         } else
  1387.             ERROR("Illegal register specified (%d)", regval, 1)
  1388.                 else
  1389.             return 1;
  1390.  
  1391.     return 0;
  1392. }
  1393.  
  1394. /*
  1395.     Get a jump offset and set.
  1396. */
  1397. int
  1398. getjump(char **pline, word orgaddr)
  1399. {
  1400.     long        val;
  1401.     long        offs;
  1402.  
  1403.     if (getexpr(pline, orgaddr, 2, &val) == 0) {
  1404.         if (pass) {
  1405.             offs = (val - (signed) addr) / 2;
  1406.             if (offs < -127 || offs >= 128)
  1407.                 ERROR("Jump range exceeded by %d words",
  1408.                       (offs < 0 ? offs + 127 : offs - 128), 1);
  1409.             WORD(orgaddr) |= (offs & 255);
  1410.         }
  1411.         return 0;
  1412.     } else
  1413.         return 1;
  1414. }
  1415.  
  1416.  
  1417. /*
  1418.     Get a bit offset and set.
  1419. */
  1420. int
  1421. getbit(char **pline, word orgaddr)
  1422. {
  1423.     long        val;
  1424.     long        offs;
  1425.  
  1426.     if (getexpr(pline, orgaddr, 1, &val) == 0) {
  1427.         if (pass) {
  1428.             offs = val;
  1429.             if (offs < -127 || offs >= 128)
  1430.                 ERROR("Bit offset out of range (%d)", offs, 1);
  1431.             WORD(orgaddr) |= (offs & 255);
  1432.         }
  1433.         return 0;
  1434.     } else
  1435.         return 1;
  1436. }
  1437.  
  1438.  
  1439. /*
  1440.     Get a count.
  1441. */
  1442. int
  1443. getcnt(char **pline, word orgaddr, byte bit, char *type)
  1444. {
  1445.     long        val;
  1446.     long        offs;
  1447.     char        err[256];
  1448.  
  1449.     if (getexpr(pline, orgaddr, 1, &val) == 0) {
  1450.         if (pass) {
  1451.             offs = val;
  1452.             if (offs < 0 || offs > 16) {
  1453.                 sprintf(err, "%s illegal (%%d)", type);
  1454.                 ERROR(err, offs, 1);
  1455.             }
  1456.             WORD(orgaddr) |= (offs & 15) << bit;
  1457.         }
  1458.         return 0;
  1459.     } else
  1460.         return 1;
  1461. }
  1462.  
  1463. /*
  1464.     Get a general thingie.
  1465. */
  1466.  
  1467. int
  1468. getgen(char **pline, word orgaddr, byte tbit, byte bit)
  1469. {
  1470.     long        val;
  1471.     byte        t;
  1472.     char        ch;
  1473.  
  1474.  
  1475.     ch = **pline;
  1476.     if (ch == '*')                // indirect?  ts=1
  1477.     {
  1478.         t = 1;
  1479.         WORD(orgaddr) |= t << tbit;
  1480.  
  1481.         (*pline)++;
  1482.  
  1483.         if (getregister(pline, orgaddr, bit))
  1484.             return 1;
  1485.  
  1486.     } else if (ch == '+')        // autoincrement?  ts=3
  1487.     {
  1488.         t = 3;
  1489.         WORD(orgaddr) |= t << tbit;
  1490.  
  1491.         (*pline)++;
  1492.  
  1493.         ch = **pline;
  1494.         if (ch == '*')            // better be this
  1495.             (*pline)++;
  1496.         else
  1497.             ERROR("Syntax error at '%s'", *pline, 1);
  1498.  
  1499.         if (getregister(pline, orgaddr, bit))
  1500.             return 1;
  1501.  
  1502.     } else if (ch == '@')        // symbolic or indexed?  ts=2
  1503.     {
  1504.         t = 2;
  1505.         WORD(orgaddr) |= t << tbit;
  1506.  
  1507.         (*pline)++;
  1508.  
  1509.         if (getexpr(pline, orgaddr, 2, &val))
  1510.             return 1;
  1511.  
  1512.         if (val < -32768 || val > 65535)
  1513.             ERROR("Index/addr too large (%ld)", val, 1);
  1514.  
  1515.         if (pushw(val))
  1516.             return 1;
  1517.  
  1518.         *pline = skipspaces(*pline);
  1519.         ch = **pline;
  1520.         if (ch == '(')            // indexed memory?  ts=2
  1521.         {
  1522.             (*pline)++;
  1523.             if (getregister(pline, orgaddr, bit))
  1524.                 return 1;
  1525.             ch = **pline;
  1526.             if (ch != ')')
  1527.                 ERROR("Unterminated index register", "", 1)
  1528.                     else
  1529.                 (*pline)++;
  1530.  
  1531.         }
  1532.  
  1533.     } else                        // register?  ts = 0
  1534.     if (getregister(pline, orgaddr, bit))
  1535.         return 1;
  1536.  
  1537.     return 0;
  1538.  
  1539. }
  1540.