]> pd.if.org Git - mmurtl/commitdiff
autocommit for files dated 1995-02-09 16:53:44
authorRichard Burgess <>
Thu, 9 Feb 1995 16:53:44 +0000 (16:53 +0000)
committerNathan Wagner <nw@hydaspes.if.org>
Mon, 17 Oct 2016 14:03:48 +0000 (14:03 +0000)
msamples/dasmm/dasm.c [new file with mode: 0644]
msamples/dasmm/dasm.h [new file with mode: 0644]
msamples/dasmm/dasm.run [new file with mode: 0644]
msamples/dasmm/dasmdbg.c [new file with mode: 0644]
msamples/dasmm/dasmq.c [new file with mode: 0644]
msamples/dasmm/makeit.bat [new file with mode: 0644]
msamples/dasmm/read.me [new file with mode: 0644]

diff --git a/msamples/dasmm/dasm.c b/msamples/dasmm/dasm.c
new file mode 100644 (file)
index 0000000..6b05777
--- /dev/null
@@ -0,0 +1,3609 @@
+/*\r
+ * Assembler for MMURTL (MMURTL Version).\r
+ *\r
+ * Copyright 1991,1992,1993,1994,1995 R.A. Burgess\r
+\r
+  Version 1.2 11/20/93 - major rewrite on instruction table\r
+  Version 1.3 8/28/94 - Clear macro buf on level 1 to 0 transition\r
+  Version 1.4 9/29/94 - Smashed bug in 66| prefix for string commands\r
+  Version 1.5 10/5/94 - Optimized a couple of commands and fixed\r
+                               bug in ENTER X,X instruction.  This version seems\r
+                               really stable ("yeaaaaa Right," he says...)\r
+                               Actually it is....\r
+               10/29/94 Fix problem with sign extending bytes on ADD\r
+  Version 1.6  12/31/94 - Removed temp files on succesful assemble\r
+  Version 1.7M 1/1/95 - V1.6 ported to MMURTL. Changed memory allocation\r
+                               use AllocPage and also created internal buffers\r
+                               instead of using tmp files. Also use an internal\r
+                               read buffer of 4K to make better use of Readbytes().\r
+                               OutWord, OutDWord, and OutByte had to be renamed\r
+                               so they would not conflict with MMURTL publics of\r
+                               the same names.\r
+\r
+ */\r
+\r
+#define U32 unsigned long\r
+#define S32 long\r
+#define U16 unsigned int\r
+#define S16 int\r
+#define U8 unsigned char\r
+#define S8 char\r
+\r
+\r
+#include <ctype.h>\r
+#include <stdio.h>\r
+#include <string.h>\r
+#include <stdlib.h>\r
+\r
+#include "dasm.h"\r
+#include "runfile.h"\r
+#include "\OSSource\MMemory.h"\r
+#include "\OSSource\MFiles.h"\r
+\r
+/* variables */\r
+\r
+#define LEVELS 5\r
+U32 level = 0;                         /* current include level */\r
+U32 lineno[LEVELS];                    /* line number being parsed */\r
+U8 fContinue = 0;                      /* True if just returned from include */\r
+\r
+char srcname[LEVELS][40];      /* also active include filenames */\r
+char runname[40];\r
+char lstname[40];\r
+\r
+/* File handles for all files */\r
+\r
+FILE *src_fh[5] = {0,0,0,0,0}; /* Current source file */\r
+FILE *run_fh   = 0;                            /* Current .RUN, .DLL, or .DDR (output) */\r
+\r
+FILE *lst_fh   = 0;            /* List file */\r
+FILE *sym_fh   = 0;            /* Symbol file for debugger */\r
+\r
+#define STMPBUFS 512000\r
+\r
+U8 *pcsbuf, *pdsbuf;   /* half meg allocated buffers for code & data */\r
+U32 ics, ids;                  /* current index into tmp code & data buffers */\r
+\r
+U8 filetype = 1;               /* 1 = RUN, 2 = DLL, 3 = DDR */\r
+\r
+U8 fListA = 0;                 /* True if detailed list file */\r
+U8 fListE = 0;                 /* True if Error only list file */\r
+U8 fSymDump = 0;               /* True if we add symbols to the list file */\r
+U8 Column = 0;                 /* where are we on the LIST line */\r
+U32 error_count = 0;\r
+U32 warn_count = 0;\r
+\r
+ /* Max input line is 132, but 200 allows plenty for macro subs */\r
+S8 line_buf0[200];     /* Two buffers are swapped during macro substitution */\r
+S8 line_buf1[200];\r
+S8 *line_ptr;          /* pointer to next char on line */\r
+\r
+S8 list_buf[200];      /* Used to hold line string for list file */\r
+S8 fLineIn =0;         /* TRUE is list_buf has something to list */\r
+\r
+S8   TString[133];     /* all parsed tokens are placed here in text form */\r
+S32  CBString;         /* size of parsed token */\r
+S32  TSymnum;          /* Symbol table entry number, else 0 */\r
+U32  TNumber;          /* value of numeric token */\r
+S32  TInst;                    /* Instruction number, else 0 */\r
+S32  TReg;                     /* Register number, else 0 */\r
+S32  Token;                    /* Token type (also returned from parse) */\r
+S8   fPutBack = 0;  /* TRUE (non=zero) if last token was not used */\r
+\r
+S8   LTString[133];    /* Duplicates of Token storage for ReturnToken(); */\r
+S32  LCBString;\r
+S32  LTSymnum;\r
+U32  LTNumber;\r
+S32  LTInst;\r
+S32  LTReg;\r
+S32  LToken;\r
+\r
+S8  UString[31];       /* Place to save unknown labels for Forward Reference */\r
+S32 UCBString;         /* Size of Unknown label */\r
+\r
+/* The two Symbol tables have 5 entries;  Type, Size, Pointer to Name,\r
+   Segment Offset, and Line.\r
+   As each symbol is found, it's identifed by type, and the name\r
+   is moved to the packed symbol buffer. A pointer is added to the\r
+   table to point to the name in the buffer, while it's size, type,\r
+   segment offset, and line number are added to the table.\r
+   Macro names are also stored in the symbol table, but offset entry\r
+   for a macro indicates it's offset in the Macro buffer.\r
+*/\r
+\r
+/* Variables for symbol tables */\r
+\r
+/* Global Symbol Table */\r
+\r
+#define SYMSMAX 700\r
+#define SYMBUFMAX 16384        /* Avg of 10 byte per name, 700 Max */\r
+\r
+struct symtab {\r
+       U32  Type;              /* Token (e.g, CLabel) */\r
+       U32  Line;              /* Line symbol was declared on */\r
+       U32  Size;              /* Size of symbol name */\r
+       S8   *Ptr;              /* Pointer to name in packed buffer */\r
+       U32  Offs;              /* Offset in segment */\r
+       };\r
+\r
+struct symtab gst[SYMSMAX];    /* storage for the GST */\r
+\r
+/* S8  SymBuf[SYMBUFMAX];      */      /* Where names are stored. Will be Alloced */\r
+S8 *pSymBuf;                           /* ptr to allocated buffer */\r
+\r
+S8   *pSymNext;                /* ptr to next new entry in symbol buffer */\r
+S32  iSymNext = 1;     /* index to next new symbol table entry.  */\r
+                                       /* Starts at 1 - zero it reserved because */\r
+                                       /* Parse returns 0 for EOL */\r
+\r
+S8 fPublic = 0;\r
+S8 fExtern = 0;\r
+S8 fFarLabel = 0;\r
+\r
+/*********** Local Symbol Table *************/\r
+\r
+/* This is cleared after each include file from level 1 is closed */\r
+/* Clearing means we reset *pLSymNext to begining of buffer */\r
+/* and reset iLSymNext to 1. This "hides" local symbols. */\r
+\r
+#define LSYMSMAX 1800\r
+#define LSYMBUFMAX 32768                       /* Avg of 7 bytes per name */\r
+\r
+struct symtab lst[LSYMSMAX];   /* storage for the LST */\r
+\r
+/* S8  LSymBuf[LSYMBUFMAX]; */         /* Where names are stored.*/\r
+S8  *pLSymBuf;                                 /* for allocated buffer */\r
+\r
+S8   *pLSymNext;       /* ptr to next new entry in symbol buffer */\r
+S32  iLSymNext = 1;    /* index to next new symbol table entry.  */\r
+                                       /* Starts at 1 - zero it reserved because */\r
+                                       /* Parse returns 0 for EOL */\r
+\r
+/************* Forward Ref Table *********************************/\r
+/*\r
+   Labels that are encountered as forward references are\r
+   stored in this table.  When we run across a forward, we do\r
+   not know what segment they are refering to unless it is from\r
+   a jump, call, or loop instruction.  We will NOT know for many\r
+   items until they are actually declared.  After all the code\r
+   and data has been processed, we go through this table\r
+   and fix all the unknown references using the relative\r
+       The type of forward references are:\r
+\r
+               1) DSEG DWORD item refers to UNK item (?Seg MemRef)\r
+               2) CSEG DWORD item refers to UNK item (?Seg MemRef)\r
+               3) CSEG to CSEG relative 8  (Jump, Jc, or Loop)\r
+               4) CSEG to CSEG relative 32 (Jump or Call)\r
+\r
+       MOTE: If a calculation is made with the unknown reference, 0\r
+       is used in the calculation. We ALWAYS ADD the value we stored\r
+       with what is found when the reference is resolved.\r
+\r
+*/\r
+\r
+#define FREFTABMAX 32768\r
+#define FREFSMAX   32768/14\r
+#define FREFBUFMAX 16384\r
+\r
+/* Types of forward references. */\r
+\r
+#define DSEGREF   1            /* 32 bit Abs Ref in DSeg, to what is unknown! */\r
+#define CSEGREF   2            /* 32 bit Abs Ref in CSeg, to what is unknown! */\r
+#define CCR32REF  3            /* 32 bit Relative in CSeg */\r
+#define CCR8REF   4            /* 8 bit Relative in CSeg */\r
+\r
+struct forreftab {\r
+       U8   Type;      /* 1, 2, 3, or 4 */\r
+       U8   NameSz;    /* Size of ref name */\r
+       U32  Line;              /* Line reference was made on  (for error if not found) */\r
+       S8   *Ptr;              /* Pointer to name in packed buffer */\r
+       S32  Offs;              /* Offset in segment were it should go */\r
+       };\r
+\r
+struct forreftab *pfrt;        /* pointer to allocated table */\r
+\r
+S8   *pRefBuf;\r
+S8   *pRefNext;                /* ptr to next new entry in symbol buffer */\r
+S32  iRefNext = 0;     /* index to next new forward ref table entry.  */\r
+\r
+/************ External Reference table ************/\r
+\r
+/* External definitions that are encountered in a module are\r
+   first entered in the Global Symbol Table (GST) as externals\r
+   if they haven't already been defined (public) by the module\r
+   that owns them.\r
+   When a reference is made to an external, we see if the public has\r
+   already been defined. If so, we resolve it immediately. If not,\r
+   we make an entry in the External Reference Table (ERT).  The\r
+   entry has the following 4 pieces of information:\r
+     - Line where reference was made.\r
+     - Index to place holder entry in GST.\r
+        - Segment where reference was made (boolean - TRUE for code seg).\r
+        - Offset in that segment where the resolution will be made.\r
+   With this information we can reslove all the external references\r
+   before we write the code segment to the run file.\r
+*/\r
+\r
+#define EREFSMAX 400\r
+\r
+struct extreftab {\r
+       U8   Type;   /* Type of reference so we know how to apply it */\r
+       U32  iSym;       /* Index of gst entry. Hi bit set if CSeg ref */\r
+       U32  Offs;       /* Offset in segment were ref needs 32 bit fixing */\r
+       };\r
+\r
+struct extreftab ert[FREFSMAX];\r
+\r
+S32  iERefNext = 0;    /* index to next external ref table entry.  */\r
+\r
+U32 nExtRef;\r
+\r
+/*********** Fix Up Table *********************/\r
+\r
+/* This table holds 6 types of fixups along with the offset\r
+   in the segment to be fixed up, and if applicable, an index\r
+   to the DLL public name in the GST (which should be defined\r
+   as EXTRNDLL):\r
+     - Fixup type\r
+         - Ref in CSEG to address in DSEG\r
+         - Ref in CSEG to address in CSEG\r
+         - Ref in DSEG to address in DSEG\r
+         - Ref in DSEG to address in CSEG\r
+         - CSEG DLL near 32 bit call used\r
+         - CSEG DLL near 32 bit call defined\r
+     - Offset of 32 bit reference to be resolved\r
+     - Index to DLL public name in GST (if applicable)\r
+\r
+   With this information we can supply the loader with the TAG entries\r
+   in the RUN file needed to resolve them.  Most of these entries will\r
+   be made as we parse the code, but many will also be added after\r
+   we fix the forward references because we won't know what segment\r
+   the reference is made to until then.\r
+*/\r
+\r
+#define FIXUPSMAX    32768/7\r
+#define FIXUPBUFMAX  32768\r
+\r
+struct futab \r
+       {\r
+       U8   type;   /* Type of fixup C0, C1, C2, C3, C5, or C8 */\r
+       U32  Offs;       /* Offset in segment for 32 bit fixup */\r
+       U32  iSym;       /* index of DLL entry in gst, else 0 */\r
+       };\r
+\r
+struct futab *pfut;    /* pointer to allocated Fix Up Table */\r
+\r
+S32  iFUNext = 0;      /* index to next fix up table entry.  */\r
+                                       /* Starts at 0 */\r
+\r
+U32    nCDFix = 0;\r
+U32 nDDFix = 0;\r
+U32 nDCFix = 0;\r
+U32 nCCFix = 0;\r
+\r
+/********* Macro variables *******************/\r
+\r
+#define MACSMAX 300\r
+#define MACBUFMAX  4096\r
+\r
+S8   *rgMacPtr[MACSMAX];       /* pointer to simple macros */\r
+S8   *pMacBuf;\r
+S8   *pMacNext;                                /* ptr to next new entry in macro buffer */\r
+S32  iMacNext = 0;                     /* index to next new symbol entry */\r
+\r
+/* Variables for current segment address offset tracking */\r
+\r
+S8  fStart = 0;                        /* True if they gave a start address */\r
+S32 StartAddr = 0;             /* Filled in when .START is encountered */\r
+S32 oNextData = 0;             /* Tracks current DSEG offset */\r
+S32 oNextCode = 0;      /* Tracks current CSEG offset */\r
+S32 CodeOffset = 0;            /* From Virtual Command */\r
+S32 DataOffset = 0;            /* From Virtual Command */\r
+S32 *pNextAddr = 0;            /* Points to current segment offset counter */\r
+S8  fDataSeg = 0;              /* True if parsing DSEG, else parsing CSEG */\r
+S32 StackTotal = 0;            /* Total Stack Specified in Code segs */\r
+\r
+/******************************************************************\r
+   Variables for RAW operands in an instruction.\r
+   These are used when we read in and separate each part of the\r
+   operands so it can be evaluated.\r
+*/\r
+\r
+S32  rgToken[3][20]; /* Raw tokens in the operand (as many as 20) */\r
+S32  rgVal[3][20];   /* value if token is number/displacement */\r
+S32  rgTID[3][20];      /* Register ID if token is a register */\r
+S32  rgTCnt[3];                 /* total count of tokens in raw operand */\r
+\r
+/******************************************************************\r
+   These variables are filled in while parsing and evaluating\r
+   instructions that have been read in.\r
+   They have all the info needed to\r
+   encode the instruction into the object module and\r
+   produce FixUp Records if needed.\r
+*/\r
+\r
+/* These are used in the description of all OPERANDS for the current\r
+   instruction we are working on.\r
+*/\r
+S32  rgOpType[3];      /* Operand type for compare to instruction */\r
+S32  rgOpReg[3];    /* If reg only, this which one */\r
+S8   OpSize[3];     /* Operand size for first two (fByte, fWord, fFar etc.) */\r
+S8   OpSizeA;       /* Overall operand size for instruction */\r
+S8   OpPrefix;      /* Bit set for a segment prefix (fESp etc.) */\r
+S32  iInstEntry;       /* Which entry is it in rgINS */\r
+S32  CrntInst;         /* instruction we are working on        */\r
+S32  InstPfx;          /* Special Insturction prefix for crnt inst */\r
+S32  nOperands;                /* number of operands we found */\r
+S8   fForRef;       /* Crnt inst makes a Forward Reference */\r
+\r
+/* The following vars are used if we have a memory reference that is\r
+   encoded as part of the instruction.\r
+*/\r
+S8   OpMType;          /* Mem type (compared to rgM32). 0 if not mem type */\r
+S32  OpBase;        /* Base register if fBase is true */\r
+S32  OpIndx;        /* Index register if fIndx is true */\r
+S32  OpDisp;        /* Displacement if fDisp8 or fDisp32 is TRUE */\r
+S32  iMemEntry;                /* If mem operand, which entry in rgM32 */\r
+\r
+/* The following are used if we have immediate values to be encoded as\r
+part of the instruction.  Immediates can also be addresses such as\r
+those in Direct and Relative Jumps and Calls!\r
+*/\r
+S32  OpImm;         /* Immediate value if fOpImm is true */\r
+S8   fOpImm;           /* If OpImm has a value */\r
+S32  OpImm2;        /* Second Imm value for iSAD and other multi-Imm types */\r
+S8   fOpImm2;          /* If OpImm2 has a value */\r
+\r
+/* This is set for each type of fixup required after an instruction\r
+line.  Data fixups are done directly in the code that generates\r
+storage in DSeg. */\r
+\r
+U8   nFixUp;           /* Fixup number (Cx) */\r
+\r
+/*************************************************************************/\r
+\r
+/* In the final stages of building an instruction, these contain the\r
+   fragment bytes of encoded instructions (along with flags for\r
+   optional parts used).\r
+*/\r
+\r
+U8  bOpc1;             /* Zero if not used */\r
+U8  bOpc2;             /* Always used */\r
+U8  bModRM;            /* ModRM byte value if used */\r
+U8  bSIB;              /* SIB value if used */\r
+S8  fModRM;    /* True if bModRM is used */\r
+S8  fSIB;      /* True if bSIB is used */\r
+\r
+/*** These are used in the expression parser ******/\r
+\r
+U8  ExpType;           /* 0 = Forward, 1 = Local, 2 = Global, 3 = Current Addr */\r
+U8  ExpType0;\r
+S32 nExpSyms;          /* Used by the numeric expression evaluator */\r
+S32 iExpSym, iExpSym0; /* if a symbol value translates to a SYMOFF,\r
+                                          this holds the symbol table index. */\r
+S8  fOffset;           /* True if derived from an Offset */\r
+\r
+/* Variables for Storage allocation */\r
+\r
+\r
+S8  fMoreStorage = 0;   /* True when storage continues to next line */\r
+S32 StoreSize = 0;\r
+\r
+/****  Variables for building the RUN File (DLL or Device Driver) ********/\r
+\r
+/* Once we have the CS and DS tmp files run through to correct any external\r
+   variables or forward labels, we build the run file.  This is done\r
+   by building the tag records, sending them followed by the proper data\r
+   for each one.\r
+*/\r
+\r
+struct tagtype tag;\r
+\r
+\r
+/******************* END VARIABLES - BEGIN CODE ********************/\r
+\r
+/* ANSI prototypes for all functions are in DProtos.h */\r
+\r
+#include "DProtos.h"\r
+\r
+\r
+/***************************************************************/\r
+/* Write a DWord to the current segment and update the counter */\r
+/***************************************************************/\r
+\r
+void OutDWordX(unsigned long Data)\r
+{\r
+unsigned char *pOut, b;\r
+long i;\r
+       pOut = &Data;\r
+       if (fDataSeg) {\r
+               for (i=0; i<4; i++) {\r
+                       b = *pOut++;\r
+                       pdsbuf[ids++] = b;      /* fputc(b , ds_fh); */\r
+               }\r
+           oNextData+=4;\r
+       }\r
+       else {\r
+               for (i=0; i<4; i++) {\r
+                       b = *pOut++;\r
+                       pcsbuf[ics++] = b;      /* fputc(b , cs_fh); */\r
+               }\r
+           oNextCode+=4;\r
+    }\r
+}\r
+\r
+/******************************************************************/\r
+/* Write a DWord to the code segment and DO NOT update counter */\r
+/******************************************************************/\r
+\r
+void OutDWordCS(unsigned long Data)\r
+{\r
+unsigned char *pOut, b;\r
+long i;\r
+       pOut = &Data;\r
+       for (i=0; i<4; i++) {\r
+               b = *pOut++;\r
+               pcsbuf[ics++] = b;      /* fputc(b , cs_fh); */\r
+       }\r
+}\r
+\r
+/******************************************************************/\r
+/* Read n bytes from the code segment                                                   */\r
+/******************************************************************/\r
+\r
+void readCS(U8 *pDataRet, long cbData)\r
+{\r
+       while (cbData--)\r
+               *pDataRet++ = pcsbuf[ics++];\r
+}\r
+\r
+\r
+/******************************************************************/\r
+/* Write n bytes to the code segment and DO NOT update counter */\r
+/******************************************************************/\r
+\r
+void writeCS(U8 *pData, long cbData)\r
+{\r
+       while (cbData--)\r
+               pcsbuf[ics++] = *pData++;\r
+}\r
+\r
+\r
+/****************************************************************\r
+  Set index into code buffer\r
+*****************************************************************/\r
+\r
+void seekCS(long offset)\r
+{\r
+       ics = offset;\r
+}\r
+\r
+\r
+/******************************************************************/\r
+/* Write a DWord to the current segment and DO NOT update counter */\r
+/******************************************************************/\r
+\r
+void OutDWordDS(unsigned long Data)\r
+{\r
+unsigned char *pOut, b;\r
+long i;\r
+       pOut = &Data;\r
+       for (i=0; i<4; i++) {\r
+               b = *pOut++;\r
+               pdsbuf[ids++] = b;      /* fputc(b , ds_fh); */\r
+       }\r
+}\r
+\r
+/******************************************************************/\r
+/* Read n bytes from the code segment                                                   */\r
+/******************************************************************/\r
+\r
+void readDS(U8 *pDataRet, long cbData)\r
+{\r
+       while (cbData--)\r
+               *pDataRet++ = pdsbuf[ids++];\r
+}\r
+\r
+/******************************************************************/\r
+/* Write n bytes to the data segment and DO NOT update counter */\r
+/******************************************************************/\r
+\r
+void writeDS(U8 *pData, long cbData)\r
+{\r
+       while (cbData--)\r
+               pdsbuf[ids++] = *pData++;\r
+}\r
+\r
+/****************************************************************\r
+  Set index into data buffer\r
+*****************************************************************/\r
+\r
+void seekDS(long offset)\r
+{\r
+       ids = offset;\r
+}\r
+\r
+/**************************************************************/\r
+/* Write a Word to the current segment and update the counter */\r
+/**************************************************************/\r
+\r
+void OutWordX(unsigned long Data)\r
+{\r
+unsigned char *pOut, b;\r
+long i;\r
+       pOut = &Data;\r
+       b = *pOut++;\r
+       if (fDataSeg) {\r
+               pdsbuf[ids++] = b;      /* fputc(b , ds_fh); */\r
+               b = *pOut;\r
+               pdsbuf[ids++] = b;      /* fputc(b , ds_fh); */\r
+           oNextData+=2;\r
+       }\r
+       else {\r
+               pcsbuf[ics++] = b;      /* fputc(b , cs_fh); */\r
+               b = *pOut;\r
+               pcsbuf[ics++] = b;      /* fputc(b , cs_fh); */\r
+           oNextCode+=2;\r
+       }\r
+}\r
+\r
+/**************************************************************/\r
+/* Write a BYTE to the current segment and update the counter */\r
+/**************************************************************/\r
+\r
+void OutByteX(unsigned char Data)\r
+{\r
+       if (fDataSeg) {\r
+               pdsbuf[ids++] = Data;   /* fputc(Data , ds_fh); */\r
+           oNextData++;\r
+       }\r
+       else {\r
+               pcsbuf[ics++] = Data;   /* fputc(b , cs_fh); */\r
+           oNextCode++;\r
+       }\r
+}\r
+\r
+/*****************************************************************/\r
+/* Write a BYTE to the current segment and DO NOT update counter */\r
+/*****************************************************************/\r
+\r
+void OutByteCS(unsigned long Data)\r
+{\r
+char b;\r
+       b = Data;\r
+       pcsbuf[ics++] = b;              /* fputc(b , cs_fh); */\r
+}\r
+\r
+/* All the "grunt work" functions are in dasmq.c */\r
+\r
+#include "DASMq.c"\r
+\r
+/*********************************************\r
+This searches the Reference table for the name\r
+described by pb, cb. It only compares items that\r
+are the same length (cb == TRefSize[x]).\r
+It returns the number or 0 if not found.\r
+**********************************************/\r
+\r
+S32 findref(S8 *pb, S32 cb)  /* pointer to, and size of string */\r
+{\r
+S32 i;\r
+S8   name[132];\r
+\r
+strncpy(name, pb, cb);         /* move name local */\r
+name[cb] = 0;                                  /* null terminate */\r
+\r
+i = iRefNext;\r
+while (i>0) {                          /* backwards through forward ref table */\r
+       i--;\r
+                               /* Only compare if same size  */\r
+       if (pfrt[i].NameSz == cb) {\r
+               if (strncmp(name, pfrt[i].Ptr, cb) == 0) return(i);\r
+       }\r
+}\r
+return(0);\r
+}\r
+\r
+\r
+/*****************************************************\r
+   Evaluates only single token operands and sets up\r
+   globals so EvalOper can finish the job.\r
+   The actual value or register is left in\r
+   rgToken[op][0], and the type is placed\r
+   in rgTempl[op][0] for a memory operand.\r
+*****************************************************/\r
+S32 EvalOper1(S32 op)\r
+{\r
+S32 i;\r
+U32 symtype;\r
+\r
+       /* Set up symtype up front in case it's needed */\r
+\r
+       if (ExpType == 1)                               /* Local */\r
+               symtype = lst[iExpSym].Type;\r
+       else if (ExpType == 2) {                /* global */\r
+               if (gst[iExpSym].Type & tEXTRN)\r
+                       nExtRef = iExpSym;\r
+               symtype = gst[iExpSym].Type;\r
+       }\r
+       else symtype = 0;\r
+\r
+       switch (rgToken[op][0]) {\r
+               case REGIST:\r
+                       if (is_r32(rgTID[op][0]))  rgOpType[op] = r32;\r
+                       else if (is_r16(rgTID[op][0])) rgOpType[op] = r16;\r
+                       else if (is_r8(rgTID[op][0]))   rgOpType[op] = r8;\r
+                       else if (is_rCRG(rgTID[op][0])) rgOpType[op] = rCRG;\r
+                       else if (is_rDRG(rgTID[op][0])) rgOpType[op] = rDRG;\r
+                       else if (is_rTRG(rgTID[op][0])) rgOpType[op] = rTRG;\r
+                       else if (is_rSEG(rgTID[op][0])) rgOpType[op] = rSEG;\r
+                       rgOpReg[op] = rgTID[op][0];\r
+                       break;\r
+               case NUMBER:\r
+                       if ((rgVal[op][0] >= -128) && (rgVal[op][0] <= 127))\r
+                 rgOpType[op] = val8;\r
+                       else if ((rgVal[op][0] >= -32768) && (rgVal[op][0] <= 32767))\r
+                 rgOpType[op] = val16;\r
+                       else rgOpType[op] = val32;\r
+                       if (!fOpImm) {\r
+                   OpImm = rgVal[op][0];\r
+                   fOpImm = 1;\r
+                   }\r
+                       else {\r
+                   OpImm2 = rgVal[op][0];\r
+                   fOpImm2 = 1;\r
+                   }\r
+                       break;\r
+               case NUMOFF:            /* OFFSET var name. IMMEDIATE VALUE. */\r
+                       OpSize[op] = fDWord;\r
+                       rgOpType[op] = val32;\r
+            OpImm = rgVal[op][0];\r
+            fOpImm = 1;\r
+                       if (symtype & CLABEL)\r
+                               nFixUp = CCFIXTAG;\r
+                       else if (symtype & DLABEL)\r
+                               nFixUp = CDFIXTAG;\r
+                       if (!symtype)\r
+                               fForRef = 1;\r
+                       break;\r
+               case SYMOFF:   /* Check for ALL jump, call & Loop instructions */\r
+\r
+                       if (ExpType == 1)                               /* Local */\r
+                               symtype = lst[iExpSym].Type;\r
+                       else if (ExpType == 2) {                /* global */\r
+                               if (gst[iExpSym].Type & tEXTRN)\r
+                                       nExtRef = iExpSym;\r
+                               symtype = gst[iExpSym].Type;\r
+                       }\r
+                       else                                                    /* Unknown - Forward */\r
+                               symtype = 0;\r
+\r
+                       if (((CrntInst >= xJA) &&\r
+                            (CrntInst <= xJZ)) ||\r
+                 (CrntInst == xCALL)) {\r
+\r
+                               if (OpSize[op] & fShort)\r
+                                       rgOpType[op]  = rel8;\r
+                               else\r
+                                       rgOpType[op] = relW;\r
+                       OpImm = rgVal[op][0];\r
+                       fOpImm = 1;\r
+                       }\r
+\r
+                       else if ((CrntInst >= xLOOP) && (CrntInst <= xLOOPZ)) {\r
+                                       rgOpType[op] = rel8;\r
+                               OpImm = rgVal[op][0];\r
+                               fOpImm = 1;\r
+                       }\r
+                       else {\r
+                               rgOpType[op]  = mem;\r
+                   OpMType |= fDisp32;\r
+                   OpDisp = rgVal[op][0];\r
+                               if (symtype & CLABEL)\r
+                                       nFixUp = CCFIXTAG;\r
+                               else if (symtype & DLABEL)\r
+                                       nFixUp = CDFIXTAG;\r
+                       }\r
+                       if (!symtype)\r
+                               fForRef = 1;\r
+                       break;\r
+               default:\r
+                  line_error(15);\r
+                  return(0);\r
+       } /* switch */\r
+\r
+/*  print_Oper(op); Testing only... */\r
+\r
+return(1);\r
+}\r
+\r
+/***********  EvalOper *******************************\r
+   Evaluates the array of reserved words, registers,\r
+   numbers, etc. that should make up an operand.\r
+   For single token operands it's easy! BUT for memory\r
+   operands it gets a little more complicated.\r
+   For memory operands we look for key sequences of\r
+   tokens that make up the "effective address" as\r
+   described in the Intel documentation, then see if\r
+   we have all the pieces to make one (EA).\r
+   This returns 1 if we can classify the operand and\r
+   there were no errors.  The type of operand we find\r
+   (e.g., r8, r16, r32, val8, val16, val32, mem,\r
+   relW, etc.) is placed in rgOpType[op].\r
+   This calls EvalOper1() to handle single token\r
+   oprerands and evaluates multiple token operands\r
+   internally. The reason we break single token operands\r
+   out in a separate call is for speed and clarity\r
+   of the code.\r
+   Special handling is required for for JMP, Jcond,\r
+   and CALL instructions because they may be using\r
+   a forward reference not yet defined.  This is the\r
+   only case where such a reference is allowed.\r
+*****************************************************/\r
+\r
+S32 EvalOper(S32 op)\r
+{\r
+S32 i;\r
+S8   fDone, fOpenSQ, fError;\r
+U32 symtype;\r
+/*\r
+These are the Raw operands:\r
+S32  rgToken[3][20];  Raw tokens in the operand\r
+S32  rgVal[3][20];    value if token is number/displacement\r
+S32  rgTID[3][20];       Register ID if token is a register\r
+S32  rgTCnt[3];                  total count of tokens in raw operand\r
+\r
+ This is what is produced:\r
+*/\r
+\r
+rgOpType[op] = 0;      /* int - Operand type for compare to instruction */\r
+rgOpReg[op] = 0;    /* If reg only, this which one */\r
+\r
+i = 0;          /* index into raw tokens */\r
+fError = 0;  /* set true for invalid operand error */\r
+fDone = 0;   /* Set when no more tokens are expected in operand */\r
+fOpenSQ = 0; /* keep track of [] */\r
+\r
+/* flags for segment instruction prefix - NONE unless otherwise set */\r
+/* If it's a single token operand, take the fast, easy way out! */\r
+\r
+if (rgTCnt[op] == 1) {\r
+       return (EvalOper1(op));\r
+}\r
+\r
+else {         /* multiple tokens in operand */\r
+\r
+       /* with more than 1 token it is usually a memory reference\r
+          but not always.  We will default to mem and change those we\r
+          find that aren't.  */\r
+\r
+       rgOpType[op] = mem;\r
+\r
+       /* Segment prefix?  If so, set flag and eat 2 tokens */\r
+\r
+       if ((rgToken[op][0]==REGIST) && (is_rSEG(rgTID[op][0]))) {\r
+               if (rgToken[op][1] == COLON) {\r
+                       switch (rgToken[op][0]) {\r
+                               case rDS: OpPrefix |= fDSp; break;\r
+                               case rES: OpPrefix |= fESp; break;\r
+                               case rSS: OpPrefix |= fSSp; break;\r
+                               case rFS: OpPrefix |= fFSp; break;\r
+                               case rGS: OpPrefix |= fGSp; break;\r
+                               case rCS: OpPrefix |= fCSp; break;\r
+                               default:;\r
+                       }\r
+                       i += 2;         /* skip rSEG and colon */\r
+               }\r
+               else {\r
+                  line_error(16);\r
+                  return(0);\r
+          }\r
+       }\r
+\r
+/* Loop through the raw tokens looking for Base Reg, Index Reg,\r
+   Scale value, or displacement and setting varaibles as needed.\r
+*/\r
+\r
+       while ((i < rgTCnt[op]) &&\r
+                 (!fError) &&\r
+                 (!fDone)) {\r
+               switch (rgToken[op][i]) {\r
+\r
+               case REGIST:\r
+                       if (is_r32(rgTID[op][i])) {  /* check for Indx & Base Reg */\r
+                if (rgToken[op][i+1] == STAR) {                /* Index w/Scale */\r
+                                       if (!(OpMType & fIndx))  {      /* still OK */\r
+                        OpMType |= fIndx;\r
+                        OpIndx = rgTID[op][i];\r
+                                               if (rgToken[op][i+2] == NUMBER) {\r
+                                                       switch (rgVal[op][i+2]) {\r
+                                                       case 2: OpMType |= fScale2; break;\r
+                                                       case 4: OpMType |= fScale4; break;\r
+                                                       case 8: OpMType |= fScale8; break;\r
+                                                       default:\r
+                                                               line_error(17);\r
+                                                               fError = 1;\r
+                                                       }\r
+                                               }\r
+                                               else {\r
+                                                       line_error(18);\r
+                                                       fError = 1;\r
+                                               }\r
+                                       }\r
+                                       else {\r
+                                               line_error(19);\r
+                                               fError = 1;\r
+                                       }\r
+                                       i+=3;   /* get past *NUMBER */\r
+                }\r
+                /* Must be base, unless fBase true, then try Index */\r
+                else {\r
+                                       if (!(OpMType & fBase)) { /* Base for sure */\r
+                        OpMType |= fBase;\r
+                        OpBase = rgTID[op][i];\r
+                        i++;\r
+                                       }\r
+                                       else {  /* try Index */\r
+                                               if (!(OpMType & fIndx)) { /* It's free, use it */\r
+                               OpMType |= fIndx;\r
+                           OpIndx = rgTID[op][i];\r
+                               i++;\r
+                                               }\r
+                                       }\r
+                               }\r
+                       }\r
+                       else { /* must be 32 bit general purpose register */\r
+                               line_error(20);\r
+                               fError = 1;\r
+                       }\r
+                       break;\r
+\r
+\r
+               case SYMOFF:  /* One symbol was used by itself or in an expression */\r
+                       if (ExpType == 1)                               /* Local */\r
+                               symtype = lst[iExpSym].Type;\r
+                       else if (ExpType == 2) {                /* global */\r
+                               if (gst[iExpSym].Type & tEXTRN)\r
+                                       nExtRef = iExpSym;\r
+                               symtype = gst[iExpSym].Type;\r
+                       }\r
+                       else                                                    /* Unknown - Forward */\r
+                               symtype = 0;\r
+\r
+                       if (OpMType & (fDisp32|fDisp8)) {   /* Already a disp! */\r
+                               line_error(21);\r
+                               fError = 1;\r
+                               }\r
+\r
+                       /* Check for conditional jumps. */\r
+\r
+                       else if ((CrntInst >= xJA) &&\r
+                                    (CrntInst <= xJZ) &&\r
+                                    (CrntInst != xJMP) &&\r
+                                    (!(fOpenSQ)))\r
+                       {\r
+                                       if (OpSize[op] & fShort)\r
+                                               rgOpType[op] = rel8;\r
+                                       else rgOpType[op] = relW;\r
+                                       if (fOpImm) {\r
+                                       OpImm2 = rgVal[op][i];\r
+                                       fOpImm2 = 1;\r
+                               }\r
+                                       else {\r
+                                       OpImm = rgVal[op][i];\r
+                                       fOpImm = 1;\r
+                                       }\r
+                                       if (!symtype)\r
+                                               fForRef = 1;\r
+                       }\r
+\r
+                               /* Check for JMP */\r
+\r
+                       else if (CrntInst == xJMP)  /* &&  (!(fOpenSQ))) */\r
+                       {\r
+                               if ((OpSize[op] & fFar) || (symtype & tFAR)) {\r
+                                       rgOpType[op] = iSAD;\r
+                                       if (fOpImm) {\r
+                                       OpImm2 = rgVal[op][i];\r
+                                       fOpImm2 = 1;\r
+                               }\r
+                                       else {\r
+                                       OpImm = rgVal[op][i];\r
+                                       fOpImm = 1;\r
+                                       }\r
+                               }\r
+                               else if (OpSize[op] & fShort) {\r
+                                       rgOpType[op] = rel8;\r
+                               OpImm = rgVal[op][i];\r
+                               fOpImm = 1;\r
+                                       if (!symtype)\r
+                                               fForRef = 1;\r
+                               }\r
+                               else if (OpSize[op] & fFWord) {\r
+                                       rgOpType[op]  = memF;  /* memF = 32 disp which has 16:32 */\r
+                           OpMType |= fDisp32;\r
+                           OpDisp = rgVal[op][i];\r
+                                       if (symtype & CLABEL)\r
+                                               nFixUp = CCFIXTAG;\r
+                                       else if (symtype & DLABEL)\r
+                                               nFixUp = CDFIXTAG;\r
+                                       if (!symtype)\r
+                                               fForRef = 1;\r
+                               }\r
+                               else {\r
+                                       rgOpType[op] = relW;\r
+                                   OpImm = rgVal[op][i];\r
+                                   fOpImm = 1;\r
+                                       if (!symtype)\r
+                                               fForRef = 1;\r
+                               }\r
+                       }\r
+\r
+                               /* Check for CALL */\r
+\r
+                       else if ((CrntInst == xCALL) && (!(fOpenSQ)))\r
+                       {\r
+                               if ((OpSize[op] & fFar) || (symtype & tFAR)) {\r
+                                       rgOpType[op] = iSAD;\r
+                                       if (fOpImm) {\r
+                                       OpImm2 = rgVal[op][i];\r
+                                       fOpImm2 = 1;\r
+                                   }\r
+                                       else {\r
+                                       OpImm = rgVal[op][i];\r
+                                       fOpImm = 1;\r
+                                       }\r
+                               }\r
+                               else if (OpSize[op] & fFWord) {\r
+                                       rgOpType[op]  = memF;  /* memF = 32 disp which has 16:32 */\r
+                           OpMType |= fDisp32;\r
+                           OpDisp = rgVal[op][i];\r
+                                       if (symtype & CLABEL)\r
+                                               nFixUp = CCFIXTAG;\r
+                                       else if (symtype & DLABEL)\r
+                                               nFixUp = CDFIXTAG;\r
+                                       if (!symtype)\r
+                                               fForRef = 1;\r
+                               }\r
+                               else {          /* Relative call */\r
+                                       rgOpType[op] = relW;\r
+                                       if (!symtype)\r
+                                               fForRef = 1;\r
+                               }\r
+                       }\r
+\r
+                               /* Check for SGDT SIDT */\r
+\r
+                       else if ((CrntInst == xSGDT) || (CrntInst == xSIDT))\r
+                       {\r
+                               if (OpSize[op] & fFWord) {\r
+                                       rgOpType[op]  = memF;  /* memF = 32 disp which has 16:32 */\r
+                           OpMType |= fDisp32;\r
+                           OpDisp = rgVal[op][i];\r
+                                       if (symtype & CLABEL)\r
+                                               nFixUp = CCFIXTAG;\r
+                                       else if (symtype & DLABEL)\r
+                                               nFixUp = CDFIXTAG;\r
+                                       if (!symtype)\r
+                                               fForRef = 1;\r
+                               }\r
+                       }\r
+\r
+                         /* Check for Loop */\r
+\r
+                       else if ((CrntInst >= xLOOP) && (CrntInst <= xLOOPZ))\r
+                       {\r
+                                       rgOpType[op] = rel8;\r
+                                   OpImm = rgVal[op][0];\r
+                                   fOpImm = 1;\r
+                                       if (!symtype)\r
+                                               fForRef = 1;\r
+                       }\r
+                       else {\r
+                                   OpDisp = rgVal[op][i];\r
+                                       OpMType |= fDisp32;\r
+                                       if (symtype & CLABEL)\r
+                                               nFixUp = CCFIXTAG;\r
+                                       else if (symtype & DLABEL)\r
+                                               nFixUp = CDFIXTAG;\r
+                                       if (!symtype)\r
+                                               fForRef = 1;\r
+                       }\r
+                       i++;\r
+                       break;\r
+\r
+               case NUMBER:  /* can be 8 or 32 bit disp, or hard address */\r
+               OpDisp = rgVal[op][i];\r
+                       if ((rgVal[op][i] >= -128) && (rgVal[op][i] <= 127))\r
+                               OpMType |= fDisp8;\r
+                       else\r
+                               OpMType |= fDisp32;\r
+                       i++;\r
+                       break;\r
+\r
+               case OPENSQR:\r
+                       if (fOpenSQ) {\r
+                               line_error(23);\r
+                               fError = 1;\r
+                               }\r
+                       else fOpenSQ = 1;\r
+                       i++;\r
+                       break;\r
+               case CLOSSQR:\r
+                       if (!fOpenSQ) {\r
+                               line_error(24);\r
+                               fError = 1;\r
+                               }\r
+                       else fOpenSQ = 0;\r
+                       i++;\r
+                       break;\r
+               case COLON:             /*  for far addresses */\r
+                       i++;\r
+                       break;\r
+               case PLUS:\r
+                       i++;\r
+                       break;\r
+           case rBYTE:\r
+               if ((!OpSize[op]) && (rgToken[op][i+1] == rPTR)) {\r
+                               OpSize[op] |= fByte;\r
+                               i+=2;\r
+                               }\r
+                       else {\r
+                               line_error(25);\r
+                               fError = 1;\r
+                               }\r
+                       break;\r
+           case rWORD:\r
+               if ((!OpSize[op]) && (rgToken[op][i+1] == rPTR)) {\r
+                               OpSize[op] |= fWord;\r
+                               i+=2;\r
+                               }\r
+                       else {\r
+                               line_error(25);\r
+                               fError = 1;\r
+                               }\r
+                       break;\r
+           case rDWORD:\r
+               if ((!OpSize[op]) && (rgToken[op][i+1] == rPTR)) {\r
+                               OpSize[op] |= fDWord;\r
+                               i+=2;\r
+                               }\r
+                       else {\r
+                               line_error(25);\r
+                               fError = 1;\r
+                               }\r
+                       break;\r
+           case rFWORD:\r
+               if ((!OpSize[op]) && (rgToken[op][i+1] == rPTR)) {\r
+                               OpSize[op] |= fFWord;\r
+                               i+=2;\r
+                               }\r
+                       else {\r
+                               line_error(25);\r
+                               fError = 1;\r
+                               }\r
+                       break;\r
+               case rNEAR:\r
+               if ((!OpSize[op]) && (rgToken[op][i+1] == rPTR)) {\r
+                               OpSize[op] |= fNear;\r
+                               i+=2;\r
+                               }\r
+                       else {\r
+                               line_error(25);\r
+                               fError = 1;\r
+                               }\r
+                       break;\r
+               case rFAR:\r
+               if ((!OpSize[op]) && (rgToken[op][i+1] == rPTR)) {\r
+                               OpSize[op] |= fFar;\r
+                               i+=2;\r
+                               }\r
+                       else {\r
+                               line_error(25);\r
+                               fError = 1;\r
+                               }\r
+                       break;\r
+               case rSHORT:\r
+               if (!OpSize[op]) {\r
+                               OpSize[op] |= fShort;\r
+                               i++;\r
+                               }\r
+                       else {\r
+                               line_error(25);\r
+                               fError = 1;\r
+                               }\r
+                       break;\r
+               default: {\r
+                       line_error(32);\r
+                       fprintf(lst_fh, "  %d  ", rgToken[op][i]);  /* TESTING */\r
+                       i++;\r
+                       }\r
+\r
+               } /* switch */\r
+       } /* while */\r
+}\r
+if (fError) return(0);\r
+if ((fDone) && (i< rgTCnt[op])) {\r
+       line_error(33);\r
+       return(0);\r
+       }\r
+\r
+return(1);\r
+\r
+}\r
+\r
+/********************************************\r
+  Adds ALL forward reference to the Ref table.\r
+  This holds references to all foward addresses\r
+  (unknown) in the current module.\r
+  This stores all Refs UPPER case.\r
+*********************************************/\r
+void ForRef(U8 type, S32 Offset)\r
+{\r
+S32 i;\r
+\r
+if (pRefNext >= (pRefBuf + FREFBUFMAX))\r
+       fatal_error("Forward Reference buffer overflow...");\r
+if (iRefNext >= FREFSMAX)\r
+       fatal_error("Forward Reference table overflow...");\r
+\r
+/* Make a forward reference table entry */\r
+\r
+strncpy(pRefNext, UString, UCBString);\r
+pfrt[iRefNext].NameSz = UCBString;     /* size of name */\r
+pfrt[iRefNext].Ptr = pRefNext;\r
+pfrt[iRefNext].Line = lineno[level];   /* for error reporting */\r
+pfrt[iRefNext].Type = type;                    /* type of ref */\r
+\r
+\r
+pfrt[iRefNext].Offs = Offset;          /* Offset to correction in CS or DS */\r
+\r
+/* update for next symbol */\r
+\r
+pRefNext += UCBString;\r
+iRefNext++;\r
+\r
+}\r
+\r
+/********************************************\r
+  Adds fixup table entries to be placed in\r
+  the run file.         This includes DLL entries.\r
+*********************************************/\r
+\r
+void FixUp(U8 typef, S32 Offset, S32 iSymbol)\r
+{\r
+\r
+if (typef == CDFIXTAG)\r
+       nCDFix++;\r
+else if (typef == DDFIXTAG)\r
+       nDDFix++;\r
+else if (typef == DCFIXTAG)\r
+       nDCFix++;\r
+else if (typef == CCFIXTAG)\r
+       nCCFix++;\r
+\r
+\r
+if (iFUNext >= FIXUPSMAX)\r
+       fatal_error("Fixup Table overflow...");\r
+pfut[iFUNext].type = typef;\r
+pfut[iFUNext].Offs = Offset;\r
+pfut[iFUNext].iSym = iSymbol;  /* global symbol entry for DLL */\r
+\r
+iFUNext++;\r
+\r
+}\r
+\r
+/********************************************\r
+  Adds External Reference to table.\r
+  This DOES NOT includes DLL Refs.\r
+  ETypes are the same as ForRef types\r
+  except there and no 8 bit externals.\r
+*********************************************/\r
+\r
+void ExtRef(U8 EType, S32 iSymbol)\r
+{\r
+\r
+if (iERefNext >= EREFSMAX)\r
+       fatal_error("External Reference Table overflow...");\r
+\r
+if (fDataSeg)\r
+       ert[iERefNext].Offs = oNextData;\r
+else {\r
+       ert[iERefNext].Offs = oNextCode;\r
+       }\r
+ert[iERefNext].iSym = iSymbol;  /* global symbol entry for external */\r
+ert[iERefNext].Type = EType;  /* global symbol entry for external */\r
+\r
+iERefNext++;\r
+}\r
+\r
+/*****************************************************\r
+   Reads in all of the reserved words, numbers, math\r
+   operators, etc. that make up one operand.  They are\r
+   read into one of 3 2D arrays as indicated by "op".\r
+   Integer rgTCnt[op] is number if items.  A special\r
+   case for jump and call instructions is tested if\r
+   we end up with an Unknown Symbol as and operand.\r
+   We Error out if we have an UNKSYM without a\r
+   jump or call.\r
+*****************************************************/\r
+\r
+S32 GetOper(S32 op)\r
+{\r
+S32 i, T;\r
+\r
+i = 0;\r
+while (1) {\r
+       T = Parse();\r
+       switch (T) {\r
+         case ZERO:\r
+                   rgTCnt[op] = i;\r
+                       if (i) return(1);\r
+                       else return(0);\r
+         case REGIST:\r
+               rgTID[op][i] = TReg;\r
+               rgToken[op][i] = T;\r
+               break;\r
+         case NUMBER:  /* check for special case of REG*2,*4,*8  */\r
+               if ((i > 1) &&\r
+                       (rgToken[op][i-1] == STAR) &&\r
+                       (rgToken[op][i-2] == REGIST)) {\r
+                               rgVal[op][i] = TNumber;\r
+                               rgToken[op][i] = T;\r
+                               break;  /* only break here if we find special case */\r
+                       }                       /* Else fall thru to Expression */\r
+         case LSYMBOL:\r
+         case SYMBOL:\r
+         case DOLLAR:          /* These should all evaluate to a number!! */\r
+         case OPENRND:\r
+         case MINUS:\r
+         case UNKSYM:\r
+         case rOFFSET:\r
+               if (Expression()) {\r
+                       rgVal[op][i] = TNumber;\r
+                       rgToken[op][i] = Token;         /* Token instead of T (From Expr)*/\r
+                       }\r
+               else {\r
+                       line_error(35);\r
+                       return(0);\r
+                       }\r
+\r
+               break;\r
+         case COMMA:\r
+                       if (!i) {\r
+                               line_error(36);\r
+                               return(0);\r
+                       }\r
+                   rgTCnt[op] = i;\r
+                       ReturnToken();\r
+                       return(1);\r
+         case OPENSQR:\r
+         case CLOSSQR:\r
+         case STAR:\r
+         case PLUS:\r
+         case SLASH:\r
+         case SEMI:\r
+         case COLON:\r
+         case rFAR:\r
+         case rBYTE:\r
+         case rWORD:\r
+         case rDWORD:\r
+         case rFWORD:\r
+         case rPTR:\r
+         case rSHORT:\r
+                       rgToken[op][i] = T;\r
+                       break;\r
+         default:\r
+                       line_error(38);\r
+                       return(0);\r
+       }\r
+ i++;\r
+} /* while */\r
+}\r
+\r
+/********************************************\r
+ This finds the first matching entry in rgINS\r
+ by first matching the instruction number,\r
+ then matching operands.  The table is indexed\r
+ with an array providing the first entry for\r
+ the instruction. This speed things up a bit.\r
+*********************************************/\r
+\r
+S32 INSEntry(S32 InsNum, S32 nOpers)\r
+{\r
+S32 i;\r
+\r
+       i = rgInsLookUp[InsNum];\r
+       while (i <= nrgINS) {\r
+\r
+               /* instruction entries of the same type\r
+               are all kept together. This is an early out.\r
+               */\r
+\r
+               if (rgINS[i][0] != InsNum)\r
+                 return(0);    /* couldn't find a match at all... */\r
+\r
+               /* See if all the operators match by calling is_Comp for each.\r
+               */\r
+\r
+               if ((is_Comp(i,0)) &&\r
+                   (is_Comp(i,1)) &&\r
+                   (is_Comp(i,2)))\r
+\r
+                       return(i);              /* yes, they all match! */\r
+\r
+               i++;    /* No, goto next entry */\r
+       }\r
+}\r
+\r
+\r
+/********************************************\r
+  EmitInst spits out the instruction bytes that\r
+  were encoded into variables by EncodeInst.\r
+  This handles output to the code segment\r
+  file as well as the text to the list file.\r
+  It updates the code segment address and\r
+  also adds fixup records as they are needed.\r
+\r
+The instruction  (up to 16 bytes) is ordered\r
+as follows:\r
+  Instruction Prefix   0 or 1 byte\r
+  Address Size Prefix  0 or 1 byte\r
+  Operand Prefix       0 or 1 byte\r
+  Segment Override     0 or 1 bytes\r
+  Opcode               1 or 2 bytes\r
+  MODR/M               0 or 1 bytes\r
+  SIB                  0 or 1 bytes\r
+  Displacement         0,1,2 or 4 bytes\r
+  Immediate            0,1,2, or 4 bytes\r
+**********************************************/\r
+\r
+void EmitInst(void)\r
+{\r
+U8   oppfx;\r
+S8   sbyte;\r
+S32  sword;\r
+U32  i;                /* used local to each section if needed */\r
+\r
+\r
+\r
+       /*\r
+    Instruction prefix: 0 or 1 byte (Lock, Rep, etc.)\r
+       */\r
+\r
+       if (InstPfx) {\r
+               if (InstPfx==xLOCK) {\r
+                       if (fListA) {\r
+                               Column += 2;\r
+                               put_hexb(0x0F, lst_fh);\r
+                               }\r
+                       OutByteX(0xF0);\r
+                       }\r
+               else if ((InstPfx==xREPNE) || (InstPfx==xREPNZ)) {\r
+                       if (fListA) {\r
+                               Column += 2;\r
+                               put_hexb(0xF2, lst_fh);\r
+                               }\r
+                       OutByteX(0xf2);\r
+                       }\r
+               else {  /* Must be REP... */\r
+                       if (fListA) {\r
+                               Column += 2;\r
+                               put_hexb(0xF3, lst_fh);\r
+                               }\r
+                       OutByteX(0xf3);\r
+                       }\r
+               if (fListA)\r
+                       Column += fprintf(lst_fh, "| ");\r
+       }\r
+\r
+/*\r
+   Skip Address Size prefix: (67h)  cause we aren't\r
+   doing USE16, nor do we support 16 bit addressing modes!\r
+*/\r
+\r
+/* Operand Size prefix: 0 or 1 (66h)  */\r
+\r
+       if (OpSizeA & fWord) {\r
+               if (fListA) {\r
+                       Column += 2;\r
+                       put_hexb(0x66, lst_fh);\r
+                       Column += fprintf(lst_fh, "| ");\r
+                       }\r
+               OutByteX(0x66);\r
+               }\r
+\r
+/* Segment Override prefix */\r
+\r
+       switch (OpPrefix) {\r
+               case fDSp: oppfx = 0x3e; break;\r
+               case fESp: oppfx = 0x26; break;\r
+               case fSSp: oppfx = 0x36; break;\r
+               case fFSp: oppfx = 0x64; break;\r
+               case fGSp: oppfx = 0x65; break;\r
+               case fCSp: oppfx = 0x2e; break;\r
+               default: oppfx = 0;\r
+       }\r
+       if (oppfx) {\r
+               if (fListA) {\r
+                       Column += 2;\r
+                       put_hexb(oppfx, lst_fh);\r
+                       Column += fprintf(lst_fh, "| ");\r
+                       }\r
+                       OutByteX(oppfx);\r
+               }\r
+\r
+/*   OpCode byte 1 (optional)\r
+     bOpc1 was setup in        EncodeInst (either 0 or 0Fh)\r
+*/\r
+\r
+       if (bOpc1) {\r
+               if (fListA) {\r
+                       Column += 2;\r
+                       put_hexb(bOpc1, lst_fh);\r
+                       Column += fprintf(lst_fh, " ");\r
+                       }\r
+                       OutByteX(bOpc1);\r
+               }\r
+\r
+/*   OpCode byte 2 (always sent) */\r
+\r
+       if (fListA) {\r
+                       Column += 2;\r
+                       put_hexb(bOpc2, lst_fh);\r
+                       Column += fprintf(lst_fh, " ");\r
+               }\r
+\r
+       OutByteX(bOpc2);\r
+\r
+/*  ModR/M  (optional)  */\r
+\r
+       if (fModRM) {\r
+               if (fListA) {\r
+                       Column += 2;\r
+                       put_hexb(bModRM, lst_fh);\r
+                       Column += fprintf(lst_fh, " ");\r
+               }\r
+               OutByteX(bModRM);\r
+       }\r
+\r
+/*  SIB  (optional) */\r
+\r
+       if (fSIB) {\r
+               if (fListA) {\r
+                       Column += 2;\r
+                       put_hexb(bSIB, lst_fh);\r
+                       Column += fprintf(lst_fh, " ");\r
+               }\r
+               OutByteX(bSIB);\r
+       }\r
+\r
+/*\r
+   Disp: 0, 1, 2 or 4\r
+   A Displacement is a memory reference (an offset in a segment)\r
+   that is encoded as part of the instruction. The value to encode\r
+   is placed in OpDisp when the instruction is parsed and\r
+   evaluated.\r
+*/\r
+\r
+       if (OpMType & fDisp32) {\r
+\r
+               if (fListA) {\r
+                       Column += 8;\r
+                       put_hexd(OpDisp, lst_fh);\r
+                       if ((nExtRef) || (fForRef))\r
+                               Column += fprintf(lst_fh, "r ");\r
+                       else\r
+                               Column += fprintf(lst_fh, "  ");\r
+               }\r
+               if (nExtRef)\r
+                       ExtRef(CSEGREF, nExtRef);\r
+               else if (fForRef)\r
+                       ForRef(CSEGREF, oNextCode);\r
+               else if (nFixUp)\r
+                       FixUp(nFixUp, oNextCode, 0); /* Code ref to data */\r
+               OutDWordX(OpDisp);\r
+       }\r
+\r
+       if (OpMType & fDisp8) {\r
+\r
+               if (fListA) {\r
+                       sbyte = OpDisp;\r
+                       Column += 2;\r
+                       put_hexb(sbyte, lst_fh);\r
+                       Column += fprintf(lst_fh, "  ");\r
+               }\r
+               OutByteX(OpDisp);\r
+       }\r
+\r
+/*\r
+   Immediate: 0, 1, 2 or 4\r
+   The type of instruction operands tell us if we must encode\r
+   immediate values as part of the instruction.  All instructions\r
+   have only one immediate value except ENTER. We make a check here\r
+   to determine if it is this instruction.\r
+\r
+     imm8  = Immediate Byte in OpImm\r
+     imm16 = immediate 16 bit value in OpImm\r
+     immX  = immediate value matching OpSize in OpImm\r
+     rel8  = immediate Byte calculated from a label\r
+     relW  = immediate Word (16 or 32) calculated from a label\r
+     iSAD  = immediate DWORD:WORD from Far Pointer (OpImm & OpImm2)\r
+\r
+     immv1 is not encoded (implied by instruction)\r
+     immv3 is not encoded (also implied - INT 03 - Debug)\r
+   */\r
+       if (fOpImm) \r
+       {\r
+               if ((rgINS[iInstEntry][1] == immX) ||\r
+                   (rgINS[iInstEntry][2] == immX) ||\r
+            (rgINS[iInstEntry][3] == immX))\r
+        {\r
+                       if (OpSizeA & fByte)\r
+                       {\r
+                               if (fListA)\r
+                               {\r
+                                       sbyte = OpImm;\r
+                                       Column += 2;\r
+                                       put_hexb(sbyte, lst_fh);\r
+                                       Column += fprintf(lst_fh, "  ");\r
+                               }\r
+                               OutByteX(OpImm);\r
+                       }\r
+                       else if (OpSizeA & fWord)\r
+                       {\r
+                               if (fListA) \r
+                               {\r
+                                       sword = OpImm;\r
+                                       Column += 4;\r
+                                       put_hexw(sword, lst_fh);\r
+                                       Column += fprintf(lst_fh, "  ");\r
+                               }\r
+                               OutWordX(OpImm);\r
+                       }\r
+                       else {                                  /* MUST be a DWord */\r
+                               if (fListA) {\r
+                                       Column += 8;\r
+                                       put_hexd(OpImm, lst_fh);\r
+                                       if (nFixUp)\r
+                                               Column += fprintf(lst_fh, "r ");\r
+                                       else\r
+                                               Column += fprintf(lst_fh, "  ");\r
+                               }\r
+                               if (nExtRef)\r
+                                       ExtRef(CSEGREF, nExtRef);\r
+                               else if (fForRef)\r
+                                       ForRef(CSEGREF, oNextCode);\r
+                               else if (nFixUp)\r
+                                       FixUp(nFixUp, oNextCode, 0); /* Code ref to data */\r
+                               OutDWordX(OpImm);\r
+                       }\r
+               }\r
+\r
+               if ((rgINS[iInstEntry][1] == imm16) ||\r
+                   (rgINS[iInstEntry][2] == imm16) ||\r
+            (rgINS[iInstEntry][3] == imm16))   {\r
+                       if (fListA) {\r
+                               Column += 4;\r
+                               sword = OpImm;\r
+                               put_hexw(sword, lst_fh);\r
+                               Column += fprintf(lst_fh, "  ");\r
+                               }\r
+                       OutWordX(OpImm);\r
+               }\r
+               else if ((rgINS[iInstEntry][1] == imm8) ||\r
+                        (rgINS[iInstEntry][2] == imm8) ||\r
+                        (rgINS[iInstEntry][3] == imm8) ||\r
+                        (rgINS[iInstEntry][1] == ims8) ||\r
+                        (rgINS[iInstEntry][2] == ims8) ||\r
+                 (rgINS[iInstEntry][3] == ims8))\r
+        {\r
+                       if (fListA) {\r
+                               Column += 2;\r
+                               sbyte = OpImm;\r
+                               put_hexb(sbyte, lst_fh);\r
+                               Column += fprintf(lst_fh, "  ");\r
+                               }\r
+                       OutByteX(OpImm);\r
+               }\r
+\r
+               /* Special check for Enter. It is only instructon with 2 Imms!*/\r
+\r
+               if (rgINS[iInstEntry][0] == xENTER)\r
+        {\r
+                       if (fListA) {\r
+                               Column += 2;\r
+                               sbyte = OpImm2;\r
+                               put_hexb(sbyte, lst_fh);\r
+                               Column += fprintf(lst_fh, "  ");\r
+                               }\r
+                       OutByteX(OpImm2);\r
+               }\r
+\r
+\r
+               /* With relative values for immediates, OpImm comes in as\r
+                 the address of the target jump or call. We must take\r
+                  the current code offset (of the next instruction) and\r
+                  subtract it from the target (OpImm) to get the relative\r
+                  jump value. If it is an UNKSYM we will put the value\r
+                  of the target into the FRT to hold it and\r
+                  do the math on the second pass of the machine code.\r
+                  Math Example:\r
+\r
+                       oCode  = 100  (next instruction)\r
+                       Target =  50\r
+                       Jump = -50  (Target-Current)\r
+\r
+                       oCode  = 100  (next instruction)\r
+                       Target = 150\r
+                       Jump = 50  (Target-Current)\r
+\r
+                       Relative immediate values found in the GST as EXTERN\r
+                       require an ERT entry so they can be fixed up when\r
+                       the final code module is written to the run file.\r
+\r
+                       Relative immediate values found in the GST as PUBLICS\r
+                       can be fixed up NOW.\r
+\r
+                       Relative immediate values NOT found are assumed local\r
+                       and an entry is made in the FRT so they can be fixed\r
+                       up when this code module is written to the main\r
+                       temp code module.\r
+                  */\r
+\r
+               if (rgINS[iInstEntry][1] == relW) {\r
+                       if (nExtRef) {                                          /* list external */\r
+                               OpImm = 0;\r
+                               ExtRef(CCR32REF, nExtRef);\r
+                       }\r
+                       else if (fForRef) {                                     /* list Forward Relative */\r
+                               OpImm = 0;\r
+                               ForRef(CCR32REF, oNextCode);\r
+                       }\r
+                       else {                                                          /* Fix known ref */\r
+                               OpImm = OpImm - (oNextCode + 4);\r
+                       }\r
+\r
+                       if (fListA) {\r
+                               Column += 8;\r
+                               put_hexd(OpImm, lst_fh);\r
+                               if ((!fForRef) && (!nExtRef))\r
+                                       Column += fprintf(lst_fh, "  ");\r
+                               else\r
+                                       Column += fprintf(lst_fh, "R ");\r
+                       }\r
+                       OutDWordX(OpImm);\r
+               }\r
+\r
+               if (rgINS[iInstEntry][1] == rel8) {\r
+                       if (!fForRef) {                                 /* Fix KNOWN Relative */\r
+                               OpImm = OpImm - (oNextCode + 1);\r
+                               if ((OpImm > 127) || (OpImm < -127))\r
+                                       line_error(39);\r
+                       }\r
+                       else {                                                  /* Else List Unknown */\r
+                               ForRef(CCR8REF, oNextCode);\r
+                               OpImm = 0;\r
+                               }\r
+\r
+                       if (fListA) {\r
+                               Column += 2;\r
+                               sbyte = OpImm;\r
+                               put_hexb(sbyte, lst_fh);\r
+                               if ((!fForRef) && (!nExtRef))\r
+                                       Column += fprintf(lst_fh, "  ");\r
+                               else\r
+                                       Column += fprintf(lst_fh, "R ");\r
+                       }\r
+                       OutByteX(OpImm);\r
+               }\r
+\r
+               if (rgINS[iInstEntry][1] == iSAD) {\r
+                       if (fListA) {\r
+                               Column += 4;\r
+                               sword = OpImm;\r
+                               put_hexw(sword, lst_fh);\r
+                               Column += fprintf(lst_fh, ":");\r
+                               Column += 4;\r
+                               put_hexd(OpImm2, lst_fh);\r
+                               Column += fprintf(lst_fh, "  ");\r
+                       }\r
+                       OutWordX(OpImm);\r
+                       OutDWordX(OpImm2);\r
+               }\r
+       }\r
+}\r
+\r
+\r
+/********************************************\r
+  This encodes the instructions into bytes\r
+  and calls EmitInst() to put them into the\r
+  current code segment.        The instruction can\r
+  be as long as 16 bytes if all options are used.\r
+  The order of the bytes and their possible\r
+  sizes are as follows:\r
+   Inst Prefix: 0 or 1 (Lock, Rep, etc.)\r
+   Address Size prefix: 0 or 1 (67h) - We don't use this\r
+   Operand Size prefix: 0 or 1 (66h)\r
+   Segment Override: 0 or 1\r
+   OpCode: 1 or 2\r
+   ModR/M: 0 or 1\r
+   SIB: 0 or 1\r
+   Disp: 0, 1, 2 or 4\r
+   Immediate: 0, 1, 2 or 4\r
+   This routine follows the guidance to build\r
+   instructions given in the rgINS table\r
+   (as bit flags). It calls    EmitInst() to\r
+   emit the code, list-file information and\r
+   fixups to the FUT.\r
+   **********************************************/\r
+void EncodeInst(void)\r
+{\r
+S8   fError;\r
+S32 i;\r
+U8 bTmp;\r
+\r
+/*\r
+U8 bOpc1;              Zero if not used   THESE ARE GLOBAL...\r
+U8 bOpc2;              Always used\r
+U8 bModRM;\r
+U8 bSIB;\r
+S8 fModRM;         Is bModRM set/used?\r
+S8 fSIB;               Is bSIB set/used?\r
+*/\r
+\r
+fModRM = 0;            /* not used by default */\r
+fSIB   = 0;\r
+\r
+\r
+/* SKIP the Address Size Prefix for now because we don't do 16 Bit\r
+   Effective addresses\r
+*/\r
+\r
+\r
+/*\r
+   Now we will build the instruction in (up to) 4 temporary bytes.\r
+   We do it in temporary byte vars so we can see if an Operand Prefix\r
+   and a possible address fixup record is required before we\r
+   actually put it into the code segment.\r
+*/\r
+\r
+/*\r
+  The WORD forms of string instructions require us\r
+  to force a WORD size. We set this in the instruction table\r
+  as qUW in byte [4],\r
+*/\r
+\r
+if (rgINS[iInstEntry][4] & qUW)\r
+  OpSizeA |= fWord;\r
+\r
+/* Put in the first byte of Opcode from table (if required). qP0F is\r
+   set in rgINS[iInstEntry][4] if a 0Fh prefix is required for this inst.\r
+   A 0 in bObc1 indicates that this byte is NOT to be used.\r
+*/\r
+\r
+if (rgINS[iInstEntry][4] & qP0F)\r
+    bOpc1 = 0x0F;\r
+else bOpc1 = 0;\r
+\r
+/* Get the Opcode from table into bOpc2 */\r
+\r
+bOpc2 = rgINS[iInstEntry][5];\r
+\r
+/* The flags zMR1, zMR2, zMOP, zAR1, and zAR2 all indicate that the\r
+   ModRM is needed. The following set of if-else statements checks these\r
+   flags and sets REG/OP field of MOD/RM byte if required.\r
+   OpSize should already be set. We also complete\r
+   the instruction encoding (with the exception of any immediate values)\r
+   if the other operand is a register.\r
+*/\r
+\r
+if (rgINS[iInstEntry][7] & zMR1) {\r
+       bModRM = rgINS[iInstEntry][6];\r
+       fModRM = 1;\r
+       if (is_Reg(rgOpType[0]))\r
+           EncodeRegBits(rgOpReg[0], &bModRM, 3);\r
+       if (is_Reg(rgOpType[1])) {\r
+           EncodeRegBits(rgOpReg[1], &bModRM, 0);\r
+           bModRM |= 0xC0;     /* indictes REG in RM field */\r
+               }\r
+       }\r
+else if (rgINS[iInstEntry][7] & zMR2) {\r
+       bModRM = rgINS[iInstEntry][6];\r
+       fModRM = 1;\r
+       if (is_Reg(rgOpType[1]))\r
+           EncodeRegBits(rgOpReg[1], &bModRM, 3);\r
+       if (is_Reg(rgOpType[0])) {\r
+           EncodeRegBits(rgOpReg[0], &bModRM, 0);\r
+           bModRM |= 0xC0;     /* indictes REG in RM field */\r
+               }\r
+       }\r
+else if (rgINS[iInstEntry][7] & zMOP) {\r
+       bModRM = rgINS[iInstEntry][6];\r
+       fModRM = 1;\r
+       if (is_Reg(rgOpType[0])) {\r
+           EncodeRegBits(rgOpReg[0], &bModRM, 0);\r
+           bModRM |= 0xC0;     /* indictes REG in RM field */\r
+               }\r
+       }\r
+else if (rgINS[iInstEntry][7] & zAR1) {\r
+       bTmp = 0;\r
+    EncodeRegBits(rgOpReg[0], &bTmp, 0);\r
+       bOpc2 += bTmp;\r
+       }\r
+else if (rgINS[iInstEntry][7] & zAR2) {\r
+       bTmp = 0;\r
+    EncodeRegBits(rgOpReg[1], &bTmp, 0);\r
+       bOpc2 += bTmp;\r
+       }\r
+else if ((rgINS[iInstEntry][7] & zRG1) && (rgOpType[0] != mem)) {\r
+       bModRM = rgINS[iInstEntry][6];\r
+       fModRM = 1;\r
+    EncodeRegBits(rgOpReg[0], &bModRM, 3);\r
+    bModRM |= 0xC0;    /* indictes REG in RM field */\r
+       }\r
+\r
+\r
+       /* OpSize may not be required for many instructions, but we know\r
+          for a fact it MUST be known for memory operands!\r
+       */\r
+\r
+       if ((rgOpType[0] == mem) ||\r
+               (rgOpType[1] == mem) ||\r
+               (rgOpType[0] == memF)) {\r
+                       if  (!(OpSizeA & (fByte|fWord|fDWord|fFWord))) {\r
+                               line_error(40);\r
+                               return;\r
+                               }\r
+       }\r
+\r
+       /*\r
+          If zORD, see if we have word or dword register and OR the Opcode\r
+          (Opc2) with 01 if so.\r
+       */\r
+\r
+       if (rgINS[iInstEntry][7] & zORD) {\r
+               if (OpSizeA & (fWord | fDWord))\r
+               bOpc2 |= 0x01;\r
+               }\r
+\r
+       /* Perform the following additonal steps if we have a memory reference\r
+          as determined by iMemEntry.\r
+       */\r
+\r
+       fSIB = 0;\r
+       if (iMemEntry) {\r
+\r
+       /* If SIB is needed (as determined from OpMType), get it and also\r
+        OR ModRM by required value from rgM32 table\r
+       */\r
+\r
+               bModRM |= rgM32[iMemEntry][2];  /* Use ModRM 'OR' value from table */\r
+               if (rgM32[iMemEntry][1]) {              /* is there an SIB byte? */\r
+                       bModRM &= 0x38;                                 /* 00111000 leaves Reg bit on */\r
+                       bModRM |= rgM32[iMemEntry][2];  /* 'OR' ModRM with table value */\r
+                       bSIB = rgM32[iMemEntry][3];\r
+                       fSIB = 1;\r
+               }\r
+\r
+\r
+               /* At this point we have our Opcode, ModRM, and SIB (if required).\r
+                  The MOD and SS bit are already filled in from the table.\r
+                  This means we just stick the register values or bits for Disp etc\r
+                  in the correct positions to complete it.\r
+                  If we didn't have an SIB, we either have a single displacement,\r
+                  a base or both.\r
+               */\r
+\r
+               if (!fSIB) {            /* only a base, disp, or both */\r
+                       if (OpMType & fBase)\r
+                           EncodeRegBits(OpBase, &bModRM, 0);\r
+                       else\r
+                           bModRM |= 0x05;             /* only a disp32 */\r
+                       }\r
+               else {\r
+                       if (OpMType & fBase)\r
+                           EncodeRegBits(OpBase, &bSIB, 0);\r
+                       else bModRM |= 0x20;                            /* else set [--][--] bits */\r
+                       if (OpMType & fIndx)\r
+                           EncodeRegBits(OpIndx, &bSIB, 3);\r
+                       }\r
+       }\r
+\r
+       EmitInst();\r
+\r
+}\r
+\r
+\r
+/********************************************\r
+  When the dispatcher detects an Instruction\r
+  it calls this code to read in (via parse)\r
+  the parametrs for the instruction and to\r
+  put together the opcodes.  First we loop thru\r
+  and get up to 3 operands, then we evaluate\r
+  them (classify by type). Next we look up\r
+  the instruction and find a match for the\r
+  operand types they have specified, and\r
+  finally, we encode the instruction into the\r
+  code segment updating the code segment offset\r
+  pointer.\r
+*********************************************/\r
+void Instruction(void)\r
+{\r
+S32 i;\r
+S8   fError;\r
+S8   OpSizeTmp;\r
+\r
+fError = 0;\r
+if (fDataSeg) {\r
+       line_error(41);\r
+       return;\r
+       }\r
+\r
+/* If the instruction is a prefix instruction, save it\r
+   and Parse again to get the real instruction */\r
+\r
+if ((TInst==xREP) || (TInst==xREPE) || (TInst==xREPZ) ||\r
+    (TInst==xREPNE) || (TInst==xREPNZ) || (TInst==xLOCK)) {\r
+    InstPfx = TInst;\r
+       i = Parse();\r
+       if (i != INSTRU) {\r
+               line_error(42);\r
+               return;\r
+       }\r
+} else InstPfx = 0;\r
+\r
+/* RESET all global instruction variables */\r
+\r
+CrntInst = TInst;      /* Save the instruction */\r
+nOperands = 0;         /* none yet... */\r
+rgOpType[0] = 0;\r
+rgOpType[1] = 0;\r
+rgOpType[2] = 0;\r
+OpMType = 0;       /* char - memory type (a byte to compare to rgM32) */\r
+OpSize[0] = 0;         /* char - Mem op size (fByte, fWord, fDword, fFword) */\r
+OpSize[1] = 0;         /* char - Mem op size (fByte, fWord, fDword, fFword) */\r
+OpSizeA = 0;           /* char - Mem op size (fByte, fWord, fDword, fFword) */\r
+OpSizeTmp = 0;         /* char - Mem op size (fByte, fWord, fDword, fFword) */\r
+OpPrefix = 0;          /* For Segment register prefix flags */\r
+OpDisp = 0;         /* long - Displacement if fDisp8 or fDisp32 is TRUE */\r
+OpBase = 0;         /* int - Base register if fBase is true */\r
+OpIndx = 0;         /* int - Index register if fIndx is true */\r
+fOpImm = 0;                    /* No Immediate value yet */\r
+OpImm = 0;                     /* Default to 0 */\r
+fOpImm2 = 0;           /* No second Immediate value yet */\r
+OpImm2 = 0;                    /* Default to 0 */\r
+nFixUp = 0;                    /* Fixup type if needed, else 0 */\r
+nExtRef = 0;           /* GST entry if external ref was made */\r
+fForRef = 0;           /* No Forward Ref in crnt inst yet */\r
+ExpType = 0;           /* Type of symbol used in instruction */\r
+ExpType0 = 0;          /* Type of symbol used in instruction */\r
+iExpSym = 0;           /* Index into symtab for symbol if used */\r
+iExpSym0 = 0;          /* Index into symtab for symbol if used */\r
+\r
+if (GetOper(0)) {\r
+       nOperands++;\r
+       ExpType0 = ExpType;\r
+       iExpSym0 = iExpSym;\r
+       if ((Parse()== COMMA)) {\r
+               if (GetOper(1)) {\r
+                       nOperands++;\r
+                       if ((Parse()== COMMA)) {\r
+                               if (GetOper(2)) {\r
+                                       nOperands++;\r
+                                       if (Parse()) {\r
+                                               line_error(33);\r
+                                               return;\r
+                                       }\r
+                               }\r
+                   }\r
+               }\r
+       }\r
+}\r
+\r
+/*\r
+At this point we have the instruction operands stored in\r
+tokenized form in arrays.  We now call EvalOper() which evaluates\r
+the operands and fills in several variables that will assist in\r
+building the instruction. EvalOper() returns 1 if it was a valid\r
+operand, else 0.\r
+*/\r
+\r
+if (nOperands) {                                                               /* at least one */\r
+       if (EvalOper(0)) {\r
+               if (nOperands > 1) {                                    /* a second operand */\r
+                       if (EvalOper(1)) {\r
+                               if (nOperands > 2) {                    /* a third??? - could be... */\r
+                                       if (!(EvalOper(2)))\r
+                                               fError = 1;\r
+                               }\r
+                       }\r
+                       else fError = 1;\r
+           }\r
+       }\r
+       else fError = 1;\r
+}\r
+\r
+if (fError) return;\r
+\r
+/*\r
+   We must check to see what the word size of the instruction is\r
+   by looking at register sizes if any are included in the instruction.\r
+   If there are memory references or immediates involved, OpSizeA\r
+   MUST be set properly else it's an error!     When there is a symbol involved\r
+   such as a move to a memory variable, we check the variable size and set\r
+   the OpSize to the variable size. If it's still not set, the line will\r
+   error out when we try to build the instruction because the caller\r
+   should have explicitly set the size (e.g., DWORD PTR ...).\r
+\r
+   If a register is one of the operands in a memory transfer\r
+   (e.g., MOV [mem], EAX) then the move obviously defaults to the size\r
+   of the register (no ifs, ands, or buts).\r
+\r
+   If there is no reg involved, we then look at 'OpSize[i]'\r
+   which may have been set by the size operators (e.g., DWORD PTR).\r
+   If it's zero we look at iExpSym which was set if there was a single\r
+   symbol involved in the memory reference. If there was, then we use it.\r
+   If it is blank, we error out cause we don't know what size memory\r
+   access we are doing!\r
+   This is done for each operand then the two are compared. If one is\r
+   zero we use the other, if both have something but are different\r
+   we error out!\r
+\r
+*/\r
+       /* Find the first operand size */\r
+\r
+       /* First, let's look to see if they forced it! */\r
+\r
+       if  (OpSize[0] & (fByte|fWord|fDWord|fFWord))\r
+\r
+       { /* do nothing */ }\r
+\r
+       /* If they didn't force it, we'll look for the register size! */\r
+\r
+    else if (rgOpType[0] == r32) OpSize[0] |= fDWord;\r
+    else if (rgOpType[0] == r16) OpSize[0] |= fWord;\r
+    else if (rgOpType[0] == rSEG) OpSize[0] |= fWord;\r
+    else if (rgOpType[0] == r8) OpSize[0] |= fByte;\r
+\r
+               /* Still nothing, so let's at symbols.  */\r
+\r
+       else if (ExpType0 == 1)\r
+       {       /* Local symbol */\r
+               if (lst[iExpSym0].Type & sBYTE) OpSize[0] |= fByte;\r
+               else if (lst[iExpSym0].Type & sWORD) OpSize[0]  |= fWord;\r
+               else if (lst[iExpSym0].Type & sDWORD) OpSize[0] |= fDWord;\r
+               else if (lst[iExpSym0].Type & sFWORD) OpSize[0] |= fFWord;\r
+       }\r
+    else if (ExpType0 == 2)\r
+       {   /* Global Symbol */\r
+               if (gst[iExpSym0].Type & sBYTE) OpSize[0] |= fByte;\r
+               else if (gst[iExpSym0].Type & sWORD) OpSize[0] |= fWord;\r
+               else if (gst[iExpSym0].Type & sDWORD) OpSize[0] |= fDWord;\r
+               else if (gst[iExpSym0].Type & sFWORD) OpSize[0] |= fFWord;\r
+       }\r
+       else if (ExpType0 == 3)\r
+               OpSize[0] |= fDWord;            /* $ defaults to DWord */\r
+\r
+\r
+       /* Find the second operand size. Check "forced fit" first */\r
+\r
+       if  (OpSize[1] & (fByte|fWord|fDWord|fFWord))\r
+       { /* do nothing */ }\r
+\r
+    else if (rgOpType[1] == r32) OpSize[1] |= fDWord;\r
+    else if (rgOpType[1] == r16) OpSize[1] |= fWord;\r
+    else if (rgOpType[1] == rSEG) OpSize[1] |= fWord;\r
+    else if (rgOpType[1] == r8) OpSize[1] |= fByte;\r
+\r
+               /* No registers, so let's look to see if they forced it! */\r
+\r
+               /* Still nothing, so let's at symbols.  */\r
+\r
+       else if (ExpType == 1)\r
+       {       /* Local symbol */\r
+               if (lst[iExpSym].Type & sBYTE) OpSize[1] |= fByte;\r
+               else if (lst[iExpSym].Type & sWORD) OpSize[1]  |= fWord;\r
+               else if (lst[iExpSym].Type & sDWORD) OpSize[1] |= fDWord;\r
+               else if (lst[iExpSym].Type & sFWORD) OpSize[1] |= fFWord;\r
+       }\r
+    else if (ExpType == 2)\r
+       {   /* Global Symbol */\r
+               if (gst[iExpSym].Type & sBYTE) OpSize[1] |= fByte;\r
+               else if (gst[iExpSym].Type & sWORD) OpSize[1] |= fWord;\r
+               else if (gst[iExpSym].Type & sDWORD) OpSize[1] |= fDWord;\r
+               else if (gst[iExpSym].Type & sFWORD) OpSize[1] |= fFWord;\r
+       }\r
+       else if (ExpType == 3)\r
+               OpSize[1] |= fDWord;            /* $ defaults to DWord */\r
+\r
+    /* Special cases for operand size matching. */\r
+\r
+       if (CrntInst == xOUT)\r
+               OpSize[0] = OpSize[1];\r
+\r
+\r
+/*\r
+   Now that have the operands, and we know the TYPE of data (fByte etc.)\r
+   we call INSEntry to find the matching\r
+   entry in the array that describes each instruction. If we don't\r
+   find one that matches we error out telling them they have bad\r
+   operands.\r
+*/\r
+\r
+/* find first matching entry in rgINS */\r
+\r
+    iInstEntry = INSEntry(CrntInst, nOperands);\r
+\r
+    if (!iInstEntry) {\r
+       line_error(44);\r
+       return;\r
+    }\r
+\r
+    /* Now we make sure that we have set all operand sizes\r
+       and check for special cases as defined in rgINS.\r
+       */\r
+\r
+       if (rgINS[iInstEntry][7] & zSIZ)\r
+        OpSize[1] = OpSize[0];\r
+\r
+    if (!OpSize[1])\r
+        OpSize[1] = OpSize[0];\r
+\r
+    if (!OpSize[0])\r
+        OpSize[0] = OpSize[1];\r
+\r
+    /* Give them an error if operand sizes don't match */\r
+\r
+    if (nOperands > 1)\r
+        if (OpSize[0] != OpSize[1]) {\r
+           line_error(43);\r
+              return;\r
+          }\r
+\r
+       OpSizeA = OpSize[0];   /* Set primary operand size */\r
+\r
+/* If either the first or second operand was memory, we have to find\r
+   which entry in rgM32 it matches before we can encode it. If none\r
+   matches it is an invalid memory operand.  If neither is a mem operand\r
+   we set iMemEntry to zero.  There is the special case of moffs type\r
+   which is a short form of displacmement when moving data to and from thew\r
+   accumulator (e.g., MOV EAX, VAR1).  We check for this and skip the\r
+   mem check if this is the instruction type we are on.\r
+*/\r
+\r
+       if ((rgINS[iInstEntry][1] == moff) || (rgINS[iInstEntry][2] == moff))\r
+               iMemEntry = 0;\r
+       else if ((rgOpType[0]==mem) ||\r
+                        (rgOpType[1]==mem) ||\r
+                        (rgOpType[0]==memF))\r
+       {\r
+\r
+               for (i=1; i<nrgM32; i++) {\r
+                       if (OpMType == rgM32[i][0]) break;\r
+               }\r
+\r
+               /* if i is off the end of the array we\r
+                  didn't find an entry that matched\r
+               */\r
+\r
+               if (i==nrgM32) {\r
+                       line_error(45);\r
+                       return;\r
+               }\r
+                       else iMemEntry = i;\r
+       }\r
+       else iMemEntry = 0;\r
+\r
+/*\r
+ At this point we should have all information we need to actually\r
+ encode the instruction (unless it's a forward ref). So we call EncodeInst.\r
+*/\r
+\r
+EncodeInst();\r
+\r
+\r
+}\r
+\r
+\r
+/********************************************\r
+   Create Storage in current segment. At this\r
+   point we should see a storage statement as\r
+   the current token followed by a number (or\r
+   string if DB). If string (DB) we insert\r
+   single byte values (one per char) into the\r
+   segment.\r
+*********************************************/\r
+void Storage(void)\r
+{\r
+S32 TSave, NSave, nDUP;\r
+S32 i, j, sword;\r
+S8   fColon, fExpectColon, fComma, fDUP;\r
+U32 symtype;\r
+\r
+fDUP = 0;\r
+nDUP = 1;              /* default duplicate value */\r
+fComma = 0;\r
+fColon = 0;\r
+fExpectColon = 0;\r
+\r
+if (!fMoreStorage) {           /* is it a continuation of previous line? */\r
+       switch(Token) {                 /* parse returns Token */\r
+               case rDB:\r
+                       StoreSize = 1;\r
+               break;\r
+           case rDW:\r
+               StoreSize = 2;\r
+               break;\r
+           case rDD:\r
+               StoreSize = 4;\r
+               break;\r
+               case rDF:\r
+               StoreSize = 6;\r
+               break;\r
+               default:;\r
+       }\r
+}\r
+\r
+/* Now we loop thru looking for strings and numbers taking into account\r
+   the special case of DF which should be DWORD:WORD, and OFFSET\r
+   which will be a DWORD.\r
+*/\r
+\r
+while (1) {\r
+       if (fMoreStorage) {\r
+               i = Token;\r
+               fMoreStorage = 0;\r
+       }\r
+       else i = Parse();\r
+\r
+       switch(i) {\r
+               case STRING:\r
+                       fComma=0;\r
+                       if (StoreSize==1) {\r
+                               for(j=0; j<CBString; j++) {\r
+                                       if (fListA) {\r
+                                               put_hexb(TString[j], lst_fh);\r
+                                               Column += 2;\r
+                                               Column += fprintf(lst_fh, "  ");\r
+                                               if (Column > 51) {\r
+                                                       fprintf(lst_fh, "\r\n                ");\r
+                                                       Column=16;\r
+                                               }\r
+                                       }\r
+                                       OutByteX(TString[j]);\r
+                               }\r
+                       }\r
+                       else {\r
+                               line_error(46);\r
+                               return;\r
+                       }\r
+                       break;\r
+               case rOFFSET:\r
+                       if (StoreSize != 4) {\r
+                               line_error(50);\r
+                               return;\r
+                       }\r
+                       /* fall thru to evaluate & store value */\r
+               case NUMBER:\r
+               case DOLLAR:    /* These should all evaluate to a number. */\r
+               case OPENRND:   /* If it's SYMOFF, we do a fixup or Forward Ref */\r
+               case MINUS:\r
+               case SYMBOL:\r
+               case LSYMBOL:\r
+               case UNKSYM:\r
+                       fComma=0;\r
+                       if (!(Expression()))    /* 0 means error was emmited. */\r
+                               return;\r
+\r
+                       symtype = 0;            /* default to no symbol type */\r
+                       nExtRef = 0;            /* default to no external ref */\r
+\r
+                       if ((Token==SYMOFF) || (Token==NUMOFF))\r
+                       {\r
+                               if (ExpType == 1)                               /* Local */\r
+                                       symtype = lst[iExpSym].Type;\r
+                               else if (ExpType == 2) {                /* global */\r
+                                       symtype = gst[iExpSym].Type;\r
+                                       if (gst[iExpSym].Type & tEXTRN)\r
+                                               nExtRef = iExpSym;\r
+                               }\r
+                       }\r
+\r
+                       if (!fDUP) {\r
+                               NSave = TNumber;\r
+                               TSave = Token;\r
+                               if (Parse() == rDUP)\r
+                               {\r
+                                       nDUP = NSave;\r
+                                       fDUP = 1;\r
+                    Parse();\r
+                    if (Token == OPENRND) {\r
+                                               if (!(Expression()))    /* 0 means error was emitted.*/\r
+                                                       return;\r
+                                       }\r
+                                       else\r
+                                               line_error(47);\r
+                                       /* TNumber now has (VALUE) from DUP */\r
+                               }\r
+                               else {\r
+                                       ReturnToken();\r
+                                       TNumber = NSave;\r
+                                       Token = TSave;\r
+                               }\r
+                       }\r
+\r
+                       if (StoreSize==6)\r
+                       {\r
+                               if (fColon) {\r
+                                       fColon=0;               /* reset it */\r
+                                       if (fListA) {\r
+                                               sword = TNumber;\r
+                                               Column += 4;\r
+                                               put_hexw(sword, lst_fh);\r
+                                               Column += fprintf(lst_fh, " ");\r
+                                               }\r
+                                       OutWordX(TNumber);\r
+                               }\r
+                               else {\r
+                                       fExpectColon = 1;\r
+                                       if (fListA) {\r
+                                               Column += 8;\r
+                                               put_hexd(TNumber, lst_fh);\r
+                                               Column += fprintf(lst_fh, " ");\r
+                                               }\r
+                                       OutDWordX(TNumber);\r
+                               }\r
+                       }\r
+                       else if (StoreSize==4) {\r
+                               if (fDUP)\r
+                               {\r
+                                       if (fListA) {\r
+                                         if ((Token == SYMOFF) || (Token == NUMOFF))\r
+                                           Column += fprintf(lst_fh, "%08lX * (%08lXr)",nDUP,TNumber);\r
+                                         else\r
+                                           Column += fprintf(lst_fh, "%08lX * (%08lX)",nDUP,TNumber);\r
+                                       }\r
+                                       while (nDUP--)\r
+                                       {\r
+                                               if ((Token==SYMOFF) || (Token==NUMOFF))\r
+                                               {\r
+                                                       if (fDataSeg) {         /* Data Seg */\r
+                                                               if (nExtRef)\r
+                                                                       ExtRef(DSEGREF, iExpSym);\r
+                                                               else if (!symtype)\r
+                                                                       ForRef(DSEGREF, oNextData);\r
+                                                               else if (symtype & CLABEL)\r
+                                                                       FixUp(DCFIXTAG, oNextData, 0);\r
+                                                               else if (symtype & DLABEL)\r
+                                                                       FixUp(DDFIXTAG, oNextData, 0);\r
+                                                       }\r
+                                                       else {                          /* Code Seg */\r
+                                                               if (nExtRef)\r
+                                                                       ExtRef(CSEGREF, iExpSym);\r
+                                                               if (!symtype)\r
+                                                                       ForRef(CSEGREF, oNextCode);\r
+                                                               else if (symtype & CLABEL)\r
+                                                                       FixUp(CCFIXTAG, oNextCode, 0);\r
+                                                               else if (symtype & DLABEL)\r
+                                                                       FixUp(CDFIXTAG, oNextCode, 0);\r
+                                                       }\r
+                                               }\r
+                                               OutDWordX(TNumber);\r
+                                   }\r
+                               }\r
+                               else {\r
+                                       if (fListA)\r
+                                       {\r
+                                         if ((Token == SYMOFF) || (Token == NUMOFF))\r
+                                           Column += fprintf(lst_fh, " %08lXr", TNumber);\r
+                                         else\r
+                                           Column += fprintf(lst_fh, " %08lX", TNumber);\r
+                                       }\r
+\r
+                                       /* Fixup & Forref here! */\r
+                                       if ((Token==SYMOFF) || (Token==NUMOFF))\r
+                                       {\r
+                                         if (fDataSeg)\r
+                                         {                                     /* Data Seg */\r
+                                               if (nExtRef)\r
+                                                       ExtRef(DSEGREF, iExpSym);\r
+                                               else if (!symtype)\r
+                                                       ForRef(DSEGREF, oNextData);\r
+                                               else if (symtype & CLABEL)\r
+                                                       FixUp(DCFIXTAG, oNextData, 0);\r
+                                               else if (symtype & DLABEL)\r
+                                                       FixUp(DDFIXTAG, oNextData, 0);\r
+                                         }\r
+                                         else\r
+                                         {                                     /* Code Seg */\r
+                                               if (nExtRef)\r
+                                                       ExtRef(CSEGREF, iExpSym);\r
+                                               else if (!symtype)\r
+                                                       ForRef(CSEGREF, oNextCode);\r
+                                               else if (symtype & CLABEL)\r
+                                                       FixUp(CCFIXTAG, oNextCode, 0);\r
+                                               else if (symtype & DLABEL)\r
+                                                       FixUp(CDFIXTAG, oNextCode, 0);\r
+                                         }\r
+                                       }\r
+                                       OutDWordX(TNumber);\r
+                               }\r
+                       }\r
+                       else if (StoreSize==2) {\r
+                               if (fDUP) {\r
+                                       if (fListA)\r
+                                         Column += fprintf(lst_fh, "%08lX * (%04lX) ",nDUP,TNumber);\r
+                                       while (nDUP--)\r
+                                               OutWordX(TNumber);\r
+                                       }\r
+                               else {\r
+                                       if (fListA)\r
+                                               Column += fprintf(lst_fh, "%04lX ", TNumber);\r
+                                       OutWordX(TNumber);\r
+                                       }\r
+                       }\r
+                       else {\r
+                               if (fDUP) {\r
+                                       if (fListA)\r
+                                         Column += fprintf(lst_fh, "%08lX * (%02lX) ",nDUP,TNumber);\r
+                                       while (nDUP--)\r
+                                               OutByteX(TNumber);\r
+                                       }\r
+                               else {\r
+                                       if (fListA)\r
+                                         Column += fprintf(lst_fh, "%02lX ", TNumber);\r
+                                       OutByteX(TNumber);\r
+                                       }\r
+                       }\r
+                       break;\r
+               case COMMA:     /* Just eat the comma */\r
+                       if (fComma) {\r
+                               line_error(48);\r
+                               return;\r
+                       }\r
+                       fComma = 1;\r
+                       break;\r
+               case COLON:\r
+                       fComma=0;\r
+                       if ((StoreSize == 6) && (fExpectColon)) {\r
+                               fColon = 1;\r
+                               fExpectColon = 0;\r
+                       }\r
+                       else {\r
+                               line_error(49);\r
+                               return;\r
+                       }\r
+                       break;\r
+               case ZERO:\r
+                       if (fComma)     fMoreStorage = 1;\r
+                       return;\r
+               default: {\r
+                       line_error(51);\r
+                       fMoreStorage = 0;\r
+                       return;\r
+                       }\r
+       }\r
+}\r
+}\r
+\r
+/********************************************\r
+  Add new GLOBAL symbol to table (TString).\r
+  Then parse again to hand off to\r
+  proper function. This stores all\r
+  Symbols UPPER case.\r
+*********************************************/\r
+void NewSymbol()\r
+{\r
+S32 i;\r
+S8   fColon, fStorage;\r
+\r
+       if ((pSymNext + CBString) >= (pSymBuf + SYMBUFMAX))\r
+               fatal_error("Symbol buffer overflow...");\r
+       if (iSymNext >= SYMSMAX)\r
+               fatal_error("Symbol table overflow...");\r
+\r
+       strncpy(pSymNext, TString, CBString);\r
+       gst[iSymNext].Size = CBString;\r
+       gst[iSymNext].Type = 0;                         /* initialize type */\r
+       gst[iSymNext].Ptr = pSymNext;\r
+       gst[iSymNext].Line = lineno[level];\r
+       gst[iSymNext].Offs = 0;\r
+\r
+       /* All declarations that reach NewSymbol are either at\r
+       level 0 or defined as PUBLIC or EXTERN. \r
+       */\r
+\r
+       if (fExtern)\r
+               gst[iSymNext].Type |= tEXTRN;\r
+       else\r
+               gst[iSymNext].Type |= tPUBLIC;\r
+\r
+       if (fFarLabel) gst[iSymNext].Type |= tFAR;\r
+\r
+       if (fDataSeg) {\r
+               if (!fExtern)\r
+                       gst[iSymNext].Offs = oNextData;\r
+           gst[iSymNext].Type |= DLABEL;\r
+       }\r
+       else {\r
+               if (!fExtern)\r
+                       gst[iSymNext].Offs = oNextCode;\r
+               gst[iSymNext].Type |= CLABEL;\r
+       }\r
+\r
+       /* update for next symbol */\r
+       pSymNext += CBString;\r
+       iSymNext++;\r
+\r
+\r
+       /* Now, parse again and hand off. We have just added a symbol\r
+       so expect to see an EQU, COLON or Storage statement.\r
+       If we don't see one of these it's an error unless it's an extern.\r
+       If we see a COLON we parse again and expect an instruction or EOL!\r
+       */\r
+\r
+       fStorage = 0;\r
+       fColon=0;\r
+       i = Parse();\r
+\r
+       if (i == COLON) {\r
+               fColon = 1;\r
+               if (fDataSeg) {\r
+               line_error(49);\r
+                   return;\r
+               }\r
+               i = Parse();\r
+       }\r
+\r
+       switch(i) {             /* parse returns Token */\r
+               case INSTRU:\r
+                   if (fDataSeg) {\r
+                       line_error(41);\r
+                           return;\r
+                       }\r
+                       if (!fColon) {\r
+                       line_error(54);\r
+                           return;\r
+                       }\r
+                   Instruction();\r
+                   break;\r
+           case rDB:\r
+                       gst[iSymNext-1].Type |= sBYTE;          /*  type */\r
+                       fStorage = 1;\r
+                       break;\r
+           case rDW:\r
+                       gst[iSymNext-1].Type |= sWORD;  /*  type */\r
+                       fStorage = 1;\r
+                       break;\r
+           case rDD:\r
+                       gst[iSymNext-1].Type |= sDWORD; /*  type */\r
+                       fStorage = 1;\r
+                       break;\r
+               case rDF:\r
+                       if ((!fDataSeg) && (!fColon)) {\r
+                               line_error(54);\r
+                                   return;\r
+                               }\r
+                       gst[iSymNext-1].Type |= sFWORD; /*  type */\r
+                       fStorage = 1;\r
+                       break;\r
+               case rEQU:\r
+               line_error(55);\r
+       /*              AddMacro(); */\r
+                       break;\r
+               case COLON:\r
+                       if (fExtern)\r
+                       return;\r
+               case ZERO:\r
+                       if ((fDataSeg) && (!fExtern))\r
+                               line_error(56);\r
+                       break;\r
+               default:\r
+                       if (fDataSeg)\r
+                               line_error(56);\r
+         }\r
+\r
+       if (gst[iSymNext-1].Type & tEXTRN)\r
+               fStorage = 0;\r
+\r
+       if (fStorage)\r
+               Storage();\r
+}\r
+\r
+/********************************************\r
+  This changes an EXTRN entry in the gst to\r
+  a PUBLIC once we find it.  This checks to\r
+  make sure the extern declaration was the\r
+  same type as this public.\r
+*********************************************/\r
+\r
+void MakePublic(void)\r
+{\r
+S32 i;\r
+S8   fColon, fStorage;\r
+\r
+       if (gst[TSymnum].Type & tPUBLIC) {\r
+               line_error(64);\r
+               return;\r
+       }\r
+\r
+       if ((fDataSeg) && (!(gst[TSymnum].Type & DLABEL))) {\r
+               line_error(69);\r
+               return;\r
+       }\r
+\r
+       if ((!fDataSeg) && (!(gst[TSymnum].Type & CLABEL))) {\r
+               line_error(69);\r
+               return;\r
+       }\r
+\r
+       gst[TSymnum].Type |= tPUBLIC;   /* Turn ON Public */\r
+       gst[TSymnum].Type &= ~tEXTRN;   /* Turn off EXTERN */\r
+\r
+       if (fDataSeg)\r
+               gst[TSymnum].Offs = oNextData;\r
+       else\r
+               gst[TSymnum].Offs = oNextCode;\r
+\r
+       /* Now, parse again and hand off. We have just added a symbol\r
+       so expect to see an EQU, COLON or Storage statement.\r
+       If we don't see one of these it's an error unless it's an extern.\r
+       If we see a COLON we parse again and expect an instruction or EOL!\r
+       */\r
+\r
+fStorage = 0;\r
+fColon=0;\r
+i = Parse();\r
+\r
+if (i == COLON) {\r
+       fColon = 1;\r
+       if (fDataSeg) {\r
+       line_error(49);\r
+           return;\r
+       }\r
+       i = Parse();\r
+}\r
+\r
+switch(i) {            /* parse returns Token */\r
+       case INSTRU:\r
+           if (fDataSeg) {\r
+               line_error(41);\r
+                   return;\r
+               }\r
+               if (!fColon) {\r
+               line_error(54);\r
+                   return;\r
+               }\r
+           Instruction();\r
+           break;\r
+    case rDB:\r
+               gst[TSymnum].Type |= sBYTE;             /*  type */\r
+               fStorage = 1;\r
+               break;\r
+    case rDW:\r
+               gst[TSymnum].Type |= sWORD;     /*  type */\r
+               fStorage = 1;\r
+               break;\r
+    case rDD:\r
+               gst[TSymnum].Type |= sDWORD;    /*  type */\r
+               fStorage = 1;\r
+               break;\r
+       case rDF:\r
+               if ((!fDataSeg) && (!fColon)) {\r
+                       line_error(54);\r
+                           return;\r
+                       }\r
+               gst[TSymnum].Type |= sFWORD;    /*  type */\r
+               fStorage = 1;\r
+               break;\r
+       case rEQU:\r
+       line_error(55);\r
+               break;\r
+       case COLON:\r
+               return;\r
+       default:\r
+               if (fDataSeg)\r
+                       line_error(56);\r
+  }\r
+\r
+if (fStorage)\r
+       Storage();\r
+\r
+}\r
+\r
+\r
+/********************************************\r
+  This checks to ensure multiple externs are\r
+  the same type when we run across them, and\r
+  also that an extern is the same type if\r
+  the public is already declared.\r
+*********************************************/\r
+void CheckExtern(void)\r
+{\r
+       /* Check to make sure new extern and symbol are same type */\r
+\r
+       if ((fDataSeg) && (!(gst[TSymnum].Type & DLABEL))) {\r
+               line_error(69);\r
+               return;\r
+       }\r
+\r
+       if ((!fDataSeg) && (!(gst[TSymnum].Type & CLABEL))) {\r
+               line_error(69);\r
+               return;\r
+       }\r
+}\r
+\r
+\r
+/********************************************\r
+  Add new LOCAL symbol to table (TString).\r
+  Then parse again to hand off to\r
+  proper function. This stores all\r
+  Symbols UPPER case.\r
+*********************************************/\r
+void NewLSymbol(void)\r
+{\r
+S32 i;\r
+S8   fColon, fStorage;\r
+\r
+if ((pLSymNext + CBString) >= (pLSymBuf + LSYMBUFMAX))\r
+       fatal_error("Local symbol buffer overflow...");\r
+if (iLSymNext >= LSYMSMAX)\r
+       fatal_error("Local symbol table overflow...");\r
+\r
+strncpy(pLSymNext, TString, CBString);\r
+lst[iLSymNext].Size = CBString;\r
+lst[iLSymNext].Type = 0;                               /* initialize type */\r
+lst[iLSymNext].Ptr = pLSymNext;\r
+lst[iLSymNext].Line = lineno[level];\r
+\r
+if (fDataSeg) {\r
+       lst[iLSymNext].Offs = oNextData;\r
+       lst[iLSymNext].Type |= DLABEL;\r
+       }\r
+else {\r
+       lst[iLSymNext].Offs = oNextCode;\r
+       lst[iLSymNext].Type |= CLABEL;\r
+       }\r
+\r
+/* update for next symbol */\r
+pLSymNext += CBString;\r
+iLSymNext++;\r
+\r
+/* Now, parse again and hand off. We have just added a symbol\r
+so expect to see an EQU, COLON or Storage statement.\r
+If we don't see one of these it's an error!\r
+If we see a COLON we parse again and expect an instruction or EOL!\r
+ */\r
+\r
+fStorage = 0;\r
+fColon=0;\r
+i = Parse();\r
+\r
+if (i == COLON) {\r
+       fColon = 1;\r
+       if (fDataSeg) {\r
+       line_error(49);\r
+           return;\r
+       }\r
+       i = Parse();\r
+}\r
+\r
+switch(i) {            /* parse returns Token */\r
+       case INSTRU:\r
+           if (fDataSeg) {\r
+               line_error(41);\r
+                   return;\r
+               }\r
+               if (!fColon) {\r
+               line_error(54);\r
+                   return;\r
+               }\r
+           Instruction();\r
+           break;\r
+    case rDB:\r
+               lst[iLSymNext-1].Type |= sBYTE;         /*  type */\r
+               fStorage = 1;\r
+               break;\r
+    case rDW:\r
+               lst[iLSymNext-1].Type |= sWORD; /*  type */\r
+               fStorage = 1;\r
+               break;\r
+    case rDD:\r
+               lst[iLSymNext-1].Type |= sDWORD;        /*  type */\r
+               fStorage = 1;\r
+               break;\r
+       case rDF:\r
+               if ((!fDataSeg) && (!fColon)) {\r
+                       line_error(54);\r
+                           return;\r
+                       }\r
+               lst[iLSymNext-1].Type |= sFWORD;        /*  type */\r
+               fStorage = 1;\r
+               break;\r
+       case rEQU:\r
+               AddMacro();\r
+               break;\r
+       case COLON:\r
+               return;\r
+       default:\r
+               if (fDataSeg)\r
+                       line_error(56);\r
+  }\r
+\r
+if (lst[iLSymNext-1].Type & tEXTRN)\r
+       fStorage = 0;\r
+\r
+if (fStorage)\r
+       Storage();\r
+\r
+}\r
+\r
+/*****************************************\r
+ After we transition from level 1 back to\r
+ level 0 we go back to the point in the\r
+ code or data file where we began writing this\r
+ section and resolve all forward code\r
+ and local data references. These will be\r
+ referenced in the module we just finished.\r
+ ******************************************/\r
+\r
+void Resolve(void)\r
+{\r
+long i, isym;\r
+S32 Relative;\r
+S32 Partial;\r
+S32 AddFix;\r
+\r
+       i = 0;\r
+\r
+       while (i < iRefNext)  /* While there are forward references */\r
+       {\r
+               if (pfrt[i].Type == DSEGREF)            /* Ref is in DSEG */\r
+               {\r
+                       seekDS(pfrt[i].Offs - DataOffset);\r
+                       readDS(&Partial, 4);\r
+                       seekDS(pfrt[i].Offs - DataOffset);\r
+                       AddFix = pfrt[i].Offs - DataOffset;\r
+               }\r
+               else    /* Ref is in CSEG */\r
+               {\r
+                       seekCS(pfrt[i].Offs - CodeOffset);\r
+\r
+                       if (pfrt[i].Type == CSEGREF)     /* IT'S ABSOLUTE! */\r
+                       {\r
+                               readCS(&Partial, 4);\r
+                               seekCS(pfrt[i].Offs - CodeOffset);\r
+                               AddFix = pfrt[i].Offs - CodeOffset;\r
+                       }\r
+               }\r
+               /* We are where we should write the reference\r
+                  now we need to find it in the local symbol table\r
+                  and calculate the proper offset.  The calculation\r
+                  is different for Relative and absolute references.\r
+                  For Relative, we subtract the address where the correction\r
+                  is going to be stored from the offset of reference.\r
+                  For Absolute, we read what was already at the address\r
+                  and add it to the offset of the referenced item.\r
+                  Both of these are also adjusted for the Virtual segment offset.\r
+               */\r
+\r
+               /* Look in the Local Symbol table first! */\r
+\r
+               isym = findLsymbol(pfrt[i].Ptr, pfrt[i].NameSz);\r
+\r
+               if (isym)               /* we found it! */\r
+               {\r
+                       if (pfrt[i].Type == CCR8REF)            /* 8 bit relative */\r
+                       {\r
+                               Relative = lst[isym].Offs - (pfrt[i].Offs - CodeOffset + 1);\r
+                               OutByteCS(Relative);\r
+                       }\r
+                       else if (pfrt[i].Type == CCR32REF) /* 32 bit relative */\r
+                       {\r
+                               /* Fixed to make relatives ok in Virtual Segs */\r
+\r
+                               Relative = (lst[isym].Offs - CodeOffset) -\r
+                                          (pfrt[i].Offs - CodeOffset + 4);\r
+                               OutDWordCS(Relative);\r
+                       }\r
+                       else if (pfrt[i].Type == CSEGREF)  /* 32 bit absolute */\r
+                       {\r
+                               Partial += lst[isym].Offs;\r
+\r
+                               if (lst[isym].Type & CLABEL)\r
+                                       FixUp(CCFIXTAG, AddFix, 0);\r
+                               else if (lst[isym].Type & DLABEL)\r
+                                       FixUp(CDFIXTAG, AddFix, 0);\r
+\r
+                               OutDWordCS(Partial);\r
+                       }\r
+                       else if (pfrt[i].Type == DSEGREF)\r
+                       {\r
+                               Partial += lst[isym].Offs;                      /* RAB was + DataOffset */\r
+\r
+                               if (lst[isym].Type & CLABEL)\r
+                                       FixUp(DCFIXTAG, AddFix, 0);\r
+                               else if (lst[isym].Type & DLABEL)\r
+                                       FixUp(DDFIXTAG, AddFix, 0);\r
+\r
+                               OutDWordDS(Partial);\r
+                       }\r
+               }\r
+               else    /* Look in Global table */\r
+               {\r
+\r
+                       isym = findGsymbol(pfrt[i].Ptr, pfrt[i].NameSz);\r
+\r
+                       if (isym)\r
+\r
+                       {               /* we found it! */\r
+\r
+\r
+                               if (pfrt[i].Type == CCR8REF) {          /* 8 bit relative */\r
+                                       Relative = gst[isym].Offs - (pfrt[i].Offs - CodeOffset + 1);\r
+                                       OutByteCS(Relative);\r
+                               }\r
+                               else if (pfrt[i].Type == CCR32REF) {  /*  32 bit relative */\r
+                                       Relative = gst[isym].Offs - (pfrt[i].Offs - CodeOffset + 4);\r
+                                       OutDWordCS(Relative);\r
+                               }\r
+                               else if (pfrt[i].Type == CSEGREF) {\r
+                                       Partial += gst[isym].Offs;\r
+\r
+                                       if (gst[isym].Type & CLABEL)\r
+                                               FixUp(CCFIXTAG, AddFix, 0);\r
+                                       else if (gst[isym].Type & DLABEL)\r
+                                               FixUp(CDFIXTAG, AddFix, 0);\r
+\r
+                                       OutDWordCS(Partial);\r
+                               }\r
+                               else if (pfrt[i].Type == DSEGREF)\r
+                               {\r
+                                       Partial += gst[isym].Offs;\r
+\r
+                                       if (gst[isym].Type & CLABEL)\r
+                                               FixUp(DCFIXTAG, AddFix, 0);\r
+                                       else if (gst[isym].Type & DLABEL)\r
+                                               FixUp(DDFIXTAG, AddFix, 0);\r
+\r
+                                       OutDWordDS(Partial);\r
+                               }\r
+                       }\r
+                       else\r
+                               prev_error("Unresolved symbol in current module", pfrt[i].Line);\r
+               }\r
+               i++;\r
+       }\r
+\r
+       ics = oNextCode - CodeOffset;\r
+       ids = oNextData - DataOffset;\r
+\r
+}\r
+\r
+/*****************************************\r
+ When we have processed all the source\r
+ we call this to resolve ALL externals.\r
+ ******************************************/\r
+\r
+void ResolveExt(void)\r
+{\r
+long i, isym;\r
+S32 Relative;\r
+S32 Partial;\r
+S32 AddFix;\r
+char name[31];\r
+\r
+i = 0;\r
+Partial = 0;\r
+Relative = 0;\r
+AddFix = 0;\r
+\r
+while (i < iERefNext) {        /* While there are unresolved externals */\r
+\r
+       /* See if ref is in GST as PUBLIC */\r
+\r
+       isym = ert[i].iSym;\r
+\r
+       if (gst[isym].Type & tPUBLIC) {\r
+\r
+               if (ert[i].Type == DSEGREF) {                                   /* Ref is in DSEG */\r
+\r
+                       seekDS(ert[i].Offs - DataOffset);\r
+                       readDS(&Partial, 4);\r
+                       seekDS(ert[i].Offs - DataOffset);\r
+                       AddFix = ert[i].Offs - DataOffset;\r
+               }\r
+               else  {                                                                                 /* Ref is in CSEG */\r
+\r
+                       seekCS(ert[i].Offs - CodeOffset);\r
+\r
+                       if (ert[i].Type == CSEGREF) {                    /* and IT'S ABSOLUTE! */\r
+                               readCS(&Partial, 4);\r
+                               seekCS(ert[i].Offs - CodeOffset);\r
+                               AddFix = ert[i].Offs - CodeOffset;\r
+                       }\r
+               }\r
+                       /* We are where we should write the reference\r
+                          now we need to use the index in the external ref\r
+                          table to see if it has been defined PUBLIC.\r
+                          If so, we resolve it, else we error out.\r
+                          To resolve it, the calculation is different for Relative\r
+                          and absolute references.\r
+                          For Relative, we subtract the address where the correction\r
+                          is going to be stored from the offset of reference.\r
+                          For Absolute, we read what was already at the address\r
+                          and add it to the offset of the referenced item.\r
+                          Both of these are also adjusted for the Virtual segment offset.\r
+                       */\r
+\r
+               if (ert[i].Type == CCR32REF) {  /*  32 bit relative */\r
+\r
+                       /* Fixed to make relatives ok in Virtual Segs */\r
+\r
+                       Relative = (gst[isym].Offs - CodeOffset) -\r
+                                  (ert[i].Offs - CodeOffset + 4);\r
+                       OutDWordCS(Relative);\r
+               }\r
+               else if (ert[i].Type == CSEGREF) {\r
+                       Partial += gst[isym].Offs;\r
+\r
+                       if (gst[isym].Type & DLABEL)\r
+                               FixUp(CDFIXTAG, AddFix, 0);\r
+                       else if (gst[isym].Type & CLABEL)\r
+                               FixUp(CCFIXTAG, AddFix, 0);\r
+\r
+                       OutDWordCS(Partial);\r
+               }\r
+               else if (ert[i].Type == DSEGREF) {\r
+                       Partial += gst[isym].Offs;\r
+\r
+                       if (gst[isym].Type & CLABEL)\r
+                               FixUp(DCFIXTAG, AddFix, 0);\r
+                       else if (gst[isym].Type & DLABEL)\r
+                                       FixUp(DDFIXTAG, AddFix, 0);\r
+\r
+                       OutDWordDS(Partial);\r
+               }\r
+       }\r
+       else {\r
+               strncpy(name, gst[isym].Ptr, gst[isym].Size);\r
+               name[gst[isym].Size] = '\0';\r
+               fprintf(lst_fh, "Unresolved external: %s\n", name);\r
+               Column = 0;\r
+               ++error_count;\r
+       }\r
+i++;\r
+}      /* while more Erefs */\r
+\r
+ics = oNextCode - CodeOffset;\r
+ids = oNextData - DataOffset;\r
+\r
+}\r
+\r
+/*****************************************\r
+  If there were no errors, and all looks\r
+  well, we build the run file. This consists\r
+  of building the required tags in order\r
+  and writing them to the file with the\r
+  data.\r
+******************************************/\r
+\r
+void BuildRunFile(void)\r
+{\r
+unsigned char b;\r
+long i;\r
+long sdata;\r
+\r
+       tag.id = IDTAG;                                         /* File type */\r
+       tag.len = 1;\r
+       fwrite(&tag, 5, 1, run_fh);                     /* Write the tag record */\r
+       fwrite(&filetype, 1, 1, run_fh);        /* Write the filetype */\r
+\r
+       /* Version tag goes here */\r
+       /* DatTime tag goes here */\r
+       /* Comment tag(s) goes here */\r
+\r
+       tag.id = SEGTAG;                                        /* Initial Segment Sizes */\r
+       tag.len = 12;\r
+       fwrite(&tag, 5, 1, run_fh);                     /* Write the tag record */\r
+       fwrite(&StackTotal, 4, 1, run_fh);      /* Write the Stacktotal */\r
+       sdata = oNextCode - CodeOffset;         /* Size of CS.TMP */\r
+       fwrite(&sdata, 4, 1, run_fh);           /* Write the Code Size */\r
+       sdata = oNextData - DataOffset;         /* Size of DS.TMP */\r
+       fwrite(&sdata, 4, 1, run_fh);           /* Write the Data Size */\r
+\r
+       printf("Stack Size: %ld\r\n", StackTotal);\r
+       printf("Code  Size: %ld\r\n", oNextCode - CodeOffset);\r
+       printf("Data  Size: %ld\r\n", oNextData - DataOffset);\r
+\r
+       tag.id = DOFFTAG;                                       /* Assumed Data Offset */\r
+       tag.len = 4;\r
+       fwrite(&tag, 5, 1, run_fh);                     /* Write the tag record */\r
+       fwrite(&DataOffset, 4, 1, run_fh);      /* Write the data */\r
+\r
+       tag.id = COFFTAG;                                       /* Assumed Code Offset */\r
+       tag.len = 4;\r
+       fwrite(&tag, 5, 1, run_fh);                     /* Write the tag record */\r
+       fwrite(&CodeOffset, 4, 1, run_fh);      /* Write the data */\r
+\r
+       tag.id = STRTTAG;                                       /* Starting Address */\r
+       tag.len = 4;\r
+       fwrite(&tag, 5, 1, run_fh);                     /* Write the tag record */\r
+       fwrite(&StartAddr, 4, 1, run_fh);       /* Write the data */\r
+\r
+       tag.id = CODETAG;                                       /* Code Segment */\r
+       tag.len = oNextCode - CodeOffset;       /* Size of CS.TMP */\r
+       fwrite(&tag, 5, 1, run_fh);                     /* Write the tag record */\r
+\r
+       sdata = tag.len;                        /* WRITE the Code seg */\r
+       fwrite(pcsbuf, 1, sdata, run_fh);\r
+\r
+       tag.id = DATATAG;                                       /* Data Segment */\r
+       tag.len = oNextData - DataOffset;       /* Size of DS.TMP */\r
+       fwrite(&tag, 5, 1, run_fh);                     /* Write the tag record */\r
+\r
+       sdata = tag.len;                        /* WRITE the Data seg */\r
+       fwrite(pdsbuf, 1, sdata, run_fh);\r
+\r
+       if (nCDFix) {\r
+               tag.id = CDFIXTAG;                                      /* CSEG Data Fixups */\r
+               tag.len = nCDFix * 4;                           /* Count * 4 of Fixups */\r
+               fwrite(&tag, 5, 1, run_fh);                     /* Write the tag record */\r
+               i = iFUNext;\r
+               while (i--) {                                           /* Write CD fixups */\r
+                       if (pfut[i].type == CDFIXTAG)\r
+                               fwrite(&pfut[i].Offs, 1, 4, run_fh);\r
+               }\r
+       }\r
+\r
+       if (nCCFix) {\r
+               tag.id = CCFIXTAG;                                      /* CSEG Code Fixups */\r
+               tag.len = nCCFix * 4;                           /* Count * 4 of Fixups */\r
+               fwrite(&tag, 5, 1, run_fh);                     /* Write the tag record */\r
+               i = iFUNext;\r
+               while (i--)     {                                               /* Write CC fixups */\r
+                       if (pfut[i].type == CCFIXTAG)\r
+                               fwrite(&pfut[i].Offs, 1, 4, run_fh);\r
+               }\r
+       }\r
+\r
+       if (nDDFix) {\r
+               tag.id = DDFIXTAG;                                      /* DESG Data Fixups */\r
+               tag.len = nDDFix * 4;                           /* Count * 4 of Fixups */\r
+               fwrite(&tag, 5, 1, run_fh);                     /* Write the tag record */\r
+               i = iFUNext;\r
+               while (i--)     {                                               /* Write DD fixups */\r
+                       if (pfut[i].type == DDFIXTAG)\r
+                               fwrite(&pfut[i].Offs, 1, 4, run_fh);\r
+               }\r
+       }\r
+\r
+       if (nDCFix) {\r
+               tag.id = DCFIXTAG;                                      /* DESG Code Fixups */\r
+               tag.len = nDCFix * 4;                           /* Count * 4 of Fixups */\r
+               fwrite(&tag, 5, 1, run_fh);                     /* Write the tag record */\r
+               i = iFUNext;\r
+               while (i--)     {                                               /* Write DC fixups */\r
+                       if (pfut[i].type == DCFIXTAG)\r
+                               fwrite(&pfut[i].Offs, 1, 4, run_fh);\r
+               }\r
+       }\r
+\r
+       /* DLL Address fixup tag goes here */\r
+       /* DLL Public tag goes here */\r
+\r
+       tag.id = ENDTAG;                                                /* End Tag */\r
+       tag.len = 4;    /* Size of CS.TMP */\r
+       fwrite(&tag, 5, 1, run_fh);                             /* Write the tag record */\r
+       sdata = 0;\r
+       fwrite(&sdata, 4, 1, run_fh);                   /* Write the tag record */\r
+\r
+}\r
+\r
+\r
+/*****************************************\r
+    Reads a whole line into line buffer.\r
+******************************************/\r
+\r
+S32 readline(void)\r
+{\r
+U32 i;\r
+U8 *pLine;\r
+\r
+if (!(fgets(line_ptr = line_buf0, 100, src_fh[level])))\r
+{\r
+\r
+       if (level) {    /* we are in a nested include */\r
+               fclose(src_fh[level]);\r
+               --level;\r
+               if (level==0) {         /* back up one level */\r
+\r
+                       /* Processes forward references from this module */\r
+                       Resolve();\r
+\r
+                       if (fSymDump) {\r
+                               DumpLSymbols();\r
+                               DumpFRT();\r
+                       }\r
+\r
+                       /* Clear local symbol, forward refs, & macro tables */\r
+\r
+                       iLSymNext = 1;  /* 1st entry.  */\r
+                       pLSymNext = pLSymBuf; /* beginning of buffer */\r
+\r
+                       iRefNext = 0;   /* 1st entry.  */\r
+                       pRefNext = pRefBuf;             /* Allocate memory - Was RefBuf */\r
+\r
+                       iMacNext = 0;                   /* 1st entry */\r
+                       pMacNext = pMacBuf;             /* Begining of buffer */\r
+\r
+\r
+               }\r
+               if (fListA)\r
+                       fprintf(lst_fh, "\r\n                ");\r
+               fprintf(lst_fh, "CONTINUING-> %s, Level:%d\r\n", srcname[level],level);\r
+           fprintf(lst_fh, "\r\n");\r
+\r
+               if (lineno[level]) --lineno[level];\r
+               fContinue = 1;\r
+       }\r
+       else\r
+       {               /* We are at the end of the ATF file */\r
+\r
+               /* Processes forward references from Level 0 */\r
+               Resolve();\r
+\r
+               if (fSymDump)\r
+               {\r
+                       DumpGSymbols();\r
+                       DumpFRT();\r
+               }\r
+\r
+               if (!fStart)\r
+                       line_error(12); /* Starting address not found */\r
+\r
+               if (!error_count)\r
+                       ResolveExt();\r
+\r
+               printf("%d Errors\r\n%d Warnings\r\n", error_count, warn_count);\r
+\r
+               if (fListA | fListE)\r
+                       fprintf(lst_fh,"%d Errors\r\n%d Warnings\r\n",\r
+                                       error_count,warn_count);\r
+\r
+               if (!error_count)\r
+               {\r
+                       printf("Building Run file...\r\n");\r
+                       BuildRunFile();\r
+                       printf(" Done.\r\n");\r
+               }\r
+\r
+               fclose(lst_fh);\r
+               fclose(src_fh[level]);\r
+           exit(1);\r
+       }\r
+ }\r
+\r
+ list_buf[0] = 0;\r
+ if (fListA) {\r
+        pLine = line_ptr;\r
+        i=0;\r
+        while (isspace(*pLine)) pLine++;\r
+        while ((*pLine) && (*pLine != ';') && (*pLine != 0x0A))\r
+               list_buf[i++] = *pLine++;\r
+        while ((i) && (list_buf[i-1] == ' ')) --i; /* eat trailing spaces */\r
+        list_buf[i] = 0;                                                       /* null terminate */\r
+        if (i) fLineIn = 1;\r
+        else fLineIn = 0;\r
+        }\r
+ ++lineno[level];\r
+ return(1);\r
+}\r
+\r
+\r
+/********************************************\r
+   Dispatch calls Parse from the beginning\r
+   of a line and calls the proper routine\r
+   based on what it finds (from Parse()).\r
+   Dispatch  calls readline to get a new line\r
+   after each of the line-specific modules\r
+   gets done with it's line or lines(s).\r
+*********************************************/\r
+\r
+void Dispatch(void)\r
+{\r
+S32 i, j;\r
+S8   st[80];\r
+\r
+while (1) {\r
+  readline();\r
+\r
+  if (fContinue) {             /* We have just returned from an include */\r
+       fContinue = 0;          /* and must reread the line without processing */\r
+       continue;\r
+       }\r
+\r
+  if (lineno[level] == 1) {\r
+       if (fListA)\r
+               fprintf(lst_fh, "\r\n                ");\r
+       fprintf(lst_fh, "PROCESSING-> %s, Level:%d\r\n", srcname[level], level);\r
+       }\r
+\r
+  if (fListA) {\r
+      Column = fprintf(lst_fh, "%06d ", lineno[level]);\r
+      }\r
+\r
+  fPublic = 0;\r
+  fExtern = 0;\r
+  fFarLabel = 0;\r
+\r
+  i = Parse();\r
+  if (fMoreStorage)\r
+       Storage();\r
+  else switch (i) {\r
+    case INSTRU:\r
+                       if (fListA)\r
+                               Column += fprintf(lst_fh, "%08lX ", *pNextAddr);\r
+                       Instruction();\r
+                       break;\r
+       case REGIST:\r
+                       line_error(63);\r
+                       break;\r
+       case SYMBOL:\r
+                       line_error(64);\r
+                       break;\r
+       case LSYMBOL:\r
+                       line_error(65);\r
+                       break;\r
+       case STRING:\r
+       case NUMBER:\r
+                       line_error(66);\r
+                       break;\r
+       case rPUBLIC:\r
+                       fPublic = 1;\r
+                       if (fListA)\r
+                               Column += fprintf(lst_fh, "%08lX ", *pNextAddr);\r
+                       j = Parse();\r
+                       if (j==SYMBOL)\r
+                                       MakePublic();\r
+                       else if (j==UNKSYM)\r
+                               NewSymbol();\r
+                       else\r
+                               line_error(67);\r
+                       break;\r
+       case rEXTRN:\r
+                       fExtern = 1;\r
+                       if (fListA)\r
+                               Column += fprintf(lst_fh, "%08lX ", *pNextAddr);\r
+                       j = Parse();\r
+                       if (j==SYMBOL)\r
+                                       CheckExtern();\r
+                       else if (j==UNKSYM)\r
+                               NewSymbol();\r
+                       else\r
+                               line_error(67);\r
+                       break;\r
+       case UNKSYM:\r
+                       if (fListA)\r
+                               Column += fprintf(lst_fh, "%08lX ", *pNextAddr);\r
+                       if (level)\r
+                               NewLSymbol();\r
+                       else\r
+                               NewSymbol();\r
+                       break;\r
+       case DOT:\r
+                       Command();\r
+                       break;\r
+       case rDB:\r
+       case rDD:\r
+       case rDW:\r
+       case rDF:\r
+               if (fListA)\r
+                       Column += fprintf(lst_fh, "%08lX ", *pNextAddr);\r
+               Storage();\r
+               break;\r
+       case ZERO:\r
+               break;\r
+       default:\r
+               line_error(68);\r
+               break;\r
+       }\r
+\r
+  if ((fLineIn) && (fListA)) {\r
+         while (Column < 53) Column += fprintf(lst_fh, " ");\r
+         fprintf(lst_fh, "%s", list_buf);\r
+      }\r
+  if (Column)\r
+         fprintf(lst_fh, "\r\n");\r
+\r
+ } /* while */\r
+}\r
+\r
+/*********************\r
+* Main program\r
+**********************/\r
+\r
+void main(S32 argc, S8   *argv[])\r
+{\r
+S8   *ptr, *pname;\r
+S32  i, j, fdone;\r
+U32 erc;\r
+\r
+       lst_fh = stdout;        /* default the list file */\r
+\r
+       for(i=1; i < argc; ++i) {\r
+               ptr = argv[i];\r
+               if (*ptr == '/') {\r
+                 ptr++;\r
+                 switch(*ptr) {\r
+                       case 'L' :                      /* List file ON */\r
+                       case 'l' :\r
+                               fListA = 1;\r
+                               break;\r
+                       case 'S' :                      /* Dump Symbols */\r
+                       case 's' :\r
+                               fSymDump = 1;\r
+                               break;\r
+                       case 'E' :                      /* List file ON for errors/warns only */\r
+                       case 'e' :\r
+                               fListE = 1;\r
+                               break;\r
+                       case 'D' :                      /* Process as DLL */\r
+                       case 'd' :\r
+                               filetype = 2;\r
+                               break;\r
+                       case 'V' :                      /* Process as Devive Driver */\r
+                       case 'v' :\r
+                               filetype = 3;\r
+                               break;\r
+                       default:\r
+                               fatal_error("Invalid option\n");\r
+                               break;\r
+                 }\r
+               }\r
+               else {\r
+                       if(!src_fh[0]) {\r
+                               strncpy(srcname, argv[i], 39);\r
+                               src_fh[0] = fopen(argv[i], "r");\r
+                               }\r
+                       else if(!run_fh) {\r
+                               strncpy(runname, argv[i], 39);\r
+                               if(!(run_fh = fopen(argv[i], "wb"))) {\r
+                                 fatal_error("Can't open RUN file\n");\r
+                                 }\r
+                               }\r
+                       else\r
+                               fatal_error("Too many options\n"); /* Too many parameters */\r
+          }\r
+       }\r
+\r
+/* Input file not explicitly named errors out */\r
+       if(!src_fh[0]) {\r
+               printf("Usage: ATFfile [RunFile] /L /E /D /V\r\n");\r
+               printf("/L = Complete List file generated\r\n");\r
+               printf("/S = Include SYMBOLS (only in complete list file)\r\n");\r
+               printf("/E = List file for Errors/warnings only\r\n");\r
+               printf("/D = Process as Dynamic link library\r\n");\r
+               printf("/V = Process as deVice driver\r\n");\r
+               fatal_error("Can't open Template file\n"); /* Can't open ATF file */\r
+               }\r
+\r
+/* Output file not explicitly named defaults to Source.RUN */\r
+\r
+       if(!run_fh)     {                       /* default asm name to SourceName.run */\r
+               strncpy(runname, srcname, 40);\r
+               pname=runname;\r
+               while ((*pname != '.') && (*pname!= '\0')) pname++;\r
+               *pname++ = '.';\r
+        if (filetype == 2) {\r
+                *pname++ = 'D';\r
+                *pname++ = 'L';\r
+                *pname++ = 'L';\r
+        }\r
+        else if (filetype == 3) {\r
+                *pname++ = 'D';\r
+                *pname++ = 'D';\r
+                *pname++ = 'R';\r
+        }\r
+        else {\r
+         filetype = 1;\r
+                *pname++ = 'R';\r
+                *pname++ = 'U';\r
+                *pname++ = 'N';\r
+               }\r
+               *pname   = '\0';\r
+               if(!(run_fh = fopen(runname, "wb"))) {\r
+                       fatal_error("Can't open OUTPUT file\n");  /* Can't open RUN file */\r
+                       }\r
+               }\r
+\r
+/* List file named Source.LIS for fListA and fListE only. */\r
+\r
+       if (fListA | fListE) {\r
+               strncpy(lstname, srcname, 40);\r
+               pname=lstname;\r
+               while ((*pname != '.') && (*pname!= '\0')) pname++;\r
+               *pname++ = '.';\r
+               *pname++ = 'L';\r
+               *pname++ = 'I';\r
+               *pname++ = 'S';\r
+               *pname   = '\0';\r
+               if(!(lst_fh = fopen(lstname, "w")))\r
+                       fatal_error("Can't open list file (source.LIS)\n"); /* Can't open List file */\r
+               }\r
+               else\r
+            lst_fh = stdout;\r
+\r
+printf("DASM Ver 1.7M (c) R.A. Burgess 1992,1993,1994,1995\r\n\r\n");\r
+\r
+if (fListA | fListE)\r
+       fprintf(lst_fh, "DASM Ver 1.7M (c) R.A. Burgess 1992,1993,1994,1995\r\n\r\n");\r
+\r
+if (fListA)\r
+       fprintf(lst_fh,\r
+    "LINE   OFFSET   ACTION/DATA/CODE                     SOURCE\r\n\r\n");\r
+\r
+       erc = AllocPage(LSYMBUFMAX/4096, &pLSymBuf);\r
+       if (erc)\r
+               fatal_error("Can't Allocate buffer 1\n");\r
+\r
+       erc = AllocPage(SYMBUFMAX/4096, &pSymBuf);\r
+       if (erc)\r
+               fatal_error("Can't Allocate buffer 2\n");\r
+\r
+       erc = AllocPage(MACBUFMAX/4096, &pMacBuf);\r
+       if (erc)\r
+               fatal_error("Can't Allocate buffer 3\n");\r
+\r
+       erc = AllocPage(FREFBUFMAX/4096, &pRefBuf);\r
+       if (erc)\r
+               fatal_error("Can't Allocate buffer 4\n");\r
+\r
+       erc = AllocPage(FREFTABMAX/4096, &pfrt);\r
+       if (erc)\r
+               fatal_error("Can't Allocate buffer 5\n");\r
+\r
+       erc = AllocPage(FIXUPBUFMAX/4096, &pfut);\r
+       if (erc)\r
+               fatal_error("Can't Allocate buffer 6\n");\r
+\r
+\r
+pSymNext = pSymBuf;            /* Allocate memory - Was SymBuf */\r
+pLSymNext = pLSymBuf;  /* Allocate memory - Was LSymBuf */\r
+pMacNext = pMacBuf;            /* Allocate memory - Was MacBuf */\r
+pRefNext = pRefBuf;            /* Allocate memory - Was RefBuf */\r
+\r
+pNextAddr = &oNextData;        /* default to DataSeg */\r
+\r
+erc = AllocPage(STMPBUFS/4096, &pcsbuf);\r
+if (erc)\r
+       fatal_error("Can't Allocate CS buffer \n");\r
+\r
+erc = AllocPage(STMPBUFS/4096, &pdsbuf);\r
+if (erc)\r
+       fatal_error("Can't Allocate DS buffer \n");\r
+\r
+ics = 0;                       /* current index into tmp buffers */\r
+ids = 0;\r
+\r
+/* We now build a dynamic instruction lookup table which indexes\r
+the first entry of an instruction in the opcode array 'rgINS'.\r
+This is done dynamically because we are still optimizing.\r
+*/\r
+\r
+/* i is the instruction we are indexing */\r
+/* j is the position in rgINS */\r
+\r
+for (i=1; i<ninst+1; i++) {\r
+       for (j=1; j<nrgINS; j++) {\r
+               if (rgINS[j][0] == i) {\r
+               rgInsLookUp[i] = j;\r
+               break;\r
+               }\r
+       }\r
+}\r
+\r
+Dispatch();\r
+exit(0);\r
+}\r
diff --git a/msamples/dasmm/dasm.h b/msamples/dasmm/dasm.h
new file mode 100644 (file)
index 0000000..5397063
--- /dev/null
@@ -0,0 +1,1355 @@
+/* 386 D-Group ASSEMBLER.  Header file.\r
+   Copyright 1992 R.A. Burgess\r
+*/\r
+\r
+ /* The DASM parser returns a TOKEN type and fills in certain\r
+   global variables with the values found.  The token type is\r
+   placed in Token as well as being returned to the caller.\r
+*/\r
+\r
+/* The following are the TOKEN types returned by the parser or\r
+   the expression analyzer :\r
+*/\r
+\r
+#define ZERO   0       /* Parser returned NOTHING (blank or EOL) */\r
+#define INSTRU 1       /* 386 instruction. Number placed in TInst. */\r
+#define REGIST 2       /* 386 register is placed in TReg */\r
+#define SYMBOL 3       /* In symbol table. Sym number placed in TSymnum */\r
+#define LSYMBOL        4       /* In symbol table. LSym number placed in TSymnum */\r
+#define STRING 5       /* 'quoted' string of characters left in TString */\r
+#define NUMBER 6       /* Valid value placed in TNumber */\r
+#define NUMOFF 7       /* Valid TNumber derived from OFFSET (needs fix) */\r
+#define UNKSYM 8       /* Qualifies as a sym but not found. Left in TString */\r
+#define SYMOFF 9   /* Symbol offset value (from Expression analyzer) */\r
+#define ERROR  10      /* Bad char found in line. Line terminated by Parse(). */\r
+\r
+/* alphabetized list of reserved words excluding registers and\r
+   instructions.  They must be alphabetized for binary search\r
+   function to work. They begin with #89 so they don't conflict\r
+   with other token values. */\r
+\r
+#define nreserved 30\r
+#define srsvd 8                        /* size of a reserved storage */\r
+#define nrsvd1 94              /* must be the first number of rgReserved */\r
+char rgReserved[nreserved][srsvd]  = {         /* 109 bytes */\r
+         "ALIGN",     /*  94 */\r
+         "BYTE",      /*  95 */\r
+         "CODE",      /*  96 */\r
+         "DATA",      /*  97 */\r
+         "DB",        /*  98 */\r
+         "DD",        /*  99 */\r
+         "DF",        /* 100 */\r
+         "DUP",       /* 101 */\r
+         "DW",        /* 102 */\r
+         "DWORD",     /* 103 */\r
+            "END",       /* 104 */\r
+         "EQU",       /* 105 */\r
+         "EXTRN",     /* 106 */\r
+         "FAR",       /* 107 */\r
+         "FWORD",     /* 108 */\r
+         "INCLUDE",   /* 109 */\r
+         "NAME",      /* 110 */\r
+         "NEAR",      /* 111 */\r
+         "OFFSET",    /* 112 */\r
+         "PARA",      /* 113 */\r
+         "PTR",       /* 114 */\r
+                "PUBLIC",    /* 115 */\r
+         "SEARCH",    /* 116 */\r
+         "SHORT",     /* 117 */\r
+         "STACK",     /* 118 */\r
+         "START",     /* 119 */\r
+         "USE16",     /* 120 */\r
+         "USE32",     /* 121 */\r
+         "VIRTUAL",   /* 122 */\r
+         "WORD",      /* 123  up to 127 MAX */\r
+         };\r
+\r
+/* The following reserved "words" are recognized by Parse.\r
+   This list MUST agree with the numbering of the table\r
+   rgReserved above.\r
+*/\r
+\r
+#define  rALIGN                94      /* .ALIGN n - Align code segment   */\r
+#define  rBYTE         95      /* for forcing types on operands   */\r
+#define  rCODE         96      /* .CODE - begin/continue code segment   */\r
+#define         rDATA          97      /* .DATA - begin/continue data segment   */\r
+#define  rDB           98      /* storage of byte(s) or (strings) */\r
+#define  rDD           99      /* double words */\r
+#define  rDF           100 /* FWord (OFF:SEL) */\r
+#define  rDUP          101     /* duplicated storage of DB, DW or DD */\r
+#define  rDW           102     /* storage of words follows */\r
+#define  rDWORD                103     /* for forcing types on operands */\r
+#define  rEND          104     /* .END - file end - no more segments    */\r
+#define  rEQU          105     /* EQUATE for numbers/addresses only */\r
+#define  rEXTRN     106  /* for EXTERNAL definition */\r
+#define  rFAR          107     /* FAR operator for calls */\r
+#define  rFWORD                108     /* for forcing types on operands */\r
+#define  rINCLUDE      109     /* .INCLUDE - Include file for assembly  */\r
+#define  rNAME         110     /* .NAME to name a segment */\r
+#define  rNEAR         111     /* NEAR operator for calls (default) */\r
+#define  rOFFSET       112     /* offset in segment of ... */\r
+#define  rPARA         113     /* PTR operator for mem ops */\r
+#define  rPTR          114     /* PTR operator for mem ops */\r
+#define  rPUBLIC    115        /* for PUBLIC declarations */\r
+#define  rSEARCH       116     /* SEARCH command for Lib files  */\r
+#define  rSHORT                117     /* SHORT operator for relative jumps   */\r
+#define  rSTACK                118     /* .START - Entry point for execution    */\r
+#define  rSTART                119     /* .STACK - Sets initial stack size   */\r
+#define  rUSE16     120 /* .USE16 (16 bit segment) */\r
+#define  rUSE32     121 /* .USE16 (16 bit segment) */\r
+#define  rVIRTUAL      122 /* .VIRTUAL n - Data @ virtual address n */\r
+#define  rWORD         123 /*  WORD operator for mem ops */\r
+\r
+/* Special characters. They are treated as reserved words but are\r
+   not searched alphabetically.  They must maintain their ASCII\r
+   values (other tokens are numbers "around" them).\r
+*/\r
+\r
+#define  DOLLAR                0x24   /* 36 */\r
+#define  SQUOTE                0x27   /* 39 */\r
+#define  OPENRND       0x28   /* 40 */\r
+#define  CLOSRND       0x29   /* 41 */\r
+#define  STAR          0x2a   /* 42 */\r
+#define  PLUS          0x2b   /* 43 */\r
+#define  COMMA         0x2c   /* 44 */\r
+#define  MINUS         0x2d   /* 45 */\r
+#define  DOT           0x2e   /* 46 */\r
+#define  SLASH         0x2f   /* 47 */\r
+#define  COLON         0x3a   /* 58 */\r
+#define  SEMI          0x3b   /* 59 */\r
+#define  OPENSQR       0x5b   /* 91 */\r
+#define  CLOSSQR       0x5d   /* 93 */\r
+\r
+/* The following bits identify symbol types in GST & LST */\r
+\r
+#define CLABEL  0x0001  /* Code label - SymPtr has Offset in Code seg */\r
+#define DLABEL  0x0002  /* Data label - SymPtr has Offset in Data seg */\r
+#define MACRO   0x0004  /* No offset associated -  pts to string */\r
+#define sBYTE  0x0008  /* Data label for BYTE (8 bit)   */\r
+#define sWORD  0x0010  /* Data label for WORD (16 bit)  */\r
+#define sDWORD 0x0020  /* Data label for DWORD (32 bit) */\r
+#define sFWORD 0x0040  /* Data label for FWORD (48 bit) */\r
+#define tEXTRN  0x0080  /* Defined External, Public not found yet */\r
+#define tFAR    0x0100  /* Defined as FAR, default is near */\r
+#define tPUBLIC 0x0200  /* Defined as PUBLIC */\r
+\r
+\r
+/* This is an alphabetical array of all the 386 registers.\r
+   It it used for a binary search for a register name. If\r
+   the beginning number (128) is changed here you must make\r
+   sure to change the define nreg1 to match to the search\r
+   routine will give you the correct number They start at 128\r
+   so they don't conflict with operand types in instruction table\r
+   rgINS[].\r
+*/\r
+\r
+#define nregs 52\r
+#define sregs 4\r
+#define nreg1 128\r
+\r
+char rgreg[nregs][4]  = {              /* 176 bytes */\r
+\r
+      "AH",    /* 128 */\r
+      "AL",    /* 129 */\r
+      "AX",    /* 130 */\r
+         "BH",    /* 131 */\r
+         "BL",    /* 132 */\r
+         "BP",    /* 133 */\r
+         "BX",    /* 134 */\r
+         "CH",    /* 135 */\r
+         "CL",    /* 136 */\r
+         "CR0",   /* 137 */\r
+         "CR1",   /* 138 */\r
+         "CR2",   /* 139 */\r
+      "CR3",   /* 140 */\r
+         "CS",    /* 141 */\r
+         "CX",    /* 142 */\r
+         "DH",    /* 143 */\r
+         "DI",    /* 144 */\r
+         "DL",    /* 145 */\r
+         "DR0",   /* 146 */\r
+         "DR1",   /* 147 */\r
+         "DR2",   /* 148 */\r
+         "DR3",   /* 149 */\r
+         "DR6",   /* 150 */\r
+         "DR7",   /* 151 */\r
+         "DS",    /* 152 */\r
+         "DX",    /* 153 */\r
+      "EAX",   /* 154 */\r
+         "EBP",   /* 155 */\r
+         "EBX",   /* 156 */\r
+         "ECX",   /* 157 */\r
+         "EDI",   /* 158 */\r
+         "EDX",   /* 159 */\r
+         "ESI",   /* 160 */\r
+         "ES",    /* 161 */\r
+         "ESP",   /* 162 */\r
+         "FS",    /* 163 */\r
+         "GS",    /* 164 */\r
+         "SI",    /* 165 */\r
+         "SP",    /* 166 */\r
+         "SS",    /* 167 */\r
+         "TR6",   /* 168 */\r
+         "TR7"};  /* 169 */\r
+\r
+#define rAH  128\r
+#define rAL  129\r
+#define rAX  130\r
+#define rBH  131\r
+#define rBL  132\r
+#define rBP  133\r
+#define rBX  134\r
+#define rCH  135\r
+#define rCL  136\r
+#define rCR0 137\r
+#define rCR1 138\r
+#define rCR2 139\r
+#define rCR3 140\r
+#define rCS  141\r
+#define rCX  142\r
+#define rDH  143\r
+#define rDI  144\r
+#define rDL  145\r
+#define rDR0 146\r
+#define rDR1 147\r
+#define rDR2 148\r
+#define rDR3 149\r
+#define rDR6 150\r
+#define rDR7 151\r
+#define rDS  152\r
+#define rDX  153\r
+#define rEAX 154\r
+#define rEBP 155\r
+#define rEBX 156\r
+#define rECX 157\r
+#define rEDI 158\r
+#define rEDX 159\r
+#define rESI 160\r
+#define rES  161\r
+#define rESP 162\r
+#define rFS  163\r
+#define rGS  164\r
+#define rSI  165\r
+#define rSP  166\r
+#define rSS  167\r
+#define rTR6 168\r
+#define rTR7 169\r
+\r
+/* This is an alaphebetical array of all the 386 instructions */\r
+/* It it used for a binary search for an instruction  */\r
+\r
+#define ninst 208\r
+#define sinst 7                                        /* size of a instruction storage */\r
+\r
+long rgInsLookUp[ninst+1];             /* Lookup for instruction table */\r
+\r
+char rginst[ninst][sinst] = {  /*  1456 bytes */\r
+\r
+    "AAA",     /* 001 */\r
+    "AAD",     /* 002 */\r
+    "AAM",     /* 003 */\r
+       "AAS",     /* 004 */\r
+       "ADC",     /* 005 */\r
+       "ADD",     /* 006 */\r
+       "AND",     /* 007 */\r
+       "ARPL",    /* 008 */\r
+\r
+       "BOUND",   /* 009 */\r
+       "BSF",     /* 010 */\r
+       "BSR",     /* 011 */\r
+       "BT",      /* 012 */\r
+       "BTC",     /* 013 */\r
+       "BTR",     /* 014 */\r
+       "BTS",     /* 015 */\r
+\r
+       "CALL",    /* 016 */\r
+       "CBW",     /* 017 */\r
+       "CDQ",     /* 018 */\r
+       "CLC",     /* 019 */\r
+       "CLD",     /* 020 */\r
+       "CLI",     /* 021 */\r
+       "CLTS",    /* 022 */\r
+       "CMC",     /* 023 */\r
+       "CMP",     /* 024 */\r
+       "CMPS",    /* 025 */\r
+       "CMPSB",   /* 026 */\r
+       "CMPSD",   /* 027 */\r
+       "CMPSW",   /* 028 */\r
+       "CWD",     /* 029 */\r
+       "CWDE",    /* 030 */\r
+\r
+       "DAA",     /* 031 */\r
+       "DAS",     /* 032 */\r
+       "DEC",     /* 033 */\r
+       "DIV",     /* 034 */\r
+\r
+       "ENTER",   /* 035 */\r
+\r
+       "HLT",     /* 036 */\r
+\r
+       "IDIV",    /* 037 */\r
+       "IMUL",    /* 038 */\r
+       "IN",      /* 039 */\r
+       "INC",     /* 040 */\r
+       "INS",     /* 041 */\r
+       "INSB",    /* 042 */\r
+       "INSD",    /* 043 */\r
+       "INSW",    /* 044 */\r
+       "INT",     /* 045 */\r
+       "INTO",    /* 046 */\r
+       "IRET",    /* 047 */\r
+       "IRETD",   /* 048 */\r
+\r
+       "JA",      /* 049 */\r
+       "JAE",     /* 050 */\r
+       "JB",      /* 051 */\r
+       "JBE",     /* 052 */\r
+       "JC",      /* 053 */\r
+       "JCXZ",    /* 054 */\r
+       "JE",      /* 055 */\r
+       "JECXZ",   /* 056 */\r
+       "JG",      /* 057 */\r
+       "JGE",     /* 058 */\r
+       "JL",      /* 059 */\r
+       "JLE",     /* 060 */\r
+       "JMP",     /* 061 */\r
+       "JNA",     /* 062 */\r
+       "JNAE",    /* 063 */\r
+       "JNB",     /* 064 */\r
+       "JNBE",    /* 065 */\r
+       "JNC",     /* 066 */\r
+       "JNE",     /* 067 */\r
+       "JNG",     /* 068 */\r
+       "JNGE",    /* 069 */\r
+       "JNL",     /* 070 */\r
+       "JNLE",    /* 071 */\r
+       "JNO",     /* 072 */\r
+       "JNP",     /* 073 */\r
+       "JNS",     /* 074 */\r
+       "JNZ",     /* 075 */\r
+       "JO",      /* 076 */\r
+       "JP",      /* 077 */\r
+       "JPE",     /* 078 */\r
+       "JPO",     /* 079 */\r
+       "JS",      /* 080 */\r
+       "JZ",      /* 081 */\r
+\r
+       "LAHF",    /* 082 */\r
+       "LAR",     /* 083 */\r
+       "LDS",     /* 084 */\r
+       "LEA",     /* 085 */\r
+       "LEAVE",   /* 086 */\r
+       "LES",     /* 087 */\r
+       "LFS",     /* 088 */\r
+       "LGDT",    /* 089 */\r
+       "LGS",     /* 090 */\r
+       "LIDT",    /* 091 */\r
+       "LLDT",    /* 092 */\r
+       "LMSW",    /* 093 */\r
+       "LOCK",    /* 094 */\r
+       "LODS",    /* 095 */\r
+       "LODSB",   /* 096 */\r
+       "LODSD",   /* 097 */\r
+       "LODSW",   /* 098 */\r
+       "LOOP",    /* 099 */\r
+       "LOOPE",   /* 100 */\r
+       "LOOPNE",  /* 101 */\r
+       "LOOPNZ",  /* 102 */\r
+       "LOOPZ",   /* 103 */\r
+       "LSL",     /* 104 */\r
+       "LSS",     /* 105 */\r
+       "LTR",     /* 106 */\r
+\r
+       "MOV",     /* 107 */\r
+       "MOVS",    /* 108 */\r
+       "MOVSB",   /* 109 */\r
+       "MOVSD",   /* 110 */\r
+       "MOVSW",   /* 111 */\r
+       "MOVSX",   /* 112 */\r
+       "MOVZX",   /* 113 */\r
+       "MUL",     /* 114 */\r
+\r
+       "NEG",     /* 115 */\r
+       "NOP",     /* 116 */\r
+       "NOT",     /* 117 */\r
+\r
+       "OR",      /* 118 */\r
+       "OUT",     /* 119 */\r
+       "OUTS",    /* 120 */\r
+       "OUTSB",   /* 121 */\r
+       "OUTSD",   /* 122 */\r
+       "OUTSW",   /* 123 */\r
+\r
+       "POP",     /* 124 */\r
+       "POPA",    /* 125 */\r
+       "POPAD",   /* 126 */\r
+       "POPF",    /* 127 */\r
+       "POPFD",   /* 128 */\r
+       "PUSH",    /* 129 */\r
+       "PUSHA",   /* 130 */\r
+    "PUSHAD",  /* 131 */\r
+    "PUSHF",   /* 132 */\r
+    "PUSHFD",  /* 133 */\r
+\r
+    "RCL",     /* 134 */\r
+    "RCR",     /* 135 */\r
+    "REP",     /* 136 */\r
+    "REPE",    /* 137 */\r
+    "REPNE",   /* 138 */\r
+    "REPNZ",   /* 139 */\r
+    "REPZ",    /* 140 */\r
+    "RET",     /* 141 */\r
+    "RETF",    /* 142 */\r
+    "RETN",    /* 143 */\r
+    "ROL",     /* 144 */\r
+    "ROR",     /* 145 */\r
+\r
+    "SAHF",    /* 146 */\r
+    "SAL",     /* 147 */\r
+    "SAR",     /* 148 */\r
+    "SBB",     /* 149 */\r
+    "SCAS",    /* 150 */\r
+    "SCASB",   /* 151 */\r
+    "SCASD",   /* 152 */\r
+    "SCASW",   /* 153 */\r
+    "SETA",    /* 154 */\r
+    "SETAE",   /* 155 */\r
+    "SETB",    /* 156 */\r
+    "SETBE",   /* 157 */\r
+    "SETC",    /* 158 */\r
+    "SETE",    /* 159 */\r
+    "SETG",    /* 160 */\r
+    "SETGE",   /* 161 */\r
+    "SETL",    /* 162 */\r
+    "SETLE",   /* 163 */\r
+    "SETNA",   /* 164 */\r
+    "SETNAE",  /* 165 */\r
+    "SETNB",   /* 166 */\r
+    "SETNBE",  /* 167 */\r
+    "SETNC",   /* 168 */\r
+       "SETNE",   /* 169 */\r
+       "SETNG",   /* 170 */\r
+       "SETNGE",  /* 171 */\r
+       "SETNL",   /* 172 */\r
+    "SETNLE",  /* 173 */\r
+    "SETNO",   /* 174 */\r
+    "SETNP",   /* 175 */\r
+    "SETNS",   /* 176 */\r
+    "SETNZ",   /* 177 */\r
+    "SETO",    /* 178 */\r
+    "SETP",    /* 179 */\r
+    "SETPE",   /* 180 */\r
+    "SETPO",   /* 181 */\r
+    "SETS",    /* 182 */\r
+    "SETZ",    /* 183 */\r
+    "SGDT",    /* 184 */\r
+    "SHL",     /* 185 */\r
+    "SHLD",    /* 186 */\r
+    "SHR",     /* 187 */\r
+    "SHRD",    /* 188 */\r
+    "SIDT",    /* 189 */\r
+    "SLDT",    /* 190 */\r
+    "SMSW",    /* 191 */\r
+    "STC",     /* 192 */\r
+    "STD",     /* 193 */\r
+    "STI",     /* 194 */\r
+    "STOS",    /* 195 */\r
+    "STOSB",   /* 196 */\r
+    "STOSD",   /* 197 */\r
+    "STOSW",   /* 198 */\r
+    "STR",     /* 199 */\r
+    "SUB",     /* 200 */\r
+\r
+    "TEST",    /* 201 */\r
+\r
+    "VERR",    /* 202 */\r
+    "VERW",    /* 203 */\r
+\r
+    "WAIT",    /* 204 */\r
+       "XCHG",    /* 205 */\r
+    "XLAT",    /* 206 */\r
+    "XLATB",   /* 207 */\r
+    "XOR"};    /* 208 */\r
+\r
+#define xAAA    1\r
+#define xAAD    2\r
+#define xAAM    3\r
+#define xAAS    4\r
+#define xADC    5\r
+#define xADD    6\r
+#define xAND    7\r
+#define xARPL   8\r
+\r
+#define xBOUND  9\r
+#define xBSF    10\r
+#define xBSR    11\r
+#define xBT     12\r
+#define xBTC    13\r
+#define xBTR    14\r
+#define xBTS    15\r
+\r
+#define xCALL   16\r
+#define xCBW    17\r
+#define xCDQ    18\r
+#define xCLC    19\r
+#define xCLD    20\r
+#define xCLI    21\r
+#define xCLTS   22\r
+#define xCMC    23\r
+#define xCMP    24\r
+#define xCMPS   25\r
+#define xCMPSB  26\r
+#define xCMPSD  27\r
+#define xCMPSW  28\r
+#define xCWD    29\r
+#define xCWDE   30\r
+\r
+#define xDAA    31\r
+#define xDAS    32\r
+#define xDEC    33\r
+#define xDIV    34\r
+\r
+#define xENTER  35\r
+#define xHLT    36\r
+\r
+#define xIDIV   37\r
+#define xIMUL   38\r
+#define xIN     39\r
+#define xINC    40\r
+#define xINS    41\r
+#define xINSB   42\r
+#define xINSD   43\r
+#define xINSW   44\r
+#define xINT    45\r
+#define xINTO   46\r
+#define xIRET   47\r
+#define xIRETD  48\r
+\r
+#define xJA     49\r
+#define xJAE    50\r
+#define xJB     51\r
+#define xJBE    52\r
+#define xJC     53\r
+#define xJCXZ   54\r
+#define xJE     55\r
+#define xJECXZ  56\r
+#define xJG     57\r
+#define xJGE    58\r
+#define xJL     59\r
+#define xJLE    60\r
+#define xJMP    61\r
+#define xJNA    62\r
+#define xJNAE   63\r
+#define xJNB    64\r
+#define xJNBE   65\r
+#define xJNC    66\r
+#define xJNE    67\r
+#define xJNG    68\r
+#define xJNGE   69\r
+#define xJNL    70\r
+#define xJNLE   71\r
+#define xJNO    72\r
+#define xJNP    73\r
+#define xJNS    74\r
+#define xJNZ    75\r
+#define xJO     76\r
+#define xJP     77\r
+#define xJPE    78\r
+#define xJPO    79\r
+#define xJS     80\r
+#define xJZ     81\r
+\r
+#define xLAHF   82\r
+#define xLAR    83\r
+#define xLDS    84\r
+#define xLEA    85\r
+#define xLEAVE  86\r
+#define xLES    87\r
+#define xLFS    88\r
+#define xLGDT   89\r
+#define xLGS    90\r
+#define xLIDT   91\r
+#define xLLDT   92\r
+#define xLMSW   93\r
+#define xLOCK   94\r
+#define xLODS   95\r
+#define xLODSB  96\r
+#define xLODSD  97\r
+#define xLODSW  98\r
+#define xLOOP   99\r
+#define xLOOPE  100\r
+#define xLOOPNE 101\r
+#define xLOOPNZ 102\r
+#define xLOOPZ  103\r
+#define xLSL    104\r
+#define xLSS    105\r
+#define xLTR    106\r
+\r
+#define xMOV    107\r
+#define xMOVS   108\r
+#define xMOVSB  109\r
+#define xMOVSD  110\r
+#define xMOVSW  111\r
+#define xMOVSX  112\r
+#define xMOVZX  113\r
+#define xMUL    114\r
+\r
+#define xNEG    115\r
+#define xNOP    116\r
+#define xNOT    117\r
+\r
+#define xOR     118\r
+#define xOUT    119\r
+#define xOUTS   120\r
+#define xOUTSB  121\r
+#define xOUTSD  122\r
+#define xOUTSW  123\r
+\r
+#define xPOP    124\r
+#define xPOPA   125\r
+#define xPOPAD  126\r
+#define xPOPF   127\r
+#define xPOPFD  128\r
+#define xPUSH   129\r
+#define xPUSHA  130\r
+#define xPUSHAD 131\r
+#define xPUSHF  132\r
+#define xPUSHFD 133\r
+\r
+#define xRCL    134\r
+#define xRCR    135\r
+#define xREP    136\r
+#define xREPE   137\r
+#define xREPNE  138\r
+#define xREPNZ  139\r
+#define xREPZ   140\r
+#define xRET    141\r
+#define xRETF   142\r
+#define xRETN   143\r
+#define xROL    144\r
+#define xROR    145\r
+\r
+#define xSAHF   146\r
+#define xSAL    147\r
+#define xSAR    148\r
+#define xSBB    149\r
+#define xSCAS   150\r
+#define xSCASB  151\r
+#define xSCASD  152\r
+#define xSCASW  153\r
+#define xSETA   154\r
+#define xSETAE  155\r
+#define xSETB   156\r
+#define xSETBE  157\r
+#define xSETC   158\r
+#define xSETE   159\r
+#define xSETG   160\r
+#define xSETGE  161\r
+#define xSETL   162\r
+#define xSETLE  163\r
+#define xSETNA  164\r
+#define xSETNAE 165\r
+#define xSETNB  166\r
+#define xSETNBE 167\r
+#define xSETNC  168\r
+#define xSETNE  169\r
+#define xSETNG  170\r
+#define xSETNGE 171\r
+#define xSETNL  172\r
+#define xSETNLE 173\r
+#define xSETNO  174\r
+#define xSETNP  175\r
+#define xSETNS  176\r
+#define xSETNZ  177\r
+#define xSETO   178\r
+#define xSETP   179\r
+#define xSETPE  180\r
+#define xSETPO  181\r
+#define xSETS   182\r
+#define xSETZ   183\r
+#define xSGDT   184\r
+#define xSHL    185\r
+#define xSHLD   186\r
+#define xSHR    187\r
+#define xSHRD   188\r
+#define xSIDT   189\r
+#define xSLDT   190\r
+#define xSMSW   191\r
+#define xSTC    192\r
+#define xSTD    193\r
+#define xSTI    194\r
+#define xSTOS   195\r
+#define xSTOSB  196\r
+#define xSTOSD  197\r
+#define xSTOSW  198\r
+#define xSTR    199\r
+#define xSUB    200\r
+\r
+#define xTEST   201\r
+\r
+#define xVERR   202\r
+#define xVERW   203\r
+\r
+#define xWAIT   204\r
+#define xXCHG   205\r
+#define xXLAT   206\r
+#define xXLATB  207\r
+#define xXOR    208\r
+\r
+\r
+#define nrinst 80                      /* number of float instructions */\r
+#define srinst 8\r
+char rgrinst[nrinst][srinst] = {               /*  560 bytes */\r
+\r
+       "F2XM1",     /* 01 */\r
+       "FABS",      /* 02 */\r
+       "FADD",      /* 03 */\r
+       "FADDP",     /* 04 */\r
+       "FBLD",      /* 05 */\r
+       "FBSTP",     /* 06 */\r
+       "FCHS",      /* 07 */\r
+       "FCLEX",     /* 08 */\r
+       "FCOM",      /* 09 */\r
+       "FCOMP",     /* 10 */\r
+       "FCOMPP",    /* 11 */\r
+       "FCOS",      /* 12 */\r
+       "FDECSTP",   /* 13 */\r
+       "FDIV",      /* 14 */\r
+       "FDIVP",     /* 15 */\r
+       "FDIVR",     /* 16 */\r
+       "FDIVRP",    /* 17 */\r
+       "FFREE",     /* 18 */\r
+       "FIADD",     /* 19 */\r
+       "FICOM",     /* 20 */\r
+       "FICOMP",    /* 21 */\r
+       "FIDIV",     /* 22 */\r
+       "FIDIVR",    /* 23 */\r
+       "FILD",      /* 24 */\r
+       "FIMUL",     /* 25 */\r
+       "FINCSTP",   /* 26 */\r
+       "FINIT",     /* 27 */\r
+       "FIST",      /* 28 */\r
+       "FISTP",     /* 29 */\r
+       "FISUB",     /* 30 */\r
+       "FISUBR",    /* 31 */\r
+       "FLD",       /* 32 */\r
+       "FLD1",      /* 33 */\r
+       "FLDCW",     /* 34 */\r
+       "FLDENV",    /* 35 */\r
+       "FLDL2E",    /* 36 */\r
+       "FLDL2T",    /* 37 */\r
+       "FLDLG2",    /* 38 */\r
+       "FLDLN2",    /* 39 */\r
+       "FLDPI",     /* 40 */\r
+       "FLDZ",      /* 41 */\r
+       "FMUL",      /* 42 */\r
+       "FMULP",     /* 43 */\r
+       "FNCLEX",    /* 44 */\r
+       "FNINIT",    /* 45 */\r
+       "FNOP",      /* 46 */\r
+       "FNSAVE",    /* 47 */\r
+       "FNSTCW",    /* 48 */\r
+       "FNSTENV",   /* 49 */\r
+       "FNSTSW",    /* 50 */\r
+       "FPATAN",    /* 51 */\r
+       "FPREM",     /* 52 */\r
+       "FPREM1",    /* 53 */\r
+       "FPTAN",     /* 54 */\r
+       "FRNDINT",   /* 55 */\r
+       "FRSTOR",    /* 56 */\r
+       "FSAVE",     /* 57 */\r
+       "FSCALE",    /* 58 */\r
+       "FSIN",      /* 59 */\r
+       "FSINCOS",   /* 60 */\r
+       "FSQRT",     /* 61 */\r
+       "FST",       /* 62 */\r
+       "FSTCW",     /* 63 */\r
+       "FSTENV",    /* 64 */\r
+       "FSTP",      /* 65 */\r
+       "FSTSW",     /* 66 */\r
+       "FSUB",      /* 67 */\r
+       "FSUBP",     /* 68 */\r
+       "FSUBPR",    /* 69 */\r
+       "FSUBR",     /* 70 */\r
+       "FTST",      /* 71 */\r
+       "FUCOM",     /* 72 */\r
+       "FUCOMP",    /* 73 */\r
+       "FUCOMPP",   /* 74 */\r
+       "FWAIT",     /* 75 */\r
+       "FXAM",      /* 76 */\r
+       "FXCH",      /* 77 */\r
+       "FXTRACT",   /* 78 */\r
+       "FYL2X",     /* 79 */\r
+       "FYL2XP1" }; /* 80 */\r
+\r
+\r
+/*  END OF INSTRUCTIONS  */\r
+\r
+/* Allowed Operand types for instruction sequences\r
+   Start numbering at 61 so they don't conflict with\r
+   token values or special characters */\r
+\r
+#define rel8   61      /* mem address within +/-127 bytes of currnt address */\r
+#define relW   62      /* mem address relative (WORD/DWORD) of current addr */\r
+#define iSAD   63      /* immediate segment address (seg16:offset16/32)  */\r
+#define r8     64      /* Reg: AL, BL, CL, DL, AH, BH, CH, DH            */\r
+#define r16    65      /* Reg: AX, BX, CX, DX, SP, BP, SI, DI            */\r
+#define r32    66      /* Reg: EAX, EBX, ECX, EDX, ESP, EBP, ESI, EDI    */\r
+#define rREG   67   /* Any 8, 16 or 32 bit general register */\r
+#define rRGW   68   /* Any 16 or 32 bit general register    */\r
+#define rACC   69   /* Reg: Accumulator AL, AX, EAX (any size) */\r
+#define rSEG   70   /* Reg: CS, DS, SS, ES, FS, GS   */\r
+#define rCRG   71   /* Reg: CR0, CR2, CR3 */\r
+#define rDRG   72   /* Reg: DR0, DR1, DR2, DR3, DR6, DR7 */\r
+#define rTRG   73   /* Reg: TR6, TR7 */\r
+#define imm8   74      /* Immediate BYTE - UNSIGNED*/\r
+#define ims8   75      /* Immediate BYTE - Will be SIGN Extended!!! */\r
+#define imm16  76      /* Immediate WORD signed value  */\r
+#define immX   77   /* immediate size value to match the other operand */\r
+#define rm8    78      /* r8 or memory address to BYTE                   */\r
+#define rm16   79      /* r16 or memory address to WORD                  */\r
+#define rRM    80   /* Any 8, 16 or 32 bit register or memory ref     */\r
+#define rRMW   81   /* Any 16 or 32 bit register or memory ref        */\r
+#define mem    82      /* Memory address. Any legal data mem reference   */\r
+#define memF   83      /* Memory address of a 16:32 ptr value   */\r
+#define moff   84      /* Memory address (Immediate, Disp only, Seg relative)*/\r
+#define immv3  85   /* immediate value 3 for INT 03 debug */\r
+#define immv1  86   /* immediate value 1 for some instructions (SHL etc.) */\r
+\r
+/* these are only used in the rgMEM32 table */\r
+\r
+#define val8   87      /* Indicates numeric value for displacement, */\r
+#define val16  88   /*  immediate, address, etc. Used in memory model */\r
+#define val32  89      /*  template. */\r
+\r
+\r
+/*  Instruction sequence lookup table is made of:\r
+       - Instruction number (from definitions above)\r
+       - Opr1-3 are the legal operands for the instructions\r
+       - Opc is base opcode.\r
+       - Oprm is the ModR/M byte (if needed). It is partially filled in\r
+         and used as indicated by Om1 below.\r
+       - Opfx - Operand prefix and operand count for instruction.\r
+               qP0F - Prefix Opc with 0x0f\r
+               qUW  - Use 0x66 prefix always\r
+               qU16 - If USE16 prefix Opcodes with 0x66.\r
+               qU32 - If USE32 prefix Opcodes with 0x66.\r
+\r
+       - Om1 -  Modifications or additions to OpCode to complete instruction:\r
+               zMOP - Use Oprm as ModR/M byte (which is already filled in\r
+                          partially with Opcode in bits 3-5). If operand 1 is\r
+                          register, placed code in R/M field of ModR/M byte (bits 0-2).\r
+                          If operand 1 is mem, handle normally. In special case of\r
+                          AAD and AAM instructions Oprm is actually second byte of\r
+                          opcode (no operands to handle).\r
+               zMR1 - Use Oprm as ModR/M byte. Register in operand 1\r
+                          must be encoded in REG/OPC field of ModR/M. If reg in\r
+                          operand 2 it must be incoded in R/M field.\r
+               zMR2 - Use Oprm as ModR/M byte. Register in operand 2\r
+                          must be encoded in REG/OPC field of ModR/M. If reg in\r
+                          operand 1, it must be encoded in R/M field.\r
+               zORD - OR Opc1 with 01 if WORD or DWORD reg/mem\r
+               zAR1 - No ModRM, Add register code in operand 1 to Opc byte to\r
+                      complete the opcode.\r
+               zAR2 - No ModRM, Add register code in operand 2 to Opc byte to\r
+                      complete the opcode.\r
+               zRG1 - If register in operand 1, it must be encoded in\r
+                      REG/OPC field of ModR/M, else handle memory operand normally.\r
+           zSIZ - This is not actually a modification to the instruction,\r
+                  but tells the assembler that the operand sizes will not\r
+                  match and that it's ok.  The operand size should be the\r
+                  size of the first operand.\r
+\r
+ */\r
+\r
+/* Prefix instruction/operand count byte */\r
+\r
+#define qP0F 0x01\r
+#define qU16 0x02\r
+#define qU32 0x04\r
+#define qUW  0x08\r
+\r
+/* OM1 instruction byte  (Opcode Modifier/Special build instructions) */\r
+#define zMOP 0x01\r
+#define zMR1 0x02\r
+#define zMR2 0x04\r
+#define zORD 0x08\r
+#define zAR1 0x10\r
+#define zAR2 0x20\r
+#define zRG1 0x40\r
+#define zSIZ 0x80\r
+\r
+\r
+/* Certain table entries were added for optimization to ensure that\r
+   the shortest instruction is used in all cases.  This adds about\r
+   50 lines to the table, but it's well worth the overhead!\r
+*/\r
+\r
+#define nrgINS 338\r
+unsigned char rgINS[nrgINS][8] = {  /* 338 * 8 = */\r
+\r
+/*Inst   Opr1    Opr2   Opr3  Opfx        Opc   Oprm   Om1          */\r
+\r
+{0      , 0,     0,     0,    0,          0,     0,    0            },\r
+{xAAA   , 0,     0,     0,    0,          0x37,  0,    0            },\r
+{xAAD   , 0,     0,     0,    0,          0xd5,  0x0A, zMOP         },\r
+{xAAM   , 0,     0,     0,    0,          0xd4,  0x0A, zMOP         },\r
+{xADC   , rACC,  immX,  0,    0,          0x14,  0,    zORD         },\r
+{xADC   , rRMW,  imm8,  0,    0,          0x83,  0x10, zMOP         },\r
+{xADC   , rRM,   immX,  0,    0,          0x80,  0x10, zMOP|zORD    },\r
+{xADC   , rRM,   rREG,  0,    0,          0x10,  0,    zMR2|zORD    },\r
+{xADC   , rREG,  rRM,   0,    0,          0x12,  0,    zMR1|zORD    },\r
+\r
+{xADD   , rRMW,  ims8,  0,    0,          0x83,  0,    zMOP         },\r
+{xADD   , rACC,  immX,  0,    0,          0x04,  0,    zORD         },\r
+{xADD   , rRM,   immX,  0,    0,          0x80,  0,    zMOP|zORD    },\r
+{xADD   , rREG,  rRM,   0,    0,          0x02,  0,    zMR1|zORD    },\r
+{xADD   , rRM,   rREG,  0,    0,          0x00,  0,    zMR2|zORD    },\r
+\r
+{xAND   , rRMW,  ims8,  0,    0,          0x83,  0x20, zMOP         },\r
+{xAND   , rACC,  immX,  0,    0,          0x24,  0,    zORD         },\r
+{xAND   , rRM,   immX,  0,    0,          0x80,  0x20, zMOP|zORD    },\r
+{xAND   , rREG,  rRM,   0,    0,          0x22,  0,    zMR1|zORD    },\r
+{xAND   , rRM,   rREG,  0,    0,          0x20,  0,    zMR2|zORD    },\r
+\r
+{xARPL  , rm16,  r16,   0,    0,          0x63,  0,    zMR2         },\r
+{xBOUND , rRMW,  mem,   0,    0,          0x62,  0,    zMR1         },\r
+{xBSF   , rRGW,  rRMW,  0,    qP0F,       0xbc,  0,    zMR1         },\r
+{xBSR   , rRGW,  rRMW,  0,    qP0F,       0xbd,  0,    zMR1         },\r
+{xBT    , rRMW,  rRGW,  0,    qP0F,       0xa3,  0,    zMR2         },\r
+{xBT    , rRMW,  imm8,  0,    qP0F,       0xba,  0x20, zMOP         },\r
+{xBTC   , rRMW,  rRGW,  0,    qP0F,       0xbb,  0,    zMR2         },\r
+{xBTC   , rRMW,  imm8,  0,    qP0F,       0xba,  0x38, zMOP         },\r
+{xBTR   , rRMW,  rRGW,  0,    qP0F,       0xb3,  0,    zMR2         },\r
+{xBTR   , rRMW,  imm8,  0,    qP0F,       0xba,  0x30, zMOP         },\r
+{xBTS   , rRMW,  rRGW,  0,    qP0F,       0xab,  0,    zMR2         },\r
+{xBTS   , rRMW,  imm8,  0,    qP0F,       0xba,  0x28, zMOP         },\r
+{xCALL  , relW,  0,     0,    0,          0xe8,  0,    0            },\r
+{xCALL  , rRMW,  0,     0,    0,          0xff,  0x10, zMOP         },\r
+{xCALL  , iSAD,  0,     0,    0,          0x9a,  0,    0            },\r
+{xCALL  , memF,  0,     0,    0,          0xff,  0x18, zMOP         },\r
+{xCBW   , 0,     0,     0,    qU32,       0x98,  0,    0            },\r
+{xCWDE  , 0,     0,     0,    qU16,       0x98,  0,    0            },\r
+{xCLC   , 0,     0,     0,    0,          0xf8,  0,    0            },\r
+{xCLD   , 0,     0,     0,    0,          0xfc,  0,    0            },\r
+{xCLI   , 0,     0,     0,    0,          0xfa,  0,    0            },\r
+{xCLTS  , 0,     0,     0,    qP0F,       0x06,  0,    0            },\r
+{xCMC   , 0,     0,     0,    0,          0xf5,  0,    0            },\r
+\r
+{xCMP   , rRMW,  ims8,  0,    0,          0x83,  0x38, zMOP         },\r
+{xCMP   , rACC,  immX,  0,    0,          0x3c,  0,    zORD         },\r
+{xCMP   , rRM,   immX,  0,    0,          0x80,  0x38, zMOP|zORD    },\r
+{xCMP   , rREG,  rRM,   0,    0,          0x3a,  0,    zMR1|zORD    },\r
+{xCMP   , rRM,   rREG,  0,    0,          0x38,  0,    zMR2|zORD    },\r
+\r
+{xCMPSB , 0,     0,     0,     0,         0xa6,  0,    0            },\r
+{xCMPSD , 0,     0,     0,     0,         0xa7,  0,    0            },\r
+{xCMPSW , 0,     0,     0,     qUW,       0xa7,  0,    0            },\r
+{xCWD   , 0,     0,     0,     qUW,      0x99,  0,    0            },\r
+{xCDQ   , 0,     0,     0,     qU16,      0x99,  0,    0            },\r
+{xDAA   , 0,     0,     0,     0,         0x27,  0,    0            },\r
+{xDAS   , 0,     0,     0,     0,         0x2f,  0,    0            },\r
+{xDEC   , rRGW,  0,     0,     0,         0x48,  0,    zAR1         },\r
+{xDEC   , rRM,   0,     0,     0,         0xfe,  0x08, zMOP|zORD    },\r
+{xDIV   , rRM,   0,     0,     0,         0xf6,  0x30, zMOP|zORD    },\r
+{xENTER , imm16, imm8,  0,     0,         0xc8,  0,    zSIZ         },\r
+{xHLT   , 0,     0,     0,     0,         0xf4,  0,    0            },\r
+{xIDIV  , rRM,   0,     0,     0,         0xf6,  0x38, zMOP|zORD    },\r
+{xIMUL  , rRM,   0,     0,     0,         0xf6,  0x28, zMOP|zORD    },\r
+{xIMUL  , rRGW,  rRMW,  0,     qP0F,      0xaf,  0,    zMR1         },\r
+{xIMUL  , rRGW,  rRMW,  imm8,  0,         0x6b,  0,    zMR1         },\r
+{xIMUL  , rRGW,  imm8,  0,     0,         0x6b,  0,    zMR1|zSIZ    },\r
+{xIMUL  , rRGW,  rRMW,  immX,  0,         0x69,  0,    zMR1         },\r
+{xIMUL  , rRGW,  immX,  0,     0,         0x69,  0,    zMR1         },\r
+{xIN    , rACC,  imm8,  0,     0,         0xe4,  0,    zORD|zSIZ    },\r
+{xIN    , rACC,  rDX,   0,     0,         0xec,  0,    zORD|zSIZ    },\r
+{xINC   , rRGW,  0,     0,     0,         0x40,  0,    zAR1         },\r
+{xINC   , rRM,   0,     0,     0,         0xfe,  0,    zMOP|zORD    },\r
+{xINSB  , 0,     0,     0,     0,         0x6C,  0,    0            },\r
+{xINSD  , 0,     0,     0,     0,         0x6D,  0,    0            },\r
+{xINSW  , 0,     0,     0,     qUW,       0x6D,  0,    0            },\r
+{xINT   , immv3, 0,     0,     0,         0xcc,  0,    0            },\r
+{xINT   , imm8,  0,     0,     0,         0xcd,  0,    0            },\r
+{xINTO  , 0,     0,     0,     0,         0xce,  0,    0            },\r
+{xIRET  , 0,     0,     0,     qUW,       0xcf,  0,    0            },\r
+{xIRETD , 0,     0,     0,     0,         0xcf,  0,    0            },\r
+{xJA    , rel8,  0,     0,     0,         0x77,  0,    0            },\r
+{xJA    , relW,  0,     0,     qP0F,      0x87,  0,    0            },\r
+{xJAE   , rel8,  0,     0,     0,         0x73,  0,    0            },\r
+{xJAE   , relW,  0,     0,     qP0F,      0x83,  0,    0            },\r
+{xJB    , rel8,  0,     0,     0,         0x72,  0,    0            },\r
+{xJB    , relW,  0,     0,     qP0F,      0x82,  0,    0            },\r
+{xJBE   , rel8,  0,     0,     0,         0x76,  0,    0            },\r
+{xJBE   , relW,  0,     0,     qP0F,      0x86,  0,    0            },\r
+{xJC    , rel8,  0,     0,     0,         0x72,  0,    0            },\r
+{xJC    , relW,  0,     0,     qP0F,      0x82,  0,    0            },\r
+{xJCXZ  , rel8,  0,     0,     0,         0xe3,  0,    0            },\r
+{xJNBE  , rel8,  0,     0,     0,         0x77,  0,    0            },\r
+{xJNBE  , relW,  0,     0,     qP0F,      0x87,  0,    0            },\r
+{xJNB   , rel8,  0,     0,     0,         0x73,  0,    0            },\r
+{xJNB   , relW,  0,     0,     qP0F,      0x83,  0,    0            },\r
+{xJNC   , rel8,  0,     0,     0,         0x73,  0,    0            },\r
+{xJNC   , relW,  0,     0,     qP0F,      0x83,  0,    0            },\r
+{xJNA   , rel8,  0,     0,     0,         0x76,  0,    0            },\r
+{xJNA   , relW,  0,     0,     qP0F,      0x86,  0,    0            },\r
+{xJNAE  , rel8,  0,     0,     0,         0x72,  0,    0            },\r
+{xJNAE  , relW,  0,     0,     qP0F,      0x82,  0,    0            },\r
+{xJECXZ , rel8,  0,     0,     0,         0xe3,  0,    0            },\r
+{xJE    , rel8,  0,     0,     0,         0x74,  0,    0            },\r
+{xJE    , relW,  0,     0,     qP0F,      0x84,  0,    0            },\r
+{xJG    , rel8,  0,     0,     0,         0x7f,  0,    0            },\r
+{xJG    , relW,  0,     0,     qP0F,      0x8f,  0,    0            },\r
+{xJGE   , rel8,  0,     0,     0,         0x7d,  0,    0            },\r
+{xJGE   , relW,  0,     0,     qP0F,      0x8d,  0,    0            },\r
+{xJNL   , rel8,  0,     0,     0,         0x7d,  0,    0            },\r
+{xJNL   , relW,  0,     0,     qP0F,      0x8d,  0,    0            },\r
+{xJL    , rel8,  0,     0,     0,         0x7c,  0,    0            },\r
+{xJL    , relW,  0,     0,     qP0F,      0x8c,  0,    0            },\r
+{xJNGE  , rel8,  0,     0,     0,         0x7c,  0,    0            },\r
+{xJNGE  , relW,  0,     0,     qP0F,      0x8c,  0,    0            },\r
+{xJLE   , rel8,  0,     0,     0,         0x7e,  0,    0            },\r
+{xJLE   , relW,  0,     0,     qP0F,      0x8e,  0,    0            },\r
+{xJNG   , rel8,  0,     0,     0,         0x7e,  0,    0            },\r
+{xJNG   , relW,  0,     0,     qP0F,      0x8e,  0,    0            },\r
+{xJNE   , rel8,  0,     0,     0,         0x75,  0,    0            },\r
+{xJNE   , relW,  0,     0,     qP0F,      0x85,  0,    0            },\r
+{xJNLE  , rel8,  0,     0,     0,         0x7f,  0,    0            },\r
+{xJNLE  , relW,  0,     0,     qP0F,      0x8f,  0,    0            },\r
+{xJNO   , rel8,  0,     0,     0,         0x71,  0,    0            },\r
+{xJNO   , relW,  0,     0,     qP0F,      0x81,  0,    0            },\r
+{xJNP   , rel8,  0,     0,     0,         0x7b,  0,    0            },\r
+{xJNP   , relW,  0,     0,     qP0F,      0x8b,  0,    0            },\r
+{xJNS   , rel8,  0,     0,     0,         0x79,  0,    0            },\r
+{xJNS   , relW,  0,     0,     qP0F,      0x89,  0,    0            },\r
+{xJNZ   , rel8,  0,     0,     0,         0x75,  0,    0            },\r
+{xJNZ   , relW,  0,     0,     qP0F,      0x85,  0,    0            },\r
+{xJO    , rel8,  0,     0,     0,         0x70,  0,    0            },\r
+{xJO    , relW,  0,     0,     qP0F,      0x80,  0,    0            },\r
+{xJP    , rel8,  0,     0,     0,         0x7a,  0,    0            },\r
+{xJP    , relW,  0,     0,     qP0F,      0x8a,  0,    0            },\r
+{xJPO   , rel8,  0,     0,     0,         0x7b,  0,    0            },\r
+{xJPO   , relW,  0,     0,     qP0F,      0x8b,  0,    0            },\r
+{xJPE   , rel8,  0,     0,     0,         0x7a,  0,    0            },\r
+{xJPE   , relW,  0,     0,     qP0F,      0x8a,  0,    0            },\r
+{xJS    , rel8,  0,     0,     0,         0x78,  0,    0            },\r
+{xJS    , relW,  0,     0,     qP0F,      0x88,  0,    0            },\r
+{xJZ    , rel8,  0,     0,     0,         0x74,  0,    0            },\r
+{xJZ    , relW,  0,     0,     qP0F,      0x84,  0,    0            },\r
+{xJMP   , rel8,  0,     0,     0,         0xeb,  0,    0            },\r
+{xJMP   , relW,  0,     0,     0,         0xe9,  0,    0            },\r
+{xJMP   , rRMW,  0,     0,     0,         0xff,  0x20, zMOP         },\r
+{xJMP   , iSAD,  0,     0,     0,         0xea,  0,    0            },\r
+{xJMP   , memF,  0,     0,     0,         0xff,  0x28, zMOP         },\r
+{xLAHF  , 0,     0,     0,     0,         0x9f,  0,    0            },\r
+{xLAR   , rRGW,  rRMW,  0,     qP0F,      0x02,  0,    zMR1         },\r
+{xLEA   , rRGW,  mem,   0,     0,         0x8d,  0,    zMR1|zSIZ    },\r
+{xLEAVE , 0,     0,     0,     0,         0xc9,  0,    0            },\r
+{xLGDT  , memF,  0,     0,     qP0F,      0x01,  0x10, zMOP         },\r
+{xLIDT  , memF,  0,     0,     qP0F,      0x01,  0x18, zMOP         },\r
+{xLDS   , rRGW,  memF,  0,     0,         0xc5,  0,    zMR1         },\r
+{xLSS   , rRGW,  memF,  0,     qP0F,      0xb2,  0,    zMR1         },\r
+{xLES   , rRGW,  memF,  0,     0,         0xc4,  0,    zMR1         },\r
+{xLFS   , rRGW,  memF,  0,     qP0F,      0xb4,  0,    zMR1         },\r
+{xLGS   , rRGW,  memF,  0,     qP0F,      0xb5,  0,    zMR1         },\r
+{xLLDT  , rm16,  0,     0,     qP0F,      0x00,  0x10, zMOP         },\r
+{xLMSW  , rm16,  0,     0,     qP0F,      0x01,  0x30, zMOP         },\r
+{xLOCK  , 0,     0,     0,     0,         0xf0,  0,    0            },\r
+{xLODSB , 0,     0,     0,     0,         0xac,  0,    0            },\r
+{xLODSD , 0,     0,     0,     0,         0xad,  0,    0            },\r
+{xLODSW , 0,     0,     0,     qUW,       0xad,  0,    0            },\r
+{xLOOP  , rel8,  0,     0,     0,         0xe2,  0,    0            },\r
+{xLOOPE , rel8,  0,     0,     0,         0xe1,  0,    0            },\r
+{xLOOPZ , rel8,  0,     0,     0,         0xe1,  0,    0            },\r
+{xLOOPNE, rel8,  0,     0,     0,         0xe0,  0,    0            },\r
+{xLOOPNZ, rel8,  0,     0,     0,         0xe0,  0,    0            },\r
+{xLSL   , rRGW,  rRMW,  0,     qP0F,      0x03,  0,    zMR1         },\r
+{xLTR   , rm16,  0,     0,     qP0F,      0x00,  0x18, zMOP         },\r
+{xMOV   , rACC,  moff,  0,     0,         0xA0,  0,    zORD         },\r
+{xMOV   , moff,  rACC,  0,     0,         0xA2,  0,    zORD         },\r
+{xMOV   , r8,    imm8,  0,     0,         0xb0,  0,    zAR1         },\r
+{xMOV   , rRGW,  immX,  0,     0,         0xb8,  0,    zAR1         },\r
+{xMOV   , rREG,  rRM,   0,     0,         0x8a,  0,    zMR1|zORD    },\r
+{xMOV   , rRM,   rREG,  0,     0,         0x88,  0,    zMR2|zORD    },\r
+{xMOV   , rRM,   immX,  0,     0,         0xc6,  0,    zMR1|zORD    },/*?*/\r
+{xMOV   , rm16,  rSEG,  0,     0,         0x8c,  0,    zMR2         },\r
+{xMOV   , rSEG,  rm16,  0,     0,         0x8e,  0,    zMR1         },\r
+{xMOV   , r32,   rCRG,  0,     qP0F,      0x20,  0,    zMR2         },\r
+{xMOV   , rCRG,  r32,   0,     qP0F,      0x22,  0,    zMR1         },\r
+{xMOV   , r32,   rDRG,  0,     qP0F,      0x21,  0,    zMR2         },\r
+{xMOV   , rDRG,  r32,   0,     qP0F,      0x23,  0,    zMR1         },\r
+{xMOV   , r32,   rTRG,  0,     qP0F,      0x24,  0,    zMR2         },\r
+{xMOV   , rTRG,  r32,   0,     qP0F,      0x26,  0,    zMR1         },\r
+{xMOVSB , 0,     0,     0,     0,         0xa4,  0,    0            },\r
+{xMOVSD , 0,     0,     0,     0,         0xa5,  0,    0            },\r
+{xMOVSW , 0,     0,     0,     qUW,       0xa5,  0,    0            },\r
+{xMOVSX , r32,   rm16,  0,     qP0F,      0xbf,  0,    zMR1|zSIZ    },\r
+{xMOVSX , rRGW,  rm8,   0,     qP0F,      0xbe,  0,    zMR1|zSIZ    },\r
+{xMOVZX , r32,   rm16,  0,     qP0F,      0xb7,  0,    zMR1|zSIZ    },\r
+{xMOVZX , rRGW,  rm8,   0,     qP0F,      0xb6,  0,    zMR1|zSIZ    },\r
+{xMUL   , rRM,   0,     0,     0,         0xf6,  0x20, zMOP|zORD    },\r
+{xNEG   , rRM,   0,     0,     0,         0xf6,  0x18, zMOP|zORD    },\r
+{xNOP   , 0,     0,     0,     0,         0x90,  0,    0            },\r
+{xNOT   , rRM,   0,     0,     0,         0xf6,  0x10, zMOP|zORD    },\r
+\r
+{xOR    , rRMW,  ims8,  0,     0,         0x83,  0x08, zMOP         },\r
+{xOR    , rACC,  immX,  0,     0,         0x0c,  0,    zORD         },\r
+{xOR    , rRM,   immX,  0,     0,         0x80,  0x08, zMOP|zORD    },\r
+{xOR    , rREG,  rRM,   0,     0,         0x0a,  0,    zMR1|zORD    },\r
+{xOR    , rRM,   rREG,  0,     0,         0x08,  0,    zMR2|zORD    },\r
+\r
+{xOUT   , imm8,  rACC,  0,     0,         0xe6,  0,    zORD         },\r
+{xOUT   , rDX,   rACC,  0,     0,         0xee,  0,    zORD         },\r
+{xOUTSB , 0,     0,     0,     0,         0x6e,  0,    0            },\r
+{xOUTSD , 0,     0,     0,     0,         0x6f,  0,    0            },\r
+{xOUTSW , 0,     0,     0,     qUW,       0x6f,  0,    0            },\r
+{xPOP   , mem,   0,     0,     0,         0x8f,  0,    zMOP         },\r
+{xPOP   , rRGW,  0,     0,     0,         0x58,  0,    zAR1         },\r
+{xPOP   , rDS,   0,     0,     0,         0x1f,  0,    0            },\r
+{xPOP   , rES,   0,     0,     0,         0x07,  0,    0            },\r
+{xPOP   , rSS,   0,     0,     0,         0x17,  0,    0            },\r
+{xPOP   , rFS,   0,     0,     qP0F,      0xa1,  0,    0            },\r
+{xPOP   , rGS,   0,     0,     qP0F,      0xa9,  0,    0            },\r
+{xPOPA  , 0,     0,     0,     0,         0x61,  0,    0            },\r
+{xPOPAD , 0,     0,     0,     0,         0x61,  0,    0            },\r
+{xPOPF  , 0,     0,     0,     0,         0x9d,  0,    0            },\r
+{xPOPFD , 0,     0,     0,     0,         0x9d,  0,    0            },\r
+{xPUSH  , mem,   0,     0,     0,         0xff,  0x30, zMOP         },\r
+{xPUSH  , rRGW,  0,     0,     0,         0x50,  0,    zAR1         },\r
+{xPUSH  , ims8,  0,     0,     0,         0x6a,  0,    0            },\r
+{xPUSH  , immX,  0,     0,     0,         0x68,  0,    0            },\r
+{xPUSH  , rCS,   0,     0,     0,         0x0e,  0,    0            },\r
+{xPUSH  , rSS,   0,     0,     0,         0x16,  0,    0            },\r
+{xPUSH  , rDS,   0,     0,     0,         0x1e,  0,    0            },\r
+{xPUSH  , rES,   0,     0,     0,         0x06,  0,    0            },\r
+{xPUSH  , rFS,   0,     0,     qP0F,      0xa0,  0,    0            },\r
+{xPUSH  , rGS,   0,     0,     qP0F,      0xa8,  0,    0            },\r
+{xPUSHA , 0,     0,     0,     0,         0x60,  0,    0            },\r
+{xPUSHAD, 0,     0,     0,     0,         0x60,  0,    0            },\r
+{xPUSHF , 0,     0,     0,     0,         0x9c,  0,    0            },\r
+{xPUSHFD, 0,     0,     0,     0,         0x9c,  0,    0            },\r
+{xRCL   , rRM,   immv1, 0,     0,         0xd0,  0x10, zMOP|zORD|zSIZ },\r
+{xRCL   , rRM,   rCL,   0,     0,         0xd2,  0x10, zMOP|zORD|zSIZ },\r
+{xRCL   , rRM,   imm8,  0,     0,         0xc0,  0x10, zMOP|zORD|zSIZ },\r
+{xRCR   , rRM,   immv1, 0,     0,         0xd0,  0x18, zMOP|zORD|zSIZ },\r
+{xRCR   , rRM,   rCL,   0,     0,         0xd2,  0x18, zMOP|zORD|zSIZ },\r
+{xRCR   , rRM,   imm8,  0,     0,         0xc0,  0x18, zMOP|zORD|zSIZ },\r
+{xROL   , rRM,   immv1, 0,     0,         0xd0,  0,    zMOP|zORD|zSIZ },\r
+{xROL   , rRM,   rCL,   0,     0,         0xd2,  0,    zMOP|zORD|zSIZ },\r
+{xROL   , rRM,   imm8,  0,     0,         0xc0,  0,    zMOP|zORD|zSIZ },\r
+{xROR   , rRM,   immv1, 0,     0,         0xd0,  0x08, zMOP|zORD|zSIZ },\r
+{xROR   , rRM,   rCL,   0,     0,         0xd2,  0x08, zMOP|zORD|zSIZ },\r
+{xROR   , rRM,   imm8,  0,     0,         0xc0,  0x08, zMOP|zORD|zSIZ },\r
+{xREP   , 0,     0,     0,     0,         0xf3,  0,    0            },\r
+{xREPE  , 0,     0,     0,     0,         0xf3,  0,    0            },\r
+{xREPNE , 0,     0,     0,     0,         0xf2,  0,    0            },\r
+{xRETN  , 0,     0,     0,     0,         0xc3,  0,    0            },\r
+{xRETN  , imm16, 0,     0,     0,         0xc2,  0,    0            },\r
+{xRETF  , 0,     0,     0,     0,         0xcb,  0,    0            },\r
+{xRETF  , imm16, 0,     0,     0,         0xca,  0,    0            },\r
+{xSAL   , rRM,   immv1, 0,     0,         0xd0,  0x20, zMOP|zORD|zSIZ },\r
+{xSAL   , rRM,   rCL,   0,     0,         0xd2,  0x20, zMOP|zORD|zSIZ },\r
+{xSAL   , rRM,   imm8,  0,     0,         0xc0,  0x20, zMOP|zORD|zSIZ },\r
+{xSAR   , rRM,   immv1, 0,     0,         0xd0,  0x38, zMOP|zORD|zSIZ },\r
+{xSAR   , rRM,   rCL,   0,     0,         0xd2,  0x38, zMOP|zORD|zSIZ },\r
+{xSAR   , rRM,   imm8,  0,     0,         0xc0,  0x38, zMOP|zORD|zSIZ },\r
+{xSHL   , rRM,   immv1, 0,     0,         0xd0,  0x20, zMOP|zORD|zSIZ },\r
+{xSHL   , rRM,   rCL,   0,     0,         0xd2,  0x20, zMOP|zORD|zSIZ },\r
+{xSHL   , rRM,   imm8,  0,     0,         0xc0,  0x20, zMOP|zORD|zSIZ },\r
+{xSHR   , rRM,   immv1, 0,     0,         0xd0,  0x28, zMOP|zORD|zSIZ },\r
+{xSHR   , rRM,   rCL,   0,     0,         0xd2,  0x28, zMOP|zORD|zSIZ },\r
+{xSHR   , rRM,   imm8,  0,     0,         0xc0,  0x28, zMOP|zORD|zSIZ },\r
+\r
+{xSBB   , rRMW,  ims8,  0,     0,         0x83,  0x18, zMOP         },\r
+{xSBB   , rACC,  immX,  0,     0,         0x1c,  0,    zORD         },\r
+{xSBB   , rRM,   immX,  0,     0,         0x80,  0x18, zMOP|zORD    },\r
+{xSBB   , rREG,  rRM,   0,     0,         0x1a,  0,    zMR1|zORD    },\r
+{xSBB   , rRM,   rREG,  0,     0,         0x18,  0,    zMR2|zORD    },\r
+\r
+{xSCASB , 0,     0,     0,     0,         0xae,  0,    0            },\r
+{xSCASD , 0,     0,     0,     0,         0xaf,  0,    0            },\r
+{xSCASW , 0,     0,     0,     qUW,       0xaf,  0,    0            },\r
+{xSETA  , rm8,   0,     0,     qP0F,      0x97,  0,    zRG1         },\r
+{xSETAE , rm8,   0,     0,     qP0F,      0x93,  0,    zRG1         },\r
+{xSETB  , rm8,   0,     0,     qP0F,      0x92,  0,    zRG1         },\r
+{xSETBE , rm8,   0,     0,     qP0F,      0x96,  0,    zRG1         },\r
+{xSETC  , rm8,   0,     0,     qP0F,      0x92,  0,    zRG1         },\r
+{xSETE  , rm8,   0,     0,     qP0F,      0x94,  0,    zRG1         },\r
+{xSETG  , rm8,   0,     0,     qP0F,      0x9F,  0,    zRG1         },\r
+{xSETGE , rm8,   0,     0,     qP0F,      0x9D,  0,    zRG1         },\r
+{xSETL  , rm8,   0,     0,     qP0F,      0x9C,  0,    zRG1         },\r
+{xSETLE , rm8,   0,     0,     qP0F,      0x9E,  0,    zRG1         },\r
+{xSETNA , rm8,   0,     0,     qP0F,      0x96,  0,    zRG1         },\r
+{xSETNAE, rm8,   0,     0,     qP0F,      0x92,  0,    zRG1         },\r
+{xSETNB , rm8,   0,     0,     qP0F,      0x93,  0,    zRG1         },\r
+{xSETNBE, rm8,   0,     0,     qP0F,      0x97,  0,    zRG1         },\r
+{xSETNC , rm8,   0,     0,     qP0F,      0x93,  0,    zRG1         },\r
+{xSETNE , rm8,   0,     0,     qP0F,      0x95,  0,    zRG1         },\r
+{xSETNG , rm8,   0,     0,     qP0F,      0x9E,  0,    zRG1         },\r
+{xSETNGE, rm8,   0,     0,     qP0F,      0x9C,  0,    zRG1         },\r
+{xSETNL , rm8,   0,     0,     qP0F,      0x9D,  0,    zRG1         },\r
+{xSETNLE, rm8,   0,     0,     qP0F,      0x9F,  0,    zRG1         },\r
+{xSETNO , rm8,   0,     0,     qP0F,      0x91,  0,    zRG1         },\r
+{xSETNP , rm8,   0,     0,     qP0F,      0x9B,  0,    zRG1         },\r
+{xSETNS , rm8,   0,     0,     qP0F,      0x99,  0,    zRG1         },\r
+{xSETNZ , rm8,   0,     0,     qP0F,      0x95,  0,    zRG1         },\r
+{xSETO  , rm8,   0,     0,     qP0F,      0x90,  0,    zRG1         },\r
+{xSETP  , rm8,   0,     0,     qP0F,      0x9A,  0,    zRG1         },\r
+{xSETPE , rm8,   0,     0,     qP0F,      0x9A,  0,    zRG1         },\r
+{xSETPO , rm8,   0,     0,     qP0F,      0x9B,  0,    zRG1         },\r
+{xSETS  , rm8,   0,     0,     qP0F,      0x98,  0,    zRG1         },\r
+{xSETZ  , rm8,   0,     0,     qP0F,      0x94,  0,    zRG1         },\r
+{xSGDT  , memF,  0,     0,     qP0F,      0x01,  0,    zMOP         },\r
+{xSIDT  , memF,  0,     0,     qP0F,      0x01,  0x08, zMOP         },\r
+{xSHLD  , rRMW,  rRGW,  imm8,  qP0F,      0xa4,  0,    0            },\r
+{xSHLD  , rRMW,  rRGW,  rCL,   qP0F,      0xa5,  0,    0            },\r
+{xSHRD  , rRMW,  rRGW,  imm8,  qP0F,      0xac,  0,    0            },\r
+{xSHRD  , rRMW,  rRGW,  rCL,   qP0F,      0xad,  0,    0            },\r
+{xSLDT  , rm16,  0,     0,     qP0F,      0x00,  0,    zMOP         },\r
+{xSMSW  , rm16,  0,     0,     qP0F,      0x01,  0x20, zMOP         },\r
+{xSTC   , 0,     0,     0,     0,         0xf9,  0,    0            },\r
+{xSTI   , 0,     0,     0,     0,         0xfb,  0,    0            },\r
+{xSTD   , 0,     0,     0,     0,         0xfd,  0,    0            },\r
+{xSTOSB , 0,     0,     0,     0,         0xaa,  0,    0            },\r
+{xSTOSD , 0,     0,     0,     0,         0xab,  0,    0            },\r
+{xSTOSW , 0,     0,     0,     qUW,       0xab,  0,    0            },\r
+{xSTR   , rm16,  0,     0,     qP0F,      0x00,  0x08, zMOP         },\r
+\r
+{xSUB   , rRMW,  ims8,  0,     0,         0x83,  0x28, zMOP         },\r
+{xSUB   , rACC,  immX,  0,     0,         0x2c,  0,    zORD         },\r
+{xSUB   , rRM,   immX,  0,     0,         0x80,  0x28, zMOP|zORD    },\r
+{xSUB   , rREG,  rRM,   0,     0,         0x2a,  0,    zMR1|zORD    },\r
+{xSUB   , rRM,   rREG,  0,     0,         0x28,  0,    zMR2|zORD    },\r
+\r
+{xTEST  , rACC,  immX,  0,     0,         0xa8,  0,    zORD         },\r
+{xTEST  , rRM,   immX,  0,     0,         0xf6,  0,    zMOP|zORD    },\r
+{xTEST  , rREG,  rRM,   0,     0,         0x84,  0,    zMR1|zORD    },\r
+{xVERR  , rm16,  0,     0,     qP0F,      0x00,  0x20, zMOP         },\r
+{xVERW  , rm16,  0,     0,     qP0F,      0x00,  0x28, zMOP         },\r
+{xWAIT  , 0,     0,     0,     0,         0x9b,  0,    0            },\r
+{xXCHG  , r16,   rAX,   0,     0,         0x90,  0,    zAR1         },\r
+{xXCHG  , rAX,   r16,   0,     0,         0x90,  0,    zAR2         },\r
+{xXCHG  , r32,   rEAX,  0,     0,         0x90,  0,    zAR1         },\r
+{xXCHG  , rEAX,  r32,   0,     0,         0x90,  0,    zAR2         },\r
+{xXCHG  , rRM,   rREG,  0,     0,         0x86,  0,    zMR2|zORD    },\r
+{xXCHG  , rREG,  rRM,   0,     0,         0x86,  0,    zMR1|zORD    },\r
+{xXLAT  , mem,   0,     0,     0,         0x00,  0,    0            },\r
+{xXLATB , 0,     0,     0,     0,         0x00,  0,    0            },\r
+\r
+{xXOR   , rRMW,  ims8,  0,     0,         0x83,  0x30, zMOP         },\r
+{xXOR   , rACC,  immX,  0,     0,         0x34,  0,    zORD         },\r
+{xXOR   , rRM,   immX,  0,     0,         0x80,  0x30, zMOP|zORD    },\r
+{xXOR   , rREG,  rRM,   0,     0,         0x32,  0,    zMR1|zORD    },\r
+{xXOR   , rRM,   rREG,  0,     0,         0x30,  0,    zMR2|zORD    },\r
+};\r
+\r
+/* END of instruction sequence definitions  */\r
+\r
+/* This table provides look-up instructions on building the ModR/M and\r
+   SIB bytes (optional) for all memory references.\r
+   THIS IS ONLY FOR MEMORY REFERENCES.\r
+   The Mod value in this table can be ORed to the ModR/M byte\r
+   and SS value in this table can be ORed to the SIB byte\r
+   for the instruction you're building.\r
+*/\r
+\r
+\r
+#define fBase   0x01\r
+#define fIndx   0x02   /* fScale = 1 by default when fIndx is present */\r
+#define fScale2 0x04\r
+#define fScale4 0x08\r
+#define fScale8 0x10\r
+#define fDisp8  0x20\r
+#define fDisp32 0x40\r
+\r
+#define UseSIB  1\r
+#define nrgM32 20\r
+\r
+U8 rgM32[20][4] = {\r
+/*                                    UseSIB  Mod   SS */\r
+{   0,                                 0,    0x00, 0x00 },\r
+{   fBase,                             0,    0x00, 0x00 },\r
+{   fBase | fIndx,                     1,    0x04, 0x00 },\r
+{   fIndx | fScale2,                   1,    0x04, 0x40 },\r
+{   fIndx | fScale4,                   1,    0x04, 0x80 },\r
+{   fIndx | fScale8,                   1,    0x04, 0xC0 },\r
+{   fDisp32,                           0,    0x05, 0x00 },\r
+{   fBase | fIndx | fScale2,           1,    0x04, 0x40 },\r
+{   fBase | fIndx | fScale4,           1,    0x04, 0x80 },\r
+{   fBase | fIndx | fScale8,           1,    0x04, 0xC0 },\r
+{   fBase | fDisp8,                    0,    0x40, 0x00 },\r
+{   fBase | fDisp32,                   0,    0x80, 0x00 },\r
+{   fBase | fIndx | fDisp8,            1,    0x44, 0x00 },\r
+{   fBase | fIndx | fDisp32,           1,    0x84, 0x00 },\r
+{   fBase | fIndx | fScale2 | fDisp8,  1,    0x44, 0x40 },\r
+{   fBase | fIndx | fScale4 | fDisp8,  1,    0x44, 0x80 },\r
+{   fBase | fIndx | fScale8 | fDisp8,  1,    0x44, 0xC0 },\r
+{   fBase | fIndx | fScale2 | fDisp32, 1,    0x84, 0x40 },\r
+{   fBase | fIndx | fScale4 | fDisp32, 1,    0x84, 0x80 },\r
+{   fBase | fIndx | fScale8 | fDisp32, 1,    0x84, 0xC0 },\r
+};\r
+\r
+\r
+/* The following 16 bit addressing modes are recognized: */\r
+/* UseSIB is always 0 in 16 bit addressing modes */\r
+\r
+#define nrgM16 24\r
+\r
+int rgM16[24][8] = {\r
+\r
+/*                                       UseSIB  Mod     SS */\r
+       {rBX,    rSI,    0,     0,   0,   0,     0,      0},\r
+       {rBX,    rDI,    0,     0,   0,   0,     0,      0},\r
+       {rBP,    rSI,    0,     0,   0,   0,     0,      0},\r
+       {rBP,    rDI,    0,     0,   0,   0,     0,      0},\r
+       {rSI,    0,      0,     0,   0,   0,     0,      0},\r
+       {rDI,    0,      0,     0,   0,   0,     0,      0},\r
+       {val16,  0,      0,     0,   0,   0,     0,      0},\r
+       {rBX,    0,      0,     0,   0,   0,     0,      0},\r
+       {rBX,    rSI,    val8,  0,   0,   0,     0,      0},\r
+       {rBX,    rDI,    val8,  0,   0,   0,     0,      0},\r
+       {rBP,    rSI,    val8,  0,   0,   0,     0,      0},\r
+       {rBP,    rDI,    val8,  0,   0,   0,     0,      0},\r
+       {rSI,    val8,   0,     0,   0,   0,     0,      0},\r
+       {rDI,    val8,   0,         0,   0,   0,     0,      0},\r
+       {rBP,    val8,   0,         0,   0,   0,     0,      0},\r
+       {rBX,    val8,   0,         0,   0,   0,     0,      0},\r
+       {rBX,    rSI,    val16, 0,   0,   0,     0,      0},\r
+       {rBX,    rDI,    val16, 0,   0,   0,     0,      0},\r
+       {rBP,    rSI,    val16, 0,   0,   0,     0,      0},\r
+       {rBP,    rDI,    val16, 0,   0,   0,     0,      0},\r
+       {rSI,    val16,  0,     0,   0,   0,     0,      0},\r
+       {rDI,    val16,  0,         0,   0,   0,     0,      0},\r
+       {rBP,    val16,  0,         0,   0,   0,     0,      0},\r
+       {rBX,    val16,  0,     0,   0,   0,     0,      0},\r
+       };\r
+\r
+/* End of memory Look-up tables */\r
+\r
+/* The following flag bits are used to determine memory operand size\r
+   either by looking at the register involved, or by seeing the user\r
+   force the size with WORD PTR (etc.).  They are put in variable\r
+   OpSize and used by the functions that encode the instruction.\r
+*/\r
+\r
+#define fByte  0x01\r
+#define fWord  0x02\r
+#define fDWord 0x04\r
+#define fFWord 0x08\r
+#define fNear  0x10\r
+#define fFar   0x20\r
+#define fShort 0x40\r
+#define fPtr   0x80            /* not currently used... */\r
+\r
+/* The following flag bits are used to determine if a register prefix\r
+   was specified as part of a memory address. The flag bits are set in\r
+   char variable OpPrefix.\r
+*/\r
+\r
+#define fDSp   0x01\r
+#define fESp   0x02\r
+#define fSSp   0x04\r
+#define fFSp   0x08\r
+#define fGSp   0x10\r
+#define fCSp   0x20\r
+\r
+/*  END OF HEADER FILE */\r
diff --git a/msamples/dasmm/dasm.run b/msamples/dasmm/dasm.run
new file mode 100644 (file)
index 0000000..60ff21b
Binary files /dev/null and b/msamples/dasmm/dasm.run differ
diff --git a/msamples/dasmm/dasmdbg.c b/msamples/dasmm/dasmdbg.c
new file mode 100644 (file)
index 0000000..f3e5fe3
--- /dev/null
@@ -0,0 +1,83 @@
+/* Used only for debugging the operand evaluator\r
+   This prints the OpType, OpMtype (hex byte), and\r
+   if it is a memory operand, it also prints the Base,\r
+   Indx, Disp, and size if they exist.\r
+   THIS IS NOT INCLUDED IN DELIVERED DASM.EXE\r
+*/\r
+\r
+void print_Oper(int op)\r
+{\r
+switch (rgOpType[op]) {\r
+       case r32:\r
+        fputs("r32= ", lst_fp);\r
+               put_num(rgOpReg[op], lst_fp);\r
+        break;\r
+       case r16:\r
+        fputs("r16= ", lst_fp);\r
+               put_num(rgOpReg[op], lst_fp);\r
+        break;\r
+       case r8:\r
+        fputs("r8= ", lst_fp);\r
+               put_num(rgOpReg[op], lst_fp);\r
+        break;\r
+       case rCRG:\r
+        fputs("rCRG= ", lst_fp);\r
+               put_num(rgOpReg[op], lst_fp);\r
+        break;\r
+       case rDRG:\r
+        fputs("rDRG= ", lst_fp);\r
+               put_num(rgOpReg[op], lst_fp);\r
+        break;\r
+       case rTRG:\r
+        fputs("rTRG= ", lst_fp);\r
+               put_num(rgOpReg[op], lst_fp);\r
+        break;\r
+       case rSEG:\r
+        fputs("rSEG= ", lst_fp);\r
+               put_num(rgOpReg[op], lst_fp);\r
+        break;\r
+\r
+       case mem:               /* memory operand */\r
+        fputs("MemOp- ", lst_fp);\r
+        if (OpMType & fBase) {         /* Base register */\r
+               fputs(" Base-", lst_fp);\r
+                       put_num(rgOpBase[op], lst_fp);\r
+                       }\r
+        if (OpMType & fIndx) {         /* Index Register */\r
+               fputs(" Indx-", lst_fp);\r
+                       put_num(rgOpIndx[op], lst_fp);\r
+               if (OpMType & fScale2) {                /* scale value 2 */\r
+                       fputs(" Scale2 ", lst_fp);\r
+                               }\r
+               if (OpMType & fScale4) {                /* scale value 4 */\r
+                           fputs(" Scale4 ", lst_fp);\r
+                               }\r
+               if (OpMType & fScale8) {                /* scale value 8 */\r
+                            fputs(" Scale8 ", lst_fp);\r
+                               }\r
+                       }\r
+        if (OpMType & fDisp8) {           /* Disp 8 value */\r
+               fputs(" Disp8-", lst_fp);\r
+                       put_hex(rgOpDisp[op], 2, lst_fp);\r
+                       }\r
+        if (OpMType & fDisp32) {           /* Disp 32 value */\r
+               fputs(" Disp32-", lst_fp);\r
+                       put_hex(rgOpDisp[op], 8, lst_fp);\r
+                       }\r
+               break;\r
+       case val8:\r
+        fputs("Val8=", lst_fp);\r
+               put_num(rgOpDisp[op], lst_fp);\r
+        break;\r
+       case val16:\r
+        fputs("Val16=", lst_fp);\r
+               put_num(rgOpDisp[op], lst_fp);\r
+        break;\r
+       case val32:\r
+        fputs("Val32=", lst_fp);\r
+               put_num(rgOpDisp[op], lst_fp);\r
+        break;\r
+       default:\r
+           fputs(" UNK Operand ", lst_fp);\r
+}\r
+}\r
diff --git a/msamples/dasmm/dasmq.c b/msamples/dasmm/dasmq.c
new file mode 100644 (file)
index 0000000..c6e0a19
--- /dev/null
@@ -0,0 +1,1574 @@
+/* DASMQ.c contains procedures that are stable and are not\r
+  subject to change during debugging and development. They\r
+  have been moved out of the main module to reduce SCROLL Mania...\r
+\r
+*/\r
+\r
+/******************************************\r
+* Determine if a character is alphabetic\r
+* or underscore. These can be used for first\r
+* or subsequent chars in an identifier.\r
+*******************************************/\r
+\r
+char is_ident(char chr)\r
+{\r
+       return (isalpha(chr)) || (chr == '_');\r
+}\r
+\r
+\r
+/********************************************\r
+  Determine if character is "skip" character.\r
+  All values from 0x20 down to CTRL-A are\r
+  skipped.\r
+*********************************************/\r
+\r
+char isskip(char chr)\r
+{\r
+       if ((chr > 0) && (chr <= ' ')) return(1);\r
+       else return(0);\r
+}\r
+/**************************************\r
+  Write a Hex byte to a file fout.\r
+***************************************/\r
+\r
+void put_hexb(U8 value, FILE *fout)\r
+{\r
+S8  stack[10];\r
+U32 i, j;\r
+\r
+       i = 0; j = 2;\r
+       do {\r
+               stack[i] = (value % 16) + '0';\r
+               if (stack[i] > 0x39)\r
+            stack[i] += 7;\r
+               i++;\r
+               }\r
+       while(value /= 16);\r
+       while (i < j--) {                       /* zero pad front end to width */\r
+               fputc('0', fout);\r
+               }\r
+       while(i) {\r
+               fputc(stack[--i], fout);\r
+               }\r
+}\r
+\r
+/**************************************\r
+  Write a Hex number to a file fout.\r
+***************************************/\r
+\r
+void put_hexw(U32 value, FILE *fout)\r
+{\r
+S8  stack[10];\r
+U32 i, j;\r
+\r
+       i = 0;\r
+       j = 4;\r
+       do {\r
+               stack[i] = (value % 16) + '0';\r
+               if (stack[i] > 0x39)\r
+            stack[i] += 7;\r
+               i++;\r
+               }\r
+       while(value /= 16);\r
+       while (i < j--) {                       /* zero pad front end to width */\r
+               fputc('0', fout);\r
+               }\r
+       while(i) {\r
+               fputc(stack[--i], fout);\r
+               }\r
+}\r
+\r
+/**************************************\r
+  Write a hex dword to a file fout.\r
+***************************************/\r
+\r
+void put_hexd(U32 value, FILE *fout)\r
+{\r
+S8  stack[10];\r
+U32 i, j;\r
+\r
+       i = 0;\r
+       j = 8;\r
+       do {\r
+               stack[i] = (value % 16) + '0';\r
+               if (stack[i] > 0x39)\r
+            stack[i] += 7;\r
+               i++;\r
+               }\r
+       while(value /= 16);\r
+       while (i < j--) {                       /* zero pad front end to width */\r
+               fputc('0', fout);\r
+               }\r
+       while(i) {\r
+               fputc(stack[--i], fout);\r
+               }\r
+}\r
+\r
+\r
+/*************************************\r
+  Acquires VALUE for Expression()\r
+*************************************/\r
+long expr4(long *val)\r
+{\r
+long k;\r
+\r
+if (Token == rOFFSET) {\r
+       fOffset = 1;\r
+       Parse();\r
+       }\r
+\r
+if (Token == OPENRND) {                        /* Open paren */\r
+       Parse();\r
+       k=expr1(val);\r
+       if (Token == CLOSRND) {\r
+               Parse();\r
+               }\r
+       else{\r
+               line_error(1);\r
+               return(0);\r
+               }\r
+       }\r
+else if (Token == NUMBER) {\r
+       *val = TNumber;\r
+       Parse();                                /* set up for next token check */\r
+       }\r
+else if (Token == LSYMBOL) {\r
+       nExpSyms++;\r
+       *val = lst[TSymnum].Offs;\r
+       iExpSym = TSymnum;              /* so we can trace symbol number came from */\r
+       ExpType = 1;\r
+       Parse();                                /* set up for next token check */\r
+       }\r
+else if (Token == SYMBOL) {\r
+       nExpSyms++;\r
+       *val = gst[TSymnum].Offs;\r
+       iExpSym = TSymnum;              /* so we can trace symbol number came from */\r
+       ExpType = 2;\r
+       Parse();                                /* set up for next token check */\r
+       }\r
+else if (Token == UNKSYM) {\r
+       nExpSyms++;\r
+       *val = 0;                               /* No offset for UNKSYM */\r
+       iExpSym =0;\r
+       ExpType = 0;                    /* 0 means forward ref. No Assumption. */\r
+\r
+       /* Save name for forward reference */\r
+       strncpy(UString, TString, 30);\r
+       if (CBString > 30)\r
+               UCBString = 30;\r
+       else\r
+               UCBString = CBString;                   /* Size of Unknown label */\r
+       UString[UCBString] = '\0';                      /* Null terminate */\r
+\r
+       Parse();                                /* set up for next token check */\r
+       }\r
+else if (Token == DOLLAR) {\r
+       if (fDataSeg)\r
+               *val = oNextData;\r
+       else\r
+               *val = oNextCode;\r
+       ExpType = 3;\r
+       Parse();                                /* set up for next token check */\r
+       }\r
+else{\r
+       line_error(2);\r
+       return(0);\r
+       }\r
+return(1);\r
+}\r
+\r
+/*****************************************\r
+ Evaluates a UNARY MINUS for Expression()\r
+*****************************************/\r
+long expr3(long *val)\r
+{\r
+long k;\r
+\r
+if (Token == MINUS) {          /* Unary MINUS */\r
+       Parse();                                /* set up for next token check */\r
+       k=expr4(val);\r
+       if (k) {\r
+               *val = -(*val);\r
+               return(1);\r
+               }\r
+       else {\r
+               line_error(3);\r
+               return(0);\r
+               }\r
+       }\r
+else {\r
+       k = expr4(val);\r
+       return(k);\r
+       }\r
+}\r
+\r
+\r
+/*************************************\r
+ Evaluates a * and / Expression()\r
+*************************************/\r
+long expr2(long *val)\r
+{\r
+long k;\r
+long val2;\r
+\r
+k=expr3(val);\r
+if ((Token != STAR) && (Token != SLASH))\r
+       return(k);\r
+while(1) {\r
+       if (Token == STAR) {            /* MULTIPLY */\r
+               Parse();                                /* set up for next token check */\r
+               if(expr2(&val2))\r
+                       *val *= val2;\r
+               }\r
+       else if (Token == SLASH) {      /* DIVIDE */\r
+               Parse();                                /* set up for next token check */\r
+               if(expr2(&val2))\r
+                       *val /= val2;\r
+               }\r
+       else return(1);  /* Expr doesn't continue but it's OK to here */\r
+}\r
+}\r
+\r
+/*************************************\r
+  Evaluates a + and - for Expression()\r
+*************************************/\r
+long expr1(long *val)\r
+{\r
+long k;\r
+long val2;\r
+\r
+k=expr2(val);\r
+if ((Token != PLUS) && (Token != MINUS)) return(k);\r
+while(1) {\r
+       if (Token == PLUS) {\r
+               Parse();\r
+               if (Token==REGIST) return(1);   /* allow for N+REG */\r
+               if(expr2(&val2))\r
+                       *val += val2;\r
+               else return(0);\r
+               }\r
+       else if (Token == MINUS) {\r
+               Parse();\r
+               if (Token==REGIST) return(1);   /* allow for N+REG */\r
+               if(expr2(&val2))\r
+                       *val -= val2;\r
+               else return(0);\r
+               }\r
+       else return(1);  /* Expr doesn't continue but it's OK to here */\r
+}\r
+}\r
+\r
+/*******************************************\r
+  Expression is called to evaluate a math\r
+  expression made of constants, and/or\r
+  address labels (offsets).\r
+  Uses functions expr1 - expr4 recursively\r
+  to handle parenthetical expressions\r
+  while keeping standard math operator\r
+  precedence correct. Exits with (0) if error\r
+  in expression is encountered. Exits with\r
+  1 if value is left in TNumber.  If a NON\r
+  math Token is encountered but expression\r
+  was OK to that point, it calls ReturnToken\r
+  and leaves the currenly evaluated number\r
+  as the current token.\r
+\r
+  If a single symbol or a single "current address"\r
+  opeator ($) is used in the expression, it will\r
+  return with SYMOFF as the Token type with the\r
+  offset value in TNumber, and the symbol\r
+  in TSymnum. If the OFFSET operator is used,\r
+  it will return with the offset in TNumber\r
+  and it will be a NUMOFF.\r
+  If more than 1 symbol or the\r
+  current address operator ($) and a symbol\r
+  is used it will assume a simple numeric\r
+  value from the computation and return\r
+  NUMBER as it's token.\r
+********************************************/\r
+\r
+long Expression(void)\r
+{\r
+long val;\r
+\r
+/* iExpSym = 0; */\r
+nExpSyms = 0;\r
+fOffset = 0;\r
+\r
+if (expr1(&val)) {\r
+\r
+    if (Token)                 /* if not EOL (EOL returns 0) */\r
+               ReturnToken();  /*   give back non-expression token */\r
+       if (nExpSyms == 1) {\r
+               if (fOffset)\r
+                       Token = NUMOFF; /* Derived from OFFSET cmd */\r
+               else\r
+                       Token = SYMOFF; /* single address operator used (Mem Type) */\r
+       }\r
+       else\r
+               Token = NUMBER; /* Make current token a NUMBER */\r
+\r
+       TSymnum = iExpSym;      /* We can tell where number came from */\r
+       TNumber = val;          /* Tell em what it is */\r
+       return(1);                      /* Tell em they got one */\r
+}\r
+else return(0);                        /* Tell em they got an error */\r
+}\r
+\r
+/*****************************************************\r
+   Determines if token is 32 bit general register.\r
+*****************************************************/\r
+long is_r32(long id)\r
+{\r
+switch (id) {\r
+       case rEAX:\r
+       case rEBX:\r
+       case rECX:\r
+       case rEDX:\r
+       case rESI:\r
+       case rEDI:\r
+       case rEBP:\r
+       case rESP: return(1);\r
+       default:   return(0);\r
+  }\r
+}\r
+\r
+/*****************************************************\r
+   Determines if token is 16 bit general.\r
+*****************************************************/\r
+long is_r16(long id)\r
+{\r
+switch (id) {\r
+       case rAX:\r
+       case rBX:\r
+       case rCX:\r
+       case rDX:\r
+       case rSI:\r
+       case rDI:\r
+       case rBP:\r
+       case rSP: return(1);\r
+       default:  return(0);\r
+  }\r
+}\r
+\r
+/*****************************************************\r
+   Determines if token is 8 bit general register.\r
+*****************************************************/\r
+long is_r8(long id)\r
+{\r
+switch (id) {\r
+       case rAL:\r
+       case rBL:\r
+       case rCL:\r
+       case rDL:\r
+       case rAH:\r
+       case rBH:\r
+       case rCH:\r
+       case rDH: return(1);\r
+       default:  return(0);\r
+  }\r
+}\r
+\r
+/*****************************************************\r
+   Determines if token is Segment Register.\r
+*****************************************************/\r
+long is_rSEG(long id)\r
+{\r
+switch (id) {\r
+       case rDS:\r
+       case rES:\r
+       case rCS:\r
+       case rFS:\r
+       case rGS:\r
+       case rSS: return(1);\r
+       default:   return(0);\r
+  }\r
+}\r
+\r
+/*****************************************************\r
+   Determines if token is Debug register.\r
+*****************************************************/\r
+long is_rDRG(long id)\r
+{\r
+switch (id) {\r
+       case rDR0:\r
+       case rDR1:\r
+       case rDR2:\r
+       case rDR3:\r
+       case rDR6:\r
+       case rDR7: return(1);\r
+       default:   return(0);\r
+  }\r
+}\r
+\r
+/*****************************************************\r
+   Determines if token is Control register.\r
+*****************************************************/\r
+long is_rCRG(long id)\r
+{\r
+return ((id == rCR0) || (id == rCR2) || (id == rCR3));\r
+}\r
+\r
+/*****************************************************\r
+   Determines if token is Test register.\r
+*****************************************************/\r
+long is_rTRG(long id)\r
+{\r
+return ((id == rTR6) || (id == rTR7));\r
+}\r
+\r
+/*****************************************************\r
+   Determines if operand entry in instruction (ins) is\r
+   compatible with the operand type the user gave (op).\r
+   An entry of 0 may match which means there is no\r
+   operand.\r
+*****************************************************/\r
+\r
+\r
+long is_Comp(long ins, long op)\r
+{\r
+switch (rgINS[ins][op+1]) {    /* check against op type in instruction */\r
+    case 0:\r
+       if (!rgOpType[op]) return(1);   /* no operand in either matches */\r
+               break;\r
+    case rel8:\r
+       if (rgOpType[op] == rel8) return(1);\r
+       break;\r
+    case relW:\r
+       if (rgOpType[op] == relW) return(1);\r
+       break;\r
+    case iSAD:\r
+       if (rgOpType[op] == r8) return(1);\r
+       break;\r
+    case r8:\r
+       if (rgOpType[op] == r8) return(1);\r
+       break;\r
+    case r16:\r
+       if (rgOpType[op] == r16) return(1);\r
+       break;\r
+    case r32:\r
+       if (rgOpType[op] == r32) return(1);\r
+       break;\r
+    case rREG:\r
+       if ((rgOpType[op] == r8) ||\r
+            (rgOpType[op] == r16) ||\r
+            (rgOpType[op] == r32)) return(1);\r
+       break;\r
+    case rRGW:\r
+       if ((rgOpType[op] == r16) ||\r
+            (rgOpType[op] == r32)) return(1);\r
+       break;\r
+    case rACC:\r
+       if (((rgOpType[op] == r8) && (rgOpReg[op] == rAL)) ||\r
+            ((rgOpType[op] == r16) && (rgOpReg[op] == rAX)) ||\r
+            ((rgOpType[op] == r32) && (rgOpReg[op] == rEAX)))\r
+        return(1);\r
+       break;\r
+    case rSEG:\r
+       if (rgOpType[op] == rSEG) return(1);\r
+       break;\r
+    case rCRG:\r
+       if (rgOpType[op] == rCRG) return(1);\r
+       break;\r
+    case rDRG:\r
+       if (rgOpType[op] == rDRG) return(1);\r
+       break;\r
+    case rTRG:\r
+       if (rgOpType[op] == rTRG) return(1);\r
+       break;\r
+    case imm8:\r
+       if (rgOpType[op] == val8)\r
+           return(1);\r
+\r
+       if ((rgOpType[op] == val16) &&\r
+           (OpImm < 256) &&\r
+           (OpImm >= 0))\r
+           return(1);\r
+\r
+       break;\r
+    case ims8: /* This is where a byte in an instruction\r
+                will be sign extended. We will only allow byte values\r
+                           between -128 and 127 to be compatible here. This is because\r
+                           they can put AND EAX, A0h and we have to assume they DON'T\r
+                           want it extended into a negative 32 bit integer such as 0FFFFFFA0h.\r
+                       */\r
+       if (rgOpType[op] == val8)\r
+           return(1);\r
+\r
+       if ((rgOpType[op] == val16) &&\r
+           (OpImm < 128) &&\r
+           (OpImm >= 0))\r
+           return(1);\r
+\r
+       break;\r
+    case imm16:\r
+       if ((rgOpType[op] == val8) ||\r
+           (rgOpType[op] == val16)) return(1);\r
+       break;\r
+    case immX:\r
+       if ((rgOpType[op] == val8) ||\r
+           (rgOpType[op] == val16) ||\r
+           (rgOpType[op] == val32)) return(1);\r
+       break;\r
+    case rm8:\r
+       if ((rgOpType[op] == r8) ||\r
+           ((rgOpType[op] == mem) && (OpSize[op] & fByte))) return(1);\r
+       break;\r
+    case rm16:\r
+       if ((rgOpType[op] == r16) ||\r
+           ((rgOpType[op] == mem) && (OpSize[op] & fWord)) ) return(1);\r
+       break;\r
+    case rRM:\r
+       if ((rgOpType[op] == r8) ||\r
+           (rgOpType[op] == r16) ||\r
+           (rgOpType[op] == r32) ||\r
+           (rgOpType[op] == mem)) return(1);\r
+       break;\r
+    case rRMW:\r
+               if (rgOpType[op] == mem)\r
+               {\r
+                       if (OpSize[op] & fFWord)\r
+                               return(0);\r
+                       if (OpSize[op] & fByte)\r
+                               return(0);\r
+                       return(1);\r
+               }\r
+       if ((rgOpType[op] == r16) ||\r
+            (rgOpType[op] == r32))\r
+            return(1);\r
+               break;\r
+       case mem:\r
+               if ((rgOpType[op] == mem) && (!(OpSize[op] & fFWord))) return(1);\r
+               break;\r
+       case memF:\r
+               if ((rgOpType[op] == memF) && (OpSize[op] & fFWord)) return(1);\r
+               break;\r
+    case moff:\r
+       if ((rgOpType[op] == mem) &&\r
+               (OpMType & fDisp32)  &&\r
+               ((OpMType & fIndx)==0) &&\r
+               ((OpMType & fBase)==0))\r
+       return(1);\r
+       break;\r
+    case immv3:\r
+       if ((rgOpType[op] == val8) &&\r
+           (OpImm == 3)) return(1);\r
+       break;\r
+    case immv1:\r
+       if ((rgOpType[op] == val8) &&\r
+           (OpImm == 1)) return(1);\r
+       break;\r
+    case rDX:\r
+       if ((rgOpType[op] == r16) &&\r
+           (rgOpReg[op] == rDX)) return(1);\r
+       break;\r
+    case rCL:\r
+       if ((rgOpType[op] == r8) &&\r
+           (rgOpReg[op] == rCL)) return(1);\r
+       break;\r
+    case rAL:\r
+       if ((rgOpType[op] == r8) &&\r
+           (rgOpReg[op] == rAL)) return(1);\r
+       break;\r
+    case rAX:\r
+       if ((rgOpType[op] == r16) &&\r
+           (rgOpReg[op] == rAX)) return(1);\r
+       break;\r
+    case rEAX:\r
+       if ((rgOpType[op] == r32) &&\r
+           (rgOpReg[op] == rEAX)) return(1);\r
+       break;\r
+    case rCS:\r
+    case rSS:\r
+    case rDS:\r
+    case rES:\r
+    case rFS:\r
+    case rGS:\r
+       if ((rgOpType[op] == rSEG) &&\r
+           (rgOpReg[op] == rgINS[ins][op+1])) return(1);\r
+       break;\r
+       default:;\r
+       }\r
+return(0);\r
+}\r
+\r
+/*****************************************************\r
+   Determines if entry in rgOpType is a register.\r
+*****************************************************/\r
+\r
+long is_Reg(long op)\r
+{\r
+       switch (op) {   /* This should be the value from rgOpType[x] */\r
+               case r8:\r
+           case r16:\r
+           case r32:\r
+           case rCRG:\r
+           case rDRG:\r
+           case rTRG:\r
+               return(1);\r
+               default:;\r
+       }\r
+       return(0);\r
+}\r
+\r
+\r
+/*********************************************\r
+This displays the string and exits for a FATAL\r
+assembler error.\r
+**********************************************/\r
+\r
+void fatal_error(S8   *pst)\r
+{\r
+\r
+++error_count;\r
+\r
+if (fListA | fListE) {\r
+       fprintf(lst_fh, "\r\nFATAL ERROR, line %ld - %s\r\n", lineno[level], pst);\r
+\r
+/*\r
+       DumpGSymbols();\r
+       DumpLSymbols();\r
+*/\r
+       fclose(lst_fh);\r
+       }\r
+\r
+printf("\r\nFATAL ERROR, line %ld - %s\r\n", lineno[level], pst);\r
+printf("%d Errors\r\n%d Warnings\r\n", error_count, warn_count);\r
+\r
+exit(1);\r
+}\r
+\r
+/*********************************************\r
+This displays the string and line number for\r
+non-fatal errors.\r
+**********************************************/\r
+\r
+void line_error(long num)\r
+{\r
+S8 *p;\r
+\r
+       switch (num) {\r
+       case  1: p="Invalid expression, ')' expected";          break;\r
+       case  2: p="Invalid expression, value expected";        break;\r
+       case  3: p="Value expected after unary '-'";            break;\r
+       case  4: p="Too many digits for numeric radix";         break;\r
+       case  5: p="Invalid character in a number";                     break;\r
+       case  6: p="Unterminated string";                                       break;\r
+       case  7: p="Unrecognized character";                            break;\r
+       case  8: p="Invalid Alignment specified";                       break;\r
+       case  9: p="Start command only allowed in CSEG";                break;\r
+       case 10: p="Virtual command must be first in segment";  break;\r
+       case 11: p="Invalid Virtual value";                                     break;\r
+       case 12: p="Starting address not found";                        break;\r
+       case 13: p="Stack command not allowed in DSEG";         break;\r
+       case 14: p="Invalid DOT command";                                       break;\r
+       case 15: p="Invalid Operand";                                           break;\r
+       case 16: p="Invalid segment register use";                      break;\r
+       case 17: p="Invalid scale value 'Reg*?'";                       break;\r
+       case 18: p="Scale value expected (*2,*4,*8)";           break;\r
+       case 19: p="Too many address scale values";                     break;\r
+       case 20: p="Invalid register for memory operand";       break;\r
+       case 21: p="Invalid memory operand";                            break;\r
+       case 22: p="Offset must be from data segment";          break;\r
+       case 23: p="Nested brackets";                                           break;\r
+       case 24: p="Unbalanced brackets";                                       break;\r
+       case 25: p="Invalid operand size attribute";            break;\r
+       case 26:\r
+       case 27:\r
+       case 28:\r
+       case 29:\r
+       case 30:\r
+       case 31: p="";                                                                                  break;\r
+       case 32: p="Unknown token in operand array";                    break;\r
+       case 33: p="Too many operands or extra character";              break;\r
+       case 34: p="";                                                                                  break;\r
+       case 35: p="Invalid expression or numeric value";       break;\r
+       case 36: p="Operand expected before comma";                             break;\r
+       case 37: p="";                                                                                  break;\r
+       case 38: p="Invalid character or reserved word in operand";     break;\r
+       case 39: p="Relative jump out of range";                                        break;\r
+       case 40: p="Operand size NOT specified or implied";                     break;\r
+       case 41: p="Instructions not allowed in data segment";          break;\r
+       case 42: p="Instruction expected after prefix";                         break;\r
+       case 43: p="Operand sizes don't match";                                         break;\r
+       case 44: p="Wrong operand type for instruction";                        break;\r
+       case 45: p="Incorrect format for memory operand";                       break;\r
+       case 46: p="Strings only valid for DB storage";                         break;\r
+       case 47: p="Expected '(' after 'DUP'";                                          break;\r
+       case 48: p="Storage expected between commas";                           break;\r
+       case 49: p="':' not expected";                                                          break;\r
+       case 50: p="DWord storage required for OFFSET";                         break;\r
+       case 51: p="Invalid storage value";                                                     break;\r
+       case 52:\r
+       case 53: p="";                                                                                          break;\r
+       case 54: p="':' expected after last label";                                     break;\r
+       case 55: p="Macro not allowed in lexical level 0";                      break;\r
+       case 56: p="EQU or Storage expected";                                           break;\r
+       case 57:\r
+       case 58:\r
+       case 59:\r
+       case 60:\r
+       case 61:\r
+       case 62: p="";                                                                                          break;\r
+       case 63: p="Instruction expected before register name";         break;\r
+       case 64: p="Public Symbol already defined";                                     break;\r
+       case 65: p="Local symbol already defined";                                      break;\r
+       case 66: p="Number not expected";                                                       break;\r
+       case 67: p="New symbol must follow PUBLIC keyword";                     break;\r
+       case 68: p="Label, Command, Instruction, or Storage expected";  break;\r
+       case 69: p="Inconsistant redeclaration";                                                break;\r
+       case 70: p="";                                                                                                  break;\r
+       default:\r
+               break;\r
+    }\r
+\r
+  fprintf(lst_fh, "\r\nERROR: %d, line: %ld, %s\r\n", num, lineno[level], p);\r
+  *line_ptr = 0;                               /* this KILLS the rest of the line */\r
+  Column = 0;\r
+  ++error_count;\r
+}\r
+\r
+/*********************************************\r
+This displays the string and line number for\r
+errors dicovered AFTER we past the line.\r
+This is for non-fatal errors.\r
+**********************************************/\r
+\r
+void prev_error(S8  *pst, S32 line)\r
+{\r
+   fprintf(lst_fh, "\r\nERROR, line %d - %s\r\n", line, pst);\r
+  Column = 0;\r
+  ++error_count;\r
+}\r
+\r
+/**********************************************************\r
+  The parser calls this when it detects a digit leaving\r
+  the line_ptr* pointing to digit. It accepts base 2, 10\r
+  & 16. Base 2 numbers are suffixed with a B or b, base 16\r
+  with an h or H and base 10 with no suffix.\r
+***********************************************************/\r
+\r
+U32 get_number(void)\r
+{\r
+U32  value, base;\r
+S8   c, i;\r
+S32  len;\r
+S8   st[33];\r
+  value = 0;\r
+  len = 0;\r
+  base = 10;                                           /* default base is 10 */\r
+\r
+  while(isxdigit(c = *line_ptr)) {     /* get all the digits */\r
+       st[len++] = c;\r
+       line_ptr++;\r
+  }\r
+\r
+  if ((*line_ptr== 'h') || (*line_ptr== 'H')) {   /* looks like hex */\r
+       line_ptr++;\r
+       base = 16;\r
+  }\r
+  else if ((st[len-1] == 'b') || (st[len-1] == 'B')) {\r
+       base = 2;\r
+       len--;\r
+  }\r
+  if (((base == 2) && (len > 33)) ||\r
+         ((base == 10) && (len > 10)) ||\r
+         ((base == 16) && (len > 9))) {\r
+       line_error(4);\r
+       return(0);\r
+  }\r
+  i = 0;\r
+  do {\r
+       c = st[i];\r
+       if(isdigit(c))                                  /* convert numeric digits */\r
+               c -= '0';\r
+       else if(c >= 'a')                               /* convert lower case alphas */\r
+               c -= ('a' - 10);\r
+       else if(c >= 'A')                               /* convert upper case alphas */\r
+               c -= ('A' - 10);\r
+       else\r
+               break;\r
+       if(c >= base) {                                 /* outside of base */\r
+               line_error(5);\r
+               return(0);\r
+       }\r
+       value = (value * base) + c;             /* include in total */\r
+       i++; }\r
+  while(i < len);                                              /* to length of string */\r
+  return value;\r
+}\r
+\r
+/*********************************************\r
+This is a fast binary search for a reserved\r
+word that is not an instructions or a register.\r
+**********************************************/\r
+\r
+S32 findrsvd(S8 *pb, S32 cb)  /* pointer to and size of string */\r
+{\r
+S32 f, m, n, k;\r
+S8   id[8];\r
+\r
+ if (cb>srsvd) return(0);              /* can't be a reserved word */\r
+ strncpy(id, pb, cb);                  /* move string local */\r
+ id[cb] = 0;                                   /* null terminate */\r
+\r
+ m = 0;\r
+ n = nreserved-1;\r
+ while (m<=n) {\r
+    k = m + (n-m) / 2;\r
+       f = strncmp(id, rgReserved[k], srsvd-1);\r
+    if (!f) return(k + nrsvd1);                        /* found it!   */\r
+    else if (f > 0)                                            /* it was less */\r
+          m = k+1;\r
+       else                                                            /* it was more  */\r
+          n = k-1;\r
+ }\r
+ return(0);\r
+}\r
+\r
+/*********************************************\r
+This is a fast binary search for an instuction.\r
+It returns the number or 0 if not found.\r
+**********************************************/\r
+\r
+S32 findinst(S8 *pb, S32 cb)  /* pointer to and size of parsed string */\r
+{\r
+S32 f, m, n, k;\r
+S8   id[6];\r
+\r
+ if (cb>sinst) return(0);              /* can't be an instruction */\r
+ strncpy(id, pb, cb);          /* move string local */\r
+ id[cb] = 0;                           /* null terminate */\r
+\r
+ m = 0;\r
+ n = ninst-1;\r
+ while (m<=n) {\r
+    k = m + (n-m) / 2;\r
+       f = strncmp(id, rginst[k], sinst-1);\r
+    if (!f) return(k+1);                               /* found it!   */\r
+    else if (f > 0)                                            /* id was less */\r
+          m = k+1;\r
+       else                                                            /* idwas more  */\r
+          n = k-1;\r
+ }\r
+ return(0);\r
+}\r
+\r
+/*********************************************\r
+This is a fast binary search for a register.\r
+It returns the number or 0 if not found.\r
+**********************************************/\r
+\r
+S32 findreg(S8 *pb, S32 cb)  /* pointer to, and size of parsed string */\r
+{\r
+S32 f, m, n, k;\r
+S8   id[3];\r
+\r
+ if ((cb>sregs-1) || (cb<2)) return(0);        /* can't be a register */\r
+ strncpy(id, pb, cb);                          /* move string local */\r
+ id[cb] = 0;                                           /* null pad */\r
+\r
+ m = 0;\r
+ n = nregs-1;\r
+ while (m<=n) {\r
+    k = m + (n-m) / 2;\r
+       f = strncmp(id, rgreg[k], sregs-1);\r
+    if (!f) return(k+nreg1);                   /* found it!   */\r
+    else if (f > 0)                                            /* it was less */\r
+          m = k+1;\r
+       else                                                            /* it was more  */\r
+          n = k-1;\r
+ }\r
+ return(0);\r
+}\r
+\r
+/*********************************************\r
+This searches the LOCAL symbol table for the name\r
+described by pb, cb. It only compares items that\r
+are the same length (cb == TSymsize[x]).\r
+It returns the number or 0 if not found.\r
+**********************************************/\r
+\r
+S32 findLsymbol(S8 *pb, S32 cb)  /* pointer to, and size of string */\r
+{\r
+S32 i;\r
+S8   name[132];\r
+\r
+strncpy(name, pb, cb);         /* move name local */\r
+name[cb] = 0;                                  /* null terminate */\r
+\r
+i = iLSymNext;\r
+while (i>1) {                          /* backwards through symbol table */\r
+       i--;\r
+                               /* Only compare if same size  */\r
+       if (lst[i].Size == cb) {\r
+               if (strncmp(name, lst[i].Ptr, cb) == 0) return(i);\r
+               }\r
+       }\r
+return(0);             /* not found... */\r
+}\r
+\r
+\r
+/*********************************************\r
+This searches the symbol table for the name\r
+described by pb, cb. It only compares items that\r
+are the same length (cb == TSymsize[x]).\r
+If the include level is greater than 0 it\r
+searches the local first, then the global.\r
+If at level 0, it only searches the global.\r
+It returns the number or 0 if not found.\r
+**********************************************/\r
+\r
+S32 findGsymbol(S8 *pb, S32 cb)  /* pointer to, and size of string */\r
+{\r
+S32 i;\r
+S8   name[132];\r
+\r
+strncpy(name, pb, cb);         /* move name local */\r
+name[cb] = 0;                                  /* null terminate */\r
+\r
+i = iSymNext;\r
+while (i>1) {                          /* backwards through symbol table */\r
+       i--;\r
+                               /* Only compare if same size  */\r
+       if (gst[i].Size == cb) {\r
+               if (strncmp(name, gst[i].Ptr, cb) == 0) return(i);\r
+               }\r
+       }\r
+return(0);             /* not found... */\r
+}\r
+\r
+/*********************************************\r
+       DUMP SYMBOL TABLE FOR TESTING\r
+**********************************************/\r
+\r
+void DumpGSymbols(void)\r
+{\r
+S32 i;\r
+S8   name[132];\r
+\r
+fprintf(lst_fh, "PUBLIC SYMBOLS: \r\n");\r
+\r
+i = 1;\r
+while (i<iSymNext) {                                           /* forward through symbol table */\r
+       strncpy(name, gst[i].Ptr, gst[i].Size); /* move to name */\r
+       name[gst[i].Size] = 0;                                  /* null terminate */\r
+\r
+       fprintf(lst_fh, "Name: %s      Offset %08lX  ", name, gst[i].Offs);\r
+       if (gst[i].Type & CLABEL)\r
+               fprintf(lst_fh, "CSEG  ");\r
+       if (gst[i].Type & DLABEL)\r
+               fprintf(lst_fh, "DSEG  ");\r
+       if (gst[i].Type & sBYTE)\r
+               fprintf(lst_fh, "BYTE  ");\r
+       if (gst[i].Type & sWORD)\r
+               fprintf(lst_fh, "WORD  ");\r
+       if (gst[i].Type & sDWORD)\r
+               fprintf(lst_fh, "DWORD  ");\r
+       if (gst[i].Type & sFWORD)\r
+               fprintf(lst_fh, "FWORD  ");\r
+       if (gst[i].Type & tEXTRN)\r
+               fprintf(lst_fh, "EXTRN  ");\r
+       if (gst[i].Type & tFAR)\r
+               fprintf(lst_fh, "FAR    ");\r
+       if (gst[i].Type & tPUBLIC)\r
+               fprintf(lst_fh, "PUBLIC ");\r
+       if (gst[i].Type & MACRO)\r
+               fprintf(lst_fh, "MACRO  ");\r
+       fprintf(lst_fh, "\r\n");\r
+       i++;\r
+       }\r
+\r
+}\r
+\r
+/*********************************************\r
+       DUMP SYMBOL TABLE FOR TESTING\r
+**********************************************/\r
+\r
+void DumpLSymbols(void)\r
+{\r
+S32 i;\r
+S8   name[132];\r
+\r
+fprintf(lst_fh, "LOCAL SYMBOLS: \r\n");\r
+\r
+i = 1;\r
+while (i<iLSymNext) {                                          /* forward through symbol table */\r
+       strncpy(name, lst[i].Ptr, lst[i].Size); /* move to name */\r
+       name[lst[i].Size] = 0;                                  /* null terminate */\r
+\r
+       fprintf(lst_fh, "Name: %s      Offset %lX   ", name, lst[i].Offs);\r
+       if (lst[i].Type & CLABEL)\r
+               fprintf(lst_fh, "CSEG  ");\r
+       if (lst[i].Type & DLABEL)\r
+               fprintf(lst_fh, "DSEG  ");\r
+       if (lst[i].Type & sBYTE)\r
+               fprintf(lst_fh, "BYTE  ");\r
+       if (lst[i].Type & sWORD)\r
+               fprintf(lst_fh, "WORD  ");\r
+       if (lst[i].Type & sDWORD)\r
+               fprintf(lst_fh, "DWORD  ");\r
+       if (lst[i].Type & sFWORD)\r
+               fprintf(lst_fh, "FWORD  ");\r
+       if (lst[i].Type & tEXTRN)\r
+               fprintf(lst_fh, "EXTRN  ");\r
+       if (lst[i].Type & tFAR)\r
+               fprintf(lst_fh, "FAR    ");\r
+       if (lst[i].Type & tPUBLIC)\r
+               fprintf(lst_fh, "PUBLIC ");\r
+       if (lst[i].Type & MACRO)\r
+               fprintf(lst_fh, "MACRO");\r
+       fprintf(lst_fh, "\r\n");\r
+       i++;\r
+       }\r
+}\r
+\r
+/*********************************************\r
+       DUMP Forward Reference Table for testing\r
+**********************************************/\r
+\r
+void DumpFRT(void)\r
+{\r
+S32 i;\r
+S8   name[132];\r
+\r
+fprintf(lst_fh, "FORWARD REFERENCES:\n");\r
+\r
+i = 0;\r
+while (i<iRefNext) {                                           /* forward through symbol table */\r
+       strncpy(name, pfrt[i].Ptr, pfrt[i].NameSz);     /* move to name */\r
+       name[pfrt[i].NameSz] = 0;                                       /* null terminate */\r
+\r
+       fprintf(lst_fh, "Name: %s      Offset: %lX   Line: %d\n",\r
+                       name,\r
+                       pfrt[i].Offs,\r
+                       pfrt[i].Line);\r
+       i++;\r
+       }\r
+\r
+}\r
+\r
+/*********************************************\r
+This sets the global variable fPutBack to TRUE\r
+and copies the current token info so save it\r
+so it can be used again. (returning a token\r
+to the stream...)\r
+**********************************************/\r
+void ReturnToken(void)\r
+{\r
+strncpy(LTString, TString, 132);\r
+LCBString = CBString;\r
+LTSymnum = TSymnum;\r
+LTNumber = TNumber;\r
+LTInst = TInst;\r
+LTReg = TReg;\r
+LToken = Token;\r
+fPutBack = 1;\r
+}\r
+\r
+\r
+/********************************************\r
+ Parse reads and identifies the next token\r
+ for the caller. See SASM.h for info on each\r
+ of the tokens it identifies.\r
+ Token type is placed in Token.\r
+ All parsed chars are placed in TString.\r
+ Size of TString is placed in CBString.\r
+ Converted numeric values are put in TNumber.\r
+ Instruction numbers are placed in TInst.\r
+ Declared symbol ID numbers are placed in TSymnum.\r
+\r
+ Unidentified strings are first checked for\r
+ macro substitution and replaced with the\r
+ stored string if found. If no macro is\r
+ found, the symbol table is searched to see if\r
+ it's a symbol. If so, it's returned. If not\r
+ a symbol, Parse assumes it may be a new one\r
+ and leaves it in TString with the TokenType\r
+ of UNKSYM.\r
+*********************************************/\r
+\r
+S32 Parse(void)\r
+{\r
+S32  i;\r
+\r
+if (fPutBack) {                /* if a symbol was put back this makes it current */\r
+       strncpy(TString, LTString, 132);\r
+       CBString = LCBString;\r
+       TSymnum = LTSymnum;\r
+       TNumber = LTNumber;\r
+       TInst = LTInst;\r
+       TReg = LTReg;\r
+       Token = LToken;\r
+       fPutBack = 0;\r
+       return(Token);\r
+}\r
+\r
+begin:                         /* return here after MACRO substitution */\r
+ TSymnum = 0;\r
+ TInst = 0;\r
+ TReg = 0;\r
+ Token = 0;\r
+ TString[0] = 0;\r
+ CBString = 0;\r
+ TNumber = 0;\r
+\r
+ while(isskip(*line_ptr)) line_ptr++;          /* skip while space */\r
+ if (!(*line_ptr)) return(0);                          /* end of line */\r
+\r
+ if    (*line_ptr == SEMI)                                     /* if comment */\r
+ {\r
+       *line_ptr = 0;                                  /* kill rest of line */\r
+       return(0);                                              /* return 0 for EOL */\r
+ }\r
+\r
+  /* See if it's a legal 1st char for identifier or reserved word. */\r
+  /* If so, pick it up and put it in TString ALL UPPER CASE */\r
+\r
+ i=0;\r
+ if (is_ident(*line_ptr))\r
+ {\r
+        while( (isalnum(*line_ptr)) || (*line_ptr == '_') )\r
+        {\r
+                TString[i++] = toupper(*line_ptr++);\r
+        }\r
+       CBString = i;\r
+       TString[i] = 0;\r
+\r
+    if (TReg = findreg(TString, i))    /* Register? */\r
+               return (Token = REGIST);\r
+\r
+    if (TInst = findinst(TString, i))  /* Instruction? */\r
+               return (Token = INSTRU);\r
+\r
+    if (Token = findrsvd(TString, i))  /* Reserved Word? */\r
+               return (Token);\r
+\r
+       if (level) {\r
+               if (TSymnum = findLsymbol(TString, i)) {\r
+\r
+                       if (lst[TSymnum].Type & MACRO) {                /* MACRO !! */\r
+                         i = lst[TSymnum].Offs;                                /* get number */\r
+                         strcpy(line_buf1, rgMacPtr[i]);               /* move it in */\r
+                         strncat(line_buf1, line_ptr, 132);    /* cat rest of line */\r
+                         line_ptr = line_buf1;\r
+                         goto begin;\r
+                       }\r
+                       else return (Token = LSYMBOL);\r
+               }\r
+       }\r
+\r
+       if (TSymnum = findGsymbol(TString, i))\r
+       {\r
+                return (Token = SYMBOL);\r
+       }\r
+       else return (Token = UNKSYM);\r
+ }\r
+\r
+ /* If char was not legal for an identifier the only things left\r
+    are digits, special characters, and 'strings' */\r
+\r
+ if (isdigit(*line_ptr))\r
+ {\r
+       TNumber = get_number();\r
+       return (Token = NUMBER);\r
+ }\r
+ switch (*line_ptr) {\r
+       case DOLLAR:\r
+       case OPENRND:\r
+       case CLOSRND:\r
+       case STAR:\r
+       case PLUS:\r
+       case COMMA:\r
+       case MINUS:\r
+       case DOT:\r
+       case SLASH:\r
+       case COLON:\r
+       case OPENSQR:\r
+       case CLOSSQR:\r
+               {\r
+               Token = *line_ptr;\r
+               TString[0] = *line_ptr++;\r
+               TString[1] = 0;\r
+               CBString = 1;\r
+               return (Token);\r
+               }\r
+    case SQUOTE:\r
+       {\r
+               line_ptr++;\r
+               while ((*line_ptr) && (*line_ptr != SQUOTE) && (i < 132))\r
+                       TString[i++] = *line_ptr++;\r
+               CBString = i;\r
+               if (*line_ptr != SQUOTE)\r
+                       line_error(6);\r
+               else\r
+                       line_ptr++;             /* next char if this is SQUOTE */\r
+               TString[i] = 0;         /* null terminate string */\r
+               CBString = i;           /* Set size */\r
+               return(Token = STRING);\r
+               }\r
+    default: {\r
+               line_error(7);\r
+               return(Token = ERROR);\r
+       }\r
+ } /* end switch */\r
+}\r
+\r
+/**************************************\r
+  Handles include files for INCLUDE and\r
+  SEARCH commands.\r
+***************************************/\r
+void DoInclude(char *pName)\r
+{\r
+               if (level < LEVELS-1) {\r
+                        ++level;\r
+\r
+                       strcpy(srcname[level], pName);\r
+\r
+                       if(!(src_fh[level] = fopen(srcname[level], "r"))) {\r
+                               --level;\r
+                               fatal_error("Can't open INCLUDE file\n");\r
+                               }\r
+                       else\r
+                               lineno[level] = 0;\r
+\r
+                       if (fListA) {\r
+                               Column += fprintf(lst_fh, "%08lX ", *pNextAddr);\r
+                               Column += fprintf(lst_fh, "INCLUDE: %s", srcname[level]);\r
+                               }\r
+                       }\r
+               else\r
+                       fatal_error("EXCEEDED MAX INCLUDE DEPTH (5)");\r
+\r
+}\r
+\r
+/*******************************************\r
+  Handles SEARCH command for library search.\r
+  We open the PUB file given and find the\r
+  first filename. We save this name, then\r
+  run through the publics seeing if we\r
+  need any of them.\r
+*******************************************/\r
+void DoSearch(char *pName)\r
+{\r
+\r
+}\r
+\r
+\r
+/********************************************\r
+   Handles DOT Commands\r
+*********************************************/\r
+void Command(void)\r
+{\r
+U32 num;\r
+S32 i, ii;\r
+char tmpname[50];\r
+\r
+i = Parse();\r
+\r
+switch(i)\r
+{\r
+       case rDATA:\r
+               fDataSeg = 1;\r
+               if (fListA) {\r
+                       pNextAddr = &oNextData;\r
+                       Column += fprintf(lst_fh, "%08lX ", *pNextAddr);\r
+                       Column += fprintf(lst_fh, "<- DSEG Begin", lst_fh);\r
+                       }\r
+               break;\r
+       case rCODE:\r
+               fDataSeg = 0;\r
+               if (fListA) {\r
+                       pNextAddr = &oNextCode;\r
+                       Column += fprintf(lst_fh, "%08lX ", *pNextAddr);\r
+                       Column += fprintf(lst_fh, "<- CSEG Begin", lst_fh);\r
+                       }\r
+               break;\r
+       case rALIGN:\r
+               ii = Parse();\r
+               if (fListA)\r
+                       Column += fprintf(lst_fh, "%08lX ", *pNextAddr);\r
+               if (ii == rWORD)\r
+               {\r
+                       if (fListA)\r
+                               Column += fprintf(lst_fh, "<- WORD ALIGN, PAD: ", lst_fh);\r
+                       if (fDataSeg)\r
+                       {\r
+                               if (oNextData & 1)\r
+                               {\r
+                                       OutByteX(0);    /* EMIT byte to Data seg, value 0 */\r
+                                       if (fListA)\r
+                                               Column += fprintf(lst_fh, "00 ", lst_fh);\r
+                               }\r
+                       }\r
+                       else\r
+                       {\r
+                               if (oNextCode & 1)\r
+                               {\r
+                                       OutByteX(0x90); /* EMIT byte to Code seg, 0x90 (NOP) */\r
+                                       if (fListA)\r
+                                               Column += fprintf(lst_fh, "90 ", lst_fh);\r
+                               }\r
+                       }\r
+               }\r
+               else if (ii == rDWORD)\r
+               {\r
+                       if (fListA)\r
+                               Column += fprintf(lst_fh, "<- DWORD ALIGN, PAD: ", lst_fh);\r
+                       if (fDataSeg)\r
+                       {\r
+                               while (oNextData & 3) {\r
+                                       OutByteX(0);    /* EMIT byte to Data seg, value 0 */\r
+                                       if (fListA)\r
+                                               Column += fprintf(lst_fh, "00 ", lst_fh);\r
+                               }\r
+                       }\r
+                       else\r
+                       {\r
+                               while (oNextCode & 3)\r
+                               {\r
+                                       OutByteX(0x90); /* EMIT byte to Code seg, 0x90 (NOP) */\r
+                                       if (fListA)\r
+                                               Column += fprintf(lst_fh, "90 ", lst_fh);\r
+                               }\r
+                       }\r
+               }\r
+               else if (ii == rPARA)\r
+               {\r
+                       if (fListA)\r
+                               Column += fprintf(lst_fh, "<- PARA(16) ALIGN, PAD: ", lst_fh);\r
+                       if (fDataSeg)\r
+                       {\r
+                               while (oNextData & 0x0f) {\r
+                                       OutByteX(0);    /* EMIT byte to Data seg, value 0 */\r
+                                       if (fListA)\r
+                                               Column += fprintf(lst_fh, "00 ", lst_fh);\r
+                               }\r
+                       }\r
+                       else\r
+                       {\r
+                               while (oNextCode & 0x0f)\r
+                               {\r
+                                       OutByteX(0x90); /* EMIT byte to Code seg, 0x90 (NOP) */\r
+                                       if (fListA)\r
+                                               Column += fprintf(lst_fh, "90 ", lst_fh);\r
+                               }\r
+                       }\r
+               }\r
+               else\r
+                       line_error(8);\r
+               break;\r
+       case rEND:\r
+               if (fListA) {\r
+                       Column += fprintf(lst_fh, "%08lX ", *pNextAddr);\r
+                       Column += fprintf(lst_fh, "<- END of Source ");\r
+                       }\r
+               break;\r
+       case rSTART:\r
+               if (!fDataSeg) {\r
+                       if (fListA) {\r
+                               Column += fprintf(lst_fh, "%08lX ", *pNextAddr);\r
+                               Column += fprintf(lst_fh, "<- START Address ");\r
+                               }\r
+            fStart = 1;\r
+            StartAddr = oNextCode;\r
+                       }\r
+               else\r
+                       line_error(9);\r
+               break;\r
+       case rVIRTUAL:\r
+               if (fDataSeg) {\r
+                       if (fListA)\r
+                               Column += fprintf(lst_fh, "VIRTUAL Segment address: ");\r
+                       if (Parse() == NUMBER) {\r
+                               if (oNextData > 0)\r
+                                       line_error(10);\r
+                               else {\r
+                                       if (fListA)\r
+                                               Column += fprintf(lst_fh, "%08lX", TNumber);\r
+                                       oNextData = TNumber;\r
+                                       DataOffset = TNumber;\r
+                               }\r
+                       }\r
+                       else\r
+                         line_error(11);\r
+               }\r
+               else {\r
+                       if (fListA)\r
+                               Column += fprintf(lst_fh, "VIRTUAL Segment address: ");\r
+                       if (Parse() == NUMBER) {\r
+                               if (oNextCode > 0)\r
+                                       line_error(10);\r
+                               else {\r
+                                       if (fListA)\r
+                                               Column += fprintf(lst_fh, "%08lX", TNumber);\r
+                                       oNextCode = TNumber;\r
+                                       CodeOffset = TNumber;\r
+                               }\r
+                   }\r
+                       else\r
+                         line_error(11);\r
+               }\r
+               break;\r
+       case rINCLUDE:\r
+               tmpname[0] = 0;         /* default to null name */\r
+               while (isskip(*line_ptr)) line_ptr++;\r
+               i=0;\r
+               while ((*line_ptr) && (*line_ptr != ';') && (!isskip(*line_ptr)))\r
+                       tmpname[i++] = *line_ptr++;\r
+               tmpname[i] = 0;                                 /* null terminate */\r
+\r
+               DoInclude(tmpname);\r
+               break;\r
+       case rSEARCH:\r
+               tmpname[0] = 0;         /* default to null name */\r
+               while (isskip(*line_ptr)) line_ptr++;\r
+               i=0;\r
+               while ((*line_ptr) && (*line_ptr != ';') && (!isskip(*line_ptr)))\r
+                       tmpname[i++] = *line_ptr++;\r
+               tmpname[i] = 0;                                 /* null terminate */\r
+\r
+               DoSearch(tmpname);\r
+               break;\r
+       case rSTACK:\r
+               if (!fDataSeg) {\r
+                       if (fListA)\r
+                               Column += fprintf(lst_fh, "Stack Total: ");\r
+                       if (Parse() == NUMBER) {\r
+                               StackTotal += TNumber;\r
+                               if (fListA)\r
+                                       Column += fprintf(lst_fh, "%08lX", StackTotal);\r
+                       }\r
+                       else\r
+                               line_error(35); /* Invalid number or expression */\r
+               }\r
+               else\r
+                 line_error(13);\r
+               break;\r
+       default: line_error(14);\r
+               return;\r
+}\r
+}\r
+\r
+/********************************************\r
+ This adds the 3 bit code for the specified\r
+ register to the ModRM or SIB bytes which\r
+ is pointed to by *modbyte. nshift is the\r
+ number of bits to shift the register code\r
+ before ORing it with *modbyte (ModRM or SIB).\r
+*********************************************/\r
+\r
+void EncodeRegBits(S32 regnum, S8   *modbyte, S32 nshift)\r
+{\r
+\r
+switch (regnum) {\r
+       case rAL:\r
+       case rAX:               /* value is 1 don't do anything */\r
+       case rEAX:\r
+       case rES:\r
+       case rCR0:\r
+       case rDR0:\r
+               break;\r
+       case rCL:\r
+       case rCX:\r
+       case rECX:\r
+       case rCS:\r
+       case rCR1:\r
+       case rDR1:\r
+               *modbyte |= (1 << nshift);\r
+               break;\r
+       case rDL:\r
+       case rDX:\r
+       case rEDX:\r
+       case rSS:\r
+       case rCR2:\r
+       case rDR2:\r
+               *modbyte |= (2 << nshift);\r
+               break;\r
+       case rBL:\r
+       case rBX:\r
+       case rEBX:\r
+       case rDS:\r
+       case rCR3:\r
+       case rDR3:\r
+               *modbyte |= (3 << nshift);\r
+               break;\r
+       case rAH:\r
+       case rSP:\r
+       case rESP:\r
+               *modbyte |= (4 << nshift);\r
+               break;\r
+       case rCH:\r
+       case rBP:\r
+       case rEBP:\r
+       case rFS:\r
+               *modbyte |= (5 << nshift);\r
+               break;\r
+       case rDH:\r
+       case rSI:\r
+       case rESI:\r
+       case rGS:\r
+       case rTR6:\r
+       case rDR6:\r
+               *modbyte |= (6 << nshift);\r
+               break;\r
+       case rBH:\r
+       case rDI:\r
+       case rEDI:\r
+       case rTR7:\r
+       case rDR7:\r
+               *modbyte |= (7 << nshift);\r
+               break;\r
+       default:;               /* if it's not one of these we do nothing */\r
+}\r
+}\r
+\r
+/********************************************\r
+  Add Macro to LOCAL symbol table.\r
+  The last symbol added to the symbol\r
+  table is the label for this macro.\r
+\r
+*********************************************/\r
+void AddMacro(void)\r
+{\r
+S32 i, j;\r
+S8   mac[100];\r
+\r
+mac[0] = 0;\r
+\r
+if (iMacNext >= MACBUFMAX-50)\r
+       fatal_error("Macro buffer overflow...");\r
+if (iMacNext >= MACSMAX)\r
+       fatal_error("Macro table overflow...");\r
+\r
+i = 0; j = 0;\r
+while(isskip(*line_ptr)) line_ptr++;           /* skip while space */\r
+\r
+/* Read the macro including white space upto EOL or comment.\r
+   j keeps track of the last NON-space character so we don't\r
+   store unneeded spaces at the end of the macro.\r
+*/\r
+\r
+while ((*line_ptr) && (*line_ptr != SEMI)) {\r
+       mac[i++] = *line_ptr++;\r
+       if (mac[i-1] > 0x20) j = i;                     /* j will be length */\r
+}\r
+\r
+strncpy(pMacNext, mac, j);\r
+\r
+/* These are all "iLSymNext-1" because the Macro label has\r
+   already been added to the symbol table when AddMacro\r
+   is called.\r
+*/\r
+\r
+lst[iLSymNext-1].Type = 0;                     /* cancel previous type */\r
+lst[iLSymNext-1].Type |= MACRO;                /* initialize type */\r
+\r
+rgMacPtr[iMacNext] = pMacNext;         /* store mac ptr in pmac array */\r
+lst[iLSymNext-1].Offs = iMacNext;      /* store mac # in offset */\r
+iMacNext++;\r
+pMacNext += j;\r
+*pMacNext = 0;                                         /* null terminate the macro */\r
+pMacNext++;\r
+\r
+}\r
diff --git a/msamples/dasmm/makeit.bat b/msamples/dasmm/makeit.bat
new file mode 100644 (file)
index 0000000..9a9e5dd
--- /dev/null
@@ -0,0 +1,2 @@
+CM32 DASM.c\r
+DASM DASM.ATF\r
diff --git a/msamples/dasmm/read.me b/msamples/dasmm/read.me
new file mode 100644 (file)
index 0000000..a843487
--- /dev/null
@@ -0,0 +1,13 @@
+This is the DASM Assembler ported to run under MMURTL.\r
+It has been modified to use MMURTL memory management\r
+calls directly.\r
+It produces the same run file as its DOS counterpart.\r
+You will notice, the like the ported version of CM32,\r
+it runs slower (about 150%) than the DOS version.\r
+\r
+This is for 2 reasons. The CM32 compiler was used to build it.\r
+CM32 is hardly a "production" compiler.\r
+Its code generation is no competition for the likes of Borland.\r
+The second reason is that the processor is being shared with\r
+several other tasks that wake up and do things (such as\r
+display the time or tick count in the monitor).\r