--- /dev/null
+/*\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
--- /dev/null
+/* 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
--- /dev/null
+/* 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
--- /dev/null
+/* 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
--- /dev/null
+CM32 DASM.c\r
+DASM DASM.ATF\r
--- /dev/null
+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