]> pd.if.org Git - mmurtl/blob - msamples/dasmm/dasm.c
autocommit for files dated 1995-02-09 16:53:44
[mmurtl] / msamples / dasmm / dasm.c
1 /*\r
2  * Assembler for MMURTL (MMURTL Version).\r
3  *\r
4  * Copyright 1991,1992,1993,1994,1995 R.A. Burgess\r
5 \r
6   Version 1.2 11/20/93 - major rewrite on instruction table\r
7   Version 1.3 8/28/94 - Clear macro buf on level 1 to 0 transition\r
8   Version 1.4 9/29/94 - Smashed bug in 66| prefix for string commands\r
9   Version 1.5 10/5/94 - Optimized a couple of commands and fixed\r
10                                 bug in ENTER X,X instruction.  This version seems\r
11                                 really stable ("yeaaaaa Right," he says...)\r
12                                 Actually it is....\r
13                10/29/94 Fix problem with sign extending bytes on ADD\r
14   Version 1.6  12/31/94 - Removed temp files on succesful assemble\r
15   Version 1.7M 1/1/95 - V1.6 ported to MMURTL. Changed memory allocation\r
16                                 use AllocPage and also created internal buffers\r
17                                 instead of using tmp files. Also use an internal\r
18                                 read buffer of 4K to make better use of Readbytes().\r
19                                 OutWord, OutDWord, and OutByte had to be renamed\r
20                                 so they would not conflict with MMURTL publics of\r
21                                 the same names.\r
22 \r
23  */\r
24 \r
25 #define U32 unsigned long\r
26 #define S32 long\r
27 #define U16 unsigned int\r
28 #define S16 int\r
29 #define U8 unsigned char\r
30 #define S8 char\r
31 \r
32 \r
33 #include <ctype.h>\r
34 #include <stdio.h>\r
35 #include <string.h>\r
36 #include <stdlib.h>\r
37 \r
38 #include "dasm.h"\r
39 #include "runfile.h"\r
40 #include "\OSSource\MMemory.h"\r
41 #include "\OSSource\MFiles.h"\r
42 \r
43 /* variables */\r
44 \r
45 #define LEVELS 5\r
46 U32 level = 0;                          /* current include level */\r
47 U32 lineno[LEVELS];                     /* line number being parsed */\r
48 U8 fContinue = 0;                       /* True if just returned from include */\r
49 \r
50 char srcname[LEVELS][40];       /* also active include filenames */\r
51 char runname[40];\r
52 char lstname[40];\r
53 \r
54 /* File handles for all files */\r
55 \r
56 FILE *src_fh[5] = {0,0,0,0,0};  /* Current source file */\r
57 FILE *run_fh   = 0;                             /* Current .RUN, .DLL, or .DDR (output) */\r
58 \r
59 FILE *lst_fh   = 0;             /* List file */\r
60 FILE *sym_fh   = 0;             /* Symbol file for debugger */\r
61 \r
62 #define STMPBUFS 512000\r
63 \r
64 U8 *pcsbuf, *pdsbuf;    /* half meg allocated buffers for code & data */\r
65 U32 ics, ids;                   /* current index into tmp code & data buffers */\r
66 \r
67 U8 filetype = 1;                /* 1 = RUN, 2 = DLL, 3 = DDR */\r
68 \r
69 U8 fListA = 0;                  /* True if detailed list file */\r
70 U8 fListE = 0;                  /* True if Error only list file */\r
71 U8 fSymDump = 0;                /* True if we add symbols to the list file */\r
72 U8 Column = 0;                  /* where are we on the LIST line */\r
73 U32 error_count = 0;\r
74 U32 warn_count = 0;\r
75 \r
76  /* Max input line is 132, but 200 allows plenty for macro subs */\r
77 S8 line_buf0[200];      /* Two buffers are swapped during macro substitution */\r
78 S8 line_buf1[200];\r
79 S8 *line_ptr;           /* pointer to next char on line */\r
80 \r
81 S8 list_buf[200];       /* Used to hold line string for list file */\r
82 S8 fLineIn =0;          /* TRUE is list_buf has something to list */\r
83 \r
84 S8   TString[133];      /* all parsed tokens are placed here in text form */\r
85 S32  CBString;          /* size of parsed token */\r
86 S32  TSymnum;           /* Symbol table entry number, else 0 */\r
87 U32  TNumber;           /* value of numeric token */\r
88 S32  TInst;                     /* Instruction number, else 0 */\r
89 S32  TReg;                      /* Register number, else 0 */\r
90 S32  Token;                     /* Token type (also returned from parse) */\r
91 S8   fPutBack = 0;  /* TRUE (non=zero) if last token was not used */\r
92 \r
93 S8   LTString[133];     /* Duplicates of Token storage for ReturnToken(); */\r
94 S32  LCBString;\r
95 S32  LTSymnum;\r
96 U32  LTNumber;\r
97 S32  LTInst;\r
98 S32  LTReg;\r
99 S32  LToken;\r
100 \r
101 S8  UString[31];        /* Place to save unknown labels for Forward Reference */\r
102 S32 UCBString;          /* Size of Unknown label */\r
103 \r
104 /* The two Symbol tables have 5 entries;  Type, Size, Pointer to Name,\r
105    Segment Offset, and Line.\r
106    As each symbol is found, it's identifed by type, and the name\r
107    is moved to the packed symbol buffer. A pointer is added to the\r
108    table to point to the name in the buffer, while it's size, type,\r
109    segment offset, and line number are added to the table.\r
110    Macro names are also stored in the symbol table, but offset entry\r
111    for a macro indicates it's offset in the Macro buffer.\r
112 */\r
113 \r
114 /* Variables for symbol tables */\r
115 \r
116 /* Global Symbol Table */\r
117 \r
118 #define SYMSMAX 700\r
119 #define SYMBUFMAX 16384         /* Avg of 10 byte per name, 700 Max */\r
120 \r
121 struct symtab {\r
122         U32  Type;              /* Token (e.g, CLabel) */\r
123         U32  Line;              /* Line symbol was declared on */\r
124         U32  Size;              /* Size of symbol name */\r
125         S8   *Ptr;              /* Pointer to name in packed buffer */\r
126         U32  Offs;              /* Offset in segment */\r
127         };\r
128 \r
129 struct symtab gst[SYMSMAX];     /* storage for the GST */\r
130 \r
131 /* S8  SymBuf[SYMBUFMAX];       */      /* Where names are stored. Will be Alloced */\r
132 S8 *pSymBuf;                            /* ptr to allocated buffer */\r
133 \r
134 S8   *pSymNext;         /* ptr to next new entry in symbol buffer */\r
135 S32  iSymNext = 1;      /* index to next new symbol table entry.  */\r
136                                         /* Starts at 1 - zero it reserved because */\r
137                                         /* Parse returns 0 for EOL */\r
138 \r
139 S8 fPublic = 0;\r
140 S8 fExtern = 0;\r
141 S8 fFarLabel = 0;\r
142 \r
143 /*********** Local Symbol Table *************/\r
144 \r
145 /* This is cleared after each include file from level 1 is closed */\r
146 /* Clearing means we reset *pLSymNext to begining of buffer */\r
147 /* and reset iLSymNext to 1. This "hides" local symbols. */\r
148 \r
149 #define LSYMSMAX 1800\r
150 #define LSYMBUFMAX 32768                        /* Avg of 7 bytes per name */\r
151 \r
152 struct symtab lst[LSYMSMAX];    /* storage for the LST */\r
153 \r
154 /* S8  LSymBuf[LSYMBUFMAX]; */          /* Where names are stored.*/\r
155 S8  *pLSymBuf;                                  /* for allocated buffer */\r
156 \r
157 S8   *pLSymNext;        /* ptr to next new entry in symbol buffer */\r
158 S32  iLSymNext = 1;     /* index to next new symbol table entry.  */\r
159                                         /* Starts at 1 - zero it reserved because */\r
160                                         /* Parse returns 0 for EOL */\r
161 \r
162 /************* Forward Ref Table *********************************/\r
163 /*\r
164    Labels that are encountered as forward references are\r
165    stored in this table.  When we run across a forward, we do\r
166    not know what segment they are refering to unless it is from\r
167    a jump, call, or loop instruction.  We will NOT know for many\r
168    items until they are actually declared.  After all the code\r
169    and data has been processed, we go through this table\r
170    and fix all the unknown references using the relative\r
171         The type of forward references are:\r
172 \r
173                 1) DSEG DWORD item refers to UNK item (?Seg MemRef)\r
174                 2) CSEG DWORD item refers to UNK item (?Seg MemRef)\r
175                 3) CSEG to CSEG relative 8  (Jump, Jc, or Loop)\r
176                 4) CSEG to CSEG relative 32 (Jump or Call)\r
177 \r
178         MOTE: If a calculation is made with the unknown reference, 0\r
179         is used in the calculation. We ALWAYS ADD the value we stored\r
180         with what is found when the reference is resolved.\r
181 \r
182 */\r
183 \r
184 #define FREFTABMAX 32768\r
185 #define FREFSMAX   32768/14\r
186 #define FREFBUFMAX 16384\r
187 \r
188 /* Types of forward references. */\r
189 \r
190 #define DSEGREF   1             /* 32 bit Abs Ref in DSeg, to what is unknown! */\r
191 #define CSEGREF   2             /* 32 bit Abs Ref in CSeg, to what is unknown! */\r
192 #define CCR32REF  3             /* 32 bit Relative in CSeg */\r
193 #define CCR8REF   4             /* 8 bit Relative in CSeg */\r
194 \r
195 struct forreftab {\r
196         U8   Type;      /* 1, 2, 3, or 4 */\r
197         U8   NameSz;    /* Size of ref name */\r
198         U32  Line;              /* Line reference was made on  (for error if not found) */\r
199         S8   *Ptr;              /* Pointer to name in packed buffer */\r
200         S32  Offs;              /* Offset in segment were it should go */\r
201         };\r
202 \r
203 struct forreftab *pfrt; /* pointer to allocated table */\r
204 \r
205 S8   *pRefBuf;\r
206 S8   *pRefNext;         /* ptr to next new entry in symbol buffer */\r
207 S32  iRefNext = 0;      /* index to next new forward ref table entry.  */\r
208 \r
209 /************ External Reference table ************/\r
210 \r
211 /* External definitions that are encountered in a module are\r
212    first entered in the Global Symbol Table (GST) as externals\r
213    if they haven't already been defined (public) by the module\r
214    that owns them.\r
215    When a reference is made to an external, we see if the public has\r
216    already been defined. If so, we resolve it immediately. If not,\r
217    we make an entry in the External Reference Table (ERT).  The\r
218    entry has the following 4 pieces of information:\r
219      - Line where reference was made.\r
220      - Index to place holder entry in GST.\r
221          - Segment where reference was made (boolean - TRUE for code seg).\r
222          - Offset in that segment where the resolution will be made.\r
223    With this information we can reslove all the external references\r
224    before we write the code segment to the run file.\r
225 */\r
226 \r
227 #define EREFSMAX 400\r
228 \r
229 struct extreftab {\r
230         U8   Type;   /* Type of reference so we know how to apply it */\r
231         U32  iSym;       /* Index of gst entry. Hi bit set if CSeg ref */\r
232         U32  Offs;       /* Offset in segment were ref needs 32 bit fixing */\r
233         };\r
234 \r
235 struct extreftab ert[FREFSMAX];\r
236 \r
237 S32  iERefNext = 0;     /* index to next external ref table entry.  */\r
238 \r
239 U32 nExtRef;\r
240 \r
241 /*********** Fix Up Table *********************/\r
242 \r
243 /* This table holds 6 types of fixups along with the offset\r
244    in the segment to be fixed up, and if applicable, an index\r
245    to the DLL public name in the GST (which should be defined\r
246    as EXTRNDLL):\r
247      - Fixup type\r
248          - Ref in CSEG to address in DSEG\r
249          - Ref in CSEG to address in CSEG\r
250          - Ref in DSEG to address in DSEG\r
251          - Ref in DSEG to address in CSEG\r
252          - CSEG DLL near 32 bit call used\r
253          - CSEG DLL near 32 bit call defined\r
254      - Offset of 32 bit reference to be resolved\r
255      - Index to DLL public name in GST (if applicable)\r
256 \r
257    With this information we can supply the loader with the TAG entries\r
258    in the RUN file needed to resolve them.  Most of these entries will\r
259    be made as we parse the code, but many will also be added after\r
260    we fix the forward references because we won't know what segment\r
261    the reference is made to until then.\r
262 */\r
263 \r
264 #define FIXUPSMAX    32768/7\r
265 #define FIXUPBUFMAX  32768\r
266 \r
267 struct futab \r
268         {\r
269         U8   type;   /* Type of fixup C0, C1, C2, C3, C5, or C8 */\r
270         U32  Offs;       /* Offset in segment for 32 bit fixup */\r
271         U32  iSym;       /* index of DLL entry in gst, else 0 */\r
272         };\r
273 \r
274 struct futab *pfut;     /* pointer to allocated Fix Up Table */\r
275 \r
276 S32  iFUNext = 0;       /* index to next fix up table entry.  */\r
277                                         /* Starts at 0 */\r
278 \r
279 U32     nCDFix = 0;\r
280 U32 nDDFix = 0;\r
281 U32 nDCFix = 0;\r
282 U32 nCCFix = 0;\r
283 \r
284 /********* Macro variables *******************/\r
285 \r
286 #define MACSMAX 300\r
287 #define MACBUFMAX  4096\r
288 \r
289 S8   *rgMacPtr[MACSMAX];        /* pointer to simple macros */\r
290 S8   *pMacBuf;\r
291 S8   *pMacNext;                         /* ptr to next new entry in macro buffer */\r
292 S32  iMacNext = 0;                      /* index to next new symbol entry */\r
293 \r
294 /* Variables for current segment address offset tracking */\r
295 \r
296 S8  fStart = 0;                 /* True if they gave a start address */\r
297 S32 StartAddr = 0;              /* Filled in when .START is encountered */\r
298 S32 oNextData = 0;              /* Tracks current DSEG offset */\r
299 S32 oNextCode = 0;      /* Tracks current CSEG offset */\r
300 S32 CodeOffset = 0;             /* From Virtual Command */\r
301 S32 DataOffset = 0;             /* From Virtual Command */\r
302 S32 *pNextAddr = 0;             /* Points to current segment offset counter */\r
303 S8  fDataSeg = 0;               /* True if parsing DSEG, else parsing CSEG */\r
304 S32 StackTotal = 0;             /* Total Stack Specified in Code segs */\r
305 \r
306 /******************************************************************\r
307    Variables for RAW operands in an instruction.\r
308    These are used when we read in and separate each part of the\r
309    operands so it can be evaluated.\r
310 */\r
311 \r
312 S32  rgToken[3][20]; /* Raw tokens in the operand (as many as 20) */\r
313 S32  rgVal[3][20];   /* value if token is number/displacement */\r
314 S32  rgTID[3][20];       /* Register ID if token is a register */\r
315 S32  rgTCnt[3];          /* total count of tokens in raw operand */\r
316 \r
317 /******************************************************************\r
318    These variables are filled in while parsing and evaluating\r
319    instructions that have been read in.\r
320    They have all the info needed to\r
321    encode the instruction into the object module and\r
322    produce FixUp Records if needed.\r
323 */\r
324 \r
325 /* These are used in the description of all OPERANDS for the current\r
326    instruction we are working on.\r
327 */\r
328 S32  rgOpType[3];       /* Operand type for compare to instruction */\r
329 S32  rgOpReg[3];    /* If reg only, this which one */\r
330 S8   OpSize[3];     /* Operand size for first two (fByte, fWord, fFar etc.) */\r
331 S8   OpSizeA;       /* Overall operand size for instruction */\r
332 S8   OpPrefix;      /* Bit set for a segment prefix (fESp etc.) */\r
333 S32  iInstEntry;        /* Which entry is it in rgINS */\r
334 S32  CrntInst;          /* instruction we are working on        */\r
335 S32  InstPfx;           /* Special Insturction prefix for crnt inst */\r
336 S32  nOperands;         /* number of operands we found */\r
337 S8   fForRef;       /* Crnt inst makes a Forward Reference */\r
338 \r
339 /* The following vars are used if we have a memory reference that is\r
340    encoded as part of the instruction.\r
341 */\r
342 S8   OpMType;           /* Mem type (compared to rgM32). 0 if not mem type */\r
343 S32  OpBase;        /* Base register if fBase is true */\r
344 S32  OpIndx;        /* Index register if fIndx is true */\r
345 S32  OpDisp;        /* Displacement if fDisp8 or fDisp32 is TRUE */\r
346 S32  iMemEntry;         /* If mem operand, which entry in rgM32 */\r
347 \r
348 /* The following are used if we have immediate values to be encoded as\r
349 part of the instruction.  Immediates can also be addresses such as\r
350 those in Direct and Relative Jumps and Calls!\r
351 */\r
352 S32  OpImm;         /* Immediate value if fOpImm is true */\r
353 S8   fOpImm;            /* If OpImm has a value */\r
354 S32  OpImm2;        /* Second Imm value for iSAD and other multi-Imm types */\r
355 S8   fOpImm2;           /* If OpImm2 has a value */\r
356 \r
357 /* This is set for each type of fixup required after an instruction\r
358 line.  Data fixups are done directly in the code that generates\r
359 storage in DSeg. */\r
360 \r
361 U8   nFixUp;            /* Fixup number (Cx) */\r
362 \r
363 /*************************************************************************/\r
364 \r
365 /* In the final stages of building an instruction, these contain the\r
366    fragment bytes of encoded instructions (along with flags for\r
367    optional parts used).\r
368 */\r
369 \r
370 U8  bOpc1;              /* Zero if not used */\r
371 U8  bOpc2;              /* Always used */\r
372 U8  bModRM;             /* ModRM byte value if used */\r
373 U8  bSIB;               /* SIB value if used */\r
374 S8  fModRM;     /* True if bModRM is used */\r
375 S8  fSIB;       /* True if bSIB is used */\r
376 \r
377 /*** These are used in the expression parser ******/\r
378 \r
379 U8  ExpType;            /* 0 = Forward, 1 = Local, 2 = Global, 3 = Current Addr */\r
380 U8  ExpType0;\r
381 S32 nExpSyms;           /* Used by the numeric expression evaluator */\r
382 S32 iExpSym, iExpSym0;  /* if a symbol value translates to a SYMOFF,\r
383                                            this holds the symbol table index. */\r
384 S8  fOffset;            /* True if derived from an Offset */\r
385 \r
386 /* Variables for Storage allocation */\r
387 \r
388 \r
389 S8  fMoreStorage = 0;   /* True when storage continues to next line */\r
390 S32 StoreSize = 0;\r
391 \r
392 /****  Variables for building the RUN File (DLL or Device Driver) ********/\r
393 \r
394 /* Once we have the CS and DS tmp files run through to correct any external\r
395    variables or forward labels, we build the run file.  This is done\r
396    by building the tag records, sending them followed by the proper data\r
397    for each one.\r
398 */\r
399 \r
400 struct tagtype tag;\r
401 \r
402 \r
403 /******************* END VARIABLES - BEGIN CODE ********************/\r
404 \r
405 /* ANSI prototypes for all functions are in DProtos.h */\r
406 \r
407 #include "DProtos.h"\r
408 \r
409 \r
410 /***************************************************************/\r
411 /* Write a DWord to the current segment and update the counter */\r
412 /***************************************************************/\r
413 \r
414 void OutDWordX(unsigned long Data)\r
415 {\r
416 unsigned char *pOut, b;\r
417 long i;\r
418         pOut = &Data;\r
419         if (fDataSeg) {\r
420                 for (i=0; i<4; i++) {\r
421                         b = *pOut++;\r
422                         pdsbuf[ids++] = b;      /* fputc(b , ds_fh); */\r
423                 }\r
424             oNextData+=4;\r
425         }\r
426         else {\r
427                 for (i=0; i<4; i++) {\r
428                         b = *pOut++;\r
429                         pcsbuf[ics++] = b;      /* fputc(b , cs_fh); */\r
430                 }\r
431             oNextCode+=4;\r
432     }\r
433 }\r
434 \r
435 /******************************************************************/\r
436 /* Write a DWord to the code segment and DO NOT update counter */\r
437 /******************************************************************/\r
438 \r
439 void OutDWordCS(unsigned long Data)\r
440 {\r
441 unsigned char *pOut, b;\r
442 long i;\r
443         pOut = &Data;\r
444         for (i=0; i<4; i++) {\r
445                 b = *pOut++;\r
446                 pcsbuf[ics++] = b;      /* fputc(b , cs_fh); */\r
447         }\r
448 }\r
449 \r
450 /******************************************************************/\r
451 /* Read n bytes from the code segment                                                    */\r
452 /******************************************************************/\r
453 \r
454 void readCS(U8 *pDataRet, long cbData)\r
455 {\r
456         while (cbData--)\r
457                 *pDataRet++ = pcsbuf[ics++];\r
458 }\r
459 \r
460 \r
461 /******************************************************************/\r
462 /* Write n bytes to the code segment and DO NOT update counter */\r
463 /******************************************************************/\r
464 \r
465 void writeCS(U8 *pData, long cbData)\r
466 {\r
467         while (cbData--)\r
468                 pcsbuf[ics++] = *pData++;\r
469 }\r
470 \r
471 \r
472 /****************************************************************\r
473   Set index into code buffer\r
474 *****************************************************************/\r
475 \r
476 void seekCS(long offset)\r
477 {\r
478         ics = offset;\r
479 }\r
480 \r
481 \r
482 /******************************************************************/\r
483 /* Write a DWord to the current segment and DO NOT update counter */\r
484 /******************************************************************/\r
485 \r
486 void OutDWordDS(unsigned long Data)\r
487 {\r
488 unsigned char *pOut, b;\r
489 long i;\r
490         pOut = &Data;\r
491         for (i=0; i<4; i++) {\r
492                 b = *pOut++;\r
493                 pdsbuf[ids++] = b;      /* fputc(b , ds_fh); */\r
494         }\r
495 }\r
496 \r
497 /******************************************************************/\r
498 /* Read n bytes from the code segment                                                    */\r
499 /******************************************************************/\r
500 \r
501 void readDS(U8 *pDataRet, long cbData)\r
502 {\r
503         while (cbData--)\r
504                 *pDataRet++ = pdsbuf[ids++];\r
505 }\r
506 \r
507 /******************************************************************/\r
508 /* Write n bytes to the data segment and DO NOT update counter */\r
509 /******************************************************************/\r
510 \r
511 void writeDS(U8 *pData, long cbData)\r
512 {\r
513         while (cbData--)\r
514                 pdsbuf[ids++] = *pData++;\r
515 }\r
516 \r
517 /****************************************************************\r
518   Set index into data buffer\r
519 *****************************************************************/\r
520 \r
521 void seekDS(long offset)\r
522 {\r
523         ids = offset;\r
524 }\r
525 \r
526 /**************************************************************/\r
527 /* Write a Word to the current segment and update the counter */\r
528 /**************************************************************/\r
529 \r
530 void OutWordX(unsigned long Data)\r
531 {\r
532 unsigned char *pOut, b;\r
533 long i;\r
534         pOut = &Data;\r
535         b = *pOut++;\r
536         if (fDataSeg) {\r
537                 pdsbuf[ids++] = b;      /* fputc(b , ds_fh); */\r
538                 b = *pOut;\r
539                 pdsbuf[ids++] = b;      /* fputc(b , ds_fh); */\r
540             oNextData+=2;\r
541         }\r
542         else {\r
543                 pcsbuf[ics++] = b;      /* fputc(b , cs_fh); */\r
544                 b = *pOut;\r
545                 pcsbuf[ics++] = b;      /* fputc(b , cs_fh); */\r
546             oNextCode+=2;\r
547         }\r
548 }\r
549 \r
550 /**************************************************************/\r
551 /* Write a BYTE to the current segment and update the counter */\r
552 /**************************************************************/\r
553 \r
554 void OutByteX(unsigned char Data)\r
555 {\r
556         if (fDataSeg) {\r
557                 pdsbuf[ids++] = Data;   /* fputc(Data , ds_fh); */\r
558             oNextData++;\r
559         }\r
560         else {\r
561                 pcsbuf[ics++] = Data;   /* fputc(b , cs_fh); */\r
562             oNextCode++;\r
563         }\r
564 }\r
565 \r
566 /*****************************************************************/\r
567 /* Write a BYTE to the current segment and DO NOT update counter */\r
568 /*****************************************************************/\r
569 \r
570 void OutByteCS(unsigned long Data)\r
571 {\r
572 char b;\r
573         b = Data;\r
574         pcsbuf[ics++] = b;              /* fputc(b , cs_fh); */\r
575 }\r
576 \r
577 /* All the "grunt work" functions are in dasmq.c */\r
578 \r
579 #include "DASMq.c"\r
580 \r
581 /*********************************************\r
582 This searches the Reference table for the name\r
583 described by pb, cb. It only compares items that\r
584 are the same length (cb == TRefSize[x]).\r
585 It returns the number or 0 if not found.\r
586 **********************************************/\r
587 \r
588 S32 findref(S8 *pb, S32 cb)  /* pointer to, and size of string */\r
589 {\r
590 S32 i;\r
591 S8   name[132];\r
592 \r
593 strncpy(name, pb, cb);          /* move name local */\r
594 name[cb] = 0;                           /* null terminate */\r
595 \r
596 i = iRefNext;\r
597 while (i>0) {                           /* backwards through forward ref table */\r
598         i--;\r
599                                 /* Only compare if same size  */\r
600         if (pfrt[i].NameSz == cb) {\r
601                 if (strncmp(name, pfrt[i].Ptr, cb) == 0) return(i);\r
602         }\r
603 }\r
604 return(0);\r
605 }\r
606 \r
607 \r
608 /*****************************************************\r
609    Evaluates only single token operands and sets up\r
610    globals so EvalOper can finish the job.\r
611    The actual value or register is left in\r
612    rgToken[op][0], and the type is placed\r
613    in rgTempl[op][0] for a memory operand.\r
614 *****************************************************/\r
615 S32 EvalOper1(S32 op)\r
616 {\r
617 S32 i;\r
618 U32 symtype;\r
619 \r
620         /* Set up symtype up front in case it's needed */\r
621 \r
622         if (ExpType == 1)                               /* Local */\r
623                 symtype = lst[iExpSym].Type;\r
624         else if (ExpType == 2) {                /* global */\r
625                 if (gst[iExpSym].Type & tEXTRN)\r
626                         nExtRef = iExpSym;\r
627                 symtype = gst[iExpSym].Type;\r
628         }\r
629         else symtype = 0;\r
630 \r
631         switch (rgToken[op][0]) {\r
632                 case REGIST:\r
633                         if (is_r32(rgTID[op][0]))  rgOpType[op] = r32;\r
634                         else if (is_r16(rgTID[op][0])) rgOpType[op] = r16;\r
635                         else if (is_r8(rgTID[op][0]))   rgOpType[op] = r8;\r
636                         else if (is_rCRG(rgTID[op][0])) rgOpType[op] = rCRG;\r
637                         else if (is_rDRG(rgTID[op][0])) rgOpType[op] = rDRG;\r
638                         else if (is_rTRG(rgTID[op][0])) rgOpType[op] = rTRG;\r
639                         else if (is_rSEG(rgTID[op][0])) rgOpType[op] = rSEG;\r
640                         rgOpReg[op] = rgTID[op][0];\r
641                         break;\r
642                 case NUMBER:\r
643                         if ((rgVal[op][0] >= -128) && (rgVal[op][0] <= 127))\r
644                  rgOpType[op] = val8;\r
645                         else if ((rgVal[op][0] >= -32768) && (rgVal[op][0] <= 32767))\r
646                  rgOpType[op] = val16;\r
647                         else rgOpType[op] = val32;\r
648                         if (!fOpImm) {\r
649                     OpImm = rgVal[op][0];\r
650                     fOpImm = 1;\r
651                     }\r
652                         else {\r
653                     OpImm2 = rgVal[op][0];\r
654                     fOpImm2 = 1;\r
655                     }\r
656                         break;\r
657                 case NUMOFF:            /* OFFSET var name. IMMEDIATE VALUE. */\r
658                         OpSize[op] = fDWord;\r
659                         rgOpType[op] = val32;\r
660             OpImm = rgVal[op][0];\r
661             fOpImm = 1;\r
662                         if (symtype & CLABEL)\r
663                                 nFixUp = CCFIXTAG;\r
664                         else if (symtype & DLABEL)\r
665                                 nFixUp = CDFIXTAG;\r
666                         if (!symtype)\r
667                                 fForRef = 1;\r
668                         break;\r
669                 case SYMOFF:   /* Check for ALL jump, call & Loop instructions */\r
670 \r
671                         if (ExpType == 1)                               /* Local */\r
672                                 symtype = lst[iExpSym].Type;\r
673                         else if (ExpType == 2) {                /* global */\r
674                                 if (gst[iExpSym].Type & tEXTRN)\r
675                                         nExtRef = iExpSym;\r
676                                 symtype = gst[iExpSym].Type;\r
677                         }\r
678                         else                                                    /* Unknown - Forward */\r
679                                 symtype = 0;\r
680 \r
681                         if (((CrntInst >= xJA) &&\r
682                              (CrntInst <= xJZ)) ||\r
683                  (CrntInst == xCALL)) {\r
684 \r
685                                 if (OpSize[op] & fShort)\r
686                                         rgOpType[op]  = rel8;\r
687                                 else\r
688                                         rgOpType[op] = relW;\r
689                         OpImm = rgVal[op][0];\r
690                         fOpImm = 1;\r
691                         }\r
692 \r
693                         else if ((CrntInst >= xLOOP) && (CrntInst <= xLOOPZ)) {\r
694                                         rgOpType[op] = rel8;\r
695                                 OpImm = rgVal[op][0];\r
696                                 fOpImm = 1;\r
697                         }\r
698                         else {\r
699                                 rgOpType[op]  = mem;\r
700                     OpMType |= fDisp32;\r
701                     OpDisp = rgVal[op][0];\r
702                                 if (symtype & CLABEL)\r
703                                         nFixUp = CCFIXTAG;\r
704                                 else if (symtype & DLABEL)\r
705                                         nFixUp = CDFIXTAG;\r
706                         }\r
707                         if (!symtype)\r
708                                 fForRef = 1;\r
709                         break;\r
710                 default:\r
711                    line_error(15);\r
712                    return(0);\r
713         } /* switch */\r
714 \r
715 /*  print_Oper(op); Testing only... */\r
716 \r
717 return(1);\r
718 }\r
719 \r
720 /***********  EvalOper *******************************\r
721    Evaluates the array of reserved words, registers,\r
722    numbers, etc. that should make up an operand.\r
723    For single token operands it's easy! BUT for memory\r
724    operands it gets a little more complicated.\r
725    For memory operands we look for key sequences of\r
726    tokens that make up the "effective address" as\r
727    described in the Intel documentation, then see if\r
728    we have all the pieces to make one (EA).\r
729    This returns 1 if we can classify the operand and\r
730    there were no errors.  The type of operand we find\r
731    (e.g., r8, r16, r32, val8, val16, val32, mem,\r
732    relW, etc.) is placed in rgOpType[op].\r
733    This calls EvalOper1() to handle single token\r
734    oprerands and evaluates multiple token operands\r
735    internally. The reason we break single token operands\r
736    out in a separate call is for speed and clarity\r
737    of the code.\r
738    Special handling is required for for JMP, Jcond,\r
739    and CALL instructions because they may be using\r
740    a forward reference not yet defined.  This is the\r
741    only case where such a reference is allowed.\r
742 *****************************************************/\r
743 \r
744 S32 EvalOper(S32 op)\r
745 {\r
746 S32 i;\r
747 S8   fDone, fOpenSQ, fError;\r
748 U32 symtype;\r
749 /*\r
750 These are the Raw operands:\r
751 S32  rgToken[3][20];  Raw tokens in the operand\r
752 S32  rgVal[3][20];    value if token is number/displacement\r
753 S32  rgTID[3][20];        Register ID if token is a register\r
754 S32  rgTCnt[3];           total count of tokens in raw operand\r
755 \r
756  This is what is produced:\r
757 */\r
758 \r
759 rgOpType[op] = 0;       /* int - Operand type for compare to instruction */\r
760 rgOpReg[op] = 0;    /* If reg only, this which one */\r
761 \r
762 i = 0;           /* index into raw tokens */\r
763 fError = 0;  /* set true for invalid operand error */\r
764 fDone = 0;   /* Set when no more tokens are expected in operand */\r
765 fOpenSQ = 0; /* keep track of [] */\r
766 \r
767 /* flags for segment instruction prefix - NONE unless otherwise set */\r
768 /* If it's a single token operand, take the fast, easy way out! */\r
769 \r
770 if (rgTCnt[op] == 1) {\r
771         return (EvalOper1(op));\r
772 }\r
773 \r
774 else {          /* multiple tokens in operand */\r
775 \r
776         /* with more than 1 token it is usually a memory reference\r
777            but not always.  We will default to mem and change those we\r
778            find that aren't.  */\r
779 \r
780         rgOpType[op] = mem;\r
781 \r
782         /* Segment prefix?  If so, set flag and eat 2 tokens */\r
783 \r
784         if ((rgToken[op][0]==REGIST) && (is_rSEG(rgTID[op][0]))) {\r
785                 if (rgToken[op][1] == COLON) {\r
786                         switch (rgToken[op][0]) {\r
787                                 case rDS: OpPrefix |= fDSp; break;\r
788                                 case rES: OpPrefix |= fESp; break;\r
789                                 case rSS: OpPrefix |= fSSp; break;\r
790                                 case rFS: OpPrefix |= fFSp; break;\r
791                                 case rGS: OpPrefix |= fGSp; break;\r
792                                 case rCS: OpPrefix |= fCSp; break;\r
793                                 default:;\r
794                         }\r
795                         i += 2;         /* skip rSEG and colon */\r
796                 }\r
797                 else {\r
798                    line_error(16);\r
799                    return(0);\r
800            }\r
801         }\r
802 \r
803 /* Loop through the raw tokens looking for Base Reg, Index Reg,\r
804    Scale value, or displacement and setting varaibles as needed.\r
805 */\r
806 \r
807         while ((i < rgTCnt[op]) &&\r
808                   (!fError) &&\r
809                   (!fDone)) {\r
810                 switch (rgToken[op][i]) {\r
811 \r
812                 case REGIST:\r
813                         if (is_r32(rgTID[op][i])) {  /* check for Indx & Base Reg */\r
814                 if (rgToken[op][i+1] == STAR) {                 /* Index w/Scale */\r
815                                         if (!(OpMType & fIndx))  {      /* still OK */\r
816                         OpMType |= fIndx;\r
817                         OpIndx = rgTID[op][i];\r
818                                                 if (rgToken[op][i+2] == NUMBER) {\r
819                                                         switch (rgVal[op][i+2]) {\r
820                                                         case 2: OpMType |= fScale2; break;\r
821                                                         case 4: OpMType |= fScale4; break;\r
822                                                         case 8: OpMType |= fScale8; break;\r
823                                                         default:\r
824                                                                 line_error(17);\r
825                                                                 fError = 1;\r
826                                                         }\r
827                                                 }\r
828                                                 else {\r
829                                                         line_error(18);\r
830                                                         fError = 1;\r
831                                                 }\r
832                                         }\r
833                                         else {\r
834                                                 line_error(19);\r
835                                                 fError = 1;\r
836                                         }\r
837                                         i+=3;   /* get past *NUMBER */\r
838                 }\r
839                 /* Must be base, unless fBase true, then try Index */\r
840                 else {\r
841                                         if (!(OpMType & fBase)) { /* Base for sure */\r
842                         OpMType |= fBase;\r
843                         OpBase = rgTID[op][i];\r
844                         i++;\r
845                                         }\r
846                                         else {  /* try Index */\r
847                                                 if (!(OpMType & fIndx)) { /* It's free, use it */\r
848                                 OpMType |= fIndx;\r
849                             OpIndx = rgTID[op][i];\r
850                                 i++;\r
851                                                 }\r
852                                         }\r
853                                 }\r
854                         }\r
855                         else { /* must be 32 bit general purpose register */\r
856                                 line_error(20);\r
857                                 fError = 1;\r
858                         }\r
859                         break;\r
860 \r
861 \r
862                 case SYMOFF:  /* One symbol was used by itself or in an expression */\r
863                         if (ExpType == 1)                               /* Local */\r
864                                 symtype = lst[iExpSym].Type;\r
865                         else if (ExpType == 2) {                /* global */\r
866                                 if (gst[iExpSym].Type & tEXTRN)\r
867                                         nExtRef = iExpSym;\r
868                                 symtype = gst[iExpSym].Type;\r
869                         }\r
870                         else                                                    /* Unknown - Forward */\r
871                                 symtype = 0;\r
872 \r
873                         if (OpMType & (fDisp32|fDisp8)) {   /* Already a disp! */\r
874                                 line_error(21);\r
875                                 fError = 1;\r
876                                 }\r
877 \r
878                         /* Check for conditional jumps. */\r
879 \r
880                         else if ((CrntInst >= xJA) &&\r
881                                      (CrntInst <= xJZ) &&\r
882                                      (CrntInst != xJMP) &&\r
883                                      (!(fOpenSQ)))\r
884                         {\r
885                                         if (OpSize[op] & fShort)\r
886                                                 rgOpType[op] = rel8;\r
887                                         else rgOpType[op] = relW;\r
888                                         if (fOpImm) {\r
889                                         OpImm2 = rgVal[op][i];\r
890                                         fOpImm2 = 1;\r
891                                 }\r
892                                         else {\r
893                                         OpImm = rgVal[op][i];\r
894                                         fOpImm = 1;\r
895                                         }\r
896                                         if (!symtype)\r
897                                                 fForRef = 1;\r
898                         }\r
899 \r
900                                 /* Check for JMP */\r
901 \r
902                         else if (CrntInst == xJMP)  /* &&  (!(fOpenSQ))) */\r
903                         {\r
904                                 if ((OpSize[op] & fFar) || (symtype & tFAR)) {\r
905                                         rgOpType[op] = iSAD;\r
906                                         if (fOpImm) {\r
907                                         OpImm2 = rgVal[op][i];\r
908                                         fOpImm2 = 1;\r
909                                 }\r
910                                         else {\r
911                                         OpImm = rgVal[op][i];\r
912                                         fOpImm = 1;\r
913                                         }\r
914                                 }\r
915                                 else if (OpSize[op] & fShort) {\r
916                                         rgOpType[op] = rel8;\r
917                                 OpImm = rgVal[op][i];\r
918                                 fOpImm = 1;\r
919                                         if (!symtype)\r
920                                                 fForRef = 1;\r
921                                 }\r
922                                 else if (OpSize[op] & fFWord) {\r
923                                         rgOpType[op]  = memF;  /* memF = 32 disp which has 16:32 */\r
924                             OpMType |= fDisp32;\r
925                             OpDisp = rgVal[op][i];\r
926                                         if (symtype & CLABEL)\r
927                                                 nFixUp = CCFIXTAG;\r
928                                         else if (symtype & DLABEL)\r
929                                                 nFixUp = CDFIXTAG;\r
930                                         if (!symtype)\r
931                                                 fForRef = 1;\r
932                                 }\r
933                                 else {\r
934                                         rgOpType[op] = relW;\r
935                                     OpImm = rgVal[op][i];\r
936                                     fOpImm = 1;\r
937                                         if (!symtype)\r
938                                                 fForRef = 1;\r
939                                 }\r
940                         }\r
941 \r
942                                 /* Check for CALL */\r
943 \r
944                         else if ((CrntInst == xCALL) && (!(fOpenSQ)))\r
945                         {\r
946                                 if ((OpSize[op] & fFar) || (symtype & tFAR)) {\r
947                                         rgOpType[op] = iSAD;\r
948                                         if (fOpImm) {\r
949                                         OpImm2 = rgVal[op][i];\r
950                                         fOpImm2 = 1;\r
951                                     }\r
952                                         else {\r
953                                         OpImm = rgVal[op][i];\r
954                                         fOpImm = 1;\r
955                                         }\r
956                                 }\r
957                                 else if (OpSize[op] & fFWord) {\r
958                                         rgOpType[op]  = memF;  /* memF = 32 disp which has 16:32 */\r
959                             OpMType |= fDisp32;\r
960                             OpDisp = rgVal[op][i];\r
961                                         if (symtype & CLABEL)\r
962                                                 nFixUp = CCFIXTAG;\r
963                                         else if (symtype & DLABEL)\r
964                                                 nFixUp = CDFIXTAG;\r
965                                         if (!symtype)\r
966                                                 fForRef = 1;\r
967                                 }\r
968                                 else {          /* Relative call */\r
969                                         rgOpType[op] = relW;\r
970                                         if (!symtype)\r
971                                                 fForRef = 1;\r
972                                 }\r
973                         }\r
974 \r
975                                 /* Check for SGDT SIDT */\r
976 \r
977                         else if ((CrntInst == xSGDT) || (CrntInst == xSIDT))\r
978                         {\r
979                                 if (OpSize[op] & fFWord) {\r
980                                         rgOpType[op]  = memF;  /* memF = 32 disp which has 16:32 */\r
981                             OpMType |= fDisp32;\r
982                             OpDisp = rgVal[op][i];\r
983                                         if (symtype & CLABEL)\r
984                                                 nFixUp = CCFIXTAG;\r
985                                         else if (symtype & DLABEL)\r
986                                                 nFixUp = CDFIXTAG;\r
987                                         if (!symtype)\r
988                                                 fForRef = 1;\r
989                                 }\r
990                         }\r
991 \r
992                           /* Check for Loop */\r
993 \r
994                         else if ((CrntInst >= xLOOP) && (CrntInst <= xLOOPZ))\r
995                         {\r
996                                         rgOpType[op] = rel8;\r
997                                     OpImm = rgVal[op][0];\r
998                                     fOpImm = 1;\r
999                                         if (!symtype)\r
1000                                                 fForRef = 1;\r
1001                         }\r
1002                         else {\r
1003                                     OpDisp = rgVal[op][i];\r
1004                                         OpMType |= fDisp32;\r
1005                                         if (symtype & CLABEL)\r
1006                                                 nFixUp = CCFIXTAG;\r
1007                                         else if (symtype & DLABEL)\r
1008                                                 nFixUp = CDFIXTAG;\r
1009                                         if (!symtype)\r
1010                                                 fForRef = 1;\r
1011                         }\r
1012                         i++;\r
1013                         break;\r
1014 \r
1015                 case NUMBER:  /* can be 8 or 32 bit disp, or hard address */\r
1016                 OpDisp = rgVal[op][i];\r
1017                         if ((rgVal[op][i] >= -128) && (rgVal[op][i] <= 127))\r
1018                                 OpMType |= fDisp8;\r
1019                         else\r
1020                                 OpMType |= fDisp32;\r
1021                         i++;\r
1022                         break;\r
1023 \r
1024                 case OPENSQR:\r
1025                         if (fOpenSQ) {\r
1026                                 line_error(23);\r
1027                                 fError = 1;\r
1028                                 }\r
1029                         else fOpenSQ = 1;\r
1030                         i++;\r
1031                         break;\r
1032                 case CLOSSQR:\r
1033                         if (!fOpenSQ) {\r
1034                                 line_error(24);\r
1035                                 fError = 1;\r
1036                                 }\r
1037                         else fOpenSQ = 0;\r
1038                         i++;\r
1039                         break;\r
1040                 case COLON:             /*  for far addresses */\r
1041                         i++;\r
1042                         break;\r
1043                 case PLUS:\r
1044                         i++;\r
1045                         break;\r
1046             case rBYTE:\r
1047                 if ((!OpSize[op]) && (rgToken[op][i+1] == rPTR)) {\r
1048                                 OpSize[op] |= fByte;\r
1049                                 i+=2;\r
1050                                 }\r
1051                         else {\r
1052                                 line_error(25);\r
1053                                 fError = 1;\r
1054                                 }\r
1055                         break;\r
1056             case rWORD:\r
1057                 if ((!OpSize[op]) && (rgToken[op][i+1] == rPTR)) {\r
1058                                 OpSize[op] |= fWord;\r
1059                                 i+=2;\r
1060                                 }\r
1061                         else {\r
1062                                 line_error(25);\r
1063                                 fError = 1;\r
1064                                 }\r
1065                         break;\r
1066             case rDWORD:\r
1067                 if ((!OpSize[op]) && (rgToken[op][i+1] == rPTR)) {\r
1068                                 OpSize[op] |= fDWord;\r
1069                                 i+=2;\r
1070                                 }\r
1071                         else {\r
1072                                 line_error(25);\r
1073                                 fError = 1;\r
1074                                 }\r
1075                         break;\r
1076             case rFWORD:\r
1077                 if ((!OpSize[op]) && (rgToken[op][i+1] == rPTR)) {\r
1078                                 OpSize[op] |= fFWord;\r
1079                                 i+=2;\r
1080                                 }\r
1081                         else {\r
1082                                 line_error(25);\r
1083                                 fError = 1;\r
1084                                 }\r
1085                         break;\r
1086                 case rNEAR:\r
1087                 if ((!OpSize[op]) && (rgToken[op][i+1] == rPTR)) {\r
1088                                 OpSize[op] |= fNear;\r
1089                                 i+=2;\r
1090                                 }\r
1091                         else {\r
1092                                 line_error(25);\r
1093                                 fError = 1;\r
1094                                 }\r
1095                         break;\r
1096                 case rFAR:\r
1097                 if ((!OpSize[op]) && (rgToken[op][i+1] == rPTR)) {\r
1098                                 OpSize[op] |= fFar;\r
1099                                 i+=2;\r
1100                                 }\r
1101                         else {\r
1102                                 line_error(25);\r
1103                                 fError = 1;\r
1104                                 }\r
1105                         break;\r
1106                 case rSHORT:\r
1107                 if (!OpSize[op]) {\r
1108                                 OpSize[op] |= fShort;\r
1109                                 i++;\r
1110                                 }\r
1111                         else {\r
1112                                 line_error(25);\r
1113                                 fError = 1;\r
1114                                 }\r
1115                         break;\r
1116                 default: {\r
1117                         line_error(32);\r
1118                         fprintf(lst_fh, "  %d  ", rgToken[op][i]);  /* TESTING */\r
1119                         i++;\r
1120                         }\r
1121 \r
1122                 } /* switch */\r
1123         } /* while */\r
1124 }\r
1125 if (fError) return(0);\r
1126 if ((fDone) && (i< rgTCnt[op])) {\r
1127         line_error(33);\r
1128         return(0);\r
1129         }\r
1130 \r
1131 return(1);\r
1132 \r
1133 }\r
1134 \r
1135 /********************************************\r
1136   Adds ALL forward reference to the Ref table.\r
1137   This holds references to all foward addresses\r
1138   (unknown) in the current module.\r
1139   This stores all Refs UPPER case.\r
1140 *********************************************/\r
1141 void ForRef(U8 type, S32 Offset)\r
1142 {\r
1143 S32 i;\r
1144 \r
1145 if (pRefNext >= (pRefBuf + FREFBUFMAX))\r
1146         fatal_error("Forward Reference buffer overflow...");\r
1147 if (iRefNext >= FREFSMAX)\r
1148         fatal_error("Forward Reference table overflow...");\r
1149 \r
1150 /* Make a forward reference table entry */\r
1151 \r
1152 strncpy(pRefNext, UString, UCBString);\r
1153 pfrt[iRefNext].NameSz = UCBString;      /* size of name */\r
1154 pfrt[iRefNext].Ptr = pRefNext;\r
1155 pfrt[iRefNext].Line = lineno[level];    /* for error reporting */\r
1156 pfrt[iRefNext].Type = type;                     /* type of ref */\r
1157 \r
1158 \r
1159 pfrt[iRefNext].Offs = Offset;           /* Offset to correction in CS or DS */\r
1160 \r
1161 /* update for next symbol */\r
1162 \r
1163 pRefNext += UCBString;\r
1164 iRefNext++;\r
1165 \r
1166 }\r
1167 \r
1168 /********************************************\r
1169   Adds fixup table entries to be placed in\r
1170   the run file.  This includes DLL entries.\r
1171 *********************************************/\r
1172 \r
1173 void FixUp(U8 typef, S32 Offset, S32 iSymbol)\r
1174 {\r
1175 \r
1176 if (typef == CDFIXTAG)\r
1177         nCDFix++;\r
1178 else if (typef == DDFIXTAG)\r
1179         nDDFix++;\r
1180 else if (typef == DCFIXTAG)\r
1181         nDCFix++;\r
1182 else if (typef == CCFIXTAG)\r
1183         nCCFix++;\r
1184 \r
1185 \r
1186 if (iFUNext >= FIXUPSMAX)\r
1187         fatal_error("Fixup Table overflow...");\r
1188 pfut[iFUNext].type = typef;\r
1189 pfut[iFUNext].Offs = Offset;\r
1190 pfut[iFUNext].iSym = iSymbol;  /* global symbol entry for DLL */\r
1191 \r
1192 iFUNext++;\r
1193 \r
1194 }\r
1195 \r
1196 /********************************************\r
1197   Adds External Reference to table.\r
1198   This DOES NOT includes DLL Refs.\r
1199   ETypes are the same as ForRef types\r
1200   except there and no 8 bit externals.\r
1201 *********************************************/\r
1202 \r
1203 void ExtRef(U8 EType, S32 iSymbol)\r
1204 {\r
1205 \r
1206 if (iERefNext >= EREFSMAX)\r
1207         fatal_error("External Reference Table overflow...");\r
1208 \r
1209 if (fDataSeg)\r
1210         ert[iERefNext].Offs = oNextData;\r
1211 else {\r
1212         ert[iERefNext].Offs = oNextCode;\r
1213         }\r
1214 ert[iERefNext].iSym = iSymbol;  /* global symbol entry for external */\r
1215 ert[iERefNext].Type = EType;  /* global symbol entry for external */\r
1216 \r
1217 iERefNext++;\r
1218 }\r
1219 \r
1220 /*****************************************************\r
1221    Reads in all of the reserved words, numbers, math\r
1222    operators, etc. that make up one operand.  They are\r
1223    read into one of 3 2D arrays as indicated by "op".\r
1224    Integer rgTCnt[op] is number if items.  A special\r
1225    case for jump and call instructions is tested if\r
1226    we end up with an Unknown Symbol as and operand.\r
1227    We Error out if we have an UNKSYM without a\r
1228    jump or call.\r
1229 *****************************************************/\r
1230 \r
1231 S32 GetOper(S32 op)\r
1232 {\r
1233 S32 i, T;\r
1234 \r
1235 i = 0;\r
1236 while (1) {\r
1237         T = Parse();\r
1238         switch (T) {\r
1239           case ZERO:\r
1240                     rgTCnt[op] = i;\r
1241                         if (i) return(1);\r
1242                         else return(0);\r
1243           case REGIST:\r
1244                 rgTID[op][i] = TReg;\r
1245                 rgToken[op][i] = T;\r
1246                 break;\r
1247           case NUMBER:  /* check for special case of REG*2,*4,*8  */\r
1248                 if ((i > 1) &&\r
1249                         (rgToken[op][i-1] == STAR) &&\r
1250                         (rgToken[op][i-2] == REGIST)) {\r
1251                                 rgVal[op][i] = TNumber;\r
1252                                 rgToken[op][i] = T;\r
1253                                 break;  /* only break here if we find special case */\r
1254                         }                       /* Else fall thru to Expression */\r
1255           case LSYMBOL:\r
1256           case SYMBOL:\r
1257           case DOLLAR:          /* These should all evaluate to a number!! */\r
1258           case OPENRND:\r
1259           case MINUS:\r
1260           case UNKSYM:\r
1261           case rOFFSET:\r
1262                 if (Expression()) {\r
1263                         rgVal[op][i] = TNumber;\r
1264                         rgToken[op][i] = Token;         /* Token instead of T (From Expr)*/\r
1265                         }\r
1266                 else {\r
1267                         line_error(35);\r
1268                         return(0);\r
1269                         }\r
1270 \r
1271                 break;\r
1272           case COMMA:\r
1273                         if (!i) {\r
1274                                 line_error(36);\r
1275                                 return(0);\r
1276                         }\r
1277                     rgTCnt[op] = i;\r
1278                         ReturnToken();\r
1279                         return(1);\r
1280           case OPENSQR:\r
1281           case CLOSSQR:\r
1282           case STAR:\r
1283           case PLUS:\r
1284           case SLASH:\r
1285           case SEMI:\r
1286           case COLON:\r
1287           case rFAR:\r
1288           case rBYTE:\r
1289           case rWORD:\r
1290           case rDWORD:\r
1291           case rFWORD:\r
1292           case rPTR:\r
1293           case rSHORT:\r
1294                         rgToken[op][i] = T;\r
1295                         break;\r
1296           default:\r
1297                         line_error(38);\r
1298                         return(0);\r
1299         }\r
1300  i++;\r
1301 } /* while */\r
1302 }\r
1303 \r
1304 /********************************************\r
1305  This finds the first matching entry in rgINS\r
1306  by first matching the instruction number,\r
1307  then matching operands.  The table is indexed\r
1308  with an array providing the first entry for\r
1309  the instruction. This speed things up a bit.\r
1310 *********************************************/\r
1311 \r
1312 S32 INSEntry(S32 InsNum, S32 nOpers)\r
1313 {\r
1314 S32 i;\r
1315 \r
1316         i = rgInsLookUp[InsNum];\r
1317         while (i <= nrgINS) {\r
1318 \r
1319                 /* instruction entries of the same type\r
1320                 are all kept together. This is an early out.\r
1321                 */\r
1322 \r
1323                 if (rgINS[i][0] != InsNum)\r
1324                   return(0);    /* couldn't find a match at all... */\r
1325 \r
1326                 /* See if all the operators match by calling is_Comp for each.\r
1327                 */\r
1328 \r
1329                 if ((is_Comp(i,0)) &&\r
1330                     (is_Comp(i,1)) &&\r
1331                     (is_Comp(i,2)))\r
1332 \r
1333                         return(i);              /* yes, they all match! */\r
1334 \r
1335                 i++;    /* No, goto next entry */\r
1336         }\r
1337 }\r
1338 \r
1339 \r
1340 /********************************************\r
1341   EmitInst spits out the instruction bytes that\r
1342   were encoded into variables by EncodeInst.\r
1343   This handles output to the code segment\r
1344   file as well as the text to the list file.\r
1345   It updates the code segment address and\r
1346   also adds fixup records as they are needed.\r
1347 \r
1348 The instruction  (up to 16 bytes) is ordered\r
1349 as follows:\r
1350   Instruction Prefix   0 or 1 byte\r
1351   Address Size Prefix  0 or 1 byte\r
1352   Operand Prefix       0 or 1 byte\r
1353   Segment Override     0 or 1 bytes\r
1354   Opcode               1 or 2 bytes\r
1355   MODR/M               0 or 1 bytes\r
1356   SIB                  0 or 1 bytes\r
1357   Displacement         0,1,2 or 4 bytes\r
1358   Immediate            0,1,2, or 4 bytes\r
1359 **********************************************/\r
1360 \r
1361 void EmitInst(void)\r
1362 {\r
1363 U8   oppfx;\r
1364 S8   sbyte;\r
1365 S32  sword;\r
1366 U32  i;         /* used local to each section if needed */\r
1367 \r
1368 \r
1369 \r
1370         /*\r
1371     Instruction prefix: 0 or 1 byte (Lock, Rep, etc.)\r
1372         */\r
1373 \r
1374         if (InstPfx) {\r
1375                 if (InstPfx==xLOCK) {\r
1376                         if (fListA) {\r
1377                                 Column += 2;\r
1378                                 put_hexb(0x0F, lst_fh);\r
1379                                 }\r
1380                         OutByteX(0xF0);\r
1381                         }\r
1382                 else if ((InstPfx==xREPNE) || (InstPfx==xREPNZ)) {\r
1383                         if (fListA) {\r
1384                                 Column += 2;\r
1385                                 put_hexb(0xF2, lst_fh);\r
1386                                 }\r
1387                         OutByteX(0xf2);\r
1388                         }\r
1389                 else {  /* Must be REP... */\r
1390                         if (fListA) {\r
1391                                 Column += 2;\r
1392                                 put_hexb(0xF3, lst_fh);\r
1393                                 }\r
1394                         OutByteX(0xf3);\r
1395                         }\r
1396                 if (fListA)\r
1397                         Column += fprintf(lst_fh, "| ");\r
1398         }\r
1399 \r
1400 /*\r
1401    Skip Address Size prefix: (67h)  cause we aren't\r
1402    doing USE16, nor do we support 16 bit addressing modes!\r
1403 */\r
1404 \r
1405 /* Operand Size prefix: 0 or 1 (66h)  */\r
1406 \r
1407         if (OpSizeA & fWord) {\r
1408                 if (fListA) {\r
1409                         Column += 2;\r
1410                         put_hexb(0x66, lst_fh);\r
1411                         Column += fprintf(lst_fh, "| ");\r
1412                         }\r
1413                 OutByteX(0x66);\r
1414                 }\r
1415 \r
1416 /* Segment Override prefix */\r
1417 \r
1418         switch (OpPrefix) {\r
1419                 case fDSp: oppfx = 0x3e; break;\r
1420                 case fESp: oppfx = 0x26; break;\r
1421                 case fSSp: oppfx = 0x36; break;\r
1422                 case fFSp: oppfx = 0x64; break;\r
1423                 case fGSp: oppfx = 0x65; break;\r
1424                 case fCSp: oppfx = 0x2e; break;\r
1425                 default: oppfx = 0;\r
1426         }\r
1427         if (oppfx) {\r
1428                 if (fListA) {\r
1429                         Column += 2;\r
1430                         put_hexb(oppfx, lst_fh);\r
1431                         Column += fprintf(lst_fh, "| ");\r
1432                         }\r
1433                         OutByteX(oppfx);\r
1434                 }\r
1435 \r
1436 /*   OpCode byte 1 (optional)\r
1437      bOpc1 was setup in EncodeInst (either 0 or 0Fh)\r
1438 */\r
1439 \r
1440         if (bOpc1) {\r
1441                 if (fListA) {\r
1442                         Column += 2;\r
1443                         put_hexb(bOpc1, lst_fh);\r
1444                         Column += fprintf(lst_fh, " ");\r
1445                         }\r
1446                         OutByteX(bOpc1);\r
1447                 }\r
1448 \r
1449 /*   OpCode byte 2 (always sent) */\r
1450 \r
1451         if (fListA) {\r
1452                         Column += 2;\r
1453                         put_hexb(bOpc2, lst_fh);\r
1454                         Column += fprintf(lst_fh, " ");\r
1455                 }\r
1456 \r
1457         OutByteX(bOpc2);\r
1458 \r
1459 /*  ModR/M  (optional)  */\r
1460 \r
1461         if (fModRM) {\r
1462                 if (fListA) {\r
1463                         Column += 2;\r
1464                         put_hexb(bModRM, lst_fh);\r
1465                         Column += fprintf(lst_fh, " ");\r
1466                 }\r
1467                 OutByteX(bModRM);\r
1468         }\r
1469 \r
1470 /*  SIB  (optional) */\r
1471 \r
1472         if (fSIB) {\r
1473                 if (fListA) {\r
1474                         Column += 2;\r
1475                         put_hexb(bSIB, lst_fh);\r
1476                         Column += fprintf(lst_fh, " ");\r
1477                 }\r
1478                 OutByteX(bSIB);\r
1479         }\r
1480 \r
1481 /*\r
1482    Disp: 0, 1, 2 or 4\r
1483    A Displacement is a memory reference (an offset in a segment)\r
1484    that is encoded as part of the instruction. The value to encode\r
1485    is placed in OpDisp when the instruction is parsed and\r
1486    evaluated.\r
1487 */\r
1488 \r
1489         if (OpMType & fDisp32) {\r
1490 \r
1491                 if (fListA) {\r
1492                         Column += 8;\r
1493                         put_hexd(OpDisp, lst_fh);\r
1494                         if ((nExtRef) || (fForRef))\r
1495                                 Column += fprintf(lst_fh, "r ");\r
1496                         else\r
1497                                 Column += fprintf(lst_fh, "  ");\r
1498                 }\r
1499                 if (nExtRef)\r
1500                         ExtRef(CSEGREF, nExtRef);\r
1501                 else if (fForRef)\r
1502                         ForRef(CSEGREF, oNextCode);\r
1503                 else if (nFixUp)\r
1504                         FixUp(nFixUp, oNextCode, 0); /* Code ref to data */\r
1505                 OutDWordX(OpDisp);\r
1506         }\r
1507 \r
1508         if (OpMType & fDisp8) {\r
1509 \r
1510                 if (fListA) {\r
1511                         sbyte = OpDisp;\r
1512                         Column += 2;\r
1513                         put_hexb(sbyte, lst_fh);\r
1514                         Column += fprintf(lst_fh, "  ");\r
1515                 }\r
1516                 OutByteX(OpDisp);\r
1517         }\r
1518 \r
1519 /*\r
1520    Immediate: 0, 1, 2 or 4\r
1521    The type of instruction operands tell us if we must encode\r
1522    immediate values as part of the instruction.  All instructions\r
1523    have only one immediate value except ENTER. We make a check here\r
1524    to determine if it is this instruction.\r
1525 \r
1526      imm8  = Immediate Byte in OpImm\r
1527      imm16 = immediate 16 bit value in OpImm\r
1528      immX  = immediate value matching OpSize in OpImm\r
1529      rel8  = immediate Byte calculated from a label\r
1530      relW  = immediate Word (16 or 32) calculated from a label\r
1531      iSAD  = immediate DWORD:WORD from Far Pointer (OpImm & OpImm2)\r
1532 \r
1533      immv1 is not encoded (implied by instruction)\r
1534      immv3 is not encoded (also implied - INT 03 - Debug)\r
1535    */\r
1536         if (fOpImm) \r
1537         {\r
1538                 if ((rgINS[iInstEntry][1] == immX) ||\r
1539                     (rgINS[iInstEntry][2] == immX) ||\r
1540             (rgINS[iInstEntry][3] == immX))\r
1541         {\r
1542                         if (OpSizeA & fByte)\r
1543                         {\r
1544                                 if (fListA)\r
1545                                 {\r
1546                                         sbyte = OpImm;\r
1547                                         Column += 2;\r
1548                                         put_hexb(sbyte, lst_fh);\r
1549                                         Column += fprintf(lst_fh, "  ");\r
1550                                 }\r
1551                                 OutByteX(OpImm);\r
1552                         }\r
1553                         else if (OpSizeA & fWord)\r
1554                         {\r
1555                                 if (fListA) \r
1556                                 {\r
1557                                         sword = OpImm;\r
1558                                         Column += 4;\r
1559                                         put_hexw(sword, lst_fh);\r
1560                                         Column += fprintf(lst_fh, "  ");\r
1561                                 }\r
1562                                 OutWordX(OpImm);\r
1563                         }\r
1564                         else {                                  /* MUST be a DWord */\r
1565                                 if (fListA) {\r
1566                                         Column += 8;\r
1567                                         put_hexd(OpImm, lst_fh);\r
1568                                         if (nFixUp)\r
1569                                                 Column += fprintf(lst_fh, "r ");\r
1570                                         else\r
1571                                                 Column += fprintf(lst_fh, "  ");\r
1572                                 }\r
1573                                 if (nExtRef)\r
1574                                         ExtRef(CSEGREF, nExtRef);\r
1575                                 else if (fForRef)\r
1576                                         ForRef(CSEGREF, oNextCode);\r
1577                                 else if (nFixUp)\r
1578                                         FixUp(nFixUp, oNextCode, 0); /* Code ref to data */\r
1579                                 OutDWordX(OpImm);\r
1580                         }\r
1581                 }\r
1582 \r
1583                 if ((rgINS[iInstEntry][1] == imm16) ||\r
1584                     (rgINS[iInstEntry][2] == imm16) ||\r
1585             (rgINS[iInstEntry][3] == imm16))   {\r
1586                         if (fListA) {\r
1587                                 Column += 4;\r
1588                                 sword = OpImm;\r
1589                                 put_hexw(sword, lst_fh);\r
1590                                 Column += fprintf(lst_fh, "  ");\r
1591                                 }\r
1592                         OutWordX(OpImm);\r
1593                 }\r
1594                 else if ((rgINS[iInstEntry][1] == imm8) ||\r
1595                          (rgINS[iInstEntry][2] == imm8) ||\r
1596                          (rgINS[iInstEntry][3] == imm8) ||\r
1597                          (rgINS[iInstEntry][1] == ims8) ||\r
1598                          (rgINS[iInstEntry][2] == ims8) ||\r
1599                  (rgINS[iInstEntry][3] == ims8))\r
1600         {\r
1601                         if (fListA) {\r
1602                                 Column += 2;\r
1603                                 sbyte = OpImm;\r
1604                                 put_hexb(sbyte, lst_fh);\r
1605                                 Column += fprintf(lst_fh, "  ");\r
1606                                 }\r
1607                         OutByteX(OpImm);\r
1608                 }\r
1609 \r
1610                 /* Special check for Enter. It is only instructon with 2 Imms!*/\r
1611 \r
1612                 if (rgINS[iInstEntry][0] == xENTER)\r
1613         {\r
1614                         if (fListA) {\r
1615                                 Column += 2;\r
1616                                 sbyte = OpImm2;\r
1617                                 put_hexb(sbyte, lst_fh);\r
1618                                 Column += fprintf(lst_fh, "  ");\r
1619                                 }\r
1620                         OutByteX(OpImm2);\r
1621                 }\r
1622 \r
1623 \r
1624                 /* With relative values for immediates, OpImm comes in as\r
1625                   the address of the target jump or call. We must take\r
1626                    the current code offset (of the next instruction) and\r
1627                    subtract it from the target (OpImm) to get the relative\r
1628                    jump value. If it is an UNKSYM we will put the value\r
1629                    of the target into the FRT to hold it and\r
1630                    do the math on the second pass of the machine code.\r
1631                    Math Example:\r
1632 \r
1633                         oCode  = 100  (next instruction)\r
1634                         Target =  50\r
1635                         Jump = -50  (Target-Current)\r
1636 \r
1637                         oCode  = 100  (next instruction)\r
1638                         Target = 150\r
1639                         Jump = 50  (Target-Current)\r
1640 \r
1641                         Relative immediate values found in the GST as EXTERN\r
1642                         require an ERT entry so they can be fixed up when\r
1643                         the final code module is written to the run file.\r
1644 \r
1645                         Relative immediate values found in the GST as PUBLICS\r
1646                         can be fixed up NOW.\r
1647 \r
1648                         Relative immediate values NOT found are assumed local\r
1649                         and an entry is made in the FRT so they can be fixed\r
1650                         up when this code module is written to the main\r
1651                         temp code module.\r
1652                    */\r
1653 \r
1654                 if (rgINS[iInstEntry][1] == relW) {\r
1655                         if (nExtRef) {                                          /* list external */\r
1656                                 OpImm = 0;\r
1657                                 ExtRef(CCR32REF, nExtRef);\r
1658                         }\r
1659                         else if (fForRef) {                                     /* list Forward Relative */\r
1660                                 OpImm = 0;\r
1661                                 ForRef(CCR32REF, oNextCode);\r
1662                         }\r
1663                         else {                                                          /* Fix known ref */\r
1664                                 OpImm = OpImm - (oNextCode + 4);\r
1665                         }\r
1666 \r
1667                         if (fListA) {\r
1668                                 Column += 8;\r
1669                                 put_hexd(OpImm, lst_fh);\r
1670                                 if ((!fForRef) && (!nExtRef))\r
1671                                         Column += fprintf(lst_fh, "  ");\r
1672                                 else\r
1673                                         Column += fprintf(lst_fh, "R ");\r
1674                         }\r
1675                         OutDWordX(OpImm);\r
1676                 }\r
1677 \r
1678                 if (rgINS[iInstEntry][1] == rel8) {\r
1679                         if (!fForRef) {                                 /* Fix KNOWN Relative */\r
1680                                 OpImm = OpImm - (oNextCode + 1);\r
1681                                 if ((OpImm > 127) || (OpImm < -127))\r
1682                                         line_error(39);\r
1683                         }\r
1684                         else {                                                  /* Else List Unknown */\r
1685                                 ForRef(CCR8REF, oNextCode);\r
1686                                 OpImm = 0;\r
1687                                 }\r
1688 \r
1689                         if (fListA) {\r
1690                                 Column += 2;\r
1691                                 sbyte = OpImm;\r
1692                                 put_hexb(sbyte, lst_fh);\r
1693                                 if ((!fForRef) && (!nExtRef))\r
1694                                         Column += fprintf(lst_fh, "  ");\r
1695                                 else\r
1696                                         Column += fprintf(lst_fh, "R ");\r
1697                         }\r
1698                         OutByteX(OpImm);\r
1699                 }\r
1700 \r
1701                 if (rgINS[iInstEntry][1] == iSAD) {\r
1702                         if (fListA) {\r
1703                                 Column += 4;\r
1704                                 sword = OpImm;\r
1705                                 put_hexw(sword, lst_fh);\r
1706                                 Column += fprintf(lst_fh, ":");\r
1707                                 Column += 4;\r
1708                                 put_hexd(OpImm2, lst_fh);\r
1709                                 Column += fprintf(lst_fh, "  ");\r
1710                         }\r
1711                         OutWordX(OpImm);\r
1712                         OutDWordX(OpImm2);\r
1713                 }\r
1714         }\r
1715 }\r
1716 \r
1717 \r
1718 /********************************************\r
1719   This encodes the instructions into bytes\r
1720   and calls EmitInst() to put them into the\r
1721   current code segment. The instruction can\r
1722   be as long as 16 bytes if all options are used.\r
1723   The order of the bytes and their possible\r
1724   sizes are as follows:\r
1725    Inst Prefix: 0 or 1 (Lock, Rep, etc.)\r
1726    Address Size prefix: 0 or 1 (67h) - We don't use this\r
1727    Operand Size prefix: 0 or 1 (66h)\r
1728    Segment Override: 0 or 1\r
1729    OpCode: 1 or 2\r
1730    ModR/M: 0 or 1\r
1731    SIB: 0 or 1\r
1732    Disp: 0, 1, 2 or 4\r
1733    Immediate: 0, 1, 2 or 4\r
1734    This routine follows the guidance to build\r
1735    instructions given in the rgINS table\r
1736    (as bit flags). It calls     EmitInst() to\r
1737    emit the code, list-file information and\r
1738    fixups to the FUT.\r
1739    **********************************************/\r
1740 void EncodeInst(void)\r
1741 {\r
1742 S8   fError;\r
1743 S32 i;\r
1744 U8 bTmp;\r
1745 \r
1746 /*\r
1747 U8 bOpc1;               Zero if not used   THESE ARE GLOBAL...\r
1748 U8 bOpc2;               Always used\r
1749 U8 bModRM;\r
1750 U8 bSIB;\r
1751 S8 fModRM;          Is bModRM set/used?\r
1752 S8 fSIB;                Is bSIB set/used?\r
1753 */\r
1754 \r
1755 fModRM = 0;             /* not used by default */\r
1756 fSIB   = 0;\r
1757 \r
1758 \r
1759 /* SKIP the Address Size Prefix for now because we don't do 16 Bit\r
1760    Effective addresses\r
1761 */\r
1762 \r
1763 \r
1764 /*\r
1765    Now we will build the instruction in (up to) 4 temporary bytes.\r
1766    We do it in temporary byte vars so we can see if an Operand Prefix\r
1767    and a possible address fixup record is required before we\r
1768    actually put it into the code segment.\r
1769 */\r
1770 \r
1771 /*\r
1772   The WORD forms of string instructions require us\r
1773   to force a WORD size. We set this in the instruction table\r
1774   as qUW in byte [4],\r
1775 */\r
1776 \r
1777 if (rgINS[iInstEntry][4] & qUW)\r
1778   OpSizeA |= fWord;\r
1779 \r
1780 /* Put in the first byte of Opcode from table (if required). qP0F is\r
1781    set in rgINS[iInstEntry][4] if a 0Fh prefix is required for this inst.\r
1782    A 0 in bObc1 indicates that this byte is NOT to be used.\r
1783 */\r
1784 \r
1785 if (rgINS[iInstEntry][4] & qP0F)\r
1786     bOpc1 = 0x0F;\r
1787 else bOpc1 = 0;\r
1788 \r
1789 /* Get the Opcode from table into bOpc2 */\r
1790 \r
1791 bOpc2 = rgINS[iInstEntry][5];\r
1792 \r
1793 /* The flags zMR1, zMR2, zMOP, zAR1, and zAR2 all indicate that the\r
1794    ModRM is needed. The following set of if-else statements checks these\r
1795    flags and sets REG/OP field of MOD/RM byte if required.\r
1796    OpSize should already be set. We also complete\r
1797    the instruction encoding (with the exception of any immediate values)\r
1798    if the other operand is a register.\r
1799 */\r
1800 \r
1801 if (rgINS[iInstEntry][7] & zMR1) {\r
1802         bModRM = rgINS[iInstEntry][6];\r
1803         fModRM = 1;\r
1804         if (is_Reg(rgOpType[0]))\r
1805             EncodeRegBits(rgOpReg[0], &bModRM, 3);\r
1806         if (is_Reg(rgOpType[1])) {\r
1807             EncodeRegBits(rgOpReg[1], &bModRM, 0);\r
1808             bModRM |= 0xC0;     /* indictes REG in RM field */\r
1809                 }\r
1810         }\r
1811 else if (rgINS[iInstEntry][7] & zMR2) {\r
1812         bModRM = rgINS[iInstEntry][6];\r
1813         fModRM = 1;\r
1814         if (is_Reg(rgOpType[1]))\r
1815             EncodeRegBits(rgOpReg[1], &bModRM, 3);\r
1816         if (is_Reg(rgOpType[0])) {\r
1817             EncodeRegBits(rgOpReg[0], &bModRM, 0);\r
1818             bModRM |= 0xC0;     /* indictes REG in RM field */\r
1819                 }\r
1820         }\r
1821 else if (rgINS[iInstEntry][7] & zMOP) {\r
1822         bModRM = rgINS[iInstEntry][6];\r
1823         fModRM = 1;\r
1824         if (is_Reg(rgOpType[0])) {\r
1825             EncodeRegBits(rgOpReg[0], &bModRM, 0);\r
1826             bModRM |= 0xC0;     /* indictes REG in RM field */\r
1827                 }\r
1828         }\r
1829 else if (rgINS[iInstEntry][7] & zAR1) {\r
1830         bTmp = 0;\r
1831     EncodeRegBits(rgOpReg[0], &bTmp, 0);\r
1832         bOpc2 += bTmp;\r
1833         }\r
1834 else if (rgINS[iInstEntry][7] & zAR2) {\r
1835         bTmp = 0;\r
1836     EncodeRegBits(rgOpReg[1], &bTmp, 0);\r
1837         bOpc2 += bTmp;\r
1838         }\r
1839 else if ((rgINS[iInstEntry][7] & zRG1) && (rgOpType[0] != mem)) {\r
1840         bModRM = rgINS[iInstEntry][6];\r
1841         fModRM = 1;\r
1842     EncodeRegBits(rgOpReg[0], &bModRM, 3);\r
1843     bModRM |= 0xC0;     /* indictes REG in RM field */\r
1844         }\r
1845 \r
1846 \r
1847         /* OpSize may not be required for many instructions, but we know\r
1848            for a fact it MUST be known for memory operands!\r
1849         */\r
1850 \r
1851         if ((rgOpType[0] == mem) ||\r
1852                 (rgOpType[1] == mem) ||\r
1853                 (rgOpType[0] == memF)) {\r
1854                         if  (!(OpSizeA & (fByte|fWord|fDWord|fFWord))) {\r
1855                                 line_error(40);\r
1856                                 return;\r
1857                                 }\r
1858         }\r
1859 \r
1860         /*\r
1861            If zORD, see if we have word or dword register and OR the Opcode\r
1862            (Opc2) with 01 if so.\r
1863         */\r
1864 \r
1865         if (rgINS[iInstEntry][7] & zORD) {\r
1866                 if (OpSizeA & (fWord | fDWord))\r
1867                 bOpc2 |= 0x01;\r
1868                 }\r
1869 \r
1870         /* Perform the following additonal steps if we have a memory reference\r
1871            as determined by iMemEntry.\r
1872         */\r
1873 \r
1874         fSIB = 0;\r
1875         if (iMemEntry) {\r
1876 \r
1877         /* If SIB is needed (as determined from OpMType), get it and also\r
1878          OR ModRM by required value from rgM32 table\r
1879         */\r
1880 \r
1881                 bModRM |= rgM32[iMemEntry][2];  /* Use ModRM 'OR' value from table */\r
1882                 if (rgM32[iMemEntry][1]) {              /* is there an SIB byte? */\r
1883                         bModRM &= 0x38;                                 /* 00111000 leaves Reg bit on */\r
1884                         bModRM |= rgM32[iMemEntry][2];  /* 'OR' ModRM with table value */\r
1885                         bSIB = rgM32[iMemEntry][3];\r
1886                         fSIB = 1;\r
1887                 }\r
1888 \r
1889 \r
1890                 /* At this point we have our Opcode, ModRM, and SIB (if required).\r
1891                    The MOD and SS bit are already filled in from the table.\r
1892                    This means we just stick the register values or bits for Disp etc\r
1893                    in the correct positions to complete it.\r
1894                    If we didn't have an SIB, we either have a single displacement,\r
1895                    a base or both.\r
1896                 */\r
1897 \r
1898                 if (!fSIB) {            /* only a base, disp, or both */\r
1899                         if (OpMType & fBase)\r
1900                             EncodeRegBits(OpBase, &bModRM, 0);\r
1901                         else\r
1902                             bModRM |= 0x05;             /* only a disp32 */\r
1903                         }\r
1904                 else {\r
1905                         if (OpMType & fBase)\r
1906                             EncodeRegBits(OpBase, &bSIB, 0);\r
1907                         else bModRM |= 0x20;                            /* else set [--][--] bits */\r
1908                         if (OpMType & fIndx)\r
1909                             EncodeRegBits(OpIndx, &bSIB, 3);\r
1910                         }\r
1911         }\r
1912 \r
1913         EmitInst();\r
1914 \r
1915 }\r
1916 \r
1917 \r
1918 /********************************************\r
1919   When the dispatcher detects an Instruction\r
1920   it calls this code to read in (via parse)\r
1921   the parametrs for the instruction and to\r
1922   put together the opcodes.  First we loop thru\r
1923   and get up to 3 operands, then we evaluate\r
1924   them (classify by type). Next we look up\r
1925   the instruction and find a match for the\r
1926   operand types they have specified, and\r
1927   finally, we encode the instruction into the\r
1928   code segment updating the code segment offset\r
1929   pointer.\r
1930 *********************************************/\r
1931 void Instruction(void)\r
1932 {\r
1933 S32 i;\r
1934 S8   fError;\r
1935 S8   OpSizeTmp;\r
1936 \r
1937 fError = 0;\r
1938 if (fDataSeg) {\r
1939         line_error(41);\r
1940         return;\r
1941         }\r
1942 \r
1943 /* If the instruction is a prefix instruction, save it\r
1944    and Parse again to get the real instruction */\r
1945 \r
1946 if ((TInst==xREP) || (TInst==xREPE) || (TInst==xREPZ) ||\r
1947     (TInst==xREPNE) || (TInst==xREPNZ) || (TInst==xLOCK)) {\r
1948     InstPfx = TInst;\r
1949         i = Parse();\r
1950         if (i != INSTRU) {\r
1951                 line_error(42);\r
1952                 return;\r
1953         }\r
1954 } else InstPfx = 0;\r
1955 \r
1956 /* RESET all global instruction variables */\r
1957 \r
1958 CrntInst = TInst;       /* Save the instruction */\r
1959 nOperands = 0;          /* none yet... */\r
1960 rgOpType[0] = 0;\r
1961 rgOpType[1] = 0;\r
1962 rgOpType[2] = 0;\r
1963 OpMType = 0;        /* char - memory type (a byte to compare to rgM32) */\r
1964 OpSize[0] = 0;          /* char - Mem op size (fByte, fWord, fDword, fFword) */\r
1965 OpSize[1] = 0;          /* char - Mem op size (fByte, fWord, fDword, fFword) */\r
1966 OpSizeA = 0;            /* char - Mem op size (fByte, fWord, fDword, fFword) */\r
1967 OpSizeTmp = 0;          /* char - Mem op size (fByte, fWord, fDword, fFword) */\r
1968 OpPrefix = 0;           /* For Segment register prefix flags */\r
1969 OpDisp = 0;         /* long - Displacement if fDisp8 or fDisp32 is TRUE */\r
1970 OpBase = 0;         /* int - Base register if fBase is true */\r
1971 OpIndx = 0;         /* int - Index register if fIndx is true */\r
1972 fOpImm = 0;                     /* No Immediate value yet */\r
1973 OpImm = 0;                      /* Default to 0 */\r
1974 fOpImm2 = 0;            /* No second Immediate value yet */\r
1975 OpImm2 = 0;                     /* Default to 0 */\r
1976 nFixUp = 0;                     /* Fixup type if needed, else 0 */\r
1977 nExtRef = 0;            /* GST entry if external ref was made */\r
1978 fForRef = 0;            /* No Forward Ref in crnt inst yet */\r
1979 ExpType = 0;            /* Type of symbol used in instruction */\r
1980 ExpType0 = 0;           /* Type of symbol used in instruction */\r
1981 iExpSym = 0;            /* Index into symtab for symbol if used */\r
1982 iExpSym0 = 0;           /* Index into symtab for symbol if used */\r
1983 \r
1984 if (GetOper(0)) {\r
1985         nOperands++;\r
1986         ExpType0 = ExpType;\r
1987         iExpSym0 = iExpSym;\r
1988         if ((Parse()== COMMA)) {\r
1989                 if (GetOper(1)) {\r
1990                         nOperands++;\r
1991                         if ((Parse()== COMMA)) {\r
1992                                 if (GetOper(2)) {\r
1993                                         nOperands++;\r
1994                                         if (Parse()) {\r
1995                                                 line_error(33);\r
1996                                                 return;\r
1997                                         }\r
1998                                 }\r
1999                     }\r
2000                 }\r
2001         }\r
2002 }\r
2003 \r
2004 /*\r
2005 At this point we have the instruction operands stored in\r
2006 tokenized form in arrays.  We now call EvalOper() which evaluates\r
2007 the operands and fills in several variables that will assist in\r
2008 building the instruction. EvalOper() returns 1 if it was a valid\r
2009 operand, else 0.\r
2010 */\r
2011 \r
2012 if (nOperands) {                                                                /* at least one */\r
2013         if (EvalOper(0)) {\r
2014                 if (nOperands > 1) {                                    /* a second operand */\r
2015                         if (EvalOper(1)) {\r
2016                                 if (nOperands > 2) {                    /* a third??? - could be... */\r
2017                                         if (!(EvalOper(2)))\r
2018                                                 fError = 1;\r
2019                                 }\r
2020                         }\r
2021                         else fError = 1;\r
2022             }\r
2023         }\r
2024         else fError = 1;\r
2025 }\r
2026 \r
2027 if (fError) return;\r
2028 \r
2029 /*\r
2030    We must check to see what the word size of the instruction is\r
2031    by looking at register sizes if any are included in the instruction.\r
2032    If there are memory references or immediates involved, OpSizeA\r
2033    MUST be set properly else it's an error!      When there is a symbol involved\r
2034    such as a move to a memory variable, we check the variable size and set\r
2035    the OpSize to the variable size. If it's still not set, the line will\r
2036    error out when we try to build the instruction because the caller\r
2037    should have explicitly set the size (e.g., DWORD PTR ...).\r
2038 \r
2039    If a register is one of the operands in a memory transfer\r
2040    (e.g., MOV [mem], EAX) then the move obviously defaults to the size\r
2041    of the register (no ifs, ands, or buts).\r
2042 \r
2043    If there is no reg involved, we then look at 'OpSize[i]'\r
2044    which may have been set by the size operators (e.g., DWORD PTR).\r
2045    If it's zero we look at iExpSym which was set if there was a single\r
2046    symbol involved in the memory reference. If there was, then we use it.\r
2047    If it is blank, we error out cause we don't know what size memory\r
2048    access we are doing!\r
2049    This is done for each operand then the two are compared. If one is\r
2050    zero we use the other, if both have something but are different\r
2051    we error out!\r
2052 \r
2053 */\r
2054         /* Find the first operand size */\r
2055 \r
2056         /* First, let's look to see if they forced it! */\r
2057 \r
2058         if  (OpSize[0] & (fByte|fWord|fDWord|fFWord))\r
2059 \r
2060         { /* do nothing */ }\r
2061 \r
2062         /* If they didn't force it, we'll look for the register size! */\r
2063 \r
2064     else if (rgOpType[0] == r32) OpSize[0] |= fDWord;\r
2065     else if (rgOpType[0] == r16) OpSize[0] |= fWord;\r
2066     else if (rgOpType[0] == rSEG) OpSize[0] |= fWord;\r
2067     else if (rgOpType[0] == r8) OpSize[0] |= fByte;\r
2068 \r
2069                 /* Still nothing, so let's at symbols.  */\r
2070 \r
2071         else if (ExpType0 == 1)\r
2072         {       /* Local symbol */\r
2073                 if (lst[iExpSym0].Type & sBYTE) OpSize[0] |= fByte;\r
2074                 else if (lst[iExpSym0].Type & sWORD) OpSize[0]  |= fWord;\r
2075                 else if (lst[iExpSym0].Type & sDWORD) OpSize[0] |= fDWord;\r
2076                 else if (lst[iExpSym0].Type & sFWORD) OpSize[0] |= fFWord;\r
2077         }\r
2078     else if (ExpType0 == 2)\r
2079         {   /* Global Symbol */\r
2080                 if (gst[iExpSym0].Type & sBYTE) OpSize[0] |= fByte;\r
2081                 else if (gst[iExpSym0].Type & sWORD) OpSize[0] |= fWord;\r
2082                 else if (gst[iExpSym0].Type & sDWORD) OpSize[0] |= fDWord;\r
2083                 else if (gst[iExpSym0].Type & sFWORD) OpSize[0] |= fFWord;\r
2084         }\r
2085         else if (ExpType0 == 3)\r
2086                 OpSize[0] |= fDWord;            /* $ defaults to DWord */\r
2087 \r
2088 \r
2089         /* Find the second operand size. Check "forced fit" first */\r
2090 \r
2091         if  (OpSize[1] & (fByte|fWord|fDWord|fFWord))\r
2092         { /* do nothing */ }\r
2093 \r
2094     else if (rgOpType[1] == r32) OpSize[1] |= fDWord;\r
2095     else if (rgOpType[1] == r16) OpSize[1] |= fWord;\r
2096     else if (rgOpType[1] == rSEG) OpSize[1] |= fWord;\r
2097     else if (rgOpType[1] == r8) OpSize[1] |= fByte;\r
2098 \r
2099                 /* No registers, so let's look to see if they forced it! */\r
2100 \r
2101                 /* Still nothing, so let's at symbols.  */\r
2102 \r
2103         else if (ExpType == 1)\r
2104         {       /* Local symbol */\r
2105                 if (lst[iExpSym].Type & sBYTE) OpSize[1] |= fByte;\r
2106                 else if (lst[iExpSym].Type & sWORD) OpSize[1]  |= fWord;\r
2107                 else if (lst[iExpSym].Type & sDWORD) OpSize[1] |= fDWord;\r
2108                 else if (lst[iExpSym].Type & sFWORD) OpSize[1] |= fFWord;\r
2109         }\r
2110     else if (ExpType == 2)\r
2111         {   /* Global Symbol */\r
2112                 if (gst[iExpSym].Type & sBYTE) OpSize[1] |= fByte;\r
2113                 else if (gst[iExpSym].Type & sWORD) OpSize[1] |= fWord;\r
2114                 else if (gst[iExpSym].Type & sDWORD) OpSize[1] |= fDWord;\r
2115                 else if (gst[iExpSym].Type & sFWORD) OpSize[1] |= fFWord;\r
2116         }\r
2117         else if (ExpType == 3)\r
2118                 OpSize[1] |= fDWord;            /* $ defaults to DWord */\r
2119 \r
2120     /* Special cases for operand size matching. */\r
2121 \r
2122         if (CrntInst == xOUT)\r
2123                 OpSize[0] = OpSize[1];\r
2124 \r
2125 \r
2126 /*\r
2127    Now that have the operands, and we know the TYPE of data (fByte etc.)\r
2128    we call INSEntry to find the matching\r
2129    entry in the array that describes each instruction. If we don't\r
2130    find one that matches we error out telling them they have bad\r
2131    operands.\r
2132 */\r
2133 \r
2134 /* find first matching entry in rgINS */\r
2135 \r
2136     iInstEntry = INSEntry(CrntInst, nOperands);\r
2137 \r
2138     if (!iInstEntry) {\r
2139         line_error(44);\r
2140         return;\r
2141     }\r
2142 \r
2143     /* Now we make sure that we have set all operand sizes\r
2144        and check for special cases as defined in rgINS.\r
2145         */\r
2146 \r
2147         if (rgINS[iInstEntry][7] & zSIZ)\r
2148         OpSize[1] = OpSize[0];\r
2149 \r
2150     if (!OpSize[1])\r
2151         OpSize[1] = OpSize[0];\r
2152 \r
2153     if (!OpSize[0])\r
2154         OpSize[0] = OpSize[1];\r
2155 \r
2156     /* Give them an error if operand sizes don't match */\r
2157 \r
2158     if (nOperands > 1)\r
2159         if (OpSize[0] != OpSize[1]) {\r
2160            line_error(43);\r
2161                return;\r
2162            }\r
2163 \r
2164         OpSizeA = OpSize[0];   /* Set primary operand size */\r
2165 \r
2166 /* If either the first or second operand was memory, we have to find\r
2167    which entry in rgM32 it matches before we can encode it. If none\r
2168    matches it is an invalid memory operand.  If neither is a mem operand\r
2169    we set iMemEntry to zero.  There is the special case of moffs type\r
2170    which is a short form of displacmement when moving data to and from thew\r
2171    accumulator (e.g., MOV EAX, VAR1).  We check for this and skip the\r
2172    mem check if this is the instruction type we are on.\r
2173 */\r
2174 \r
2175         if ((rgINS[iInstEntry][1] == moff) || (rgINS[iInstEntry][2] == moff))\r
2176                 iMemEntry = 0;\r
2177         else if ((rgOpType[0]==mem) ||\r
2178                          (rgOpType[1]==mem) ||\r
2179                          (rgOpType[0]==memF))\r
2180         {\r
2181 \r
2182                 for (i=1; i<nrgM32; i++) {\r
2183                         if (OpMType == rgM32[i][0]) break;\r
2184                 }\r
2185 \r
2186                 /* if i is off the end of the array we\r
2187                    didn't find an entry that matched\r
2188                 */\r
2189 \r
2190                 if (i==nrgM32) {\r
2191                         line_error(45);\r
2192                         return;\r
2193                 }\r
2194                         else iMemEntry = i;\r
2195         }\r
2196         else iMemEntry = 0;\r
2197 \r
2198 /*\r
2199  At this point we should have all information we need to actually\r
2200  encode the instruction (unless it's a forward ref). So we call EncodeInst.\r
2201 */\r
2202 \r
2203 EncodeInst();\r
2204 \r
2205 \r
2206 }\r
2207 \r
2208 \r
2209 /********************************************\r
2210    Create Storage in current segment. At this\r
2211    point we should see a storage statement as\r
2212    the current token followed by a number (or\r
2213    string if DB). If string (DB) we insert\r
2214    single byte values (one per char) into the\r
2215    segment.\r
2216 *********************************************/\r
2217 void Storage(void)\r
2218 {\r
2219 S32 TSave, NSave, nDUP;\r
2220 S32 i, j, sword;\r
2221 S8   fColon, fExpectColon, fComma, fDUP;\r
2222 U32 symtype;\r
2223 \r
2224 fDUP = 0;\r
2225 nDUP = 1;               /* default duplicate value */\r
2226 fComma = 0;\r
2227 fColon = 0;\r
2228 fExpectColon = 0;\r
2229 \r
2230 if (!fMoreStorage) {            /* is it a continuation of previous line? */\r
2231         switch(Token) {                 /* parse returns Token */\r
2232                 case rDB:\r
2233                         StoreSize = 1;\r
2234                 break;\r
2235             case rDW:\r
2236                 StoreSize = 2;\r
2237                 break;\r
2238             case rDD:\r
2239                 StoreSize = 4;\r
2240                 break;\r
2241                 case rDF:\r
2242                 StoreSize = 6;\r
2243                 break;\r
2244                 default:;\r
2245         }\r
2246 }\r
2247 \r
2248 /* Now we loop thru looking for strings and numbers taking into account\r
2249    the special case of DF which should be DWORD:WORD, and OFFSET\r
2250    which will be a DWORD.\r
2251 */\r
2252 \r
2253 while (1) {\r
2254         if (fMoreStorage) {\r
2255                 i = Token;\r
2256                 fMoreStorage = 0;\r
2257         }\r
2258         else i = Parse();\r
2259 \r
2260         switch(i) {\r
2261                 case STRING:\r
2262                         fComma=0;\r
2263                         if (StoreSize==1) {\r
2264                                 for(j=0; j<CBString; j++) {\r
2265                                         if (fListA) {\r
2266                                                 put_hexb(TString[j], lst_fh);\r
2267                                                 Column += 2;\r
2268                                                 Column += fprintf(lst_fh, "  ");\r
2269                                                 if (Column > 51) {\r
2270                                                         fprintf(lst_fh, "\r\n                ");\r
2271                                                         Column=16;\r
2272                                                 }\r
2273                                         }\r
2274                                         OutByteX(TString[j]);\r
2275                                 }\r
2276                         }\r
2277                         else {\r
2278                                 line_error(46);\r
2279                                 return;\r
2280                         }\r
2281                         break;\r
2282                 case rOFFSET:\r
2283                         if (StoreSize != 4) {\r
2284                                 line_error(50);\r
2285                                 return;\r
2286                         }\r
2287                         /* fall thru to evaluate & store value */\r
2288                 case NUMBER:\r
2289                 case DOLLAR:    /* These should all evaluate to a number. */\r
2290                 case OPENRND:   /* If it's SYMOFF, we do a fixup or Forward Ref */\r
2291                 case MINUS:\r
2292                 case SYMBOL:\r
2293                 case LSYMBOL:\r
2294                 case UNKSYM:\r
2295                         fComma=0;\r
2296                         if (!(Expression()))    /* 0 means error was emmited. */\r
2297                                 return;\r
2298 \r
2299                         symtype = 0;            /* default to no symbol type */\r
2300                         nExtRef = 0;            /* default to no external ref */\r
2301 \r
2302                         if ((Token==SYMOFF) || (Token==NUMOFF))\r
2303                         {\r
2304                                 if (ExpType == 1)                               /* Local */\r
2305                                         symtype = lst[iExpSym].Type;\r
2306                                 else if (ExpType == 2) {                /* global */\r
2307                                         symtype = gst[iExpSym].Type;\r
2308                                         if (gst[iExpSym].Type & tEXTRN)\r
2309                                                 nExtRef = iExpSym;\r
2310                                 }\r
2311                         }\r
2312 \r
2313                         if (!fDUP) {\r
2314                                 NSave = TNumber;\r
2315                                 TSave = Token;\r
2316                                 if (Parse() == rDUP)\r
2317                                 {\r
2318                                         nDUP = NSave;\r
2319                                         fDUP = 1;\r
2320                     Parse();\r
2321                     if (Token == OPENRND) {\r
2322                                                 if (!(Expression()))    /* 0 means error was emitted.*/\r
2323                                                         return;\r
2324                                         }\r
2325                                         else\r
2326                                                 line_error(47);\r
2327                                         /* TNumber now has (VALUE) from DUP */\r
2328                                 }\r
2329                                 else {\r
2330                                         ReturnToken();\r
2331                                         TNumber = NSave;\r
2332                                         Token = TSave;\r
2333                                 }\r
2334                         }\r
2335 \r
2336                         if (StoreSize==6)\r
2337                         {\r
2338                                 if (fColon) {\r
2339                                         fColon=0;               /* reset it */\r
2340                                         if (fListA) {\r
2341                                                 sword = TNumber;\r
2342                                                 Column += 4;\r
2343                                                 put_hexw(sword, lst_fh);\r
2344                                                 Column += fprintf(lst_fh, " ");\r
2345                                                 }\r
2346                                         OutWordX(TNumber);\r
2347                                 }\r
2348                                 else {\r
2349                                         fExpectColon = 1;\r
2350                                         if (fListA) {\r
2351                                                 Column += 8;\r
2352                                                 put_hexd(TNumber, lst_fh);\r
2353                                                 Column += fprintf(lst_fh, " ");\r
2354                                                 }\r
2355                                         OutDWordX(TNumber);\r
2356                                 }\r
2357                         }\r
2358                         else if (StoreSize==4) {\r
2359                                 if (fDUP)\r
2360                                 {\r
2361                                         if (fListA) {\r
2362                                           if ((Token == SYMOFF) || (Token == NUMOFF))\r
2363                                             Column += fprintf(lst_fh, "%08lX * (%08lXr)",nDUP,TNumber);\r
2364                                           else\r
2365                                             Column += fprintf(lst_fh, "%08lX * (%08lX)",nDUP,TNumber);\r
2366                                         }\r
2367                                         while (nDUP--)\r
2368                                         {\r
2369                                                 if ((Token==SYMOFF) || (Token==NUMOFF))\r
2370                                                 {\r
2371                                                         if (fDataSeg) {         /* Data Seg */\r
2372                                                                 if (nExtRef)\r
2373                                                                         ExtRef(DSEGREF, iExpSym);\r
2374                                                                 else if (!symtype)\r
2375                                                                         ForRef(DSEGREF, oNextData);\r
2376                                                                 else if (symtype & CLABEL)\r
2377                                                                         FixUp(DCFIXTAG, oNextData, 0);\r
2378                                                                 else if (symtype & DLABEL)\r
2379                                                                         FixUp(DDFIXTAG, oNextData, 0);\r
2380                                                         }\r
2381                                                         else {                          /* Code Seg */\r
2382                                                                 if (nExtRef)\r
2383                                                                         ExtRef(CSEGREF, iExpSym);\r
2384                                                                 if (!symtype)\r
2385                                                                         ForRef(CSEGREF, oNextCode);\r
2386                                                                 else if (symtype & CLABEL)\r
2387                                                                         FixUp(CCFIXTAG, oNextCode, 0);\r
2388                                                                 else if (symtype & DLABEL)\r
2389                                                                         FixUp(CDFIXTAG, oNextCode, 0);\r
2390                                                         }\r
2391                                                 }\r
2392                                                 OutDWordX(TNumber);\r
2393                                     }\r
2394                                 }\r
2395                                 else {\r
2396                                         if (fListA)\r
2397                                         {\r
2398                                           if ((Token == SYMOFF) || (Token == NUMOFF))\r
2399                                             Column += fprintf(lst_fh, " %08lXr", TNumber);\r
2400                                           else\r
2401                                             Column += fprintf(lst_fh, " %08lX", TNumber);\r
2402                                         }\r
2403 \r
2404                                         /* Fixup & Forref here! */\r
2405                                         if ((Token==SYMOFF) || (Token==NUMOFF))\r
2406                                         {\r
2407                                           if (fDataSeg)\r
2408                                           {                                     /* Data Seg */\r
2409                                                 if (nExtRef)\r
2410                                                         ExtRef(DSEGREF, iExpSym);\r
2411                                                 else if (!symtype)\r
2412                                                         ForRef(DSEGREF, oNextData);\r
2413                                                 else if (symtype & CLABEL)\r
2414                                                         FixUp(DCFIXTAG, oNextData, 0);\r
2415                                                 else if (symtype & DLABEL)\r
2416                                                         FixUp(DDFIXTAG, oNextData, 0);\r
2417                                           }\r
2418                                           else\r
2419                                           {                                     /* Code Seg */\r
2420                                                 if (nExtRef)\r
2421                                                         ExtRef(CSEGREF, iExpSym);\r
2422                                                 else if (!symtype)\r
2423                                                         ForRef(CSEGREF, oNextCode);\r
2424                                                 else if (symtype & CLABEL)\r
2425                                                         FixUp(CCFIXTAG, oNextCode, 0);\r
2426                                                 else if (symtype & DLABEL)\r
2427                                                         FixUp(CDFIXTAG, oNextCode, 0);\r
2428                                           }\r
2429                                         }\r
2430                                         OutDWordX(TNumber);\r
2431                                 }\r
2432                         }\r
2433                         else if (StoreSize==2) {\r
2434                                 if (fDUP) {\r
2435                                         if (fListA)\r
2436                                           Column += fprintf(lst_fh, "%08lX * (%04lX) ",nDUP,TNumber);\r
2437                                         while (nDUP--)\r
2438                                                 OutWordX(TNumber);\r
2439                                         }\r
2440                                 else {\r
2441                                         if (fListA)\r
2442                                                 Column += fprintf(lst_fh, "%04lX ", TNumber);\r
2443                                         OutWordX(TNumber);\r
2444                                         }\r
2445                         }\r
2446                         else {\r
2447                                 if (fDUP) {\r
2448                                         if (fListA)\r
2449                                           Column += fprintf(lst_fh, "%08lX * (%02lX) ",nDUP,TNumber);\r
2450                                         while (nDUP--)\r
2451                                                 OutByteX(TNumber);\r
2452                                         }\r
2453                                 else {\r
2454                                         if (fListA)\r
2455                                           Column += fprintf(lst_fh, "%02lX ", TNumber);\r
2456                                         OutByteX(TNumber);\r
2457                                         }\r
2458                         }\r
2459                         break;\r
2460                 case COMMA:     /* Just eat the comma */\r
2461                         if (fComma) {\r
2462                                 line_error(48);\r
2463                                 return;\r
2464                         }\r
2465                         fComma = 1;\r
2466                         break;\r
2467                 case COLON:\r
2468                         fComma=0;\r
2469                         if ((StoreSize == 6) && (fExpectColon)) {\r
2470                                 fColon = 1;\r
2471                                 fExpectColon = 0;\r
2472                         }\r
2473                         else {\r
2474                                 line_error(49);\r
2475                                 return;\r
2476                         }\r
2477                         break;\r
2478                 case ZERO:\r
2479                         if (fComma)     fMoreStorage = 1;\r
2480                         return;\r
2481                 default: {\r
2482                         line_error(51);\r
2483                         fMoreStorage = 0;\r
2484                         return;\r
2485                         }\r
2486         }\r
2487 }\r
2488 }\r
2489 \r
2490 /********************************************\r
2491   Add new GLOBAL symbol to table (TString).\r
2492   Then parse again to hand off to\r
2493   proper function. This stores all\r
2494   Symbols UPPER case.\r
2495 *********************************************/\r
2496 void NewSymbol()\r
2497 {\r
2498 S32 i;\r
2499 S8   fColon, fStorage;\r
2500 \r
2501         if ((pSymNext + CBString) >= (pSymBuf + SYMBUFMAX))\r
2502                 fatal_error("Symbol buffer overflow...");\r
2503         if (iSymNext >= SYMSMAX)\r
2504                 fatal_error("Symbol table overflow...");\r
2505 \r
2506         strncpy(pSymNext, TString, CBString);\r
2507         gst[iSymNext].Size = CBString;\r
2508         gst[iSymNext].Type = 0;                         /* initialize type */\r
2509         gst[iSymNext].Ptr = pSymNext;\r
2510         gst[iSymNext].Line = lineno[level];\r
2511         gst[iSymNext].Offs = 0;\r
2512 \r
2513         /* All declarations that reach NewSymbol are either at\r
2514         level 0 or defined as PUBLIC or EXTERN. \r
2515         */\r
2516 \r
2517         if (fExtern)\r
2518                 gst[iSymNext].Type |= tEXTRN;\r
2519         else\r
2520                 gst[iSymNext].Type |= tPUBLIC;\r
2521 \r
2522         if (fFarLabel) gst[iSymNext].Type |= tFAR;\r
2523 \r
2524         if (fDataSeg) {\r
2525                 if (!fExtern)\r
2526                         gst[iSymNext].Offs = oNextData;\r
2527             gst[iSymNext].Type |= DLABEL;\r
2528         }\r
2529         else {\r
2530                 if (!fExtern)\r
2531                         gst[iSymNext].Offs = oNextCode;\r
2532                 gst[iSymNext].Type |= CLABEL;\r
2533         }\r
2534 \r
2535         /* update for next symbol */\r
2536         pSymNext += CBString;\r
2537         iSymNext++;\r
2538 \r
2539 \r
2540         /* Now, parse again and hand off. We have just added a symbol\r
2541         so expect to see an EQU, COLON or Storage statement.\r
2542         If we don't see one of these it's an error unless it's an extern.\r
2543         If we see a COLON we parse again and expect an instruction or EOL!\r
2544         */\r
2545 \r
2546         fStorage = 0;\r
2547         fColon=0;\r
2548         i = Parse();\r
2549 \r
2550         if (i == COLON) {\r
2551                 fColon = 1;\r
2552                 if (fDataSeg) {\r
2553                 line_error(49);\r
2554                     return;\r
2555                 }\r
2556                 i = Parse();\r
2557         }\r
2558 \r
2559         switch(i) {             /* parse returns Token */\r
2560                 case INSTRU:\r
2561                     if (fDataSeg) {\r
2562                         line_error(41);\r
2563                             return;\r
2564                         }\r
2565                         if (!fColon) {\r
2566                         line_error(54);\r
2567                             return;\r
2568                         }\r
2569                     Instruction();\r
2570                     break;\r
2571             case rDB:\r
2572                         gst[iSymNext-1].Type |= sBYTE;          /*  type */\r
2573                         fStorage = 1;\r
2574                         break;\r
2575             case rDW:\r
2576                         gst[iSymNext-1].Type |= sWORD;  /*  type */\r
2577                         fStorage = 1;\r
2578                         break;\r
2579             case rDD:\r
2580                         gst[iSymNext-1].Type |= sDWORD; /*  type */\r
2581                         fStorage = 1;\r
2582                         break;\r
2583                 case rDF:\r
2584                         if ((!fDataSeg) && (!fColon)) {\r
2585                                 line_error(54);\r
2586                                     return;\r
2587                                 }\r
2588                         gst[iSymNext-1].Type |= sFWORD; /*  type */\r
2589                         fStorage = 1;\r
2590                         break;\r
2591                 case rEQU:\r
2592                 line_error(55);\r
2593         /*              AddMacro(); */\r
2594                         break;\r
2595                 case COLON:\r
2596                         if (fExtern)\r
2597                         return;\r
2598                 case ZERO:\r
2599                         if ((fDataSeg) && (!fExtern))\r
2600                                 line_error(56);\r
2601                         break;\r
2602                 default:\r
2603                         if (fDataSeg)\r
2604                                 line_error(56);\r
2605           }\r
2606 \r
2607         if (gst[iSymNext-1].Type & tEXTRN)\r
2608                 fStorage = 0;\r
2609 \r
2610         if (fStorage)\r
2611                 Storage();\r
2612 }\r
2613 \r
2614 /********************************************\r
2615   This changes an EXTRN entry in the gst to\r
2616   a PUBLIC once we find it.  This checks to\r
2617   make sure the extern declaration was the\r
2618   same type as this public.\r
2619 *********************************************/\r
2620 \r
2621 void MakePublic(void)\r
2622 {\r
2623 S32 i;\r
2624 S8   fColon, fStorage;\r
2625 \r
2626         if (gst[TSymnum].Type & tPUBLIC) {\r
2627                 line_error(64);\r
2628                 return;\r
2629         }\r
2630 \r
2631         if ((fDataSeg) && (!(gst[TSymnum].Type & DLABEL))) {\r
2632                 line_error(69);\r
2633                 return;\r
2634         }\r
2635 \r
2636         if ((!fDataSeg) && (!(gst[TSymnum].Type & CLABEL))) {\r
2637                 line_error(69);\r
2638                 return;\r
2639         }\r
2640 \r
2641         gst[TSymnum].Type |= tPUBLIC;   /* Turn ON Public */\r
2642         gst[TSymnum].Type &= ~tEXTRN;   /* Turn off EXTERN */\r
2643 \r
2644         if (fDataSeg)\r
2645                 gst[TSymnum].Offs = oNextData;\r
2646         else\r
2647                 gst[TSymnum].Offs = oNextCode;\r
2648 \r
2649         /* Now, parse again and hand off. We have just added a symbol\r
2650         so expect to see an EQU, COLON or Storage statement.\r
2651         If we don't see one of these it's an error unless it's an extern.\r
2652         If we see a COLON we parse again and expect an instruction or EOL!\r
2653         */\r
2654 \r
2655 fStorage = 0;\r
2656 fColon=0;\r
2657 i = Parse();\r
2658 \r
2659 if (i == COLON) {\r
2660         fColon = 1;\r
2661         if (fDataSeg) {\r
2662         line_error(49);\r
2663             return;\r
2664         }\r
2665         i = Parse();\r
2666 }\r
2667 \r
2668 switch(i) {             /* parse returns Token */\r
2669         case INSTRU:\r
2670             if (fDataSeg) {\r
2671                 line_error(41);\r
2672                     return;\r
2673                 }\r
2674                 if (!fColon) {\r
2675                 line_error(54);\r
2676                     return;\r
2677                 }\r
2678             Instruction();\r
2679             break;\r
2680     case rDB:\r
2681                 gst[TSymnum].Type |= sBYTE;             /*  type */\r
2682                 fStorage = 1;\r
2683                 break;\r
2684     case rDW:\r
2685                 gst[TSymnum].Type |= sWORD;     /*  type */\r
2686                 fStorage = 1;\r
2687                 break;\r
2688     case rDD:\r
2689                 gst[TSymnum].Type |= sDWORD;    /*  type */\r
2690                 fStorage = 1;\r
2691                 break;\r
2692         case rDF:\r
2693                 if ((!fDataSeg) && (!fColon)) {\r
2694                         line_error(54);\r
2695                             return;\r
2696                         }\r
2697                 gst[TSymnum].Type |= sFWORD;    /*  type */\r
2698                 fStorage = 1;\r
2699                 break;\r
2700         case rEQU:\r
2701         line_error(55);\r
2702                 break;\r
2703         case COLON:\r
2704                 return;\r
2705         default:\r
2706                 if (fDataSeg)\r
2707                         line_error(56);\r
2708   }\r
2709 \r
2710 if (fStorage)\r
2711         Storage();\r
2712 \r
2713 }\r
2714 \r
2715 \r
2716 /********************************************\r
2717   This checks to ensure multiple externs are\r
2718   the same type when we run across them, and\r
2719   also that an extern is the same type if\r
2720   the public is already declared.\r
2721 *********************************************/\r
2722 void CheckExtern(void)\r
2723 {\r
2724         /* Check to make sure new extern and symbol are same type */\r
2725 \r
2726         if ((fDataSeg) && (!(gst[TSymnum].Type & DLABEL))) {\r
2727                 line_error(69);\r
2728                 return;\r
2729         }\r
2730 \r
2731         if ((!fDataSeg) && (!(gst[TSymnum].Type & CLABEL))) {\r
2732                 line_error(69);\r
2733                 return;\r
2734         }\r
2735 }\r
2736 \r
2737 \r
2738 /********************************************\r
2739   Add new LOCAL symbol to table (TString).\r
2740   Then parse again to hand off to\r
2741   proper function. This stores all\r
2742   Symbols UPPER case.\r
2743 *********************************************/\r
2744 void NewLSymbol(void)\r
2745 {\r
2746 S32 i;\r
2747 S8   fColon, fStorage;\r
2748 \r
2749 if ((pLSymNext + CBString) >= (pLSymBuf + LSYMBUFMAX))\r
2750         fatal_error("Local symbol buffer overflow...");\r
2751 if (iLSymNext >= LSYMSMAX)\r
2752         fatal_error("Local symbol table overflow...");\r
2753 \r
2754 strncpy(pLSymNext, TString, CBString);\r
2755 lst[iLSymNext].Size = CBString;\r
2756 lst[iLSymNext].Type = 0;                                /* initialize type */\r
2757 lst[iLSymNext].Ptr = pLSymNext;\r
2758 lst[iLSymNext].Line = lineno[level];\r
2759 \r
2760 if (fDataSeg) {\r
2761         lst[iLSymNext].Offs = oNextData;\r
2762         lst[iLSymNext].Type |= DLABEL;\r
2763         }\r
2764 else {\r
2765         lst[iLSymNext].Offs = oNextCode;\r
2766         lst[iLSymNext].Type |= CLABEL;\r
2767         }\r
2768 \r
2769 /* update for next symbol */\r
2770 pLSymNext += CBString;\r
2771 iLSymNext++;\r
2772 \r
2773 /* Now, parse again and hand off. We have just added a symbol\r
2774 so expect to see an EQU, COLON or Storage statement.\r
2775 If we don't see one of these it's an error!\r
2776 If we see a COLON we parse again and expect an instruction or EOL!\r
2777  */\r
2778 \r
2779 fStorage = 0;\r
2780 fColon=0;\r
2781 i = Parse();\r
2782 \r
2783 if (i == COLON) {\r
2784         fColon = 1;\r
2785         if (fDataSeg) {\r
2786         line_error(49);\r
2787             return;\r
2788         }\r
2789         i = Parse();\r
2790 }\r
2791 \r
2792 switch(i) {             /* parse returns Token */\r
2793         case INSTRU:\r
2794             if (fDataSeg) {\r
2795                 line_error(41);\r
2796                     return;\r
2797                 }\r
2798                 if (!fColon) {\r
2799                 line_error(54);\r
2800                     return;\r
2801                 }\r
2802             Instruction();\r
2803             break;\r
2804     case rDB:\r
2805                 lst[iLSymNext-1].Type |= sBYTE;         /*  type */\r
2806                 fStorage = 1;\r
2807                 break;\r
2808     case rDW:\r
2809                 lst[iLSymNext-1].Type |= sWORD; /*  type */\r
2810                 fStorage = 1;\r
2811                 break;\r
2812     case rDD:\r
2813                 lst[iLSymNext-1].Type |= sDWORD;        /*  type */\r
2814                 fStorage = 1;\r
2815                 break;\r
2816         case rDF:\r
2817                 if ((!fDataSeg) && (!fColon)) {\r
2818                         line_error(54);\r
2819                             return;\r
2820                         }\r
2821                 lst[iLSymNext-1].Type |= sFWORD;        /*  type */\r
2822                 fStorage = 1;\r
2823                 break;\r
2824         case rEQU:\r
2825                 AddMacro();\r
2826                 break;\r
2827         case COLON:\r
2828                 return;\r
2829         default:\r
2830                 if (fDataSeg)\r
2831                         line_error(56);\r
2832   }\r
2833 \r
2834 if (lst[iLSymNext-1].Type & tEXTRN)\r
2835         fStorage = 0;\r
2836 \r
2837 if (fStorage)\r
2838         Storage();\r
2839 \r
2840 }\r
2841 \r
2842 /*****************************************\r
2843  After we transition from level 1 back to\r
2844  level 0 we go back to the point in the\r
2845  code or data file where we began writing this\r
2846  section and resolve all forward code\r
2847  and local data references. These will be\r
2848  referenced in the module we just finished.\r
2849  ******************************************/\r
2850 \r
2851 void Resolve(void)\r
2852 {\r
2853 long i, isym;\r
2854 S32 Relative;\r
2855 S32 Partial;\r
2856 S32 AddFix;\r
2857 \r
2858         i = 0;\r
2859 \r
2860         while (i < iRefNext)  /* While there are forward references */\r
2861         {\r
2862                 if (pfrt[i].Type == DSEGREF)            /* Ref is in DSEG */\r
2863                 {\r
2864                         seekDS(pfrt[i].Offs - DataOffset);\r
2865                         readDS(&Partial, 4);\r
2866                         seekDS(pfrt[i].Offs - DataOffset);\r
2867                         AddFix = pfrt[i].Offs - DataOffset;\r
2868                 }\r
2869                 else    /* Ref is in CSEG */\r
2870                 {\r
2871                         seekCS(pfrt[i].Offs - CodeOffset);\r
2872 \r
2873                         if (pfrt[i].Type == CSEGREF)     /* IT'S ABSOLUTE! */\r
2874                         {\r
2875                                 readCS(&Partial, 4);\r
2876                                 seekCS(pfrt[i].Offs - CodeOffset);\r
2877                                 AddFix = pfrt[i].Offs - CodeOffset;\r
2878                         }\r
2879                 }\r
2880                 /* We are where we should write the reference\r
2881                    now we need to find it in the local symbol table\r
2882                    and calculate the proper offset.  The calculation\r
2883                    is different for Relative and absolute references.\r
2884                    For Relative, we subtract the address where the correction\r
2885                    is going to be stored from the offset of reference.\r
2886                    For Absolute, we read what was already at the address\r
2887                    and add it to the offset of the referenced item.\r
2888                    Both of these are also adjusted for the Virtual segment offset.\r
2889                 */\r
2890 \r
2891                 /* Look in the Local Symbol table first! */\r
2892 \r
2893                 isym = findLsymbol(pfrt[i].Ptr, pfrt[i].NameSz);\r
2894 \r
2895                 if (isym)               /* we found it! */\r
2896                 {\r
2897                         if (pfrt[i].Type == CCR8REF)            /* 8 bit relative */\r
2898                         {\r
2899                                 Relative = lst[isym].Offs - (pfrt[i].Offs - CodeOffset + 1);\r
2900                                 OutByteCS(Relative);\r
2901                         }\r
2902                         else if (pfrt[i].Type == CCR32REF) /* 32 bit relative */\r
2903                         {\r
2904                                 /* Fixed to make relatives ok in Virtual Segs */\r
2905 \r
2906                                 Relative = (lst[isym].Offs - CodeOffset) -\r
2907                                            (pfrt[i].Offs - CodeOffset + 4);\r
2908                                 OutDWordCS(Relative);\r
2909                         }\r
2910                         else if (pfrt[i].Type == CSEGREF)  /* 32 bit absolute */\r
2911                         {\r
2912                                 Partial += lst[isym].Offs;\r
2913 \r
2914                                 if (lst[isym].Type & CLABEL)\r
2915                                         FixUp(CCFIXTAG, AddFix, 0);\r
2916                                 else if (lst[isym].Type & DLABEL)\r
2917                                         FixUp(CDFIXTAG, AddFix, 0);\r
2918 \r
2919                                 OutDWordCS(Partial);\r
2920                         }\r
2921                         else if (pfrt[i].Type == DSEGREF)\r
2922                         {\r
2923                                 Partial += lst[isym].Offs;                      /* RAB was + DataOffset */\r
2924 \r
2925                                 if (lst[isym].Type & CLABEL)\r
2926                                         FixUp(DCFIXTAG, AddFix, 0);\r
2927                                 else if (lst[isym].Type & DLABEL)\r
2928                                         FixUp(DDFIXTAG, AddFix, 0);\r
2929 \r
2930                                 OutDWordDS(Partial);\r
2931                         }\r
2932                 }\r
2933                 else    /* Look in Global table */\r
2934                 {\r
2935 \r
2936                         isym = findGsymbol(pfrt[i].Ptr, pfrt[i].NameSz);\r
2937 \r
2938                         if (isym)\r
2939 \r
2940                         {               /* we found it! */\r
2941 \r
2942 \r
2943                                 if (pfrt[i].Type == CCR8REF) {          /* 8 bit relative */\r
2944                                         Relative = gst[isym].Offs - (pfrt[i].Offs - CodeOffset + 1);\r
2945                                         OutByteCS(Relative);\r
2946                                 }\r
2947                                 else if (pfrt[i].Type == CCR32REF) {  /*  32 bit relative */\r
2948                                         Relative = gst[isym].Offs - (pfrt[i].Offs - CodeOffset + 4);\r
2949                                         OutDWordCS(Relative);\r
2950                                 }\r
2951                                 else if (pfrt[i].Type == CSEGREF) {\r
2952                                         Partial += gst[isym].Offs;\r
2953 \r
2954                                         if (gst[isym].Type & CLABEL)\r
2955                                                 FixUp(CCFIXTAG, AddFix, 0);\r
2956                                         else if (gst[isym].Type & DLABEL)\r
2957                                                 FixUp(CDFIXTAG, AddFix, 0);\r
2958 \r
2959                                         OutDWordCS(Partial);\r
2960                                 }\r
2961                                 else if (pfrt[i].Type == DSEGREF)\r
2962                                 {\r
2963                                         Partial += gst[isym].Offs;\r
2964 \r
2965                                         if (gst[isym].Type & CLABEL)\r
2966                                                 FixUp(DCFIXTAG, AddFix, 0);\r
2967                                         else if (gst[isym].Type & DLABEL)\r
2968                                                 FixUp(DDFIXTAG, AddFix, 0);\r
2969 \r
2970                                         OutDWordDS(Partial);\r
2971                                 }\r
2972                         }\r
2973                         else\r
2974                                 prev_error("Unresolved symbol in current module", pfrt[i].Line);\r
2975                 }\r
2976                 i++;\r
2977         }\r
2978 \r
2979         ics = oNextCode - CodeOffset;\r
2980         ids = oNextData - DataOffset;\r
2981 \r
2982 }\r
2983 \r
2984 /*****************************************\r
2985  When we have processed all the source\r
2986  we call this to resolve ALL externals.\r
2987  ******************************************/\r
2988 \r
2989 void ResolveExt(void)\r
2990 {\r
2991 long i, isym;\r
2992 S32 Relative;\r
2993 S32 Partial;\r
2994 S32 AddFix;\r
2995 char name[31];\r
2996 \r
2997 i = 0;\r
2998 Partial = 0;\r
2999 Relative = 0;\r
3000 AddFix = 0;\r
3001 \r
3002 while (i < iERefNext) { /* While there are unresolved externals */\r
3003 \r
3004         /* See if ref is in GST as PUBLIC */\r
3005 \r
3006         isym = ert[i].iSym;\r
3007 \r
3008         if (gst[isym].Type & tPUBLIC) {\r
3009 \r
3010                 if (ert[i].Type == DSEGREF) {                                   /* Ref is in DSEG */\r
3011 \r
3012                         seekDS(ert[i].Offs - DataOffset);\r
3013                         readDS(&Partial, 4);\r
3014                         seekDS(ert[i].Offs - DataOffset);\r
3015                         AddFix = ert[i].Offs - DataOffset;\r
3016                 }\r
3017                 else  {                                                                                 /* Ref is in CSEG */\r
3018 \r
3019                         seekCS(ert[i].Offs - CodeOffset);\r
3020 \r
3021                         if (ert[i].Type == CSEGREF) {                    /* and IT'S ABSOLUTE! */\r
3022                                 readCS(&Partial, 4);\r
3023                                 seekCS(ert[i].Offs - CodeOffset);\r
3024                                 AddFix = ert[i].Offs - CodeOffset;\r
3025                         }\r
3026                 }\r
3027                         /* We are where we should write the reference\r
3028                            now we need to use the index in the external ref\r
3029                            table to see if it has been defined PUBLIC.\r
3030                            If so, we resolve it, else we error out.\r
3031                            To resolve it, the calculation is different for Relative\r
3032                            and absolute references.\r
3033                            For Relative, we subtract the address where the correction\r
3034                            is going to be stored from the offset of reference.\r
3035                            For Absolute, we read what was already at the address\r
3036                            and add it to the offset of the referenced item.\r
3037                            Both of these are also adjusted for the Virtual segment offset.\r
3038                         */\r
3039 \r
3040                 if (ert[i].Type == CCR32REF) {  /*  32 bit relative */\r
3041 \r
3042                         /* Fixed to make relatives ok in Virtual Segs */\r
3043 \r
3044                         Relative = (gst[isym].Offs - CodeOffset) -\r
3045                                    (ert[i].Offs - CodeOffset + 4);\r
3046                         OutDWordCS(Relative);\r
3047                 }\r
3048                 else if (ert[i].Type == CSEGREF) {\r
3049                         Partial += gst[isym].Offs;\r
3050 \r
3051                         if (gst[isym].Type & DLABEL)\r
3052                                 FixUp(CDFIXTAG, AddFix, 0);\r
3053                         else if (gst[isym].Type & CLABEL)\r
3054                                 FixUp(CCFIXTAG, AddFix, 0);\r
3055 \r
3056                         OutDWordCS(Partial);\r
3057                 }\r
3058                 else if (ert[i].Type == DSEGREF) {\r
3059                         Partial += gst[isym].Offs;\r
3060 \r
3061                         if (gst[isym].Type & CLABEL)\r
3062                                 FixUp(DCFIXTAG, AddFix, 0);\r
3063                         else if (gst[isym].Type & DLABEL)\r
3064                                         FixUp(DDFIXTAG, AddFix, 0);\r
3065 \r
3066                         OutDWordDS(Partial);\r
3067                 }\r
3068         }\r
3069         else {\r
3070                 strncpy(name, gst[isym].Ptr, gst[isym].Size);\r
3071                 name[gst[isym].Size] = '\0';\r
3072                 fprintf(lst_fh, "Unresolved external: %s\n", name);\r
3073                 Column = 0;\r
3074                 ++error_count;\r
3075         }\r
3076 i++;\r
3077 }       /* while more Erefs */\r
3078 \r
3079 ics = oNextCode - CodeOffset;\r
3080 ids = oNextData - DataOffset;\r
3081 \r
3082 }\r
3083 \r
3084 /*****************************************\r
3085   If there were no errors, and all looks\r
3086   well, we build the run file. This consists\r
3087   of building the required tags in order\r
3088   and writing them to the file with the\r
3089   data.\r
3090 ******************************************/\r
3091 \r
3092 void BuildRunFile(void)\r
3093 {\r
3094 unsigned char b;\r
3095 long i;\r
3096 long sdata;\r
3097 \r
3098         tag.id = IDTAG;                                         /* File type */\r
3099         tag.len = 1;\r
3100         fwrite(&tag, 5, 1, run_fh);                     /* Write the tag record */\r
3101         fwrite(&filetype, 1, 1, run_fh);        /* Write the filetype */\r
3102 \r
3103         /* Version tag goes here */\r
3104         /* DatTime tag goes here */\r
3105         /* Comment tag(s) goes here */\r
3106 \r
3107         tag.id = SEGTAG;                                        /* Initial Segment Sizes */\r
3108         tag.len = 12;\r
3109         fwrite(&tag, 5, 1, run_fh);                     /* Write the tag record */\r
3110         fwrite(&StackTotal, 4, 1, run_fh);      /* Write the Stacktotal */\r
3111         sdata = oNextCode - CodeOffset;         /* Size of CS.TMP */\r
3112         fwrite(&sdata, 4, 1, run_fh);           /* Write the Code Size */\r
3113         sdata = oNextData - DataOffset;         /* Size of DS.TMP */\r
3114         fwrite(&sdata, 4, 1, run_fh);           /* Write the Data Size */\r
3115 \r
3116         printf("Stack Size: %ld\r\n", StackTotal);\r
3117         printf("Code  Size: %ld\r\n", oNextCode - CodeOffset);\r
3118         printf("Data  Size: %ld\r\n", oNextData - DataOffset);\r
3119 \r
3120         tag.id = DOFFTAG;                                       /* Assumed Data Offset */\r
3121         tag.len = 4;\r
3122         fwrite(&tag, 5, 1, run_fh);                     /* Write the tag record */\r
3123         fwrite(&DataOffset, 4, 1, run_fh);      /* Write the data */\r
3124 \r
3125         tag.id = COFFTAG;                                       /* Assumed Code Offset */\r
3126         tag.len = 4;\r
3127         fwrite(&tag, 5, 1, run_fh);                     /* Write the tag record */\r
3128         fwrite(&CodeOffset, 4, 1, run_fh);      /* Write the data */\r
3129 \r
3130         tag.id = STRTTAG;                                       /* Starting Address */\r
3131         tag.len = 4;\r
3132         fwrite(&tag, 5, 1, run_fh);                     /* Write the tag record */\r
3133         fwrite(&StartAddr, 4, 1, run_fh);       /* Write the data */\r
3134 \r
3135         tag.id = CODETAG;                                       /* Code Segment */\r
3136         tag.len = oNextCode - CodeOffset;       /* Size of CS.TMP */\r
3137         fwrite(&tag, 5, 1, run_fh);                     /* Write the tag record */\r
3138 \r
3139         sdata = tag.len;                        /* WRITE the Code seg */\r
3140         fwrite(pcsbuf, 1, sdata, run_fh);\r
3141 \r
3142         tag.id = DATATAG;                                       /* Data Segment */\r
3143         tag.len = oNextData - DataOffset;       /* Size of DS.TMP */\r
3144         fwrite(&tag, 5, 1, run_fh);                     /* Write the tag record */\r
3145 \r
3146         sdata = tag.len;                        /* WRITE the Data seg */\r
3147         fwrite(pdsbuf, 1, sdata, run_fh);\r
3148 \r
3149         if (nCDFix) {\r
3150                 tag.id = CDFIXTAG;                                      /* CSEG Data Fixups */\r
3151                 tag.len = nCDFix * 4;                           /* Count * 4 of Fixups */\r
3152                 fwrite(&tag, 5, 1, run_fh);                     /* Write the tag record */\r
3153                 i = iFUNext;\r
3154                 while (i--) {                                           /* Write CD fixups */\r
3155                         if (pfut[i].type == CDFIXTAG)\r
3156                                 fwrite(&pfut[i].Offs, 1, 4, run_fh);\r
3157                 }\r
3158         }\r
3159 \r
3160         if (nCCFix) {\r
3161                 tag.id = CCFIXTAG;                                      /* CSEG Code Fixups */\r
3162                 tag.len = nCCFix * 4;                           /* Count * 4 of Fixups */\r
3163                 fwrite(&tag, 5, 1, run_fh);                     /* Write the tag record */\r
3164                 i = iFUNext;\r
3165                 while (i--)     {                                               /* Write CC fixups */\r
3166                         if (pfut[i].type == CCFIXTAG)\r
3167                                 fwrite(&pfut[i].Offs, 1, 4, run_fh);\r
3168                 }\r
3169         }\r
3170 \r
3171         if (nDDFix) {\r
3172                 tag.id = DDFIXTAG;                                      /* DESG Data Fixups */\r
3173                 tag.len = nDDFix * 4;                           /* Count * 4 of Fixups */\r
3174                 fwrite(&tag, 5, 1, run_fh);                     /* Write the tag record */\r
3175                 i = iFUNext;\r
3176                 while (i--)     {                                               /* Write DD fixups */\r
3177                         if (pfut[i].type == DDFIXTAG)\r
3178                                 fwrite(&pfut[i].Offs, 1, 4, run_fh);\r
3179                 }\r
3180         }\r
3181 \r
3182         if (nDCFix) {\r
3183                 tag.id = DCFIXTAG;                                      /* DESG Code Fixups */\r
3184                 tag.len = nDCFix * 4;                           /* Count * 4 of Fixups */\r
3185                 fwrite(&tag, 5, 1, run_fh);                     /* Write the tag record */\r
3186                 i = iFUNext;\r
3187                 while (i--)     {                                               /* Write DC fixups */\r
3188                         if (pfut[i].type == DCFIXTAG)\r
3189                                 fwrite(&pfut[i].Offs, 1, 4, run_fh);\r
3190                 }\r
3191         }\r
3192 \r
3193         /* DLL Address fixup tag goes here */\r
3194         /* DLL Public tag goes here */\r
3195 \r
3196         tag.id = ENDTAG;                                                /* End Tag */\r
3197         tag.len = 4;    /* Size of CS.TMP */\r
3198         fwrite(&tag, 5, 1, run_fh);                             /* Write the tag record */\r
3199         sdata = 0;\r
3200         fwrite(&sdata, 4, 1, run_fh);                   /* Write the tag record */\r
3201 \r
3202 }\r
3203 \r
3204 \r
3205 /*****************************************\r
3206     Reads a whole line into line buffer.\r
3207 ******************************************/\r
3208 \r
3209 S32 readline(void)\r
3210 {\r
3211 U32 i;\r
3212 U8 *pLine;\r
3213 \r
3214 if (!(fgets(line_ptr = line_buf0, 100, src_fh[level])))\r
3215 {\r
3216 \r
3217         if (level) {    /* we are in a nested include */\r
3218                 fclose(src_fh[level]);\r
3219                 --level;\r
3220                 if (level==0) {         /* back up one level */\r
3221 \r
3222                         /* Processes forward references from this module */\r
3223                         Resolve();\r
3224 \r
3225                         if (fSymDump) {\r
3226                                 DumpLSymbols();\r
3227                                 DumpFRT();\r
3228                         }\r
3229 \r
3230                         /* Clear local symbol, forward refs, & macro tables */\r
3231 \r
3232                         iLSymNext = 1;  /* 1st entry.  */\r
3233                         pLSymNext = pLSymBuf; /* beginning of buffer */\r
3234 \r
3235                         iRefNext = 0;   /* 1st entry.  */\r
3236                         pRefNext = pRefBuf;             /* Allocate memory - Was RefBuf */\r
3237 \r
3238                         iMacNext = 0;                   /* 1st entry */\r
3239                         pMacNext = pMacBuf;             /* Begining of buffer */\r
3240 \r
3241 \r
3242                 }\r
3243                 if (fListA)\r
3244                         fprintf(lst_fh, "\r\n                ");\r
3245                 fprintf(lst_fh, "CONTINUING-> %s, Level:%d\r\n", srcname[level],level);\r
3246             fprintf(lst_fh, "\r\n");\r
3247 \r
3248                 if (lineno[level]) --lineno[level];\r
3249                 fContinue = 1;\r
3250         }\r
3251         else\r
3252         {               /* We are at the end of the ATF file */\r
3253 \r
3254                 /* Processes forward references from Level 0 */\r
3255                 Resolve();\r
3256 \r
3257                 if (fSymDump)\r
3258                 {\r
3259                         DumpGSymbols();\r
3260                         DumpFRT();\r
3261                 }\r
3262 \r
3263                 if (!fStart)\r
3264                         line_error(12); /* Starting address not found */\r
3265 \r
3266                 if (!error_count)\r
3267                         ResolveExt();\r
3268 \r
3269                 printf("%d Errors\r\n%d Warnings\r\n", error_count, warn_count);\r
3270 \r
3271                 if (fListA | fListE)\r
3272                         fprintf(lst_fh,"%d Errors\r\n%d Warnings\r\n",\r
3273                                         error_count,warn_count);\r
3274 \r
3275                 if (!error_count)\r
3276                 {\r
3277                         printf("Building Run file...\r\n");\r
3278                         BuildRunFile();\r
3279                         printf(" Done.\r\n");\r
3280                 }\r
3281 \r
3282                 fclose(lst_fh);\r
3283                 fclose(src_fh[level]);\r
3284             exit(1);\r
3285         }\r
3286  }\r
3287 \r
3288  list_buf[0] = 0;\r
3289  if (fListA) {\r
3290          pLine = line_ptr;\r
3291          i=0;\r
3292          while (isspace(*pLine)) pLine++;\r
3293          while ((*pLine) && (*pLine != ';') && (*pLine != 0x0A))\r
3294                 list_buf[i++] = *pLine++;\r
3295          while ((i) && (list_buf[i-1] == ' ')) --i; /* eat trailing spaces */\r
3296          list_buf[i] = 0;                                                       /* null terminate */\r
3297          if (i) fLineIn = 1;\r
3298          else fLineIn = 0;\r
3299          }\r
3300  ++lineno[level];\r
3301  return(1);\r
3302 }\r
3303 \r
3304 \r
3305 /********************************************\r
3306    Dispatch calls Parse from the beginning\r
3307    of a line and calls the proper routine\r
3308    based on what it finds (from Parse()).\r
3309    Dispatch  calls readline to get a new line\r
3310    after each of the line-specific modules\r
3311    gets done with it's line or lines(s).\r
3312 *********************************************/\r
3313 \r
3314 void Dispatch(void)\r
3315 {\r
3316 S32 i, j;\r
3317 S8   st[80];\r
3318 \r
3319 while (1) {\r
3320   readline();\r
3321 \r
3322   if (fContinue) {              /* We have just returned from an include */\r
3323         fContinue = 0;          /* and must reread the line without processing */\r
3324         continue;\r
3325         }\r
3326 \r
3327   if (lineno[level] == 1) {\r
3328         if (fListA)\r
3329                 fprintf(lst_fh, "\r\n                ");\r
3330         fprintf(lst_fh, "PROCESSING-> %s, Level:%d\r\n", srcname[level], level);\r
3331         }\r
3332 \r
3333   if (fListA) {\r
3334       Column = fprintf(lst_fh, "%06d ", lineno[level]);\r
3335       }\r
3336 \r
3337   fPublic = 0;\r
3338   fExtern = 0;\r
3339   fFarLabel = 0;\r
3340 \r
3341   i = Parse();\r
3342   if (fMoreStorage)\r
3343         Storage();\r
3344   else switch (i) {\r
3345     case INSTRU:\r
3346                         if (fListA)\r
3347                                 Column += fprintf(lst_fh, "%08lX ", *pNextAddr);\r
3348                         Instruction();\r
3349                         break;\r
3350         case REGIST:\r
3351                         line_error(63);\r
3352                         break;\r
3353         case SYMBOL:\r
3354                         line_error(64);\r
3355                         break;\r
3356         case LSYMBOL:\r
3357                         line_error(65);\r
3358                         break;\r
3359         case STRING:\r
3360         case NUMBER:\r
3361                         line_error(66);\r
3362                         break;\r
3363         case rPUBLIC:\r
3364                         fPublic = 1;\r
3365                         if (fListA)\r
3366                                 Column += fprintf(lst_fh, "%08lX ", *pNextAddr);\r
3367                         j = Parse();\r
3368                         if (j==SYMBOL)\r
3369                                         MakePublic();\r
3370                         else if (j==UNKSYM)\r
3371                                 NewSymbol();\r
3372                         else\r
3373                                 line_error(67);\r
3374                         break;\r
3375         case rEXTRN:\r
3376                         fExtern = 1;\r
3377                         if (fListA)\r
3378                                 Column += fprintf(lst_fh, "%08lX ", *pNextAddr);\r
3379                         j = Parse();\r
3380                         if (j==SYMBOL)\r
3381                                         CheckExtern();\r
3382                         else if (j==UNKSYM)\r
3383                                 NewSymbol();\r
3384                         else\r
3385                                 line_error(67);\r
3386                         break;\r
3387         case UNKSYM:\r
3388                         if (fListA)\r
3389                                 Column += fprintf(lst_fh, "%08lX ", *pNextAddr);\r
3390                         if (level)\r
3391                                 NewLSymbol();\r
3392                         else\r
3393                                 NewSymbol();\r
3394                         break;\r
3395         case DOT:\r
3396                         Command();\r
3397                         break;\r
3398         case rDB:\r
3399         case rDD:\r
3400         case rDW:\r
3401         case rDF:\r
3402                 if (fListA)\r
3403                         Column += fprintf(lst_fh, "%08lX ", *pNextAddr);\r
3404                 Storage();\r
3405                 break;\r
3406         case ZERO:\r
3407                 break;\r
3408         default:\r
3409                 line_error(68);\r
3410                 break;\r
3411         }\r
3412 \r
3413   if ((fLineIn) && (fListA)) {\r
3414           while (Column < 53) Column += fprintf(lst_fh, " ");\r
3415           fprintf(lst_fh, "%s", list_buf);\r
3416       }\r
3417   if (Column)\r
3418           fprintf(lst_fh, "\r\n");\r
3419 \r
3420  } /* while */\r
3421 }\r
3422 \r
3423 /*********************\r
3424 * Main program\r
3425 **********************/\r
3426 \r
3427 void main(S32 argc, S8   *argv[])\r
3428 {\r
3429 S8   *ptr, *pname;\r
3430 S32  i, j, fdone;\r
3431 U32 erc;\r
3432 \r
3433         lst_fh = stdout;        /* default the list file */\r
3434 \r
3435         for(i=1; i < argc; ++i) {\r
3436                 ptr = argv[i];\r
3437                 if (*ptr == '/') {\r
3438                   ptr++;\r
3439                   switch(*ptr) {\r
3440                         case 'L' :                      /* List file ON */\r
3441                         case 'l' :\r
3442                                 fListA = 1;\r
3443                                 break;\r
3444                         case 'S' :                      /* Dump Symbols */\r
3445                         case 's' :\r
3446                                 fSymDump = 1;\r
3447                                 break;\r
3448                         case 'E' :                      /* List file ON for errors/warns only */\r
3449                         case 'e' :\r
3450                                 fListE = 1;\r
3451                                 break;\r
3452                         case 'D' :                      /* Process as DLL */\r
3453                         case 'd' :\r
3454                                 filetype = 2;\r
3455                                 break;\r
3456                         case 'V' :                      /* Process as Devive Driver */\r
3457                         case 'v' :\r
3458                                 filetype = 3;\r
3459                                 break;\r
3460                         default:\r
3461                                 fatal_error("Invalid option\n");\r
3462                                 break;\r
3463                   }\r
3464                 }\r
3465                 else {\r
3466                         if(!src_fh[0]) {\r
3467                                 strncpy(srcname, argv[i], 39);\r
3468                                 src_fh[0] = fopen(argv[i], "r");\r
3469                                 }\r
3470                         else if(!run_fh) {\r
3471                                 strncpy(runname, argv[i], 39);\r
3472                                 if(!(run_fh = fopen(argv[i], "wb"))) {\r
3473                                   fatal_error("Can't open RUN file\n");\r
3474                                   }\r
3475                                 }\r
3476                         else\r
3477                                 fatal_error("Too many options\n"); /* Too many parameters */\r
3478            }\r
3479         }\r
3480 \r
3481 /* Input file not explicitly named errors out */\r
3482         if(!src_fh[0]) {\r
3483                 printf("Usage: ATFfile [RunFile] /L /E /D /V\r\n");\r
3484                 printf("/L = Complete List file generated\r\n");\r
3485                 printf("/S = Include SYMBOLS (only in complete list file)\r\n");\r
3486                 printf("/E = List file for Errors/warnings only\r\n");\r
3487                 printf("/D = Process as Dynamic link library\r\n");\r
3488                 printf("/V = Process as deVice driver\r\n");\r
3489                 fatal_error("Can't open Template file\n"); /* Can't open ATF file */\r
3490                 }\r
3491 \r
3492 /* Output file not explicitly named defaults to Source.RUN */\r
3493 \r
3494         if(!run_fh)     {                       /* default asm name to SourceName.run */\r
3495                 strncpy(runname, srcname, 40);\r
3496                 pname=runname;\r
3497                 while ((*pname != '.') && (*pname!= '\0')) pname++;\r
3498                 *pname++ = '.';\r
3499         if (filetype == 2) {\r
3500                  *pname++ = 'D';\r
3501                  *pname++ = 'L';\r
3502                  *pname++ = 'L';\r
3503         }\r
3504         else if (filetype == 3) {\r
3505                  *pname++ = 'D';\r
3506                  *pname++ = 'D';\r
3507                  *pname++ = 'R';\r
3508         }\r
3509         else {\r
3510          filetype = 1;\r
3511                  *pname++ = 'R';\r
3512                  *pname++ = 'U';\r
3513                  *pname++ = 'N';\r
3514                 }\r
3515                 *pname   = '\0';\r
3516                 if(!(run_fh = fopen(runname, "wb"))) {\r
3517                         fatal_error("Can't open OUTPUT file\n");  /* Can't open RUN file */\r
3518                         }\r
3519                 }\r
3520 \r
3521 /* List file named Source.LIS for fListA and fListE only. */\r
3522 \r
3523         if (fListA | fListE) {\r
3524                 strncpy(lstname, srcname, 40);\r
3525                 pname=lstname;\r
3526                 while ((*pname != '.') && (*pname!= '\0')) pname++;\r
3527                 *pname++ = '.';\r
3528                 *pname++ = 'L';\r
3529                 *pname++ = 'I';\r
3530                 *pname++ = 'S';\r
3531                 *pname   = '\0';\r
3532                 if(!(lst_fh = fopen(lstname, "w")))\r
3533                         fatal_error("Can't open list file (source.LIS)\n"); /* Can't open List file */\r
3534                 }\r
3535                 else\r
3536             lst_fh = stdout;\r
3537 \r
3538 printf("DASM Ver 1.7M (c) R.A. Burgess 1992,1993,1994,1995\r\n\r\n");\r
3539 \r
3540 if (fListA | fListE)\r
3541         fprintf(lst_fh, "DASM Ver 1.7M (c) R.A. Burgess 1992,1993,1994,1995\r\n\r\n");\r
3542 \r
3543 if (fListA)\r
3544         fprintf(lst_fh,\r
3545     "LINE   OFFSET   ACTION/DATA/CODE                     SOURCE\r\n\r\n");\r
3546 \r
3547         erc = AllocPage(LSYMBUFMAX/4096, &pLSymBuf);\r
3548         if (erc)\r
3549                 fatal_error("Can't Allocate buffer 1\n");\r
3550 \r
3551         erc = AllocPage(SYMBUFMAX/4096, &pSymBuf);\r
3552         if (erc)\r
3553                 fatal_error("Can't Allocate buffer 2\n");\r
3554 \r
3555         erc = AllocPage(MACBUFMAX/4096, &pMacBuf);\r
3556         if (erc)\r
3557                 fatal_error("Can't Allocate buffer 3\n");\r
3558 \r
3559         erc = AllocPage(FREFBUFMAX/4096, &pRefBuf);\r
3560         if (erc)\r
3561                 fatal_error("Can't Allocate buffer 4\n");\r
3562 \r
3563         erc = AllocPage(FREFTABMAX/4096, &pfrt);\r
3564         if (erc)\r
3565                 fatal_error("Can't Allocate buffer 5\n");\r
3566 \r
3567         erc = AllocPage(FIXUPBUFMAX/4096, &pfut);\r
3568         if (erc)\r
3569                 fatal_error("Can't Allocate buffer 6\n");\r
3570 \r
3571 \r
3572 pSymNext = pSymBuf;             /* Allocate memory - Was SymBuf */\r
3573 pLSymNext = pLSymBuf;   /* Allocate memory - Was LSymBuf */\r
3574 pMacNext = pMacBuf;             /* Allocate memory - Was MacBuf */\r
3575 pRefNext = pRefBuf;             /* Allocate memory - Was RefBuf */\r
3576 \r
3577 pNextAddr = &oNextData; /* default to DataSeg */\r
3578 \r
3579 erc = AllocPage(STMPBUFS/4096, &pcsbuf);\r
3580 if (erc)\r
3581         fatal_error("Can't Allocate CS buffer \n");\r
3582 \r
3583 erc = AllocPage(STMPBUFS/4096, &pdsbuf);\r
3584 if (erc)\r
3585         fatal_error("Can't Allocate DS buffer \n");\r
3586 \r
3587 ics = 0;                        /* current index into tmp buffers */\r
3588 ids = 0;\r
3589 \r
3590 /* We now build a dynamic instruction lookup table which indexes\r
3591 the first entry of an instruction in the opcode array 'rgINS'.\r
3592 This is done dynamically because we are still optimizing.\r
3593 */\r
3594 \r
3595 /* i is the instruction we are indexing */\r
3596 /* j is the position in rgINS */\r
3597 \r
3598 for (i=1; i<ninst+1; i++) {\r
3599         for (j=1; j<nrgINS; j++) {\r
3600                 if (rgINS[j][0] == i) {\r
3601                 rgInsLookUp[i] = j;\r
3602                 break;\r
3603                 }\r
3604         }\r
3605 }\r
3606 \r
3607 Dispatch();\r
3608 exit(0);\r
3609 }\r