OpenCores
URL https://opencores.org/ocsvn/rf6809/rf6809/trunk

Subversion Repositories rf6809

[/] [rf6809/] [trunk/] [software/] [a09/] [a09.c] - Blame information for rev 22

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 4 robfinch
/* A09, 6809 Assembler.
2
 
3
   (C) Copyright 1993,1994 L.C. Benschop.
4
   Parts (C) Copyright 2001-2010 H. Seib.
5
   Mods for 12-bit FPGA core 6809 by R. Finch
6
 
7
   This version of the program is distributed under the terms and conditions
8
   of the GNU General Public License version 2. See file the COPYING for details.
9
   THERE IS NO WARRANTY ON THIS PROGRAM.
10
 
11
   Generates binary image file from the lowest to
12
   the highest address with actually assembled data.
13
 
14
   Machine dependencies:
15
                  char is 8 bits.
16
                  short is 16 bits.
17
                  integer arithmetic is twos complement.
18
 
19
   syntax:
20
     a09 [-{b|r|s|x|f}filename]|[-c] [-lfilename] [-ooption] [-dsym=value]* sourcefile.
21
 
22
   Options
23
   -Vfilename    Verilog rommem declaration output
24
   -c suppresses code output
25
   -bfilename    binary output file name (default name minus a09 suffix plus .bin)
26
   -rfilename    Flex9 RELASMB-compatible output file name (relocatable)
27
   -sfilename    s-record output file name (default its a binary file)
28
   -xfilename    intel hex output file name (-"-)
29
   -ffilename    Flex9 output file name (-"-)
30
   -lfilename    list file name (default no listing)
31
   -dsym[=value] define a symbol
32
   -oopt defines an option
33
 
34
   recognized pseudoops:
35
    ext        defines an external symbol (relocating mode only)
36
    extern     -"-
37
    public     defines a public symbol (effective in relocating mode only)
38
    macro      defines a macro
39
    exitm      terminates a macro expansion
40
    endm       ends a macro definition
41
    if
42
    ifn
43
    ifc
44
    ifnc
45
    else
46
    endif
47
    dup
48
    endd
49
    org
50
    equ
51
    set
52
    setdp      sets direct page in 6809 / 6309 mode
53
    text
54
    fcb
55
    fcw
56
    fdb
57
    fcc
58
    rmb
59
    reg
60
    end
61
    include
62
    title
63
    nam
64
    ttl
65
    sttl
66
    setpg
67
    pag
68
    spc
69
    rep
70
    rpt
71
    repeat
72
    opt        define an option (see below for possible options)
73
    err
74
    abs        force absolute mode
75
    common
76
    endcom
77
    def
78
    define
79
    enddef
80
    name
81
    symlen
82
    bin, binary includes a binary file at the current position
83
 
84
   recognized options:
85
     On | Off         Meaning
86
    ------------------------------------------------------------
87
    PAG | NOP*        Page Formatting
88
    CON | NOC*        Print skipped conditional code
89
    MAC*| NOM         Print macro calling line
90
    EXP | NOE*        Print macro expansion lines
91
    SYM*| NOS         Print symbol table
92
    MUL*| NMU         Print multiple object code lines
93
    LIS*| NOL         Print assembler listing
94
    LP1 | NO1*        Print Pass 1 Listing
95
    DAT*| NOD         Print date in listing
96
    NUM | NON*        Print line numbers
97
    INV | NOI*        Print invisible lines
98
    TSC | NOT*        Strict TSC Compatibility
99
    WAR*| NOW         Print warnings
100
    CLL*| NCL         Check line length
101
    LFN | NLF*        Print long file names
102
    LLL*| NLL         List library lines
103
    GAS | NOG*        Gnu AS source style compatibility
104
    REL*| NOR         Print Relocation table in Relocating mode
105
    M68*| H63 | M00   MC6809 / HD6309 / MC6800 mode
106
    TXT | NTX*        Print text table
107
    LPA | LNP*        Listing in f9dasm patch format
108
    * denotes default value
109
 
110
 
111
   v0.1 93/11/03 Initial version.
112
 
113
   v0.2 94/03/21 Fixed PC relative addressing bug
114
                 Added SET, SETDP, INCLUDE. IF/ELSE/ENDIF
115
                 No macros yet, and no separate linkable modules.
116
 
117
   v0.1.X 99/12/20 added Intel hex option (SLB)
118
 
119
-- H.Seib Additions: --
120
 
121
   v0.2.S 01/10/13 converted to readable format
122
   v0.3   01/10/15 added transfer address processing
123
                   increased max. #symbols and other constants
124
                     (hey, this isn't CP/M anymore :-)
125
                   added a bit of intelligence to command line processing
126
                   loads file(s) into internal storage prior to processing
127
                     (this aids a lot in preventing recursive invocations)
128
                   added LIB,LIBRARY pseudoop (same as INCLUDE)
129
                   added OPT,OPTION pseudoop
130
   v0.4   01/10/22 added -t switch to increase compatibility with the
131
                   TSC FLEX Assembler line, which uses a slightly more
132
                   rigid source file format
133
   v0.5   01/10/23 added SETPG, SETLI, PAG, SPC, NAM(TTL,TITLE), STTL, REP(RPT,REPEAT)
134
   v0.6   01/10/23 added EXITM, IFN, IFC, IFNC, DUP, ENDD
135
   v0.7   01/10/29 added REG, ERR, TEXT
136
   v0.8   01/10/30 converted command line handling to -O switch for options
137
                   and added a bunch of options
138
                   RZB pseudoop added
139
   v0.9   01/11/05 clean-ups, increased TSC FLEX Assembler compatibility
140
   v0.10  01/11/15 ASM and VERSION texts predefined
141
   v0.11  01/11/27 increased TSC FLEX Assembler compatibility (labels made case sensitive)
142
   v0.12  01/11/28 added some convenience mnemonics and simulated 6800 instructions to
143
                   increase TSC FLEX Assembler compatibility
144
   v1.02  01/04/11 check for address range overlaps implemented
145
   v1.03  02/09/24 macro parser had an error; corrected
146
   v1.04  02/12/10 error message output adjusted for Visual C++ 6.0 IDE compatibility
147
                   added OPT LFN/NLF for that purpose
148
   v1.05  02/12/23 crude form of backwards ORG added to binary output
149
   v1.06  03/06/10 added OPT LLL/NLL to include/suppress listing of LIB lines
150
   v1.07  03/06/23 outsymtable() only starts with a page feed if current line
151
                   is is NOT the first line on a page
152
   v1.08  03/07/01 SKIP count for the IF(N) and IF(N)C statements added to
153
                   normal statements (i.e., outside macro definitions)
154
   v1.09  05/06/02 some cleanups
155
                   added -r format for FLEX9 RELASMB compatible output
156
                   added ABS, GLOBAL, EXT, DEFINE, ENDDEF, COMMON, ENDCOM
157
                   REL|NOR option added
158
                   GAS|NOG option added (rudimentary)
159
                   M68|H63 option added
160
   v1.10  05/06/03 made options available as numeric strings
161
                   added local label support
162
                   added SYMLEN
163
                   TXT|NTX option added
164
   v1.11  05/06/06 IFD/IFND directives added
165
                   added special checks for "0,-[-]indexreg" and "0,indexreg+[+]"
166
                   when determining the postbyte for indexed addressing modes
167
   v1.12  05/06/20 OPT CON|NOC correctly implemented
168
   v1.13           skipped for users that might have an uneasy feeling about
169
                   the number "13" >:-)
170
   v1.14  05/08/01 text symbol replacement enhanced; it was a bit TOO general.
171
                   Now, &xxx is only treated as a text variable when xxx REALLY
172
                   is a text symbol; in all other cases, it's not preprocessed.
173
                   Let the assembler engine handle eventual errors.
174
                   Thanks to Peter from Australia for pointing this out!
175
   v1.15  05/08/02 only 1 local label was allowed per address; now, as many as
176
                   possible can be at the same location.
177
                   Thanks to Peter from Australia for pointing this out!
178
   v1.16  05/08/05 SETDP is illegal in relocating mode!
179
                   SETDP without any parameter DISABLES Direct mode entirely.
180
                   Cured an interesting bug... the following sequence:
181
                              ORG 1
182
                              LDA TEST
183
                       SHIT   NOP
184
                              ORG 1
185
                       TEST   RMB 1
186
                   caused a phase error; this was caused by the invalid
187
                   assumption in scanlabel() that forward references have
188
                   a higher memory location than the current address.
189
                   Thanks to Peter from Australia for pointing this out!
190
   v1.17  08/08/05 made tests for above problem more rigorous; now ANY forward
191
                   reference to a label that's not yet defined is treated as
192
                   uncertain.
193
                   Removed a nasty bug that caused the following code to produce
194
                   incorrect values:
195
                            org $8000  (anything >= $8000 will do)
196
                         lbl rmb 8
197
                         SizeBad equ (*-lbl)/2
198
                   OPT NOL changed to OPT NO1 to allow implementing OPT LIS|NOL.
199
                   OPT LIS*|NOL added
200
                   Thanks to Peter from Australia for pointing these out!
201
   v1.18  09/08/05 backward search for local labels now searches for "<= local
202
                   address" instead of "< local address"
203
                   Thanks to Peter from Australia for pointing this out!
204
                   Added INCD / DECD convenience mnemonics
205
                   (realized as ADDD/SUBD 1)
206
   v1.19  10/08/05 Added a bunch of 6800-style mnemonics; if they conflict
207
                   with 6809 mnemonics ("INC A" for example), they are only
208
                   active in TSC mode
209
   v1.20  16/08/05 changed special checks for
210
                     "0,-[-]indexreg" and "0,indexreg+[+]"
211
                   to include all known labels and changed the scope to
212
                     ",[-[-]]indexreg[+[+]]"
213
   v1.21  21/02/06 Bug in "xxx  >0,reg" found by Margus Kliimask
214
   v1.22  03/09/08 Addded BIN(ARY) pseudo-op to include binary files
215
   v1.23  13/02/09 6800 code generation added
216
                   accept multiple input files (first one defines default
217
                     output and listing file names)
218
   v1.24  13/02/09 made compilable with gcc
219
   v1.25  05/03/09 6800 alternate mnemonics work better now
220
   v1.26  14/03/09 assembling DOS format files in Loonix works better now
221
   v1.27  20/01/10 LPA/NLP options added
222
   v1.28  21/04/10 INCD/DECD produced invalid code
223
 
224
*/
225
 
226
#include <stdio.h>
227
#include <string.h>
228
#include <ctype.h>
229
#include <malloc.h>
230
#include <stdarg.h>
231
#include <stdlib.h>
232
#include <time.h>
233
 
234
/*****************************************************************************/
235
/* Definitions                                                               */
236
/*****************************************************************************/
237
 
238
#define VERSION      "1.30"
239
#define VERSNUM      "$011D"            /* can be queried as &VERSION        */
240
 
241
#define UNIX 0                          /* set to != 0 for UNIX specials     */
242
 
243
#define MAX_PASSNO      9
244
#define MAXLABELS    8192
245
#define MAXMACROS    1024
246
#define MAXTEXTS     1024
247
#define MAXRELOCS    32768
248
#define MAXIDLEN     32
249
#define MAXLISTBYTES 7
250
#define FNLEN        256
251
#define LINELEN      1024
252
 
253
/*****************************************************************************/
254
/* Line buffer definitions                                                   */
255
/*****************************************************************************/
256
 
257
struct linebuf
258
  {
259
  struct linebuf * next;                /* pointer to next line              */
260
  struct linebuf * prev;                /* pointer to previous line          */
261
  char *fn;                             /* pointer to original file name     */
262
  long ln;                              /* line number therein               */
263
  unsigned char lvl;                    /* line level                        */
264
  unsigned char rel;                    /* relocation mode                   */
265
  char txt[1];                          /* text buffer                       */
266
  };
267
 
268
char *fnms[128] = {0};                  /* we process up to 128 different fls*/
269
short nfnms;                            /* # loaded files                    */
270
 
271
                                        /* special bits in lvl :             */
272
#define LINCAT_MACDEF       0x20        /* macro definition                  */
273
#define LINCAT_MACEXP       0x40        /* macro expansion                   */
274
#define LINCAT_INVISIBLE    0x80        /* does not appear in listing        */
275
#define LINCAT_LVLMASK      0x1F        /* mask for line levels (0..31)      */
276
 
277
struct linebuf *rootline = NULL;        /* pointer to 1st line of the file   */
278
struct linebuf *curline = NULL;         /* pointer to currently processed ln */
279
 
280
/*****************************************************************************/
281
/* Opcode definitions                                                        */
282
/*****************************************************************************/
283
 
284
struct oprecord
285
  {
286
  char * name;                          /* opcode mnemonic                   */
287
  unsigned char cat;                    /* opcode category                   */
288
  unsigned __int64 code;                /* category-dependent additional code*/
289
  unsigned char tgtNdx;
290
  };
291
 
292
                                        /* Instruction categories :          */
293
#define OPCAT_ONEBYTE        0x00       /* one byte opcodes             NOP  */
294
#define OPCAT_TWOBYTE        0x01       /* two byte opcodes             SWI2 */
295
#define OPCAT_THREEBYTE      0x02       /* three byte opcodes            TAB */
296
#define OPCAT_FOURBYTE       0x03       /* four byte opcodes             ABA */
297
#define OPCAT_IMMBYTE        0x04       /* opcodes w. imm byte         ANDCC */
298
#define OPCAT_LEA            0x05       /* load effective address       LEAX */
299
#define OPCAT_SBRANCH        0x06       /* short branches               BGE  */
300
#define OPCAT_LBR2BYTE       0x07       /* long branches 2 byte opc     LBGE */
301
#define OPCAT_LBR1BYTE       0x08       /* long branches 2 byte opc     LBRA */
302
#define OPCAT_ARITH          0x09       /* accumulator instr.           ADDA */
303
#define OPCAT_DBLREG1BYTE    0x0a       /* double reg instr 1 byte opc  LDX  */
304
#define OPCAT_DBLREG2BYTE    0x0b       /* double reg instr 2 byte opc  LDY  */
305
#define OPCAT_SINGLEADDR     0x0c       /* single address instrs        NEG  */
306
#define OPCAT_2REG           0x0d       /* 2 register instr         TFR,EXG  */
307
#define OPCAT_STACK          0x0e       /* stack instr             PSHx,PULx */
308
#define OPCAT_BITDIRECT      0x0f       /* direct bitmanipulation       AIM  */
309
#define OPCAT_BITTRANS       0x10       /* direct bit transfer         BAND  */
310
#define OPCAT_BLOCKTRANS     0x11       /* block transfer               TFM  */
311
#define OPCAT_IREG           0x12       /* inter-register operations   ADCR  */
312
#define OPCAT_QUADREG1BYTE   0x13       /* quad reg instr 1 byte opc    LDQ  */
313
#define OPCAT_2IMMBYTE       0x14       /* 2byte opcode w. imm byte    BITMD */
314
#define OPCAT_2ARITH         0x15       /* 2byte opcode accum. instr.   SUBE */
315
#define OPCAT_ACCARITH       0x16       /* acc. instr. w.explicit acc   ADD  */
316
#define OPCAT_IDXEXT         0x17       /* indexed/extended, 6800-style JMP  */
317
#define OPCAT_ACCADDR        0x18       /* single address instrs, 6800  NEG  */
318
#define OPCAT_PSEUDO         0x3f       /* pseudo-ops                        */
319
#define OPCAT_6309           0x40       /* valid for 6309 only!              */
320
#define OPCAT_NOIMM          0x80       /* immediate not allowed!       STD  */
321
 
322
                                        /* the various Pseudo-Ops            */
323
#define PSEUDO_RMB            0
324
#define PSEUDO_ELSE           1
325
#define PSEUDO_END            2
326
#define PSEUDO_ENDIF          3
327
#define PSEUDO_ENDM           4
328
#define PSEUDO_EQU            5
329
#define PSEUDO_EXT            6
330
#define PSEUDO_FCB            7
331
#define PSEUDO_FCC            8
332
#define PSEUDO_FCW            9
333
#define PSEUDO_IF            10
334
#define PSEUDO_MACRO         11
335
#define PSEUDO_ORG           12
336
#define PSEUDO_PUB           13
337
#define PSEUDO_SETDP         14
338
#define PSEUDO_SET           15
339
#define PSEUDO_INCLUDE       16
340
#define PSEUDO_OPT           17
341
#define PSEUDO_NAM           18
342
#define PSEUDO_STTL          19
343
#define PSEUDO_PAG           20
344
#define PSEUDO_SPC           21
345
#define PSEUDO_REP           22
346
#define PSEUDO_SETPG         23
347
#define PSEUDO_SETLI         24
348
#define PSEUDO_EXITM         25
349
#define PSEUDO_IFN           26
350
#define PSEUDO_IFC           27
351
#define PSEUDO_IFNC          28
352
#define PSEUDO_DUP           29
353
#define PSEUDO_ENDD          30
354
#define PSEUDO_REG           31
355
#define PSEUDO_ERR           32
356
#define PSEUDO_TEXT          33
357
#define PSEUDO_RZB           34
358
#define PSEUDO_ABS           35
359
#define PSEUDO_DEF           36
360
#define PSEUDO_ENDDEF        37
361
#define PSEUDO_COMMON        38
362
#define PSEUDO_ENDCOM        39
363
#define PSEUDO_NAME          40
364
#define PSEUDO_SYMLEN        41
365
#define PSEUDO_IFD           42
366
#define PSEUDO_IFND          43
367
#define PSEUDO_BINARY        44
368
#define PSEUDO_FCDW          45
369
 
370
struct oprecord optable09[]=
371
  {
372
  { "ABA",     OPCAT_FOURBYTE,    0x0340040ab0e0LL, 0 },
373
  { "ABS",     OPCAT_PSEUDO,      PSEUDO_ABS, 0 },
374
  { "ABX",     OPCAT_ONEBYTE,     0x3a, 0 },
375
  { "ABY",     OPCAT_TWOBYTE,     0x0310a5, 0 },
376
  { "ADC",     OPCAT_ACCARITH,    0x89, 0 },
377
  { "ADCA",    OPCAT_ARITH,       0x89, 0 },
378
  { "ADCB",    OPCAT_ARITH,       0xc9, 0 },
379
  { "ADCD",    OPCAT_6309 |
380
               OPCAT_DBLREG1BYTE, 0x189, 0 },
381
  { "ADCR",    OPCAT_6309 |
382 22 robfinch
               OPCAT_IREG,        0x131, 0 },
383 4 robfinch
  { "ADD",     OPCAT_ACCARITH,    0x8b, 0 },
384
  { "ADDA",    OPCAT_ARITH,       0x8b, 0 },
385
  { "ADDB",    OPCAT_ARITH,       0xcb, 0 },
386
  { "ADDD",    OPCAT_DBLREG1BYTE, 0xc3, 0 },
387
  { "ADDE",    OPCAT_6309 |
388 22 robfinch
               OPCAT_ARITH,      0x28b, 0 },
389 4 robfinch
  { "ADDF",    OPCAT_6309 |
390 22 robfinch
               OPCAT_ARITH,      0x2cb, 0 },
391 4 robfinch
  { "ADDR",    OPCAT_6309 |
392 22 robfinch
               OPCAT_IREG,        0x130, 0 },
393 4 robfinch
  { "ADDW",    OPCAT_6309 |
394 22 robfinch
               OPCAT_DBLREG2BYTE, 0x18b, 0 },
395 4 robfinch
  { "AIM",     OPCAT_6309 |
396
               OPCAT_BITDIRECT,   0x02, 0 },
397
  { "AND",     OPCAT_ACCARITH,    0x84, 0 },
398
  { "ANDA",    OPCAT_ARITH,       0x84, 0 },
399
  { "ANDB",    OPCAT_ARITH,       0xc4, 0 },
400
  { "ANDCC",   OPCAT_IMMBYTE,     0x1c, 0 },
401
  { "ANDD",    OPCAT_6309 |
402
               OPCAT_DBLREG1BYTE, 0x184, 0 },
403
  { "ANDR",    OPCAT_6309 |
404 22 robfinch
               OPCAT_IREG,        0x134, 0 },
405 4 robfinch
  { "ASL",     OPCAT_SINGLEADDR,  0x08, 0 },
406
  { "ASLA",    OPCAT_ONEBYTE,     0x48, 0 },
407
  { "ASLB",    OPCAT_ONEBYTE,     0x58, 0 },
408
  { "ASLD",    OPCAT_TWOBYTE,     0x058049, 0 },
409
  { "ASLD63",  OPCAT_6309 |
410 22 robfinch
               OPCAT_TWOBYTE,     0x148, 0 },
411 4 robfinch
  { "ASR",     OPCAT_SINGLEADDR,  0x07, 0 },
412
  { "ASRA",    OPCAT_ONEBYTE,     0x47, 0 },
413
  { "ASRB",    OPCAT_ONEBYTE,     0x57, 0 },
414
  { "ASRD",    OPCAT_TWOBYTE,     0x047056, 0 },
415
  { "ASRD63",  OPCAT_6309 |
416 22 robfinch
               OPCAT_TWOBYTE,     0x147, 0 },
417 4 robfinch
  { "BAND",    OPCAT_6309 |
418 22 robfinch
               OPCAT_BITTRANS,    0x230, 0 },
419 4 robfinch
  { "BCC",     OPCAT_SBRANCH,     0x24, 0 },
420
  { "BCS",     OPCAT_SBRANCH,     0x25, 0 },
421
  { "BEC",     OPCAT_SBRANCH,     0x24, 0 },
422
  { "BEOR",    OPCAT_6309 |
423 22 robfinch
               OPCAT_BITTRANS,    0x234, 0 },
424 4 robfinch
  { "BEQ",     OPCAT_SBRANCH,     0x27, 0 },
425
  { "BES",     OPCAT_SBRANCH,     0x25, 0 },
426
  { "BGE",     OPCAT_SBRANCH,     0x2c, 0 },
427
  { "BGT",     OPCAT_SBRANCH,     0x2e, 0 },
428
  { "BHI",     OPCAT_SBRANCH,     0x22, 0 },
429
  { "BHS",     OPCAT_SBRANCH,     0x24, 0 },
430
  { "BIAND",   OPCAT_6309 |
431 22 robfinch
               OPCAT_BITTRANS,    0x231, 0 },
432 4 robfinch
  { "BIEOR",   OPCAT_6309 |
433 22 robfinch
               OPCAT_BITTRANS,    0x235, 0 },
434 4 robfinch
  { "BIN",     OPCAT_PSEUDO,      PSEUDO_BINARY, 0 },
435
  { "BINARY",  OPCAT_PSEUDO,      PSEUDO_BINARY, 0 },
436
  { "BIOR",    OPCAT_6309 |
437 22 robfinch
               OPCAT_BITTRANS,    0x233, 0 },
438 4 robfinch
  { "BIT",     OPCAT_ACCARITH,    0x85, 0 },
439
  { "BITA",    OPCAT_ARITH,       0x85, 0 },
440
  { "BITB",    OPCAT_ARITH,       0xc5, 0 },
441
  { "BITD",    OPCAT_6309 |
442
               OPCAT_DBLREG1BYTE, 0x185, 0 },
443
  { "BITMD",   OPCAT_6309 |
444 22 robfinch
               OPCAT_IMMBYTE,    0x23c, 0 },
445 4 robfinch
  { "BLE",     OPCAT_SBRANCH,     0x2f, 0 },
446
  { "BLO",     OPCAT_SBRANCH,     0x25, 0 },
447
  { "BLS",     OPCAT_SBRANCH,     0x23, 0 },
448
  { "BLT",     OPCAT_SBRANCH,     0x2d, 0 },
449
  { "BMI",     OPCAT_SBRANCH,     0x2b, 0 },
450
  { "BNE",     OPCAT_SBRANCH,     0x26, 0 },
451
  { "BOR",     OPCAT_6309 |
452 22 robfinch
               OPCAT_BITTRANS,    0x232, 0 },
453 4 robfinch
  { "BPL",     OPCAT_SBRANCH,     0x2a, 0 },
454
  { "BRA",     OPCAT_SBRANCH,     0x20, 0 },
455
  { "BRN",     OPCAT_SBRANCH,     0x21, 0 },
456
  { "BSR",     OPCAT_SBRANCH,     0x8d, 0 },
457
  { "BVC",     OPCAT_SBRANCH,     0x28, 0 },
458
  { "BVS",     OPCAT_SBRANCH,     0x29, 0 },
459
  { "CBA",     OPCAT_FOURBYTE,    0x0340040a10e0LL, 0 },
460
  { "CLC",     OPCAT_TWOBYTE,     0x1c0fe, 0 },
461
  { "CLF",     OPCAT_TWOBYTE,     0x1c0bf, 0 },
462
  { "CLI",     OPCAT_TWOBYTE,     0x1c0ef, 0 },
463
  { "CLIF",    OPCAT_TWOBYTE,     0x1c0af, 0 },
464
  { "CLR",     OPCAT_SINGLEADDR,  0x0f, 0 },
465
  { "CLRA",    OPCAT_ONEBYTE,     0x4f, 0 },
466
  { "CLRB",    OPCAT_ONEBYTE,     0x5f, 0 },
467
  { "CLRD",    OPCAT_TWOBYTE,     0x4f05f, 0 },
468
  { "CLRD63",  OPCAT_6309 |
469 22 robfinch
               OPCAT_TWOBYTE,     0x14f, 0 },
470 4 robfinch
  { "CLRE",    OPCAT_6309 |
471 22 robfinch
               OPCAT_TWOBYTE,     0x24f, 0 },
472 4 robfinch
  { "CLRF",    OPCAT_6309 |
473 22 robfinch
               OPCAT_TWOBYTE,     0x25f, 0 },
474 4 robfinch
  { "CLRW",    OPCAT_6309 |
475 22 robfinch
               OPCAT_TWOBYTE,     0x15f, 0 },
476 4 robfinch
  { "CLV",     OPCAT_TWOBYTE,     0x1c0fd, 0 },
477
  { "CLZ",     OPCAT_TWOBYTE,     0x1c0fb, 0 },
478
  { "CMP",     OPCAT_ACCARITH,    0x81, 0 },
479
  { "CMPA",    OPCAT_ARITH,       0x81, 0 },
480
  { "CMPB",    OPCAT_ARITH,       0xc1, 0 },
481
  { "CMPD",    OPCAT_DBLREG1BYTE, 0x183, 0 },
482
  { "CMPE",    OPCAT_6309 |
483 22 robfinch
               OPCAT_ARITH,      0x281, 0 },
484 4 robfinch
  { "CMPF",    OPCAT_6309 |
485 22 robfinch
               OPCAT_ARITH,      0x2c1, 0 },
486 4 robfinch
  { "CMPR",    OPCAT_6309 |
487 22 robfinch
               OPCAT_IREG,        0x137, 0 },
488 4 robfinch
  { "CMPS",    OPCAT_DBLREG1BYTE, 0x28c, 4 },
489
  { "CMPU",    OPCAT_DBLREG1BYTE, 0x283, 3 },
490
  { "CMPW",    OPCAT_6309 |
491 22 robfinch
               OPCAT_DBLREG2BYTE, 0x181, 0 },
492 4 robfinch
  { "CMPX",    OPCAT_DBLREG1BYTE, 0x8c, 1 },
493
  { "CMPY",    OPCAT_DBLREG1BYTE, 0x18c, 2 },
494
  { "COM",     OPCAT_SINGLEADDR,  0x03, 0 },
495
  { "COMA",    OPCAT_ONEBYTE,     0x43, 0 },
496
  { "COMB",    OPCAT_ONEBYTE,     0x53, 0 },
497
  { "COMD",    OPCAT_6309 |
498
               OPCAT_ONEBYTE,     0x143, 0 },
499
  { "COME",    OPCAT_6309 |
500 22 robfinch
               OPCAT_TWOBYTE,     0x243, 0  },
501 4 robfinch
  { "COMF",    OPCAT_6309 |
502 22 robfinch
               OPCAT_TWOBYTE,     0x253, 0 },
503 4 robfinch
  { "COMW",    OPCAT_6309 |
504 22 robfinch
               OPCAT_TWOBYTE,     0x153, 0 },
505 4 robfinch
  { "COMMON",  OPCAT_PSEUDO,      PSEUDO_COMMON, 0 },
506
  { "CPD",     OPCAT_DBLREG1BYTE, 0x183, 0 },
507
  { "CPX",     OPCAT_DBLREG1BYTE, 0x8c, 1 },
508
  { "CPY",     OPCAT_DBLREG1BYTE, 0x18c, 2 },
509
  { "CWAI",    OPCAT_IMMBYTE,     0x3c, 0 },
510
  { "DAA",     OPCAT_ONEBYTE,     0x19, 0 },
511
  { "DEC",     OPCAT_SINGLEADDR,  0x0a, 0 },
512
  { "DECA",    OPCAT_ONEBYTE,     0x4a, 0 },
513
  { "DECB",    OPCAT_ONEBYTE,     0x5a, 0 },
514
  { "DECD",    OPCAT_THREEBYTE,   0x083000001LL, 0 },
515
  { "DECD63",  OPCAT_6309 |
516 22 robfinch
               OPCAT_TWOBYTE,     0x14a, 0 },
517 4 robfinch
  { "DECE",    OPCAT_6309 |
518 22 robfinch
               OPCAT_TWOBYTE,     0x24a, 0 },
519 4 robfinch
  { "DECF",    OPCAT_6309 |
520 22 robfinch
               OPCAT_TWOBYTE,     0x25a, 0 },
521 4 robfinch
  { "DECW",    OPCAT_6309 |
522 22 robfinch
               OPCAT_TWOBYTE,     0x15a, 0 },
523 4 robfinch
  { "DEF",     OPCAT_PSEUDO,      PSEUDO_DEF, 0 },
524
  { "DEFINE",  OPCAT_PSEUDO,      PSEUDO_DEF, 0 },
525
  { "DES",     OPCAT_TWOBYTE,     0x327ff, 4 },
526
  { "DEU",     OPCAT_TWOBYTE,     0x335ff, 3 },
527
  { "DEX",     OPCAT_TWOBYTE,     0x301ff, 1 },
528
  { "DEY",     OPCAT_TWOBYTE,     0x313ff, 2 },
529
  { "DIVD",    OPCAT_6309 |
530 22 robfinch
               OPCAT_ARITH,      0x28d, 0 },
531 4 robfinch
  { "DIVQ",    OPCAT_6309 |
532 22 robfinch
               OPCAT_DBLREG2BYTE, 0x28e, 0 },
533 4 robfinch
  { "DUP",     OPCAT_PSEUDO,      PSEUDO_DUP, 0 },
534
  { "EIM",     OPCAT_6309 |
535
               OPCAT_BITDIRECT,   0x05, 0 },
536
  { "ELSE",    OPCAT_PSEUDO,      PSEUDO_ELSE, 0 },
537
  { "END",     OPCAT_PSEUDO,      PSEUDO_END, 0 },
538
  { "ENDCOM",  OPCAT_PSEUDO,      PSEUDO_ENDCOM, 0 },
539
  { "ENDD",    OPCAT_PSEUDO,      PSEUDO_ENDD, 0 },
540
  { "ENDDEF",  OPCAT_PSEUDO,      PSEUDO_ENDDEF, 0 },
541
  { "ENDIF",   OPCAT_PSEUDO,      PSEUDO_ENDIF, 0 },
542
  { "ENDM",    OPCAT_PSEUDO,      PSEUDO_ENDM, 0 },
543
  { "EOR",     OPCAT_ACCARITH,    0x88, 0 },
544
  { "EORA",    OPCAT_ARITH,       0x88, 0 },
545
  { "EORB",    OPCAT_ARITH,       0xc8, 0 },
546
  { "EORD",    OPCAT_6309 |
547
               OPCAT_DBLREG1BYTE, 0x188, 0 },
548
  { "EORR",    OPCAT_6309 |
549 22 robfinch
               OPCAT_IREG,        0x136, 0 },
550 4 robfinch
  { "EQU",     OPCAT_PSEUDO,      PSEUDO_EQU, 0 },
551
  { "ERR",     OPCAT_PSEUDO,      PSEUDO_ERR, 0 },
552
  { "EXG",     OPCAT_2REG,        0x1e, 0 },
553
  { "EXITM",   OPCAT_PSEUDO,      PSEUDO_EXITM, 0 },
554
  { "EXT",     OPCAT_PSEUDO,      PSEUDO_EXT, 0 },
555
  { "EXTERN",  OPCAT_PSEUDO,      PSEUDO_EXT, 0 },
556
  { "FCB",     OPCAT_PSEUDO,      PSEUDO_FCB, 0 },
557
  { "FCC",     OPCAT_PSEUDO,      PSEUDO_FCC, 0 },
558
  { "FCDW",    OPCAT_PSEUDO,      PSEUDO_FCDW, 0 },
559
  { "FCW",     OPCAT_PSEUDO,      PSEUDO_FCW, 0 },
560
  { "FDB",     OPCAT_PSEUDO,      PSEUDO_FCW, 0 },
561
  { "GLOBAL",  OPCAT_PSEUDO,      PSEUDO_PUB, 0 },
562
  { "IF",      OPCAT_PSEUDO,      PSEUDO_IF, 0 },
563
  { "IFC",     OPCAT_PSEUDO,      PSEUDO_IFC, 0 },
564
  { "IFD",     OPCAT_PSEUDO,      PSEUDO_IFD, 0 },
565
  { "IFN",     OPCAT_PSEUDO,      PSEUDO_IFN, 0 },
566
  { "IFNC",    OPCAT_PSEUDO,      PSEUDO_IFNC, 0 },
567
  { "IFND",    OPCAT_PSEUDO,      PSEUDO_IFND, 0 },
568
  { "INC",     OPCAT_SINGLEADDR,  0x0c, 0 },
569
  { "INCA",    OPCAT_ONEBYTE,     0x4c, 0 },
570
  { "INCB",    OPCAT_ONEBYTE,     0x5c, 0 },
571
  { "INCD",    OPCAT_THREEBYTE,   0x0c3000001LL, 0 },
572
  { "INCD63",  OPCAT_6309 |
573 22 robfinch
               OPCAT_TWOBYTE,     0x14c, 0 },
574 4 robfinch
  { "INCE",    OPCAT_6309 |
575 22 robfinch
               OPCAT_TWOBYTE,     0x24c, 0 },
576 4 robfinch
  { "INCF",    OPCAT_6309 |
577 22 robfinch
               OPCAT_TWOBYTE,     0x25c, 0 },
578 4 robfinch
  { "INCLUDE", OPCAT_PSEUDO,      PSEUDO_INCLUDE, 0 },
579
  { "INCW",    OPCAT_6309 |
580 22 robfinch
               OPCAT_TWOBYTE,     0x15c, 0 },
581 4 robfinch
  { "INS",     OPCAT_TWOBYTE,     0x32601, 4 },
582
  { "INU",     OPCAT_TWOBYTE,     0x33401, 3 },
583
  { "INX",     OPCAT_TWOBYTE,     0x30001, 1 },
584
  { "INY",     OPCAT_TWOBYTE,     0x31201, 2 },
585
  { "JMP",     OPCAT_SINGLEADDR,  0x0e, 0 },
586
  { "JSR",     OPCAT_DBLREG1BYTE, 0x8d, 0 },
587
  { "LBCC",    OPCAT_LBR1BYTE,    0x124, 0 },
588
  { "LBCS",    OPCAT_LBR1BYTE,    0x125, 0 },
589
  { "LBEC",    OPCAT_LBR1BYTE,    0x124, 0 },
590
  { "LBEQ",    OPCAT_LBR1BYTE,    0x127, 0 },
591
  { "LBES",    OPCAT_LBR1BYTE,    0x125, 0 },
592
  { "LBGE",    OPCAT_LBR1BYTE,    0x12c, 0 },
593
  { "LBGT",    OPCAT_LBR1BYTE,    0x12e, 0 },
594
  { "LBHI",    OPCAT_LBR1BYTE,    0x122, 0 },
595
  { "LBHS",    OPCAT_LBR1BYTE,    0x124, 0 },
596
  { "LBLE",    OPCAT_LBR1BYTE,    0x12f, 0 },
597
  { "LBLO",    OPCAT_LBR1BYTE,    0x125, 0 },
598
  { "LBLS",    OPCAT_LBR1BYTE,    0x123, 0 },
599
  { "LBLT",    OPCAT_LBR1BYTE,    0x12d, 0 },
600
  { "LBMI",    OPCAT_LBR1BYTE,    0x12b, 0 },
601
  { "LBNE",    OPCAT_LBR1BYTE,    0x126, 0 },
602
  { "LBPL",    OPCAT_LBR1BYTE,    0x12a, 0 },
603
  { "LBRA",    OPCAT_LBR1BYTE,    0x16, 0 },
604
  { "LBRN",    OPCAT_LBR1BYTE,    0x121, 0 },
605
  { "LBSR",    OPCAT_LBR1BYTE,    0x17, 0 },
606
  { "LBVC",    OPCAT_LBR1BYTE,    0x128, 0 },
607
  { "LBVS",    OPCAT_LBR1BYTE,    0x129, 0 },
608
  { "LD",      OPCAT_ACCARITH,    0x86, 0 },
609
  { "LDA",     OPCAT_ARITH,       0x86, 0 },
610
  { "LDAA",    OPCAT_ARITH,       0x86, 0 },
611
  { "LDAB",    OPCAT_ARITH,       0xc6, 0 },
612
  { "LDAD",    OPCAT_DBLREG1BYTE, 0xcc, 0 },
613
  { "LDB",     OPCAT_ARITH,       0xc6, 0 },
614
  { "LDBT",    OPCAT_6309 |
615 22 robfinch
               OPCAT_BITTRANS,    0x236, 0 },
616 4 robfinch
  { "LDD",     OPCAT_DBLREG1BYTE, 0xcc, 0 },
617
  { "LDE",     OPCAT_6309 |
618 22 robfinch
               OPCAT_ARITH,      0x286, 0 },
619 4 robfinch
  { "LDF",     OPCAT_6309 |
620 22 robfinch
               OPCAT_ARITH,      0x2c6, 0 },
621 4 robfinch
  { "LDMD",    OPCAT_6309 |
622 22 robfinch
               OPCAT_IMMBYTE,    0x23d, 0 },
623 4 robfinch
  { "LDQ",     OPCAT_6309 |
624 22 robfinch
               OPCAT_QUADREG1BYTE,0x1cc, 0 },
625 4 robfinch
  { "LDS",     OPCAT_DBLREG1BYTE, 0x1ce, 4 },
626
  { "LDU",     OPCAT_DBLREG1BYTE, 0xce, 3 },
627
  { "LDW",     OPCAT_6309 |
628 22 robfinch
               OPCAT_DBLREG2BYTE, 0x186, 0 },
629 4 robfinch
  { "LDX",     OPCAT_DBLREG1BYTE, 0x8e, 1 },
630
  { "LDY",     OPCAT_DBLREG1BYTE, 0x18e, 2 },
631
  { "LEAS",    OPCAT_LEA,         0x32, 4 },
632
  { "LEAU",    OPCAT_LEA,         0x33, 3 },
633
  { "LEAX",    OPCAT_LEA,         0x30, 1 },
634
  { "LEAY",    OPCAT_LEA,         0x31, 2 },
635
  { "LIB",     OPCAT_PSEUDO,      PSEUDO_INCLUDE, 0 },
636
  { "LIBRARY", OPCAT_PSEUDO,      PSEUDO_INCLUDE, 0 },
637
  { "LSL",     OPCAT_SINGLEADDR,  0x08, 0 },
638
  { "LSLA",    OPCAT_ONEBYTE,     0x48, 0 },
639
  { "LSLB",    OPCAT_ONEBYTE,     0x58, 0 },
640
  { "LSLD",    OPCAT_TWOBYTE,     0x58049, 0 },
641
  { "LSLD63",  OPCAT_6309 |
642 22 robfinch
               OPCAT_TWOBYTE,     0x148, 0 },
643 4 robfinch
  { "LSR",     OPCAT_SINGLEADDR,  0x04, 0 },
644
  { "LSRA",    OPCAT_ONEBYTE,     0x44, 0 },
645
  { "LSRB",    OPCAT_ONEBYTE,     0x54, 0 },
646
  { "LSRD",    OPCAT_TWOBYTE,     0x44056, 0 },
647
  { "LSRD63",  OPCAT_6309 |
648 22 robfinch
               OPCAT_TWOBYTE,     0x144, 0 },
649 4 robfinch
  { "LSRW",    OPCAT_6309 |
650 22 robfinch
               OPCAT_TWOBYTE,     0x154, 0 },
651 4 robfinch
  { "MACRO",   OPCAT_PSEUDO,      PSEUDO_MACRO, 0 },
652
  { "MUL",     OPCAT_ONEBYTE,     0x3d, 0 },
653
  { "MULD",    OPCAT_6309 |
654 22 robfinch
               OPCAT_DBLREG2BYTE, 0x28f, 0 },
655 4 robfinch
  { "NAM",     OPCAT_PSEUDO,      PSEUDO_NAM, 0 },
656
  { "NAME",    OPCAT_PSEUDO,      PSEUDO_NAME, 0 },
657
  { "NEG",     OPCAT_SINGLEADDR,  0x00, 0 },
658
  { "NEGA",    OPCAT_ONEBYTE,     0x40, 0 },
659
  { "NEGB",    OPCAT_ONEBYTE,     0x50, 0 },
660
  { "NEGD",    OPCAT_6309 |
661
               OPCAT_ONEBYTE,     0x140, 0 },
662
  { "NOP",     OPCAT_ONEBYTE,     0x12, 0 },
663
  { "OIM",     OPCAT_6309 |
664
               OPCAT_BITDIRECT,   0x01, 0 },
665
  { "OPT",     OPCAT_PSEUDO,      PSEUDO_OPT, 0 },
666
  { "OPTION",  OPCAT_PSEUDO,      PSEUDO_OPT, 0 },
667
  { "ORA",     OPCAT_ARITH,       0x8a, 0 },
668
  { "ORAA",    OPCAT_ARITH,       0x8a, 0 },
669
  { "ORAB",    OPCAT_ARITH,       0xca, 0 },
670
  { "ORB",     OPCAT_ARITH,       0xca, 0 },
671
  { "ORCC",    OPCAT_IMMBYTE,     0x1a, 0 },
672
  { "ORD",     OPCAT_6309 |
673
               OPCAT_DBLREG1BYTE, 0x18a, 0 },
674
  { "ORG",     OPCAT_PSEUDO,      PSEUDO_ORG, 0 },
675
  { "ORR",     OPCAT_6309 |
676 22 robfinch
               OPCAT_IREG,        0x135, 0 },
677 4 robfinch
  { "PAG",     OPCAT_PSEUDO,      PSEUDO_PAG, 0 },
678
  { "PAGE",    OPCAT_PSEUDO,      PSEUDO_PAG, 0 },
679
  { "PSH",     OPCAT_STACK,       0x34, 0 },
680
  { "PSHA",    OPCAT_TWOBYTE,     0x34002, 0 },
681
  { "PSHB",    OPCAT_TWOBYTE,     0x34004, 0 },
682
  { "PSHD",    OPCAT_TWOBYTE,     0x34006, 0 },
683
  { "PSHS",    OPCAT_STACK,       0x34, 4 },
684
  { "PSHSW",   OPCAT_6309 |
685 22 robfinch
               OPCAT_TWOBYTE,     0x138, 0 },
686 4 robfinch
  { "PSHU",    OPCAT_STACK,       0x36, 3 },
687
  { "PSHUW",   OPCAT_6309 |
688 22 robfinch
               OPCAT_TWOBYTE,     0x13a, 0 },
689 4 robfinch
  { "PSHX",    OPCAT_TWOBYTE,     0x34010, 1 },
690
  { "PSHY",    OPCAT_TWOBYTE,     0x34020, 2 },
691
  { "PUB",     OPCAT_PSEUDO,      PSEUDO_PUB, 0 },
692
  { "PUBLIC",  OPCAT_PSEUDO,      PSEUDO_PUB, 0 },
693
  { "PUL",     OPCAT_STACK,       0x35, 0 },
694
  { "PULA",    OPCAT_TWOBYTE,     0x35002, 0 },
695
  { "PULB",    OPCAT_TWOBYTE,     0x35004, 0 },
696
  { "PULD",    OPCAT_TWOBYTE,     0x35006, 0 },
697
  { "PULS",    OPCAT_STACK,       0x35, 4 },
698
  { "PULSW",   OPCAT_6309 |
699 22 robfinch
               OPCAT_TWOBYTE,     0x139, 0 },
700 4 robfinch
  { "PULU",    OPCAT_STACK,       0x37, 3 },
701
  { "PULUW",   OPCAT_6309 |
702 22 robfinch
               OPCAT_TWOBYTE,     0x13b, 0 },
703 4 robfinch
  { "PULX",    OPCAT_TWOBYTE,     0x35010, 1 },
704
  { "PULY",    OPCAT_TWOBYTE,     0x35020, 2 },
705
  { "REG",     OPCAT_PSEUDO,      PSEUDO_REG, 0 },
706
  { "REP",     OPCAT_PSEUDO,      PSEUDO_REP, 0 },
707
  { "REPEAT",  OPCAT_PSEUDO,      PSEUDO_REP, 0 },
708
  { "RESET",   OPCAT_ONEBYTE,     0x3e, 0 },
709
  { "RMB",     OPCAT_PSEUDO,      PSEUDO_RMB, 0 },
710
  { "ROL",     OPCAT_SINGLEADDR,  0x09, 0 },
711
  { "ROLA",    OPCAT_ONEBYTE,     0x49, 0 },
712
  { "ROLB",    OPCAT_ONEBYTE,     0x59, 0 },
713
  { "ROLD",    OPCAT_6309 |
714
               OPCAT_ONEBYTE,     0x149, 0 },
715
  { "ROLW",    OPCAT_6309 |
716 22 robfinch
               OPCAT_TWOBYTE,     0x159, 0 },
717 4 robfinch
  { "ROR",     OPCAT_SINGLEADDR,  0x06, 0 },
718
  { "RORA",    OPCAT_ONEBYTE,     0x46, 0 },
719
  { "RORB",    OPCAT_ONEBYTE,     0x56, 0 },
720
  { "RORD",    OPCAT_6309 |
721
               OPCAT_ONEBYTE,     0x146, 0 },
722
  { "RORW",    OPCAT_6309 |
723 22 robfinch
               OPCAT_TWOBYTE,     0x156, 0 },
724 4 robfinch
  { "RPT",     OPCAT_PSEUDO,      PSEUDO_REP, 0 },
725
  { "RTF",     OPCAT_ONEBYTE,     0x38, 0 },
726
  { "RTI",     OPCAT_ONEBYTE,     0x3b, 0 },
727
  { "RTS",     OPCAT_ONEBYTE,     0x39, 0 },
728
  { "RZB",     OPCAT_PSEUDO,      PSEUDO_RZB, 0 },
729
  { "SBA",     OPCAT_FOURBYTE,    0x0340040a00e0LL, 0 },
730
  { "SBC",     OPCAT_ACCARITH,    0x82, 0 },
731
  { "SBCA",    OPCAT_ARITH,       0x82, 0 },
732
  { "SBCB",    OPCAT_ARITH,       0xc2, 0 },
733
  { "SBCD",    OPCAT_6309 |
734
               OPCAT_DBLREG1BYTE, 0x182, 0 },
735
  { "SBCR",    OPCAT_6309 |
736 22 robfinch
               OPCAT_IREG,        0x133, 0 },
737 4 robfinch
  { "SEC",     OPCAT_TWOBYTE,     0x1a001, 0 },
738
  { "SEF",     OPCAT_TWOBYTE,     0x1a040, 0 },
739
  { "SEI",     OPCAT_TWOBYTE,     0x1a010, 0 },
740
  { "SEIF",    OPCAT_TWOBYTE,     0x1a050, 0 },
741
  { "SET",     OPCAT_PSEUDO,      PSEUDO_SET, 0 },
742
  { "SETDP",   OPCAT_PSEUDO,      PSEUDO_SETDP, 0 },
743
  { "SETLI",   OPCAT_PSEUDO,      PSEUDO_SETLI, 0 },
744
  { "SETPG",   OPCAT_PSEUDO,      PSEUDO_SETPG, 0 },
745
  { "SEV",     OPCAT_TWOBYTE,     0x1a002, 0 },
746
  { "SEX",     OPCAT_ONEBYTE,     0x1d, 0 },
747
  { "SEXW",    OPCAT_6309 |
748
               OPCAT_ONEBYTE,     0x14, 0 },
749
  { "SEZ",     OPCAT_TWOBYTE,     0x1a004, 0 },
750
  { "SPC",     OPCAT_PSEUDO,      PSEUDO_SPC, 0 },
751
  { "STA",     OPCAT_NOIMM |
752
               OPCAT_ARITH,       0x87, 0 },
753
  { "STAA",    OPCAT_NOIMM |
754
               OPCAT_ARITH,       0x87, 0 },
755
  { "STAB",    OPCAT_NOIMM |
756
               OPCAT_ARITH,       0xc7, 0 },
757
  { "STAD",    OPCAT_NOIMM |
758
               OPCAT_DBLREG1BYTE, 0xcd, 0 },
759
  { "STB",     OPCAT_NOIMM |
760
               OPCAT_ARITH,       0xc7, 0 },
761
  { "STBT",    OPCAT_6309 |
762 22 robfinch
               OPCAT_BITTRANS,    0x237, 0 },
763 4 robfinch
  { "STD",     OPCAT_NOIMM |
764
               OPCAT_DBLREG1BYTE, 0xcd, 0 },
765
  { "STE",     OPCAT_NOIMM |
766
               OPCAT_6309 |
767 22 robfinch
               OPCAT_ARITH,      0x287, 0 },
768 4 robfinch
  { "STF",     OPCAT_NOIMM |
769
               OPCAT_6309 |
770 22 robfinch
               OPCAT_ARITH,      0x2c7, 0 },
771 4 robfinch
  { "STQ",     OPCAT_NOIMM |
772
               OPCAT_6309 |
773 22 robfinch
               OPCAT_QUADREG1BYTE,0x1cd, 0 },
774 4 robfinch
  { "STS",     OPCAT_NOIMM |
775
               OPCAT_DBLREG1BYTE, 0x1cf, 4 },
776
  { "STTL",    OPCAT_PSEUDO,      PSEUDO_STTL, 0 },
777
  { "STU",     OPCAT_NOIMM |
778
               OPCAT_DBLREG1BYTE, 0xcf, 3 },
779
  { "STW",     OPCAT_NOIMM |
780
               OPCAT_6309 |
781 22 robfinch
               OPCAT_DBLREG2BYTE, 0x187, 0 },
782 4 robfinch
  { "STX",     OPCAT_NOIMM |
783
               OPCAT_DBLREG1BYTE, 0x8f, 1 },
784
  { "STY",     OPCAT_NOIMM |
785
               OPCAT_DBLREG1BYTE, 0x18f, 2 },
786
  { "SUB",     OPCAT_ACCARITH,    0x80, 0 },
787
  { "SUBA",    OPCAT_ARITH,       0x80, 0 },
788
  { "SUBB",    OPCAT_ARITH,       0xc0, 0 },
789
  { "SUBD",    OPCAT_DBLREG1BYTE, 0x83, 0 },
790
  { "SUBE",    OPCAT_6309 |
791 22 robfinch
               OPCAT_ARITH,      0x280, 0 },
792 4 robfinch
  { "SUBF",    OPCAT_6309 |
793 22 robfinch
               OPCAT_ARITH,      0x2c0, 0 },
794 4 robfinch
  { "SUBW",    OPCAT_6309 |
795 22 robfinch
               OPCAT_DBLREG2BYTE, 0x180, 0 },
796 4 robfinch
  { "SUBR",    OPCAT_6309 |
797 22 robfinch
               OPCAT_IREG,        0x132, 0 },
798 4 robfinch
  { "SWI",     OPCAT_ONEBYTE,     0x3f, 0 },
799
  { "SWI2",    OPCAT_ONEBYTE,     0x13f, 0 },
800
  { "SWI3",    OPCAT_ONEBYTE,     0x23f, 0 },
801
  { "SYMLEN",  OPCAT_PSEUDO,      PSEUDO_SYMLEN, 0 },
802
  { "SYNC",    OPCAT_ONEBYTE,     0x13, 0 },
803
  { "TAB",     OPCAT_THREEBYTE,   0x1f08904d, 0 },
804
  { "TAP",     OPCAT_TWOBYTE,     0x1f08a, 0 },
805
  { "TBA",     OPCAT_THREEBYTE,   0x1f09804dLL, 0 },
806
  { "TEXT",    OPCAT_PSEUDO,      PSEUDO_TEXT, 0 },
807
  { "TFM",     OPCAT_6309 |
808 22 robfinch
               OPCAT_BLOCKTRANS,  0x238, 0 },
809 4 robfinch
  { "TFR",     OPCAT_2REG,        0x1f, 0 },
810
  { "TIM",     OPCAT_6309 |
811
               OPCAT_BITDIRECT,   0x0b, 0 },
812
  { "TITLE",   OPCAT_PSEUDO,      PSEUDO_NAM, 0 },
813
  { "TPA",     OPCAT_TWOBYTE,     0x1f0a8, 0 },
814
  { "TST",     OPCAT_SINGLEADDR,  0x0d, 0 },
815
  { "TSTA",    OPCAT_ONEBYTE,     0x4d, 0 },
816
  { "TSTB",    OPCAT_ONEBYTE,     0x5d, 0 },
817
  { "TSTD",    OPCAT_6309 |
818
               OPCAT_ONEBYTE,     0x14d, 0 },
819
  { "TSTE",    OPCAT_6309 |
820 22 robfinch
               OPCAT_TWOBYTE,     0x24d, 0 },
821 4 robfinch
  { "TSTF",    OPCAT_6309 |
822 22 robfinch
               OPCAT_TWOBYTE,     0x25d, 0 },
823 4 robfinch
  { "TSTW",    OPCAT_6309 |
824 22 robfinch
               OPCAT_TWOBYTE,     0x15d, 0 },
825 4 robfinch
  { "TSX",     OPCAT_TWOBYTE,     0x1f041, 1 },
826
  { "TSY",     OPCAT_FOURBYTE,    0x034040035020LL, 2 },  /* PSHS S/PULS Y */
827
  { "TTL",     OPCAT_PSEUDO,      PSEUDO_NAM, 0 },
828
  { "TXS",     OPCAT_TWOBYTE,     0x1f014, 4 },
829
  { "TYS",     OPCAT_FOURBYTE,    0x034020035040LL, 4 },  /* PSHS Y/PULS S */
830
  { "WAI",     OPCAT_TWOBYTE,     0x3c0ff, 0 },
831
  { "WORD",    OPCAT_PSEUDO,      PSEUDO_FCW, 0 },
832
};
833
 
834
struct oprecord optable00[]=
835
  {
836
  { "ABA",     OPCAT_ONEBYTE,     0x1b },
837
  { "ABS",     OPCAT_PSEUDO,      PSEUDO_ABS },
838
  { "ADC",     OPCAT_ACCARITH,    0x89 },
839
  { "ADCA",    OPCAT_ARITH,       0x89 },
840
  { "ADCB",    OPCAT_ARITH,       0xc9 },
841
  { "ADD",     OPCAT_ACCARITH,    0x8b },
842
  { "ADDA",    OPCAT_ARITH,       0x8b },
843
  { "ADDB",    OPCAT_ARITH,       0xcb },
844
  { "AND",     OPCAT_ACCARITH,    0x84 },
845
  { "ANDA",    OPCAT_ARITH,       0x84 },
846
  { "ANDB",    OPCAT_ARITH,       0xc4 },
847
  { "ASL",     OPCAT_ACCADDR,     0x08 },
848
  { "ASLA",    OPCAT_ONEBYTE,     0x48 },
849
  { "ASLB",    OPCAT_ONEBYTE,     0x58 },
850
  { "ASR",     OPCAT_ACCADDR,     0x07 },
851
  { "ASRA",    OPCAT_ONEBYTE,     0x47 },
852
  { "ASRB",    OPCAT_ONEBYTE,     0x57 },
853
  { "BCC",     OPCAT_SBRANCH,     0x24 },
854
  { "BCS",     OPCAT_SBRANCH,     0x25 },
855
  { "BEC",     OPCAT_SBRANCH,     0x24 },
856
  { "BEQ",     OPCAT_SBRANCH,     0x27 },
857
  { "BES",     OPCAT_SBRANCH,     0x25 },
858
  { "BGE",     OPCAT_SBRANCH,     0x2c },
859
  { "BGT",     OPCAT_SBRANCH,     0x2e },
860
  { "BHI",     OPCAT_SBRANCH,     0x22 },
861
  { "BHS",     OPCAT_SBRANCH,     0x24 },
862
  { "BIN",     OPCAT_PSEUDO,      PSEUDO_BINARY },
863
  { "BINARY",  OPCAT_PSEUDO,      PSEUDO_BINARY },
864
  { "BIT",     OPCAT_ACCARITH,    0x85 },
865
  { "BITA",    OPCAT_ARITH,       0x85 },
866
  { "BITB",    OPCAT_ARITH,       0xc5 },
867
  { "BLE",     OPCAT_SBRANCH,     0x2f },
868
  { "BLO",     OPCAT_SBRANCH,     0x25 },
869
  { "BLS",     OPCAT_SBRANCH,     0x23 },
870
  { "BLT",     OPCAT_SBRANCH,     0x2d },
871
  { "BMI",     OPCAT_SBRANCH,     0x2b },
872
  { "BNE",     OPCAT_SBRANCH,     0x26 },
873
  { "BPL",     OPCAT_SBRANCH,     0x2a },
874
  { "BRA",     OPCAT_SBRANCH,     0x20 },
875
  { "BSR",     OPCAT_SBRANCH,     0x8d },
876
  { "BVC",     OPCAT_SBRANCH,     0x28 },
877
  { "BVS",     OPCAT_SBRANCH,     0x29 },
878
  { "CBA",     OPCAT_ONEBYTE,     0x11 },
879
  { "CLC",     OPCAT_ONEBYTE,     0x0c },
880
  { "CLI",     OPCAT_ONEBYTE,     0x0e },
881
  { "CLR",     OPCAT_ACCADDR,     0x0f },
882
  { "CLRA",    OPCAT_ONEBYTE,     0x4f },
883
  { "CLRB",    OPCAT_ONEBYTE,     0x5f },
884
  { "CLV",     OPCAT_ONEBYTE,     0x0a },
885
  { "CMP",     OPCAT_ACCARITH,    0x81 },
886
  { "CMPA",    OPCAT_ARITH,       0x81 },
887
  { "CMPB",    OPCAT_ARITH,       0xc1 },
888
  { "COM",     OPCAT_ACCADDR,     0x03 },
889
  { "COMA",    OPCAT_ONEBYTE,     0x43 },
890
  { "COMB",    OPCAT_ONEBYTE,     0x53 },
891
  { "CPX",     OPCAT_DBLREG1BYTE, 0x8c },
892
  { "DAA",     OPCAT_ONEBYTE,     0x19 },
893
  { "DEC",     OPCAT_ACCADDR,     0x0a },
894
  { "DECA",    OPCAT_ONEBYTE,     0x4a },
895
  { "DECB",    OPCAT_ONEBYTE,     0x5a },
896
  { "DEF",     OPCAT_PSEUDO,      PSEUDO_DEF },
897
  { "DEFINE",  OPCAT_PSEUDO,      PSEUDO_DEF },
898
  { "DES",     OPCAT_ONEBYTE,     0x34 },
899
  { "DEX",     OPCAT_ONEBYTE,     0x09 },
900
  { "DUP",     OPCAT_PSEUDO,      PSEUDO_DUP },
901
  { "ELSE",    OPCAT_PSEUDO,      PSEUDO_ELSE },
902
  { "END",     OPCAT_PSEUDO,      PSEUDO_END },
903
  { "ENDCOM",  OPCAT_PSEUDO,      PSEUDO_ENDCOM },
904
  { "ENDD",    OPCAT_PSEUDO,      PSEUDO_ENDD },
905
  { "ENDDEF",  OPCAT_PSEUDO,      PSEUDO_ENDDEF },
906
  { "ENDIF",   OPCAT_PSEUDO,      PSEUDO_ENDIF },
907
  { "ENDM",    OPCAT_PSEUDO,      PSEUDO_ENDM },
908
  { "EOR",     OPCAT_ACCARITH,    0x88 },
909
  { "EORA",    OPCAT_ARITH,       0x88 },
910
  { "EORB",    OPCAT_ARITH,       0xc8 },
911
  { "EQU",     OPCAT_PSEUDO,      PSEUDO_EQU },
912
  { "ERR",     OPCAT_PSEUDO,      PSEUDO_ERR },
913
  { "EXITM",   OPCAT_PSEUDO,      PSEUDO_EXITM },
914
  { "EXT",     OPCAT_PSEUDO,      PSEUDO_EXT },
915
  { "EXTERN",  OPCAT_PSEUDO,      PSEUDO_EXT },
916
  { "FCB",     OPCAT_PSEUDO,      PSEUDO_FCB },
917
  { "FCC",     OPCAT_PSEUDO,      PSEUDO_FCC },
918
  { "FCW",     OPCAT_PSEUDO,      PSEUDO_FCW },
919
  { "FDB",     OPCAT_PSEUDO,      PSEUDO_FCW },
920
  { "GLOBAL",  OPCAT_PSEUDO,      PSEUDO_PUB },
921
  { "IF",      OPCAT_PSEUDO,      PSEUDO_IF },
922
  { "IFC",     OPCAT_PSEUDO,      PSEUDO_IFC },
923
  { "IFD",     OPCAT_PSEUDO,      PSEUDO_IFD },
924
  { "IFN",     OPCAT_PSEUDO,      PSEUDO_IFN },
925
  { "IFNC",    OPCAT_PSEUDO,      PSEUDO_IFNC },
926
  { "IFND",    OPCAT_PSEUDO,      PSEUDO_IFND },
927
  { "INC",     OPCAT_ACCADDR,     0x0c },
928
  { "INCA",    OPCAT_ONEBYTE,     0x4c },
929
  { "INCB",    OPCAT_ONEBYTE,     0x5c },
930
  { "INCLUDE", OPCAT_PSEUDO,      PSEUDO_INCLUDE },
931
  { "INS",     OPCAT_ONEBYTE,     0x31 },
932
  { "INX",     OPCAT_ONEBYTE,     0x08 },
933
  { "JMP",     OPCAT_IDXEXT,      0x4e },
934
  { "JSR",     OPCAT_IDXEXT,      0x8d },
935
  { "LDA",     OPCAT_ACCARITH,    0x86 },
936
  { "LDAA",    OPCAT_ARITH,       0x86 },
937
  { "LDAB",    OPCAT_ARITH,       0xc6 },
938
  { "LDB",     OPCAT_ARITH,       0xc6 },
939
  { "LDS",     OPCAT_DBLREG1BYTE, 0x8e },
940
  { "LDX",     OPCAT_DBLREG1BYTE, 0xce },
941
  { "LIB",     OPCAT_PSEUDO,      PSEUDO_INCLUDE },
942
  { "LIBRARY", OPCAT_PSEUDO,      PSEUDO_INCLUDE },
943
  { "LSL",     OPCAT_ACCADDR,     0x08 },
944
  { "LSLA",    OPCAT_ONEBYTE,     0x48 },
945
  { "LSLB",    OPCAT_ONEBYTE,     0x58 },
946
  { "LSR",     OPCAT_ACCADDR,     0x04 },
947
  { "LSRA",    OPCAT_ONEBYTE,     0x44 },
948
  { "LSRB",    OPCAT_ONEBYTE,     0x54 },
949
  { "MACRO",   OPCAT_PSEUDO,      PSEUDO_MACRO },
950
  { "NAM",     OPCAT_PSEUDO,      PSEUDO_NAM },
951
  { "NAME",    OPCAT_PSEUDO,      PSEUDO_NAME },
952
  { "NEG",     OPCAT_ACCADDR,     0x00 },
953
  { "NEGA",    OPCAT_ONEBYTE,     0x40 },
954
  { "NEGB",    OPCAT_ONEBYTE,     0x50 },
955
  { "NOP",     OPCAT_ONEBYTE,     0x01 },
956
  { "OPT",     OPCAT_PSEUDO,      PSEUDO_OPT },
957
  { "OPTION",  OPCAT_PSEUDO,      PSEUDO_OPT },
958
  { "ORA",     OPCAT_ARITH,       0x8a },
959
  { "ORAA",    OPCAT_ARITH,       0x8a },
960
  { "ORAB",    OPCAT_ARITH,       0xca },
961
  { "ORB",     OPCAT_ARITH,       0xca },
962
  { "ORG",     OPCAT_PSEUDO,      PSEUDO_ORG },
963
  { "PAG",     OPCAT_PSEUDO,      PSEUDO_PAG },
964
  { "PAGE",    OPCAT_PSEUDO,      PSEUDO_PAG },
965
  { "PSHA",    OPCAT_ONEBYTE,     0x36 },
966
  { "PSHB",    OPCAT_ONEBYTE,     0x37 },
967
  { "PUB",     OPCAT_PSEUDO,      PSEUDO_PUB },
968
  { "PUBLIC",  OPCAT_PSEUDO,      PSEUDO_PUB },
969
  { "PULA",    OPCAT_ONEBYTE,     0x32 },
970
  { "PULB",    OPCAT_ONEBYTE,     0x33 },
971
  { "REG",     OPCAT_PSEUDO,      PSEUDO_REG },
972
  { "REP",     OPCAT_PSEUDO,      PSEUDO_REP },
973
  { "REPEAT",  OPCAT_PSEUDO,      PSEUDO_REP },
974
  { "RMB",     OPCAT_PSEUDO,      PSEUDO_RMB },
975
  { "ROL",     OPCAT_ACCADDR,     0x09 },
976
  { "ROLA",    OPCAT_ONEBYTE,     0x49 },
977
  { "ROLB",    OPCAT_ONEBYTE,     0x59 },
978
  { "ROR",     OPCAT_ACCADDR,     0x06 },
979
  { "RORA",    OPCAT_ONEBYTE,     0x46 },
980
  { "RORB",    OPCAT_ONEBYTE,     0x56 },
981
  { "RPT",     OPCAT_PSEUDO,      PSEUDO_REP },
982
  { "RTI",     OPCAT_ONEBYTE,     0x3b },
983
  { "RTS",     OPCAT_ONEBYTE,     0x39 },
984
  { "RZB",     OPCAT_PSEUDO,      PSEUDO_RZB },
985
  { "SBA",     OPCAT_ONEBYTE,     0x10 },
986
  { "SBC",     OPCAT_ACCARITH,    0x82 },
987
  { "SBCA",    OPCAT_ARITH,       0x82 },
988
  { "SBCB",    OPCAT_ARITH,       0xc2 },
989
  { "SEC",     OPCAT_ONEBYTE,     0x0d },
990
  { "SEI",     OPCAT_ONEBYTE,     0x0f },
991
  { "SET",     OPCAT_PSEUDO,      PSEUDO_SET },
992
//{ "SETDP",   OPCAT_PSEUDO,      PSEUDO_SETDP },
993
  { "SETLI",   OPCAT_PSEUDO,      PSEUDO_SETLI },
994
  { "SETPG",   OPCAT_PSEUDO,      PSEUDO_SETPG },
995
  { "SEV",     OPCAT_ONEBYTE,     0x0b },
996
  { "SPC",     OPCAT_PSEUDO,      PSEUDO_SPC },
997
  { "STA",     OPCAT_NOIMM |
998
               OPCAT_ACCARITH,    0x87 },
999
  { "STAA",    OPCAT_NOIMM |
1000
               OPCAT_ARITH,       0x87 },
1001
  { "STAB",    OPCAT_NOIMM |
1002
               OPCAT_ARITH,       0xc7 },
1003
  { "STS",     OPCAT_NOIMM |
1004
               OPCAT_DBLREG1BYTE, 0x8f },
1005
  { "STTL",    OPCAT_PSEUDO,      PSEUDO_STTL },
1006
  { "STX",     OPCAT_NOIMM |
1007
               OPCAT_DBLREG1BYTE, 0xcf },
1008
  { "SUB",     OPCAT_ACCARITH,    0x80 },
1009
  { "SUBA",    OPCAT_ARITH,       0x80 },
1010
  { "SUBB",    OPCAT_ARITH,       0xc0 },
1011
  { "SWI",     OPCAT_ONEBYTE,     0x3f },
1012
  { "SYMLEN",  OPCAT_PSEUDO,      PSEUDO_SYMLEN },
1013
  { "TAB",     OPCAT_ONEBYTE,     0x16 },
1014
  { "TAP",     OPCAT_ONEBYTE,     0x06 },
1015
  { "TBA",     OPCAT_ONEBYTE,     0x17 },
1016
  { "TEXT",    OPCAT_PSEUDO,      PSEUDO_TEXT },
1017
  { "TITLE",   OPCAT_PSEUDO,      PSEUDO_NAM },
1018
  { "TPA",     OPCAT_ONEBYTE,     0x07 },
1019
  { "TST",     OPCAT_ACCADDR,     0x0d },
1020
  { "TSTA",    OPCAT_ONEBYTE,     0x4d },
1021
  { "TSTB",    OPCAT_ONEBYTE,     0x5d },
1022
  { "TSX",     OPCAT_ONEBYTE,     0x30 },
1023
  { "TTL",     OPCAT_PSEUDO,      PSEUDO_NAM },
1024
  { "TXS",     OPCAT_ONEBYTE,     0x35 },
1025
  { "WAI",     OPCAT_ONEBYTE,     0x3e },
1026
  };
1027
 
1028
/* expression categories...
1029
   all zeros is ordinary constant.
1030
   bit 1 indicates address within module.
1031
   bit 2 indicates external address.
1032
   bit 4 indicates this can't be relocated if it's an address.
1033
   bit 5 indicates address (if any) is negative.
1034
*/
1035
 
1036
#define EXPRCAT_INTADDR       0x02
1037
#define EXPRCAT_EXTADDR       0x04
1038
#define EXPRCAT_PUBLIC        0x08
1039
#define EXPRCAT_FIXED         0x10
1040
#define EXPRCAT_NEGATIVE      0x20
1041
 
1042
/*****************************************************************************/
1043
/* Symbol definitions                                                        */
1044
/*****************************************************************************/
1045
 
1046
struct symrecord
1047
  {
1048
  char name[MAXIDLEN + 1];              /* symbol name                       */
1049
  char cat;                             /* symbol category                   */
1050
  char isFar;                                           /* far assumed */
1051
  char isFarkw;                                         /* FAR keyword used in symbol definiton */
1052
  unsigned value;                 /* symbol value                      */
1053
  union
1054
    {
1055
    struct symrecord *parent;           /* parent symbol (for COMMON)        */
1056
    long flags;                         /* forward reference flag (otherwise)*/
1057
    } u;
1058
  };
1059
 
1060
                                        /* symbol categories :               */
1061
#define SYMCAT_CONSTANT       0x00      /* constant value (from equ)         */
1062
#define SYMCAT_VARIABLE       0x01      /* variable value (from set)         */
1063
#define SYMCAT_LABEL          0x02      /* address within module (label)     */
1064
#define SYMCAT_VARADDR        0x03      /* variable containing address       */
1065
#define SYMCAT_EXTERN         0x04      /* address in other module (extern)  */
1066
#define SYMCAT_VAREXTERN      0x05      /* variable containing extern addr.  */
1067
#define SYMCAT_UNRESOLVED     0x06      /* unresolved address                */
1068
#define SYMCAT_VARUNRESOLVED  0x07      /* var. containing unresolved addr   */
1069
#define SYMCAT_PUBLIC         0x08      /* public label                      */
1070
#define SYMCAT_MACRO          0x09      /* macro definition                  */
1071
#define SYMCAT_PUBLICUNDEF    0x0A      /* public label (yet undefined)      */
1072
#define SYMCAT_PARMNAME       0x0B      /* parameter name                    */
1073
#define SYMCAT_EMPTY          0x0D      /* empty                             */
1074
#define SYMCAT_REG            0x0E      /* REG directive                     */
1075
#define SYMCAT_TEXT           0x0F      /* /Dsymbol or TEXT label            */
1076
#define SYMCAT_COMMONDATA     0x12      /* COMMON Data                       */
1077
#define SYMCAT_COMMON         0x14      /* COMMON block                      */
1078
#define SYMCAT_LOCALLABEL     0x22      /* local label                       */
1079
#define SYMCAT_EMPTYLOCAL     0x26      /* empty local label                 */
1080
 
1081
                                        /* symbol flags:                     */
1082
#define SYMFLAG_FORWARD       0x01      /* forward reference                 */
1083
#define SYMFLAG_PASSED        0x02      /* passed forward reference          */
1084
 
1085
long symcounter = 0;                    /* # currently loaded symbols        */
1086
struct symrecord symtable[MAXLABELS];   /* symbol table (fixed size)         */
1087
long lclcounter = 0;                    /* # currently loaded local symbols  */
1088
struct symrecord lcltable[MAXLABELS];   /* local symbol table (fixed size)   */
1089
 
1090
/*****************************************************************************/
1091
/* regrecord structure definition                                            */
1092
/*****************************************************************************/
1093
 
1094
struct regrecord
1095
  {
1096
  char *name;                           /* name of the register              */
1097
  unsigned char tfr, psh;               /* bit value for tfr and psh/pul     */
1098
  };
1099
 
1100
/*****************************************************************************/
1101
/* regtable : table of all registers                                         */
1102
/*****************************************************************************/
1103
 
1104
struct regrecord regtable09[]=
1105
  {
1106
  { "D",   0x00, 0x06 },
1107
  { "X",   0x01, 0x10 },
1108
  { "Y",   0x02, 0x20 },
1109
  { "U",   0x03, 0x40 },
1110
  { "S",   0x04, 0x40 },
1111
  { "PC",  0x05, 0x80 },
1112
  { "A",   0x08, 0x02 },
1113
  { "B",   0x09, 0x04 },
1114
  { "CC",  0x0a, 0x01 },
1115
  { "CCR", 0x0a, 0x01 },
1116
  { "DP",  0x0b, 0x08 },
1117
  { "DPR", 0x0b, 0x08 },
1118
  { 0,     0,    0    }
1119
  };
1120
 
1121
struct regrecord regtable63[]=          /* same for HD6309                   */
1122
  {
1123
  { "D",   0x00, 0x06 },
1124
  { "X",   0x01, 0x10 },
1125
  { "Y",   0x02, 0x20 },
1126
  { "U",   0x03, 0x40 },
1127
  { "S",   0x04, 0x40 },
1128
  { "PC",  0x05, 0x80 },
1129
  { "W",   0x06, 0x00 },
1130
  { "V",   0x07, 0x00 },
1131
  { "A",   0x08, 0x02 },
1132
  { "B",   0x09, 0x04 },
1133
  { "CC",  0x0a, 0x01 },
1134
  { "CCR", 0x0a, 0x01 },
1135
  { "DP",  0x0b, 0x08 },
1136
  { "DPR", 0x0b, 0x08 },
1137
  { "0",   0x0c, 0x00 },
1138
  { "E",   0x0e, 0x00 },
1139
  { "F",   0x0f, 0x00 },
1140
  { 0,     0,    0    }
1141
  };
1142
 
1143
struct regrecord regtable00[]=
1144
  {
1145
  { "X",   0x01, 0x10 },
1146
  { "S",   0x04, 0x40 },
1147
  { "PC",  0x05, 0x80 },
1148
  { "A",   0x08, 0x02 },
1149
  { "B",   0x09, 0x04 },
1150
  { "CC",  0x0a, 0x01 },
1151
  { "CCR", 0x0a, 0x01 },
1152
  { 0,     0,    0    }
1153
  };
1154
 
1155
/*****************************************************************************/
1156
/* bitregtable : table of all bit transfer registers                         */
1157
/*****************************************************************************/
1158
 
1159
struct regrecord bitregtable09[] =
1160
  {
1161
  { "CC",  0x00, 0x00 },
1162
  { "A",   0x01, 0x01 },
1163
  { "B",   0x02, 0x02 },
1164
  };
1165
 
1166
struct regrecord bitregtable00[] =
1167
  {
1168
  { "CC",  0x00, 0x00 },
1169
  { "A",   0x01, 0x01 },
1170
  { "B",   0x02, 0x02 },
1171
  };
1172
 
1173
/*****************************************************************************/
1174
/* relocrecord structure definition                                          */
1175
/*****************************************************************************/
1176
 
1177
struct relocrecord
1178
  {
1179
  unsigned addr;                  /* address that needs relocation     */
1180
  char exprcat;                         /* expression category               */
1181
  struct symrecord *sym;                /* symbol for relocation             */
1182
  };
1183
 
1184
long relcounter = 0;                    /* # currently defined relocations   */
1185
struct relocrecord reltable[MAXRELOCS]; /* relocation table (fixed size)     */
1186
long relhdrfoff;                        /* FLEX Relocatable Global Hdr Offset*/
1187
 
1188
/*****************************************************************************/
1189
/* Options definitions                                                       */
1190
/*****************************************************************************/
1191
 
1192
#define OPTION_M09    0x00000001L       /* MC6809 mode                       */
1193
#define OPTION_H63    0x00000002L       /* HD6309 mode                       */
1194
#define OPTION_M00    0x00000004L       /* MC6800 mode                       */
1195
#define OPTION_PAG    0x00000008L       /* page formatting ON                */
1196
#define OPTION_CON    0x00000010L       /* print cond. skipped code          */
1197
#define OPTION_MAC    0x00000020L       /* print macro calling line (default)*/
1198
#define OPTION_EXP    0x00000040L       /* print macro expansion lines       */
1199
#define OPTION_SYM    0x00000080L       /* print symbol table (default)      */
1200
#define OPTION_MUL    0x00000100L       /* print multiple oc lines (default) */
1201
#define OPTION_LP1    0x00000200L       /* print pass 1 listing              */
1202
#define OPTION_DAT    0x00000400L       /* print date in listing (default)   */
1203
#define OPTION_NUM    0x00000800L       /* print line numbers                */
1204
#define OPTION_INV    0x00001000L       /* print invisible lines             */
1205
#define OPTION_TSC    0x00002000L       /* TSC-compatible source format      */
1206
#define OPTION_WAR    0x00004000L       /* print warnings                    */
1207
#define OPTION_CLL    0x00008000L       /* check line length (default)       */
1208
#define OPTION_LFN    0x00010000L       /* print long file names             */
1209
#define OPTION_LLL    0x00020000L       /* list library lines                */
1210
#define OPTION_GAS    0x00040000L       /* Gnu AS compatibility              */
1211
#define OPTION_REL    0x00080000L       /* print relocation table            */
1212
#define OPTION_TXT    0x00100000L       /* print text table                  */
1213
#define OPTION_LIS    0x00200000L       /* print assembler output listing    */
1214
#define OPTION_LPA    0x00400000L       /* listing in f9dasm patch format    */
1215
#define OPTION_RTF        0x00800000L
1216
#define OPTION_X32        0x01000000L           /* 32 bit index registers            */
1217
#define OPTION_X16        0x02000000L           /* 32 bit index registers            */
1218
 
1219
struct
1220
  {
1221
  char *Name;
1222
  unsigned long dwAdd;
1223
  unsigned long dwRem;
1224
  } Options[] =
1225
  {/*Name          Add      Remove */
1226
  { "PAG",  OPTION_PAG,          0 },
1227
  { "NOP",           0, OPTION_PAG },
1228
  { "CON",  OPTION_CON,          0 },
1229
  { "NOC",           0, OPTION_CON },
1230
  { "MAC",  OPTION_MAC,          0 },
1231
  { "NOM",           0, OPTION_MAC },
1232
  { "EXP",  OPTION_EXP,          0 },
1233
  { "NOE",           0, OPTION_EXP },
1234
  { "SYM",  OPTION_SYM,          0 },
1235
  { "NOS",           0, OPTION_SYM },
1236
  { "MUL",  OPTION_MUL,          0 },
1237
  { "NMU",           0, OPTION_MUL },
1238
  { "LP1",  OPTION_LP1,          0 },
1239
  { "NO1",           0, OPTION_LP1 },
1240
  { "DAT",  OPTION_DAT,          0 },
1241
  { "NOD",           0, OPTION_DAT },
1242
  { "NUM",  OPTION_NUM,          0 },
1243
  { "NON",           0, OPTION_NUM },
1244
  { "INV",  OPTION_INV,          0 },
1245
  { "NOI",           0, OPTION_INV },
1246
  { "TSC",  OPTION_TSC,          0 },
1247
  { "NOT",           0, OPTION_TSC },
1248
  { "WAR",  OPTION_WAR,          0 },
1249
  { "NOW",           0, OPTION_WAR },
1250
  { "CLL",  OPTION_CLL,          0 },
1251
  { "NCL",           0, OPTION_CLL },
1252
  { "LFN",  OPTION_LFN,          0 },
1253
  { "NLF",           0, OPTION_LFN },
1254
  { "LLL",  OPTION_LLL,          0 },
1255
  { "NLL",           0, OPTION_LLL },
1256
  { "GAS",  OPTION_GAS,          0 },
1257
  { "NOG",           0, OPTION_GAS },
1258
  { "REL",  OPTION_REL,          0 },
1259
  { "NOR",           0, OPTION_REL },
1260
  { "H63",  OPTION_H63, OPTION_M09 | OPTION_M00 },
1261
  { "M68",  OPTION_M09, OPTION_H63 | OPTION_M00 },
1262
  { "M09",  OPTION_M09, OPTION_H63 | OPTION_M00 },
1263
  { "M00",  OPTION_M00, OPTION_H63 | OPTION_M09 },
1264
  { "TXT",  OPTION_TXT,          0 },
1265
  { "NTX",           0, OPTION_TXT },
1266
  { "LIS",  OPTION_LIS,          0 },
1267
  { "NOL",           0, OPTION_LIS },
1268
  { "LPA",  OPTION_LPA, OPTION_NUM | OPTION_CLL }, // LPA inhibits NUM / CLL!
1269
  { "NLP",           0, OPTION_LPA },
1270
  { "X32",  OPTION_X32, OPTION_X16 },
1271
  { "X16",  OPTION_X16, OPTION_X32 }
1272
  };
1273
 
1274
unsigned long dwOptions =               /* options flags, init to default    */
1275
    OPTION_M09 |
1276
    OPTION_MAC |
1277
    OPTION_SYM |
1278
    OPTION_MUL |
1279
    OPTION_DAT |
1280
    OPTION_WAR |
1281
    OPTION_CLL |
1282
    OPTION_LLL |
1283
    OPTION_REL |
1284
    OPTION_LIS;
1285
 
1286
/*****************************************************************************/
1287
/* arrays of error/warning messages                                          */
1288
/*****************************************************************************/
1289
                                        /* defined error flags               */
1290
#define ERR_OK            0x0000        /* all is well                       */
1291
#define ERR_EXPR          0x0001        /* Error in expression               */
1292
#define ERR_ILLEGAL_ADDR  0x0002        /* Illegal adressing mode            */
1293
#define ERR_LABEL_UNDEF   0x0004        /* Undefined label                   */
1294
#define ERR_LABEL_MULT    0x0008        /* Label multiply defined            */
1295
#define ERR_RANGE         0x0010        /* Relative branch out of range      */
1296
#define ERR_LABEL_MISSING 0x0020        /* Missing label                     */
1297
#define ERR_OPTION_UNK    0x0040        /* Option unknown                    */
1298
#define ERR_MALLOC        0x0080        /* Out of memory                     */
1299
#define ERR_NESTING       0x0100        /* Nesting not allowed               */
1300
#define ERR_RELOCATING    0x0200        /* Statement not valid for reloc mode*/
1301
#define ERR_ERRTXT        0x4000        /* ERR text output                   */
1302
#define ERR_ILLEGAL_MNEM  0x8000        /* Illegal mnemonic                  */
1303
 
1304
char *errormsg[]=
1305
  {
1306
  "Error in expression",                /* 1     ERR_EXPR                    */
1307
  "Illegal addressing mode",            /* 2     ERR_ILLEGAL_ADDR            */
1308
  "Undefined label",                    /* 4     ERR_LABEL_UNDEF             */
1309
  "Multiple definitions of label",      /* 8     ERR_LABEL_MULT              */
1310
  "Relative branch out of range",       /* 16    ERR_RANGE                   */
1311
  "Missing label",                      /* 32    ERR_LABEL_MISSING           */
1312
  "Unknown option specified",           /* 64    ERR_OPTION_UNK              */
1313
  "Out of memory",                      /* 128   ERR_MALLOC                  */
1314
  "Nesting not allowed",                /* 256   ERR_NESTING                 */
1315
  "Illegal for current relocation mode",/* 512   ERR_RELOCATING              */
1316
  "",                                   /* 1024                              */
1317
  "",                                   /* 2048                              */
1318
  "",                                   /* 4096                              */
1319
  "",                                   /* 8192                              */
1320
  NULL,                                 /* 16384 ERR_ERRTXT (ERR output)     */
1321
  "Illegal mnemonic"                    /* 32768 ERR_ILLEGAL_MNEM            */
1322
  };
1323
 
1324
                                        /* defined warning flags             */
1325
#define WRN_OK            0x0000        /* All OK                            */
1326
#define WRN_OPT           0x0001        /* Long branch in short range        */
1327
#define WRN_SYM           0x0002        /* Symbolic text undefined           */
1328
#define WRN_AREA          0x0004        /* Area already in use               */
1329
#define WRN_AMBIG         0x0008        /* Ambiguous 6800 opcode             */
1330
 
1331
char *warningmsg[] =
1332
  {
1333
  "Long branch within short branch "    /* 1     WRN_OPT                     */
1334
      "range could be optimized",
1335
  "Symbolic text undefined",            /* 2     WRN_SYM                     */
1336
  "Area already in use",                /* 4     WRN_AREA                    */
1337
  "Ambiguous 6800 alternate notation",  /* 8     WRN_AMBIG                   */
1338
  "",                                   /* 16                                */
1339
  "",                                   /* 32                                */
1340
  "",                                   /* 64                                */
1341
  "",                                   /* 128                               */
1342
  "",                                   /* 256                               */
1343
  "",                                   /* 512                               */
1344
  "",                                   /* 1024                              */
1345
  "",                                   /* 2048                              */
1346
  "",                                   /* 4096                              */
1347
  "",                                   /* 8192                              */
1348
  "",                                   /* 18384                             */
1349
  ""                                    /* 32768                             */
1350
  };
1351
 
1352
/*****************************************************************************/
1353
/* Listing Definitions                                                       */
1354
/*****************************************************************************/
1355
 
1356
#define LIST_OFF  0x00                  /* listing is generally off          */
1357
#define LIST_ON   0x01                  /* listing is generally on           */
1358
 
1359
char listing = LIST_OFF;                /* listing flag                      */
1360
 
1361
/*****************************************************************************/
1362
/* Global variables                                                          */
1363
/*****************************************************************************/
1364
 
1365
FILE *listfile = NULL;                  /* list file                         */
1366
FILE *objfile = NULL;                   /* object file                       */
1367
char listname[FNLEN + 1];               /* list file name                    */
1368
char objname[FNLEN + 1];                /* object file name                  */
1369
char srcname[FNLEN + 1];                /* source file name                  */
1370
 
1371
                                        /* assembler mode specifics:         */
1372
struct oprecord *optable = optable09;   /* used op table                     */
1373
                                        /* size of this table                */
1374
int optablesize = sizeof(optable09) / sizeof(optable09[0]);
1375
struct regrecord *regtable = regtable09;/* used register table               */
1376
                                        /* used bit register table           */
1377
struct regrecord *bitregtable = bitregtable09;
1378
void scanoperands09(struct relocrecord *pp);
1379
void (*scanoperands)(struct relocrecord *) = scanoperands09;
1380
 
1381
char pass;                              /* Assembler pass = 1 or 2           */
1382
char relocatable = 0;                   /* relocatable object flag           */
1383
char absmode = 1;                       /* absolute mode                     */
1384
long global = 0;                        /* all labels global flag            */
1385
long common = 0;                        /* common definition flag            */
1386
struct symrecord * commonsym = NULL;    /* current common main symbol        */
1387
char terminate;                         /* termination flag                  */
1388
char generating;                        /* code generation flag              */
1389
unsigned loccounter,oldlc;        /* Location counter                  */
1390
 
1391
char inpline[LINELEN];                  /* Current input line (not expanded) */
1392
char srcline[LINELEN];                  /* Current source line               */
1393
char * srcptr;                          /* Pointer to line being parsed      */
1394
 
1395
char unknown;          /* flag to indicate value unknown */
1396
char certain;          /* flag to indicate value is certain at pass 1*/
1397
long error;            /* flags indicating errors in current line. */
1398
long errors;           /* number of errors in current pass */
1399
long warning;          /* flags indicating warnings in current line */
1400
long warnings;         /* number of warnings in current pass */
1401
long nTotErrors;                        /* total # of errors                 */
1402
long nTotWarnings;                      /* total # warnings                  */
1403
char exprcat;          /* category of expression being parsed, eg.
1404
                          label or constant, this is important when
1405
                          generating relocatable object code. */
1406
 
1407
int maxidlen = MAXIDLEN;                /* maximum ID length                 */
1408
 
1409
char modulename[MAXIDLEN + 1] = "";     /* module name buffer                */
1410
char namebuf[MAXIDLEN + 1];             /* name buffer for parsing           */
1411
char unamebuf[MAXIDLEN + 1];            /* name buffer in uppercase          */
1412
 
1413
char isFar,isFarkw;
1414
int vercount;
1415
char mode;
1416
char isX32;
1417
char isPostIndexed;
1418
 
1419
/* adressing mode:                   */
1420
#define ADRMODE_IMM  0                  /* 0 = immediate                     */
1421
#define ADRMODE_DIR  1                  /* 1 = direct                        */
1422
#define ADRMODE_EXT  2                  /* 2 = extended                      */
1423
#define ADRMODE_IDX  3                  /* 3 = indexed                       */
1424
#define ADRMODE_POST 4                  /* 4 = postbyte                      */
1425
#define ADRMODE_PCR  5                  /* 5 = PC relative (with postbyte)   */
1426
#define ADRMODE_IND  6                  /* 6 = indirect                      */
1427
#define ADRMODE_PIN  7                  /* 7 = PC relative & indirect        */
1428
#define ADRMODE_DBL_IND 8
1429
 
1430
char opsize;                            /* desired operand size :            */
1431
                                        /* 0=dunno,1=5, 2=8, 3=16, 4=32      */
1432
long operand;
1433
unsigned short postbyte;
1434
 
1435
long dpsetting = 0;                     /* Direct Page Default = 0           */
1436
 
1437
unsigned short codebuf[256];
1438
int codeptr;                            /* byte offset within instruction    */
1439
int suppress;                           /* 0=no suppress                     */
1440
                                        /* 1=until ENDIF                     */
1441
                                        /* 2=until ELSE                      */
1442
                                        /* 3=until ENDM                      */
1443
char condline = 0;                      /* flag whether on conditional line  */
1444
int ifcount;                            /* count of nested IFs within        */
1445
                                        /* suppressed text                   */
1446
 
1447
#define OUT_NONE  -1                    /* no output                         */
1448
#define OUT_BIN   0                     /* binary output                     */
1449
#define OUT_SREC  1                     /* Motorola S-Records                */
1450
#define OUT_IHEX  2                     /* Intel Hex Records                 */
1451
#define OUT_FLEX  3                     /* Flex9 ASMB-compatible output      */
1452
#define OUT_GAS   4                     /* GNU relocation output             */
1453
#define OUT_REL   5                     /* Flex9 RELASMB output              */
1454
#define OUT_VER   6
1455
int outmode = OUT_BIN;                  /* default to binary output          */
1456
 
1457
unsigned hexaddr;
1458
int hexcount;
1459
unsigned short hexbuffer[256];
1460
unsigned int chksum;
1461
unsigned vslide;
1462
 
1463
int nRepNext = 0;                       /* # repetitions for REP pseudo-op   */
1464
int nSkipCount = 0;                     /* # lines to skip                   */
1465
 
1466 16 robfinch
unsigned tfradr = 0;
1467 4 robfinch
int tfradrset = 0;
1468
 
1469
int nCurLine = 0;                       /* current output line on page       */
1470
int nCurCol = 0;                        /* current output column on line     */
1471
int nCurPage = 0;                       /* current page #                    */
1472
int nLinesPerPage = 66;                 /* # lines on a page                 */
1473
int nColsPerLine = 200;                  /* # columns per line                */
1474
char szTitle[128] = "";                 /* title for listings                */
1475
char szSubtitle[128] = "";              /* subtitle for listings             */
1476
 
1477
char szBuf1[LINELEN];                   /* general-purpose buffers for parse */
1478
char szBuf2[LINELEN];
1479
 
1480
struct linebuf *macros[MAXMACROS];      /* pointers to the macros            */
1481
int nMacros = 0;                        /* # parsed macros                   */
1482
int inMacro = 0;                        /* flag whether in macro definition  */
1483
 
1484
char *texts[MAXTEXTS];                  /* pointers to the texts             */
1485
int nPredefinedTexts = 0;               /* # predefined texts                */
1486
int nTexts = 0;                         /* # currently defined texts         */
1487
 
1488
//unsigned char bUsedBytes[8192] = {0};   /* 1 bit per byte of the address spc */
1489
 
1490
/*****************************************************************************/
1491
/* Necessary forward declarations                                            */
1492
/*****************************************************************************/
1493
 
1494
void processline();
1495
struct linebuf *readfile(char *name, unsigned char lvl, struct linebuf *after);
1496
struct linebuf *readbinary(char *name, unsigned char lvl, struct linebuf *after, struct symrecord *lp);
1497
 
1498
/*****************************************************************************/
1499
/* allocline : allocates a line of text                                      */
1500
/*****************************************************************************/
1501
 
1502
struct linebuf * allocline
1503
    (
1504
    struct linebuf *prev,
1505
    char *fn,
1506
    int line,
1507
    unsigned char lvl,
1508
    char *text
1509
    )
1510
{
1511
struct linebuf *pNew = malloc(sizeof(struct linebuf) + strlen(text));
1512
if (!pNew)
1513
  return NULL;
1514
pNew->next = (prev) ? prev->next : NULL;
1515
pNew->prev = prev;
1516
if (prev)
1517
  prev->next = pNew;
1518
if (pNew->next)
1519
  pNew->next->prev = pNew;
1520
pNew->lvl = lvl;
1521
pNew->fn = fn;
1522
pNew->ln = line;
1523
pNew->rel = ' ';
1524
strcpy(pNew->txt, text);
1525
return pNew;
1526
}
1527
 
1528
/*****************************************************************************/
1529
/* expandfn : eventually expands a file name to full-blown path              */
1530
/*****************************************************************************/
1531
 
1532
char const *expandfn(char const *fn)
1533
{
1534
#ifdef WIN32
1535
static char szBuf[_MAX_PATH];           /* allocate big buffer               */
1536
 
1537
if (dwOptions & OPTION_LFN)             /* if long file names wanted         */
1538
  return _fullpath(szBuf, fn, sizeof(szBuf));
1539
#endif
1540
 
1541
return fn;                              /* can't do that yet                 */
1542
}
1543
 
1544
/*****************************************************************************/
1545
/* PageFeed : advances the list file                                         */
1546
/*****************************************************************************/
1547
 
1548
void PageFeed()
1549
{
1550
time_t tim;
1551
struct tm *ltm;
1552
 
1553
time(&tim);
1554
ltm = localtime(&tim);
1555
 
1556
fputc('\x0c', listfile);                /* print header                      */
1557
nCurPage++;                             /* advance to next page              */
1558
fprintf(listfile, "\n\n%-32.32s ", szTitle);
1559
if (dwOptions & OPTION_DAT)
1560
  fprintf(listfile,
1561
          "%04d-%02d-%02d ",
1562
          ltm->tm_year + 1900,
1563
          ltm->tm_mon + 1,
1564
          ltm->tm_mday);
1565
fprintf(listfile,
1566
        "A09 %d Assembler V" VERSION " Page %d\n",
1567
        (dwOptions & OPTION_H63) ? 6309 :
1568
            (dwOptions & OPTION_M00) ? 6800 :
1569
            6809,
1570
        nCurPage);
1571
fprintf(listfile, "%-.79s\n\n", szSubtitle);
1572
 
1573
nCurLine = 5;                           /* remember current line             */
1574
nCurCol = 0;                            /* and reset current column          */
1575
}
1576
 
1577
/*****************************************************************************/
1578
/* putlist : puts something to the list file                                 */
1579
/*****************************************************************************/
1580
 
1581
void putlist(char *szFmt, ...)
1582
{
1583
char szList[1024];                      /* buffer for 1k list output         */
1584
char *p;
1585
 
1586
va_list al;
1587
va_start(al, szFmt);
1588
vsprintf(szList, szFmt, al);            /* generate formatted output buffer  */
1589
va_end(al);
1590
 
1591
for (p = szList; *p; p++)               /* then walk through the buffer      */
1592
  {
1593
  fputc(*p, listfile);                  /* print out each character          */
1594
  if (*p == '\n')                       /* if newline sent                   */
1595
    {
1596
    nCurLine++;
1597
    nCurCol = 0;
1598
    if ((nCurLine >= nLinesPerPage) &&  /* if beyond # lines per page        */
1599
        (dwOptions & OPTION_PAG))       /* if pagination activated           */
1600
      PageFeed();                       /* do a page feed                    */
1601
    }
1602
  else                                  /* if another character              */
1603
    {
1604
    nCurCol++;                          /* advance to next column            */
1605
    if (dwOptions & OPTION_CLL)         /* if line length checked            */
1606
      {
1607
                                        /* check if word would go too far    */
1608
      if ((nCurCol >= nColsPerLine * 3 / 4) &&
1609
          (*p == ' '))
1610
        {
1611
        int i;                          /* look whether more delimiters      */
1612
        char c;
1613
        for (i = nCurCol + 1; i < nColsPerLine; i++)
1614
          {
1615
          c = p[i - nCurCol];
1616
          if ((c == '\t') || (c == ' ') || (!c))
1617
            break;
1618
          }
1619
        if (i >= nColsPerLine)          /* if no more delimiters,            */
1620
          nCurCol = nColsPerLine;       /* make sure to advance to new line  */
1621
        }
1622
 
1623
      if (nCurCol >= nColsPerLine)      /* if it IS too far                  */
1624
        {
1625
        putlist("\n");                  /* recurse with a newline            */
1626
        nCurCol = 0;
1627
        }
1628
      }
1629
    }
1630
  }
1631
}
1632
 
1633
/*****************************************************************************/
1634
/* findop : finds a mnemonic in table using binary search                    */
1635
/*****************************************************************************/
1636
 
1637
struct oprecord * findop(char * nm)
1638
{
1639
int lo,hi,i,s;
1640
 
1641
lo = 0;
1642
hi = optablesize - 1;
1643
do
1644
  {
1645
  i = (lo + hi) / 2;
1646
  s = strcmp(optable[i].name, nm);
1647
  if (s < 0)
1648
    lo = i + 1;
1649
  else if (s > 0)
1650
    hi = i - 1;
1651
  else
1652
    break;
1653
  } while (hi >= lo);
1654
if (s)
1655
  return NULL;
1656
return optable + i;
1657
}
1658
 
1659
/*****************************************************************************/
1660
/* findlocal : finds a local symbol table record                             */
1661
/*****************************************************************************/
1662
 
1663
struct symrecord * findlocal(struct symrecord *sym, char forward, int insert)
1664
{
1665
static struct symrecord empty = {"", SYMCAT_EMPTYLOCAL, 0, {0}};
1666
int lo,hi,i,j,s;
1667
 
1668
if ((!sym) ||                           /* if no main symbol for that        */
1669
    ((!insert) &&                       /* or not inserting, but             */
1670
     (sym->cat == SYMCAT_EMPTYLOCAL)))  /*    yet undefined label            */
1671
  return sym;                           /* pass back main symbol             */
1672
 
1673
lo = 0;                                 /* do binary search for the thing    */
1674
hi = lclcounter - 1;
1675
s = 1;
1676
i = 0;
1677
while (hi >= lo)
1678
  {
1679
  i = (lo + hi) / 2;
1680
  s = lcltable[i].value - loccounter;   /* binary search for current address */
1681
  if (s < 0)
1682
    lo = i + 1;
1683
  else if (s > 0)
1684
    hi = i - 1;
1685
  else                                  /* if found,                         */
1686
    {                                   /* go to 1st of this value           */
1687
    while ((i) && (lcltable[i - 1].value == loccounter))
1688
      i--;
1689
    while ((i < lclcounter) &&          /* search for the NAME now           */
1690
           (lcltable[i].value == loccounter))
1691
      {
1692
      s = strcmp(sym->name, lcltable[i].name);
1693
      if (s <= 0)
1694
        {
1695
        if (s)
1696
          i--;
1697
        break;
1698
        }
1699
      i++;
1700
      }
1701
    if (s)                              /* if not found, re-set              */
1702
      {
1703
      if (i >= lclcounter)
1704
        s = 1;
1705
      else
1706
        s = lcltable[i].value - loccounter;
1707
      }
1708
    break;
1709
    }
1710
  }
1711
 
1712
if (insert)                             /* if inserting,                     */
1713
  {
1714
  if (!s)                               /* if address is already in use      */
1715
    {                                   /* but not the correct label         */
1716
    if (strcmp(sym->name, lcltable[i].name))
1717
      error |= ERR_LABEL_MULT;          /* set error                         */
1718
    return lcltable + i;                /* return the local symbol           */
1719
    }
1720
  i = (s < 0 ? i + 1 : i);
1721
  if (lclcounter == MAXLABELS)
1722
    {
1723
    printf("%s(%ld): error 25: out of local symbol storage\n",
1724
           expandfn(curline->fn), curline->ln);
1725
    if (((dwOptions & OPTION_LP1) || pass ==  MAX_PASSNO) && (listing & LIST_ON))
1726
      putlist( "*** Error 25: out of local symbol storage\n");
1727
    exit(4);
1728
    }
1729
  sym->cat = SYMCAT_LOCALLABEL;
1730
  for (j = lclcounter; j > i; j--)
1731
    lcltable[j] = lcltable[j - 1];
1732
  lclcounter++;
1733
  strcpy(lcltable[i].name, sym->name);
1734
  lcltable[i].cat = SYMCAT_LOCALLABEL;
1735
  lcltable[i].value = loccounter;
1736
  lcltable[i].u.parent = NULL;
1737
  return lcltable + i;                  /* pass back this symbol             */
1738
  }
1739
 
1740
if (forward)                            /* if forward search                 */
1741
  {
1742
  i = (s < 0 ? i - 1 : i);
1743
  for (; i < lclcounter; i++)
1744
    {
1745
    if ((!strcmp(lcltable[i].name, sym->name)) &&
1746
        (lcltable[i].value > loccounter))
1747
      return lcltable + i;
1748
    }
1749
  }
1750
else                                    /* if backward search                */
1751
  {
1752
  i = (s > 0 ? i + 1 : i);
1753
  for (; i >= 0; i--)
1754
    {
1755
    if ((!strcmp(lcltable[i].name, sym->name)) &&
1756
        (lcltable[i].value <= loccounter))
1757
      return lcltable + i;
1758
    }
1759
  }
1760
 
1761
return &empty;                          /* if not found, return empty label  */
1762
}
1763
 
1764
/*****************************************************************************/
1765
/* findsym : finds symbol table record; inserts if not found                 */
1766
/*           uses binary search, maintains sorted table                      */
1767
/*****************************************************************************/
1768
 
1769
struct symrecord * findsym (char * nm, int insert)
1770
{
1771
int lo,hi,i,j,s;
1772
char islocal = 0, forward = 0;
1773
char name[MAXIDLEN + 1] = "";
1774
                                        /* copy name to internal buffer      */
1775
strncpy(name, (nm) ? nm : "", sizeof(name) - 1);
1776
for (i = 0; name[i]; i++)               /* determine whether local label     */
1777
  if ((name[i] < '0') || (name[i] > '9'))
1778
    break;
1779
if (i)                                  /* if starting with number           */
1780
  {
1781
  if (!name[i])                         /* if ONLY numeric                   */
1782
    islocal = 1;                        /* this is a local label             */
1783
  else                                  /* otherwise check direction         */
1784
    {
1785
    switch(toupper(name[i]))
1786
      {
1787
      case 'B' :                        /* backward reference ?              */
1788
        islocal = 2;                    /* this is a local label reference   */
1789
        forward = 0;
1790
        break;
1791
      case 'F' :                        /* forward reference ?               */
1792
        islocal = 2;                    /* this is a local label reference   */
1793
        forward = 1;
1794
        break;
1795
      }
1796
    if (islocal && name[i + 1])         /* if followed by anything else      */
1797
      islocal = 0;                      /* reset flag for local label        */
1798
    else                                /* otherwise                         */
1799
      name[i] = 0;                      /* remove the direction              */
1800
    }
1801
  }
1802
 
1803
lo = 0;                                 /* do binary search for the thing    */
1804
hi = symcounter - 1;
1805
s = 1;
1806
i = 0;
1807
while (hi >= lo)
1808
  {
1809
  i = (lo + hi) / 2;
1810
  s = strcmp(symtable[i].name, name);
1811
  if (s < 0)
1812
    lo = i + 1;
1813
  else if (s > 0)
1814
    hi = i - 1;
1815
  else
1816
    break;
1817
  }
1818
 
1819
if (s)                                  /* if symbol not found               */
1820
  {
1821
  if (!insert)                          /* if inserting prohibited,          */
1822
    return NULL;                        /* return without pointer            */
1823
 
1824
  i = (s < 0 ? i + 1 : i);
1825
  if (symcounter == MAXLABELS)
1826
    {
1827
    printf("%s(%ld): error 23: out of symbol storage\n",
1828
           expandfn(curline->fn), curline->ln);
1829
    if (((dwOptions & OPTION_LP1) || pass == MAX_PASSNO) && (listing & LIST_ON))
1830
      putlist( "*** Error 23: out of symbol storage\n");
1831
    exit(4);
1832
    }
1833
  if (commonsym >= symtable + i)
1834
    commonsym++;
1835
  for (j = 0; j < symcounter; j++)
1836
    if (symtable[j].u.parent >= symtable + i)
1837
      symtable[j].u.parent++;
1838
  for (j = symcounter; j > i; j--)
1839
    symtable[j] = symtable[j-1];
1840
  symcounter++;
1841
  strcpy(symtable[i].name, name);
1842
  symtable[i].cat = (islocal) ? SYMCAT_EMPTYLOCAL : SYMCAT_EMPTY;
1843
  symtable[i].value = 0;
1844
  symtable[i].u.flags = 0;
1845
  }
1846
 
1847
if (islocal)                            /* if searching for a local label    */
1848
  return findlocal(symtable + i,        /* search for the local label        */
1849
                   forward, (islocal < 2));
1850
 
1851
return symtable + i;                    /* return the found or inserted sym  */
1852
}
1853
 
1854
/*****************************************************************************/
1855
/* findsymat : finds 1st symbol fo a given address                           */
1856
/*****************************************************************************/
1857
 
1858
char *findsymat(unsigned addr)
1859
{
1860
/* since the symbol table is sorted by name, this needs a sequential search  */
1861
int i;
1862
for (i = 0; i < symcounter; i++)
1863
  if (symtable[i].cat != SYMCAT_EMPTY)
1864
    {
1865
    if (symtable[i].cat == SYMCAT_TEXT)
1866
      continue;
1867
    if (symtable[i].value == addr)
1868
      return symtable[i].name;
1869
    }
1870
return NULL;
1871
}
1872
 
1873
/*****************************************************************************/
1874
/* settext : sets a text symbol                                              */
1875
/*****************************************************************************/
1876
 
1877
int settext(char *namebuf, char *text)
1878
{
1879
struct symrecord *lp = findsym(namebuf, 1);
1880
int len;
1881
int special = 0;
1882
 
1883
if (!lp)
1884
  {
1885
  error |= ERR_LABEL_UNDEF;
1886
  return -1;
1887
  }
1888
if (lp->cat != SYMCAT_EMPTY &&
1889
    lp->cat != SYMCAT_TEXT)
1890
  {
1891
  error |= ERR_LABEL_MULT;
1892
  return -1;
1893
  }
1894
 
1895
if (lp->cat != SYMCAT_EMPTY)
1896
  free(texts[lp->value]);
1897
else if (nTexts >= MAXTEXTS)
1898
  {
1899
  error |= ERR_MALLOC;
1900
  return -1;
1901
  }
1902
else
1903
  {
1904
  lp->cat = SYMCAT_TEXT;
1905
  lp->value = nTexts++;
1906
  }
1907
 
1908
if (!text)                              /* if NULL input                     */
1909
  text = "";                            /* assume empty string               */
1910
 
1911
for (len = 0; text[len]; len++)
1912
  if ((isspace(text[len])) ||
1913
      (text[len] == ','))
1914
    special = 1;
1915
if (!len)                               /* empty string?                     */
1916
  special = 1;                          /* that's special anyway.            */
1917
if (special && len &&                   /* if delimited special string       */
1918
    (text[0] == '\'' || text[0] == '\"') &&
1919
    (text[len - 1] == text[0]))
1920
  special = 0;                          /* forget that "special" flag        */
1921
 
1922
len += (special) ? 3 : 1;
1923
texts[lp->value] = malloc(len);
1924
if (texts[lp->value])
1925
  {
1926
  if (special)
1927
    texts[lp->value][0] = '\"';
1928
  strcpy(texts[lp->value] + special, text);
1929
  if (special)
1930
    strcat(texts[lp->value], "\"");
1931
  }
1932
 
1933
return lp->value;
1934
}
1935
 
1936
/*****************************************************************************/
1937
/* outsymtable : prints the symbol table                                     */
1938
/*****************************************************************************/
1939
 
1940
void outsymtable()
1941
{
1942
int i,j = 0;
1943
 
1944
if (dwOptions & OPTION_PAG)             /* if pagination active,             */
1945
  {
1946
  if (nCurLine > 5)                     /* if not on 1st line,               */
1947
    PageFeed();                         /* shift to next page                */
1948
  }
1949
else
1950
  putlist("\n");
1951
 
1952
putlist("SYMBOL TABLE");
1953
for (i = 0; i < symcounter; i++)
1954
  if (symtable[i].cat != SYMCAT_EMPTY)
1955
    {
1956
                                        /* suppress listing of predef texts  */
1957
    if ((symtable[i].cat == SYMCAT_TEXT) &&
1958
        (symtable[i].value < nPredefinedTexts))
1959
      continue;
1960
                                        /* if local label                    */
1961
    if (symtable[i].cat == SYMCAT_LOCALLABEL)
1962
      {
1963
      int k;                            /* walk local label list             */
1964
      for (k = 0; k < lclcounter; k++)
1965
        if (!strcmp(lcltable[k].name, symtable[i].name))
1966
          {
1967
          if (j % 4 == 0)
1968
            putlist("\n");
1969
          putlist( " %9s %02d %08X", lcltable[k].name, lcltable[k].cat,
1970
                                     lcltable[k].value);
1971
          j++;
1972
          }
1973
      }
1974
    else                                /* if normal label                   */
1975
      {
1976
      if (j % 4 == 0)
1977
        putlist("\n");
1978
      putlist( " %9s %02d %08X", symtable[i].name,symtable[i].cat,
1979
                                 symtable[i].value);
1980
      j++;
1981
      }
1982
    }
1983
putlist("\n%d SYMBOLS\n", j);
1984
}
1985
 
1986
/*****************************************************************************/
1987
/* outreltable : prints the relocation table                                 */
1988
/*****************************************************************************/
1989
 
1990
void outreltable()
1991
{
1992
int i,j = 0;
1993
 
1994
if (dwOptions & OPTION_PAG)             /* if pagination active,             */
1995
  {
1996
  if (nCurLine > 5)                     /* if not on 1st line,               */
1997
    PageFeed();                         /* shift to next page                */
1998
  }
1999
else
2000
  putlist("\n");
2001
 
2002
putlist("RELOCATION TABLE");
2003
for (i = 0; i < relcounter; i++)
2004
  {
2005
  char name[10];
2006
  sprintf(name, "%c%-.8s",
2007
          (reltable[i].exprcat & EXPRCAT_NEGATIVE) ? '-' : ' ',
2008
          reltable[i].sym->name);
2009
  if (j % 4 == 0)
2010
    putlist("\n");
2011
  putlist( " %9s %02d %04X",
2012
           name,
2013
           reltable[i].sym->cat,
2014
           reltable[i].addr);
2015
  j++;
2016
  }
2017
putlist("\n%d RELOCATIONS\n", j);
2018
}
2019
 
2020
/*****************************************************************************/
2021
/* outtexttable : prints the text table                                      */
2022
/*****************************************************************************/
2023
 
2024
void outtexttable()
2025
{
2026
int i,j = 0;
2027
 
2028
if (dwOptions & OPTION_PAG)             /* if pagination active,             */
2029
  {
2030
  if (nCurLine > 5)                     /* if not on 1st line,               */
2031
    PageFeed();                         /* shift to next page                */
2032
  }
2033
else
2034
  putlist("\n");
2035
 
2036
putlist("TEXT TABLE");
2037
for (i = 0; i < symcounter; i++)
2038
  if (symtable[i].cat == SYMCAT_TEXT)
2039
    {
2040
                                        /* suppress listing of predef texts  */
2041
    if (symtable[i].value < nPredefinedTexts)
2042
      continue;
2043
    putlist("\n %9s %s", symtable[i].name, texts[symtable[i].value]);
2044
    j++;
2045
    }
2046
putlist("\n%d TEXTS\n", j);
2047
}
2048
 
2049
/*****************************************************************************/
2050
/* findreg : finds a register per name                                       */
2051
/*****************************************************************************/
2052
 
2053
struct regrecord * findreg(char *nm)
2054
{
2055
int i;
2056
for (i = 0; regtable[i].name != NULL; i++)
2057
  {
2058
  if (strcmp(regtable[i].name,nm) == 0)
2059
    return regtable + i;
2060
  }
2061
return 0;
2062
}
2063
 
2064
/*****************************************************************************/
2065
/* findreg63 : finds a register per name for HD63 operations                 */
2066
/*****************************************************************************/
2067
 
2068
struct regrecord * findreg63(char *nm)
2069
{
2070
int i;
2071
for (i = 0; i < (sizeof(regtable63) / sizeof(regtable63[0])); i++)
2072
  {
2073
  if (strcmp(regtable63[i].name,nm) == 0)
2074
    return regtable63 + i;
2075
  }
2076
return 0;
2077
}
2078
 
2079
/*****************************************************************************/
2080
/* findbitreg : finds a bit transfer register per name (6309 only)           */
2081
/*****************************************************************************/
2082
 
2083
struct regrecord * findbitreg(char *nm)
2084
{
2085
int i;
2086
for (i = 0; i < (sizeof(bitregtable) / sizeof(bitregtable[0])); i++)
2087
  {
2088
  if (strcmp(bitregtable[i].name,nm) == 0)
2089
    return bitregtable + i;
2090
  }
2091
return 0;
2092
}
2093
 
2094
/*****************************************************************************/
2095
/* strupr : converts a string to uppercase (crude)                           */
2096
/*****************************************************************************/
2097
 
2098
char *strupr(char *name)
2099
{
2100
int i;
2101
if (!name)
2102
  return name;
2103
for (i = 0; name[i]; i++)
2104
  if ((name[i] >= 'a') && (name[i] <= 'z'))
2105
    name[i] -= ('a' - 'A');
2106
return name;
2107
}
2108
 
2109
/*****************************************************************************/
2110
/* addreloc : adds a relocation record to the list                           */
2111
/*****************************************************************************/
2112
 
2113
void addreloc(struct relocrecord *p)
2114
{
2115
struct relocrecord rel = {0};           /* internal copy                     */
2116
 
2117
if (p)                                  /* if there's a record,              */
2118
  rel = *p;                             /* copy to internal                  */
2119
 
2120
if ((!relocatable) ||                   /* if generating unrelocatable binary*/
2121
    (!rel.sym) ||                       /* or no symbol                      */
2122
    (pass == 1))                        /* or in pass 1                      */
2123
  return;                               /* do nothing here                   */
2124
 
2125
switch (rel.sym->cat)                   /* check symbol category             */
2126
  {
2127
  case SYMCAT_PUBLIC :                  /* public label ?                    */
2128
  case SYMCAT_LABEL :                   /* normal label ?                    */
2129
  case SYMCAT_EXTERN :                  /* external symbol ?                 */
2130
    break;                              /* these are allowed                 */
2131
  case SYMCAT_COMMONDATA :              /* Common data ?                     */
2132
    rel.sym = rel.sym->u.parent;        /* switch to COMMON block            */
2133
    break;                              /* and allow it.                     */
2134
  default :                             /* anything else                     */
2135
    return;                             /* isn't                             */
2136
  }
2137
 
2138
if (relcounter >= MAXRELOCS)            /* if no more space                  */
2139
  {                                     /* should NEVER happen... but then...*/
2140
  error |= ERR_MALLOC;                  /* set mem alloc err                 */
2141
  return;                               /* and get out of here               */
2142
  }
2143
 
2144
reltable[relcounter++] = rel;           /* add relocation record             */
2145
 
2146
switch (p->sym->cat)                    /* do specials...                    */
2147
  {
2148
  case SYMCAT_PUBLIC :                  /* public label ?                    */
2149
  case SYMCAT_LABEL :                   /* normal label ?                    */
2150
  case SYMCAT_COMMONDATA :              /* common data ?                     */
2151
    curline->rel =                      /* remember there's a relocation     */
2152
      (p->exprcat & EXPRCAT_NEGATIVE) ? '-' : '+';
2153
    break;
2154
  case SYMCAT_EXTERN :                  /* external symbol ?                 */
2155
    curline->rel =
2156
      (p->exprcat & EXPRCAT_NEGATIVE) ? 'x' : 'X';
2157
    break;
2158
  }
2159
 
2160
}
2161
 
2162
/*****************************************************************************/
2163
/* scanname : scans a name from the input buffer                             */
2164
/*****************************************************************************/
2165
 
2166
void scanname()
2167
{
2168
int i = 0;
2169
char c;
2170
char cValid;
2171
 
2172
while (1)
2173
  {
2174
  c = *srcptr++;
2175
  if ((!(dwOptions & OPTION_TSC)) &&    /* TSC Assembler is case-sensitive   */
2176
      (!(dwOptions & OPTION_GAS)) &&    /* GNU Assembler is case-sensitive   */
2177
      (c >= 'a' && c <= 'z'))
2178
    c -= 32;
2179
  cValid = 0;                           /* check for validity                */
2180
  if ((c >= '0' && c <= '9') ||         /* normally, labels may consist of   */
2181
      (c >= 'A' && c <= 'Z') ||         /* the characters A..Z,a..z,_        */
2182
      (c >= 'a' && c <= 'z') ||
2183
      (c == '_'))
2184
    cValid = 1;
2185
  if (dwOptions & OPTION_GAS)           /* for GNU AS compatibility,         */
2186
    {                                   /* the following rules apply:        */
2187
    if ((c == '.') ||                   /* .$ are valid symbol characters    */
2188
        (c == '$'))
2189
     cValid = 1;
2190
    }
2191
  if (!cValid)                          /* if invalid character encountered  */
2192
    break;                              /* stop here                         */
2193
 
2194
  if (i < maxidlen)
2195
    {
2196
    namebuf[i] = c;
2197
    unamebuf[i] = toupper(c);
2198
    i++;
2199
    }
2200
  }
2201
namebuf[i] = '\0';
2202
unamebuf[i] = '\0';
2203
srcptr--;
2204
}
2205
 
2206
/*****************************************************************************/
2207
/* skipspace : skips whitespace characters                                   */
2208
/*****************************************************************************/
2209
 
2210
void skipspace()
2211
{
2212
char c;
2213
do
2214
  {
2215
  c = *srcptr++;
2216
  } while (c == ' ' || c == '\t');
2217
srcptr--;
2218
}
2219
 
2220
long scanexpr(int, struct relocrecord *);
2221
 
2222
/*****************************************************************************/
2223
/* scandecimal : scans a decimal number                                      */
2224
/*****************************************************************************/
2225
 
2226
long scandecimal()
2227
{
2228
char c;
2229
long t = 0;
2230
c = *srcptr++;
2231
while (isdigit(c))
2232
  {
2233
  t = t * 10 + c - '0';
2234
  c = *srcptr++;
2235
  }
2236
srcptr--;
2237
return t;
2238
}
2239
 
2240
/*****************************************************************************/
2241
/* scanhex : scans hex number                                                */
2242
/*****************************************************************************/
2243
 
2244
long scanhex()
2245
{
2246
long t = 0, i = 0;
2247
 
2248
srcptr++;
2249
scanname();
2250
while (unamebuf[i] >= '0' && unamebuf[i] <= 'F')
2251
  {
2252
  t = t * 16 + unamebuf[i] - '0';
2253
  if (unamebuf[i] > '9')
2254
    t -= 7;
2255
  i++;
2256
  }
2257
if (i==0)
2258
  error |= ERR_EXPR;
2259
return t;
2260
}
2261
 
2262
/*****************************************************************************/
2263
/* scanchar : scan a character                                               */
2264
/*****************************************************************************/
2265
 
2266
long scanchar()
2267
{
2268
long  t;
2269
 
2270
srcptr++;
2271
t = *srcptr;
2272
if (t)
2273
  srcptr++;
2274
if (*srcptr == '\'')
2275
  srcptr++;
2276
return t;
2277
}
2278
 
2279
/*****************************************************************************/
2280
/* scanbin : scans a binary value                                            */
2281
/*****************************************************************************/
2282
 
2283
long scanbin()
2284
{
2285
char c;
2286
short t = 0;
2287
 
2288
srcptr++;
2289
c = *srcptr++;
2290
while (c == '0' || c == '1')
2291
  {
2292
  t = t * 2 + c - '0';
2293
  c = *srcptr++;
2294
  }
2295
srcptr--;
2296
return t;
2297
}
2298
 
2299
/*****************************************************************************/
2300
/* scanoct : scans an octal value                                            */
2301
/*****************************************************************************/
2302
 
2303
long scanoct()
2304
{
2305
char c;
2306
long t = 0;
2307
 
2308
srcptr++;
2309
c = *srcptr++;
2310
while (c >= '0' && c <= '7')
2311
  {
2312
  t = t * 8 + c - '0';
2313
  c = *srcptr++;
2314
  }
2315
srcptr--;
2316
return t;
2317
}
2318
 
2319
/*****************************************************************************/
2320
/* scanstring : scans a string into a buffer                                 */
2321
/*****************************************************************************/
2322
 
2323
char * scanstring(char *dest, int nlen)
2324
{
2325
char *s = srcptr;
2326
char *d = dest;
2327
int nInString = 0;
2328
char c;
2329
 
2330
if (*srcptr == '\'' || *srcptr == '\"')
2331
  {
2332
  nInString = 1;
2333
  srcptr++;
2334
  }
2335
 
2336
while (*srcptr)
2337
  {
2338
  if (!nInString &&
2339
      (*srcptr == ' ' || *srcptr == ','))
2340
    break;
2341
  else if (nInString && *s == *srcptr)
2342
    {
2343
    srcptr++;
2344
    break;
2345
    }
2346
  c = *srcptr++;
2347
  if (!nInString && c >= 'a' && c <= 'z')
2348
    c -= 32;
2349
  *d++ = c;
2350
  }
2351
*d = '\0';
2352
 
2353
return dest;
2354
}
2355
 
2356
 
2357
/*****************************************************************************/
2358
/* scanlabel : scans a label                                                 */
2359
/*****************************************************************************/
2360
 
2361
unsigned scanlabel(struct relocrecord *pp)
2362
{
2363
struct symrecord * p;
2364
 
2365
scanname();
2366
p = findsym(namebuf, 1);
2367
if (p->cat == SYMCAT_EMPTY)
2368
  {
2369
  p->cat = SYMCAT_UNRESOLVED;
2370
  p->value = 0;
2371
  p->u.flags |= SYMFLAG_FORWARD;
2372
  }
2373
 
2374
if (p->cat == SYMCAT_MACRO ||
2375
    p->cat == SYMCAT_PARMNAME ||
2376
    p->cat == SYMCAT_TEXT)
2377
  error |= ERR_EXPR;
2378
exprcat = p->cat & (EXPRCAT_PUBLIC | EXPRCAT_EXTADDR | EXPRCAT_INTADDR);
2379
if (exprcat == (EXPRCAT_EXTADDR | EXPRCAT_INTADDR) ||
2380
    exprcat == (EXPRCAT_PUBLIC | EXPRCAT_INTADDR))
2381
  unknown = 1;
2382
 
2383
#if 1
2384
/* anything that's not yet defined is uncertain in pass 2! */
2385
if ((p->u.flags & (SYMFLAG_FORWARD | SYMFLAG_PASSED)) == SYMFLAG_FORWARD)
2386
  certain = 0;
2387
#else
2388
if (((exprcat == EXPRCAT_INTADDR ||
2389
      exprcat == EXPRCAT_PUBLIC) &&
2390
//    (unsigned short)(p->value) > (unsigned short)loccounter) ||
2391
//    (p->u.flags & SYMFLAG_FORWARD)) ||
2392
    ((p->u.flags & (SYMFLAG_FORWARD | SYMFLAG_PASSED)) == SYMFLAG_FORWARD)) ||
2393
    exprcat == EXPRCAT_EXTADDR)
2394
  certain = 0;
2395
#endif
2396
if ((!absmode) &&                       /* if in relocating mode             */
2397
    (exprcat))                          /* and this is not a constant        */
2398
  certain = 0;                          /* this is NOT certain               */
2399
if (exprcat == EXPRCAT_PUBLIC ||
2400
    exprcat == (EXPRCAT_EXTADDR | EXPRCAT_INTADDR) ||
2401
    exprcat == (EXPRCAT_PUBLIC | EXPRCAT_INTADDR))
2402
  exprcat = EXPRCAT_INTADDR;
2403
if (pp)
2404
  {
2405
  pp->exprcat = exprcat;
2406
  pp->sym = p;
2407
  }
2408
  if (p->isFar)
2409
          isFar = 1;
2410
  if (p->isFarkw)
2411
          isFarkw = 1;
2412
return p->value;
2413
}
2414
 
2415
/*****************************************************************************/
2416
/* isfactorstart : returns whether passed character possibly starts a factor */
2417
/*****************************************************************************/
2418
 
2419
int isfactorstart(char c)
2420
{
2421
if (isalpha(c))
2422
  return 1;
2423
else if (isdigit(c))
2424
  return 1;
2425
else switch (c)
2426
  {
2427
  case '*' :
2428
  case '$' :
2429
  case '%' :
2430
  case '@' :
2431
  case '\'' :
2432
  case '(' :
2433
  case '-' :
2434
  case '+' :
2435
  case '!' :
2436
  case '~' :
2437
    return 1;
2438
  }
2439
return 0;
2440
}
2441
 
2442
/*****************************************************************************/
2443
/* scanfactor : scans an expression factor                                   */
2444
/*****************************************************************************/
2445
 
2446
long scanfactor(struct relocrecord *p)
2447
{
2448
char c;
2449
long t;
2450
 
2451
if (!(dwOptions & OPTION_TSC))
2452
  skipspace();
2453
c = *srcptr;
2454
if (isalpha(c))
2455
  return (unsigned)scanlabel(p);
2456
else if (isdigit(c))
2457
  {
2458
  char *locptr = srcptr;                /* watch out for local labels        */
2459
  char caft;
2460
  while ((*locptr >= '0') &&            /* advance to next nonnumeric        */
2461
         (*locptr <= '9'))
2462
    locptr++;
2463
  caft = toupper(*locptr);              /* get next character in uppercase   */
2464
  if ((caft == 'B') || (caft == 'F'))   /* if this might be a local reference*/
2465
    return scanlabel(p);         /* look it up.                       */
2466
  switch (c)
2467
    {
2468
    case '0' :                          /* GNU AS bin/oct/hex?               */
2469
      if (dwOptions & OPTION_GAS)       /* if GNU AS extensions,             */
2470
        {
2471
        if (srcptr[1] == 'b')           /* if binary value,                  */
2472
          {
2473
          srcptr++;                     /* advance behind 0                  */
2474
          return scanbin();             /* and treat rest as binary value    */
2475
          }
2476
        else if (srcptr[1] == 'x')      /* if hex value,                     */
2477
          {
2478
          srcptr++;                     /* advance behind 0                  */
2479
          return scanhex();             /* and treat rest as hex value       */
2480
          }
2481
        return scanoct();               /* otherwise treat as octal          */
2482
        }
2483
      /* else fall thru on purpose */
2484
    default :                           /* decimal in any case ?             */
2485
      return scandecimal();
2486
    }
2487
  }
2488
else switch (c)
2489
  {
2490
  case '*' :
2491
    srcptr++;
2492
    exprcat |= EXPRCAT_INTADDR;
2493
    return loccounter;
2494
  case '$' :
2495
    return scanhex();
2496
  case '%' :
2497
    return scanbin();
2498
  case '@' :
2499
    return scanoct();
2500
  case '\'' :
2501
    return scanchar();
2502
  case '(' :
2503
    srcptr++;
2504
    t = scanexpr(0, p);
2505
    if (!(dwOptions & OPTION_TSC))
2506
      skipspace();
2507
    if (*srcptr == ')')
2508
      srcptr++;
2509
    else
2510
      error |= ERR_EXPR;
2511
    return t;
2512
  case '-' :
2513
    srcptr++;
2514
    t = scanfactor(p);
2515
    exprcat ^= EXPRCAT_NEGATIVE;
2516
    if (p)
2517
      p->exprcat ^= EXPRCAT_NEGATIVE;
2518
    return -t;
2519
  case '+' :
2520
    srcptr++;
2521
    return scanfactor(p);
2522
  case '!' :
2523
    srcptr++;
2524
    exprcat |= EXPRCAT_FIXED;
2525
    return !scanfactor(p);
2526
  case '~' :
2527
    srcptr++;
2528
    exprcat |= EXPRCAT_FIXED;
2529
    return ~scanfactor(p);
2530
  }
2531
error |= ERR_EXPR;
2532
return 0;
2533
}
2534
 
2535
/*****************************************************************************/
2536
/* some nice macros                                                          */
2537
/*****************************************************************************/
2538
 
2539
/*define EXITEVAL { srcptr--; return t; } */
2540
#define EXITEVAL { srcptr--; parsing = 0; break; }
2541
 
2542
#define RESOLVECAT if((oldcat & 15) == 0) oldcat = 0;               \
2543
           if ((exprcat & 15) == 0)exprcat = 0;                     \
2544
           if ((exprcat == EXPRCAT_INTADDR &&                       \
2545
                oldcat == (EXPRCAT_INTADDR | EXPRCAT_NEGATIVE)) ||  \
2546
               (exprcat == (EXPRCAT_INTADDR | EXPRCAT_NEGATIVE)&&   \
2547
               oldcat == EXPRCAT_INTADDR))                          \
2548
             {                                                      \
2549
             exprcat = 0;                                           \
2550
             oldcat = 0;                                            \
2551
             }                                                      \
2552
           exprcat |= oldcat;
2553
/* resolve such cases as constant added to address or difference between
2554
   two addresses in same module */
2555
 
2556
/*****************************************************************************/
2557
/* scanexpr : scan expression                                                */
2558
/*****************************************************************************/
2559
 
2560
long scanexpr(int level, struct relocrecord *pp) /* This is what you call _recursive_ descent!!!*/
2561
{
2562
long t, u;
2563
char oldcat,c,parsing=1;
2564
struct relocrecord ip = {0}, p = {0};
2565
 
2566
exprcat = 0;
2567
if (level == 10)
2568
  return scanfactor(pp);
2569
t = scanexpr(level + 1, &ip);
2570
/* ip.exprcat = exprcat; */
2571
while (parsing)
2572
  {
2573
  p.sym = NULL;
2574
  if (!(dwOptions & OPTION_TSC))
2575
    skipspace();
2576
  c = *srcptr++;
2577
  switch(c)
2578
    {
2579
    case '*':
2580
      oldcat = exprcat;
2581
      t *= scanexpr(10, &p);
2582
      exprcat |= oldcat | EXPRCAT_FIXED;
2583
      break;
2584
    case '/':
2585
      oldcat = exprcat;
2586
      u = scanexpr(10, &p);
2587
      if (u)
2588
        t /= u;
2589
      else
2590
        error |= ERR_EXPR;
2591
      exprcat |= oldcat | EXPRCAT_FIXED;
2592
      break;
2593
    case '%':
2594
      oldcat = exprcat;
2595
      u = scanexpr(10, &p);
2596
      if (u)
2597
        t %= u;
2598
      else
2599
        error |= ERR_EXPR;
2600
      exprcat |= oldcat | EXPRCAT_FIXED;
2601
      break;
2602
    case '+':
2603
      if (level == 9)
2604
        EXITEVAL
2605
      oldcat = exprcat;
2606
      t += scanexpr(9, &p);
2607
      RESOLVECAT
2608
      break;
2609
    case '-':
2610
      if (level == 9)
2611
        EXITEVAL
2612
      oldcat = exprcat;
2613
      t -= scanexpr(9, &p);
2614
      exprcat ^= EXPRCAT_NEGATIVE;
2615
      RESOLVECAT
2616
      break;
2617
    case '<':
2618
      if (*(srcptr) == '<')
2619
        {
2620
        if (level >= 8)
2621
          EXITEVAL
2622
        srcptr++;
2623
        oldcat = exprcat;
2624
        t <<= scanexpr(8, &p);
2625
        exprcat |= oldcat | EXPRCAT_FIXED;
2626
        }
2627
      else if (*(srcptr) == '=')
2628
        {
2629
        if (level >= 7)
2630
          EXITEVAL
2631
        srcptr++;
2632
        oldcat = exprcat;
2633
        t = t <= scanexpr(7, &p);
2634
        exprcat |= oldcat | EXPRCAT_FIXED;
2635
        }
2636
      else
2637
        {
2638
        if (level >= 7)
2639
          EXITEVAL
2640
        oldcat = exprcat;
2641
        t = t < scanexpr(7, &p);
2642
        exprcat |= oldcat | EXPRCAT_FIXED;
2643
        }
2644
      break;
2645
    case '>':
2646
      if (*(srcptr) == '>')
2647
        {
2648
        if (level >= 8)
2649
          EXITEVAL
2650
        srcptr++;
2651
        oldcat = exprcat;
2652
        t >>= scanexpr(8, &p);
2653
        exprcat |= oldcat | EXPRCAT_FIXED;
2654
        }
2655
      else if (*(srcptr) == '=')
2656
        {
2657
        if (level>=7)
2658
          EXITEVAL
2659
        srcptr++;
2660
        oldcat = exprcat;
2661
        t = t >= scanexpr(7, &p);
2662
        exprcat |= oldcat | EXPRCAT_FIXED;
2663
        }
2664
      else
2665
        {
2666
        if (level >= 7)
2667
          EXITEVAL
2668
        oldcat = exprcat;
2669
        t = t > scanexpr(7, &p);
2670
        exprcat |= oldcat | EXPRCAT_FIXED;
2671
        }
2672
      break;
2673
    case '!':
2674
      if (level >= 6 || *srcptr != '=')
2675
        EXITEVAL
2676
      srcptr++;
2677
      oldcat = exprcat;
2678
      t = t != scanexpr(6, &p);
2679
      exprcat |= oldcat | EXPRCAT_FIXED;
2680
      break;
2681
    case '=':
2682
      if (level >= 6)
2683
        EXITEVAL
2684
      if (*srcptr == '=')
2685
        srcptr++;
2686
      oldcat = exprcat;
2687
      t = (t == scanexpr(6, &p));
2688
      exprcat |= oldcat | EXPRCAT_FIXED;
2689
      break;
2690
    case '&':
2691
      if (level >= 5)
2692
        EXITEVAL
2693
      oldcat = exprcat;
2694
      t &= scanexpr(5, &p);
2695
      exprcat |= oldcat | EXPRCAT_FIXED;
2696
      break;
2697
    case '^':
2698
      if (level >= 4)
2699
        EXITEVAL
2700
      oldcat = exprcat;
2701
      t ^= scanexpr(4, &p);
2702
      exprcat |= oldcat | EXPRCAT_FIXED;
2703
      break;
2704
    case '|':
2705
      if (level >= 3)
2706
        EXITEVAL
2707
      oldcat = exprcat;
2708
      t |= scanexpr(3, &p);
2709
      exprcat |= oldcat | EXPRCAT_FIXED;
2710
      break;
2711
    default:
2712
      EXITEVAL
2713
    }
2714
  p.exprcat = exprcat;
2715
  if (p.sym)
2716
    {
2717
    if (ip.sym)                         /* if 2 symbols, cancel 'em          */
2718
      {
2719
      /* a simple safeguard against cancelling local vs. external symbols
2720
         or operations between 2 external symbols.
2721
         This means that an external symbol has to be the last one in an
2722
         expression, or the others have to be paired so that they cancel
2723
         each other's effect AND their subexpression has to be parenthesized.*/
2724
      if ((ip.sym->cat == SYMCAT_EXTERN) || (p.sym->cat == SYMCAT_EXTERN))
2725
        error |= ERR_EXPR;
2726
      else
2727
        ip.sym = NULL;                  /* this might be TOO crude...        */
2728
      }
2729
    else                                /* if new symbol                     */
2730
      ip = p;                           /* use this one                      */
2731
    }
2732
  }
2733
 
2734
*pp = ip;
2735
return t;
2736
}
2737
 
2738
/*****************************************************************************/
2739
/* scanindexreg : scans an index register                                    */
2740
/*****************************************************************************/
2741
 
2742
int scanindexreg()
2743
{
2744
switch (toupper(*srcptr))
2745
  {
2746
  case 'X':
2747
    return 1;
2748
  case 'Y':
2749
    postbyte |= 0x200;
2750
    return 1;
2751
  case 'U':
2752
    postbyte |= 0x400;
2753
    return 1;
2754
  case 'S':
2755
    postbyte |= 0x600;
2756
    return 1;
2757
  }
2758
return 0;
2759
}
2760
 
2761
/*****************************************************************************/
2762
/* set3 : sets mode to at least ADRMODE_POST                                 */
2763
/*****************************************************************************/
2764
 
2765
void set3()
2766
{
2767
if (mode < ADRMODE_POST)
2768
  mode = ADRMODE_POST;
2769
}
2770
 
2771
/*****************************************************************************/
2772
/* scanspecial : scans for increments                                        */
2773
/*****************************************************************************/
2774
 
2775
void scanspecial()
2776
{
2777
set3();
2778
if (!(dwOptions & OPTION_TSC))
2779
  skipspace();
2780
if (*srcptr == '-')
2781
  {
2782
  srcptr++;
2783
  if (*srcptr == '-')
2784
    {
2785
    srcptr++;
2786
    postbyte = 0x803;
2787
    }
2788
  else
2789
    postbyte = 0x802;
2790
 
2791
  if ((dwOptions & OPTION_H63) &&       /* special for ,--W and [,--W]       */
2792
      (postbyte == 0x803) &&
2793
      (toupper(*srcptr) == 'W'))
2794
    {
2795
    postbyte = (mode == ADRMODE_IND) ? 0x900 : 0x80f;
2796
    srcptr++;
2797
    }
2798
  else if (!scanindexreg())
2799
    error |= ERR_ILLEGAL_ADDR;
2800
  else
2801
    srcptr++;
2802
  }
2803
else
2804
  {
2805
  postbyte = 0x800;
2806
  if ((dwOptions & OPTION_H63) &&       /* special for ,W, [,W], ,W++, [,W++]*/
2807
      (toupper(*srcptr) == 'W'))
2808
    {
2809
    srcptr++;                           /* advance behind W                  */
2810
    if (*srcptr == '+')
2811
      {
2812
      srcptr++;
2813
      if (*srcptr == '+')               /* ,W++ and [,W++]                   */
2814
        {
2815
        postbyte = (mode == ADRMODE_IND) ? 0xB00 : 0xA0F;
2816
        srcptr++;
2817
        }
2818
      else
2819
        error |= ERR_ILLEGAL_ADDR;
2820
      }
2821
    else                                /* ,W and [,W]                       */
2822
      postbyte = (mode == ADRMODE_IND) ? 0x900 : 0x80F;
2823
    }
2824
  else                                  /* normal index register addressing  */
2825
    {
2826
    if (!scanindexreg())
2827
      error |= ERR_ILLEGAL_ADDR;
2828
    else
2829
      srcptr++;
2830
    if (*srcptr == '+')
2831
      {
2832
      srcptr++;
2833
      if (*srcptr == '+')
2834
        {
2835
        srcptr++;
2836
        postbyte += 1;
2837
        }
2838
      }
2839
    else
2840
      postbyte += 4;
2841
    }
2842
  }
2843
}
2844
 
2845
/*****************************************************************************/
2846
/* scanindexed :                                                             */
2847
/*****************************************************************************/
2848
 
2849
void scanindexed()
2850
{
2851
set3();
2852
postbyte = 0;
2853
if ((dwOptions & OPTION_H63) &&         /* special for W as index register   */
2854
    (toupper(*srcptr) == 'W'))
2855
  {
2856
  srcptr++;
2857
  postbyte = (mode == ADRMODE_IND) ? 0xb00 : 0xa0f;
2858
  opsize = 3;
2859
  }
2860
else if (scanindexreg())
2861
  {
2862
  srcptr++;
2863
  if (opsize == 0)
2864
    {
2865
    if (unknown || !certain)
2866
      opsize = 3;
2867
    else if (operand >= -256 && operand < 256 && mode == ADRMODE_POST)
2868
      opsize = 1;
2869
    else if (operand >= -2048 && operand < 2048)
2870
      opsize = 2;
2871
    else if (operand >=-8388608 && operand < 8388608)
2872
                opsize = 3;
2873
        else
2874
      opsize = 4;
2875
    }
2876
  switch (opsize)
2877
    {
2878
    case 1:
2879 12 robfinch
      postbyte |= (operand & 511);
2880 4 robfinch
      opsize = 0;
2881
      break;
2882
    case 2:
2883 12 robfinch
      postbyte |= 0x808;
2884 4 robfinch
      break;
2885
    case 3:
2886 12 robfinch
      postbyte |= 0x809;
2887 4 robfinch
      break;
2888
        case 4:
2889 12 robfinch
          postbyte |= 0x80A;
2890 4 robfinch
          break;
2891
    }
2892
  }
2893
else
2894
  { /*pc relative*/
2895
  if (toupper(*srcptr) != 'P')
2896
    error |= ERR_ILLEGAL_ADDR;
2897
  else
2898
    {
2899
    srcptr++;
2900
    if (toupper(*srcptr) != 'C')
2901
      error |= ERR_ILLEGAL_ADDR;
2902
    else
2903
      {
2904
      srcptr++;
2905
      if (toupper(*srcptr) == 'R')
2906
        srcptr++;
2907
      }
2908
    }
2909
  mode++;
2910 12 robfinch
  postbyte |= 0x80c;
2911 4 robfinch
  if (opsize == 1)
2912
    opsize = 2;
2913
  }
2914
}
2915
 
2916
/*****************************************************************************/
2917
/* scanoperands :                                                            */
2918
/*****************************************************************************/
2919
 
2920
#define RESTORE { srcptr = oldsrcptr; c = *srcptr; goto dodefault; }
2921
 
2922
void scanoperands09(struct relocrecord *pp)
2923
{
2924
char c, *oldsrcptr, *ptr;
2925
unsigned short accpost, h63 = 0;
2926
unsigned short isIndexed = 0;
2927 12 robfinch
unsigned short indirect_byte = 0;
2928 4 robfinch
isFar = 0;
2929
isPostIndexed = 0;
2930
unknown = 0;
2931
opsize = 0;
2932
certain = 1;
2933
scano1:
2934
skipspace();
2935
c = *srcptr;
2936
mode = ADRMODE_IMM;
2937
if (c == '[')
2938
  {
2939
  c = *++srcptr;
2940
  if (c=='[') {
2941
          c = *++srcptr;
2942
          mode = ADRMODE_DBL_IND;
2943
          postbyte = 0x80F;
2944
  }
2945
  else
2946
          mode = ADRMODE_IND;
2947 12 robfinch
    indirect_byte = 0x100;
2948 4 robfinch
  }
2949
switch (toupper(c))
2950
  {
2951
  case 'D':
2952
    accpost = 0x80b;
2953
  accoffset:
2954
    oldsrcptr = srcptr;
2955
    srcptr++;
2956
    if (!(dwOptions & OPTION_TSC))
2957
      skipspace();
2958
    if (*srcptr != ',')
2959
      RESTORE
2960
    else
2961
      {
2962
                  isIndexed = 1;
2963
      if ((h63) && (!(dwOptions & OPTION_H63)))
2964
        error |= ERR_ILLEGAL_ADDR;
2965 12 robfinch
      postbyte |= accpost;
2966 4 robfinch
      srcptr++;
2967
      if (!scanindexreg())
2968
        RESTORE
2969
      else
2970
        {
2971
        srcptr++;
2972
        set3();
2973
        }
2974
      }
2975
    break;
2976
  case 'A':
2977
    accpost = 0x806;
2978
    goto accoffset;
2979
  case 'B':
2980
    accpost = 0x805;
2981
    goto accoffset;
2982
  case 'E':
2983
    accpost = 0x807;
2984
    h63 = 1;
2985
    goto accoffset;
2986
  case 'F':
2987
          if (toupper(srcptr[1])=='A' && toupper(srcptr[2])=='R' && (srcptr[3]==' '||srcptr[3]=='\t')) {
2988
                  isFar = 1;
2989
                  isFarkw = 1;
2990
                  srcptr += 3;
2991
                  goto scano1;
2992
          }
2993
    accpost = 0x80a;
2994
    h63 = 1;
2995
    goto accoffset;
2996
  case 'W' :
2997
    accpost = 0x80e;
2998
    h63 = 1;
2999
    goto accoffset;
3000
  case ',':
3001
    srcptr++;
3002
    scanspecial();
3003
    break;
3004
  case '#':
3005
    if (mode == ADRMODE_IND)
3006
      error |= ERR_ILLEGAL_ADDR;
3007
    else
3008
      mode = ADRMODE_IMM;
3009
    srcptr++;
3010
        if (*srcptr=='>') {
3011
                srcptr++;
3012
            operand = (scanexpr(0, pp) >> 24LL) & 0xffffffLL;
3013
                isFar = 0;
3014
                opsize = 3;
3015
        }
3016
        else if (*srcptr=='<') {
3017
                srcptr++;
3018
            operand = scanexpr(0, pp) & 0xffffffLL;
3019
                isFar = 0;
3020
                opsize = 3;
3021
        }
3022
        else
3023
                operand = scanexpr(0, pp);
3024
    break;
3025
  case '<':
3026
    srcptr++;
3027
    if (*srcptr == '<')
3028
      {
3029
      srcptr++;
3030
      opsize = 1;
3031
      }
3032
    else
3033
      opsize = 2;
3034
    goto dodefault;
3035
  case '>':
3036
    srcptr++;
3037
    opsize = 3;
3038
    /* fall thru on purpose */
3039
  default:
3040
  dodefault:
3041
    operand = scanexpr(0, pp);
3042
    if (!(dwOptions & OPTION_TSC))
3043
      skipspace();
3044
    if (*srcptr == ',')
3045
      {
3046
                  isIndexed = 1;
3047
      srcptr++;
3048
      if (!(dwOptions & OPTION_TSC))
3049
        skipspace();
3050
      if ((operand == 0) &&             /* special for "0,-[-]indexreg       */
3051
          (!unknown) && (certain) &&    /*         and "0,indexreg[+[+]]     */
3052
          (opsize < 3) &&               /* but NOT for ">0,indexreg"!        */
3053
          ((*srcptr == '-') ||
3054
           (scanindexreg() /* && (srcptr[1] == '+') */ )))
3055
        scanspecial();
3056
      else
3057
        scanindexed();
3058
      }
3059
    else
3060
      {
3061
      if (opsize == 0)
3062
        {
3063
        if ((unsigned)operand >= 16777216)
3064
                      opsize = 4;
3065
              else
3066
        if (unknown || !certain || dpsetting == -1 ||
3067 12 robfinch
          (signed)(operand - dpsetting * 4096) >= 2048 ||
3068
          (signed)(operand - dpsetting * 4096) < -2048)
3069 4 robfinch
          opsize = 3;
3070
        else
3071
          opsize = 2;
3072
        }
3073
      /*
3074
      if (opsize == 4) {
3075
        if ((operand & 0xff800000) == 0xff800000)
3076
          opsize = 3;
3077
        else if ((operand & 0xff800000) == 0x0)
3078
          opsize = 3;
3079
      }
3080
      */
3081
      if (opsize == 1)
3082
        opsize = 2;
3083
      if (mode == ADRMODE_IND)
3084
        {
3085
        postbyte = 0x80f;
3086
                // Why is the following set ?
3087
//        opsize = 3;
3088
        }
3089
          else if (mode == ADRMODE_DBL_IND)
3090
                  ;
3091
          else {
3092
                  switch(opsize) {
3093
                case 2: mode = ADRMODE_DIR; break;
3094
                case 3: mode = ADRMODE_EXT; break;
3095
//              case 4:
3096
                case 4: mode = ADRMODE_EXT; isFar = 1; break;
3097
                default: mode = opsize - 1;
3098
                  }
3099
          }
3100
      }
3101
  }
3102
 
3103
if (mode >= ADRMODE_IND)
3104
  {
3105
  if (!(dwOptions & OPTION_TSC))
3106
    skipspace();
3107
  if (mode != ADRMODE_DBL_IND)
3108
        postbyte |= 0x100;
3109
  if (*srcptr != ']')
3110
    error |= ERR_ILLEGAL_ADDR;
3111
  srcptr++;
3112
  if (mode==ADRMODE_DBL_IND) {
3113
          if (*srcptr != ']')
3114
                error |= ERR_ILLEGAL_ADDR;
3115
          srcptr++;
3116
  }
3117
  }
3118
  skipspace();
3119
  if (*srcptr==',') {
3120
          srcptr++;
3121
          isPostIndexed = 1;
3122 12 robfinch
    scanindexed();      // scanindexed will reset the postbyte
3123
          postbyte |= indirect_byte | 0x80;
3124 4 robfinch
  }
3125
  else {
3126
          if (postbyte==0x90F || postbyte==0x80F)
3127
                  opsize = 3;
3128
      if (mode == ADRMODE_IND || mode==ADRMODE_DBL_IND)
3129
        {
3130
/*
3131
                        if ((postbyte & 0xF)==4)        // 0 offset
3132
                                opsize = 0;
3133
                //      else if ((postbyte & 0xf)==8 || (postbyte & 0xF)==
3134
                        else
3135
                                opsize = 3;
3136
*/
3137
        }
3138
  }
3139
if (pass > 1 && unknown)
3140
  error |= ERR_LABEL_UNDEF;
3141
}
3142
 
3143
void scanoperands00(struct relocrecord *pp)
3144
{
3145
char c, *s = srcptr;
3146
 
3147
unknown = 0;
3148
opsize = 0;
3149
certain = 1;
3150
operand = 0;
3151
skipspace();
3152
c = *srcptr;
3153
mode = ADRMODE_IMM;
3154
switch (toupper(c))
3155
  {
3156
  case 'X' :                            /* "X"?                              */
3157
    scanname();
3158
    if (!strcmp(unamebuf, "X"))         /* if it's "X" alone,                */
3159
      goto XWithout;                    /* assume it means "0,X"             */
3160
    srcptr = s;                         /* else restore current offset       */
3161
    goto dodefault;                     /* and treat as label starting with X*/
3162
  case ',':                             /* ","?                              */
3163
  Indexed :
3164
    srcptr++;                           /* must be followed by "X"           */
3165
    if (!(dwOptions & OPTION_TSC))
3166
      skipspace();
3167
    scanname();
3168
    if (strcmp(unamebuf, "X"))          /* if it's NOT "X" alone,            */
3169
      {
3170
      error |= ERR_ILLEGAL_ADDR;
3171
      break;
3172
      }
3173
  XWithout :
3174
    if ((unsigned)operand < 256)
3175
      mode = ADRMODE_IDX;
3176
    else
3177
      error |= ERR_ILLEGAL_ADDR;
3178
    break;
3179
  case '#':
3180
    srcptr++;
3181
    operand = scanexpr(0, pp);
3182
    break;
3183
  case '<':
3184
    srcptr++;
3185
    if (*srcptr == '<')
3186
      {
3187
      srcptr++;
3188
      opsize = 1;
3189
      }
3190
    else
3191
      opsize = 2;
3192
    goto dodefault;
3193
  case '>':
3194
    srcptr++;
3195
    opsize = 3;
3196
    /* fall thru on purpose */
3197
  default:
3198
  dodefault:
3199
    operand = scanexpr(0, pp);
3200
    if (!(dwOptions & OPTION_TSC))
3201
      skipspace();
3202
    if (*srcptr == ',')
3203
      goto Indexed;
3204
    else
3205
      {
3206
      if (opsize == 0)
3207
        {
3208
        if (unknown || !certain ||
3209
          (unsigned short)(operand) >= 256)
3210
          opsize = 3;
3211
        else
3212
          opsize = 2;
3213
        }
3214
      if (opsize == 1)
3215
        opsize = 2;
3216
      mode = opsize - 1;
3217
      }
3218
  }
3219
 
3220
if (pass > 1 && unknown)
3221
  error |= ERR_LABEL_UNDEF;
3222
}
3223
 
3224
/*****************************************************************************/
3225
/* writerelhdr : writes a FLEX Relocatable Format header                     */
3226
/*****************************************************************************/
3227
 
3228
void writerelhdr(char wcommon)
3229
{
3230
int i;
3231
 
3232
#if 0
3233
struct                                  /* Header Layout                     */
3234
  {
3235
  unsigned char Signature;              /* Signature (always $03)            */
3236
  unsigned char flags1;                 /* Flags 1                           */
3237
  unsigned datasize;              /* size of binary data               */
3238
  unsigned char unknown1[4];            /* unknown data                      */
3239
  unsigned short extsize;               /* size of External table            */
3240
  unsigned startaddr;             /* program start address             */
3241
  unsigned char unknown2[2];            /* unknown data                      */
3242
  unsigned short globalsize;            /* size of global table              */
3243
  unsigned char unknown3[2];            /* unknown data                      */
3244
  unsigned short namesize;              /* length of module name             */
3245
  unsigned char flags2;                 /* Flags 2                           */
3246
  unsigned char unknown4[3];            /* unknown data; filler?             */
3247
  } hdr;
3248
memset(&hdr, 0, sizeof(hdr));
3249
#endif
3250
 
3251
fputc(0x04, objfile);                   /* write signature                   */
3252
 
3253
if (wcommon)                            /* if writing common data,           */
3254
  fputc(0x18, objfile);                 /* Flags1 = $18                      */
3255
else if (!absmode)                      /* if writing Relative data,         */
3256
  fputc(0x10, objfile);                 /* Flags1 = $10                      */
3257
else                                    /* if writing Absolute data,         */
3258
  fputc(0x12, objfile);                 /* Flags1 = $12                      */
3259
 
3260
if (wcommon)                            /* if writing common data            */
3261
  {                                     /* write size of data                */
3262
//  fputc((unsigned char)((commonsym->value >> 24) & 0xff), objfile);
3263
  fputc((unsigned char)((commonsym->value >> 16) & 0xff), objfile);
3264
  fputc((unsigned char)((commonsym->value >> 8) & 0xff), objfile);
3265
  fputc((unsigned char)(commonsym->value & 0xFF), objfile);
3266
  }
3267
else                                    /* otherwise                         */
3268
  {                                     /* write size of binary data         */
3269
//  fputc((unsigned char)((loccounter >> 24) & 0xff), objfile);
3270
  fputc((unsigned char)((loccounter >> 16) & 0xff), objfile);
3271
  fputc((unsigned char)((loccounter >> 8) & 0xff), objfile);
3272
  fputc((unsigned char)(loccounter & 0xFF), objfile);
3273
  }
3274
 
3275
//fputc(0, objfile);                      /* unknown data                      */
3276
fputc(0, objfile);
3277
fputc(0, objfile);
3278
fputc(0, objfile);
3279
 
3280
if (wcommon)                            /* if writing common data            */
3281
  {                                     /* external table is empty           */
3282
  fputc(0, objfile);
3283
  fputc(0, objfile);
3284
  }
3285
else
3286
  {
3287
  int extrel = 0;                       /* # external relocation records     */
3288
 
3289
  for (i = 0; i < relcounter; i++)      /* calc # external symbols           */
3290
    if ((reltable[i].sym->cat == SYMCAT_EXTERN) ||
3291
        (reltable[i].sym->cat == SYMCAT_COMMON))
3292
      extrel++;
3293
                                        /* then calculate table size         */
3294
  extrel = (extrel * 8) + (relcounter * 3);
3295
                                        /* and write it out                  */
3296
  fputc((unsigned char)(extrel >> 8), objfile);
3297
  fputc((unsigned char)(extrel & 0xFF), objfile);
3298
  }
3299
 
3300
if (wcommon ||                          /* if writing common data            */
3301
    (!tfradrset))                       /* or no transfer address given      */
3302
  {                                     /* start address is empty            */
3303
//  fputc(0, objfile);
3304
  fputc(0, objfile);
3305
  fputc(0, objfile);
3306
  fputc(0, objfile);
3307
  }
3308
else                                    /* write transfer address            */
3309
  {
3310
//  fputc((unsigned char)((tfradr >> 24) & 0xff), objfile);
3311
  fputc((unsigned char)((tfradr >> 16) & 0xff), objfile);
3312
  fputc((unsigned char)((tfradr >> 8) & 0xff), objfile);
3313
  fputc((unsigned char)(tfradr & 0xFF), objfile);
3314
  }
3315
 
3316
fputc(0, objfile);                      /* unknown data                      */
3317
fputc(0, objfile);
3318
 
3319
if (wcommon)
3320
  {                                     /* always 1 Global - the LABEL       */
3321
  fputc(0, objfile);
3322
  fputc(12, objfile);
3323
  }
3324
else                                    /* calculate & write out global size */
3325
  {
3326
  int globals = 0;
3327
  for (i = 0; i < symcounter; i++)
3328
    if (symtable[i].cat == SYMCAT_PUBLIC)
3329
      globals++;
3330
  globals *= 12;
3331
  fputc((unsigned char)(globals >> 8), objfile);
3332
  fputc((unsigned char)(globals & 0xFF), objfile);
3333
  }
3334
 
3335
fputc(0, objfile);                      /* unknown data                      */
3336
fputc(0, objfile);
3337
 
3338
if (wcommon)
3339
  {                                     /* no name size yet ...              */
3340
  size_t len;
3341
  char name[9] = "";
3342
  sprintf(name, "%-.8s", commonsym->name);
3343
  strupr(name);
3344
  len = strlen(name);
3345
  if (len)                              /* if there,                         */
3346
    len++;                              /* append a $04                      */
3347
  fputc((unsigned char)(len >> 8), objfile);
3348
  fputc((unsigned char)(len & 0xFF), objfile);
3349
  }
3350
else                                    /* write out module name size        */
3351
  {
3352
  size_t len = strlen(modulename);
3353
  if (len)                              /* if there,                         */
3354
    len++;                              /* append a $04                      */
3355
  fputc((unsigned char)(len >> 8), objfile);
3356
  fputc((unsigned char)(len & 0xFF), objfile);
3357
  }
3358
 
3359
if ((!wcommon) && (tfradrset))          /* if transfer address set           */
3360
  fputc(0x80, objfile);                 /* write $80 flag                    */
3361
else
3362
  fputc(0, objfile);
3363
 
3364
fputc(0, objfile);                      /* unknown data                      */
3365
fputc(0, objfile);
3366
fputc(0, objfile);
3367
}
3368
 
3369
/*****************************************************************************/
3370
/* writerelcommon : writes out all common blocks                             */
3371
/*****************************************************************************/
3372
 
3373
void writerelcommon()
3374
{
3375
int i, j;
3376
char name[9];
3377
                                        /* work through symbol list          */
3378
for (i = 0; i < symcounter; i++)
3379
  {
3380
  if (symtable[i].cat == SYMCAT_COMMON) /* if that is a common block         */
3381
    {
3382
    commonsym = symtable + i;           /* write it out                      */
3383
    writerelhdr(1);
3384
                                        /* then write the global definition  */
3385
    sprintf(name, "%-8.8s", symtable[i].name);
3386
    strupr(name);
3387
    fwrite(name, 1, 8, objfile);
3388
        if (symtable[i].value >= 65536)
3389
                fputc(2, objfile);                  /* unknown data                      */
3390
        else
3391
                fputc(1, objfile);                  /* unknown data                      */
3392
//    fputc((unsigned char)(symtable[i].value >> 24), objfile);
3393
    fputc((unsigned char)(symtable[i].value >> 16), objfile);
3394
    fputc((unsigned char)(symtable[i].value >> 8), objfile);
3395
    fputc((unsigned char)(symtable[i].value & 0xFF), objfile);
3396
    fputc(0x13, objfile);               /* unknown flag                      */
3397
 
3398
                                        /* then write the Common name        */
3399
    sprintf(name, "%-.8s", symtable[i].name);
3400
    strupr(name);
3401
    for (j = 0; name[j]; j++)
3402
      fputc(name[j], objfile);
3403
    fputc(0x04, objfile);
3404
 
3405
    j = (int)ftell(objfile);            /* fill last sector with zeroes      */
3406
    while (j % 252)
3407
      {
3408
      fputc(0, objfile);
3409
      j++;
3410
      }
3411
    }
3412
  }
3413
}
3414
 
3415
/*****************************************************************************/
3416
/* writerelext : writes out a FLEX Relocatable External table                */
3417
/*****************************************************************************/
3418
 
3419
void writerelext()
3420
{
3421
int i;
3422
char name[9];
3423
unsigned char flags;
3424
 
3425
for (i = 0; i < relcounter; i++)        /* write out the external data       */
3426
  {
3427
//  fputc((unsigned char)(reltable[i].addr >> 24), objfile);
3428
  fputc((unsigned char)(reltable[i].addr >> 16), objfile);
3429
  fputc((unsigned char)(reltable[i].addr >> 8), objfile);
3430
  fputc((unsigned char)(reltable[i].addr & 0xFF), objfile);
3431
 
3432
  flags = 0x00;                         /* reset flags                       */
3433
  if (reltable[i].exprcat & EXPRCAT_NEGATIVE)
3434
    flags |= 0x20;                      /* eventually add subtraction flag   */
3435
  if ((reltable[i].sym->cat == SYMCAT_EXTERN) ||
3436
      (reltable[i].sym->cat == SYMCAT_COMMON))
3437
    flags |= 0x80;                      /* eventually add External flag      */
3438
  fputc(flags, objfile);                /* write the flag bytes              */
3439
  if (flags & 0x80)                     /* eventually write external symbol  */
3440
    {
3441
    sprintf(name, "%-8.8s", reltable[i].sym->name);
3442
    strupr(name);
3443
    fwrite(name, 1, 8, objfile);
3444
    }
3445
  }
3446
}
3447
 
3448
/*****************************************************************************/
3449
/* writerelglobal : writes out FLEX Relocatable Global table                 */
3450
/*****************************************************************************/
3451
 
3452
void writerelglobal()
3453
{
3454
int i;
3455
char name[9];
3456
 
3457
for (i = 0; i < symcounter; i++)        /* write out the global data         */
3458
  {
3459
  if (symtable[i].cat == SYMCAT_PUBLIC)
3460
    {
3461
    sprintf(name, "%-8.8s", symtable[i].name);
3462
    strupr(name);
3463
    fwrite(name, 1, 8, objfile);
3464
 
3465
    fputc(0, objfile);                  /* unknown data                      */
3466
 
3467
//    fputc((unsigned char)(symtable[i].value >> 24), objfile);
3468
    fputc((unsigned char)(symtable[i].value >> 16), objfile);
3469
    fputc((unsigned char)(symtable[i].value >> 8), objfile);
3470
    fputc((unsigned char)(symtable[i].value & 0xFF), objfile);
3471
 
3472
    fputc(0x02, objfile);               /* unknown flag                      */
3473
    }
3474
  }
3475
}
3476
 
3477
/*****************************************************************************/
3478
/* writerelmodname : writes out FLEX Relocatable Module Name                 */
3479
/*****************************************************************************/
3480
 
3481
void writerelmodname()
3482
{
3483
int i;
3484
 
3485
if (!modulename[0])
3486
  return;
3487
strupr(modulename);
3488
for (i = 0; modulename[i]; i++)
3489
  fputc(modulename[i], objfile);
3490
fputc(0x04, objfile);
3491
}
3492
 
3493
/*****************************************************************************/
3494
/* flushver : write verilog                                       */
3495
/*****************************************************************************/
3496
 
3497
int calcParity(unsigned wd)
3498
{
3499
        int nn;
3500
        int bit;
3501
        int par;
3502
 
3503
        par = 0;
3504
        for (nn = 0; nn < 32; nn++) {
3505
                bit = (wd >> nn) & 1;
3506
                par = par ^ bit;
3507
        }
3508
        return par;
3509
}
3510
 
3511
void flushver()
3512
{
3513
int i;
3514
int chk;
3515
 
3516
if (hexcount)
3517
 {
3518
  if (objfile)
3519
    {
3520 22 robfinch
    i = 0;
3521
    for (i = 0; i < hexcount; i++)
3522
      fprintf(objfile, "rommem[%5d] <= 12'h%03X;\r\n", (hexaddr + i) & 0x3fff, hexbuffer[i] & 0xfff);
3523
/*
3524
        fprintf(objfile, "rommem[%5d] <= 192'h%03X%03X%03X%03X%03X%03X%03X%03X%03X%03X%03X%03X%03X%03X%03X%03X;\r\n",
3525
        (hexaddr>>4) & 0x3ff,
3526
        hexbuffer[i+15] & 0xfff,
3527
        hexbuffer[i + 14] & 0xfff,
3528
        hexbuffer[i + 13] & 0xfff,
3529
        hexbuffer[i + 12] & 0xfff,
3530
        hexbuffer[i + 11] & 0xfff,
3531
        hexbuffer[i + 10] & 0xfff,
3532
        hexbuffer[i + 9] & 0xfff,
3533
        hexbuffer[i + 8] & 0xfff,
3534
        hexbuffer[i + 7] & 0xfff,
3535
        hexbuffer[i + 6] & 0xfff,
3536
        hexbuffer[i + 5] & 0xfff,
3537
        hexbuffer[i + 4] & 0xfff,
3538
        hexbuffer[i + 3] & 0xfff,
3539
        hexbuffer[i + 2] & 0xfff,
3540
        hexbuffer[i + 1] & 0xfff,
3541
        hexbuffer[i + 0] & 0xfff
3542
     );
3543
*/
3544 4 robfinch
  hexaddr += hexcount;
3545
  hexcount = 0;
3546
  chksum = 0;
3547
        vercount++;
3548
        }
3549
  }
3550
}
3551
 
3552 22 robfinch
int crc24(int count)
3553
{
3554
  int crc = 0xB704CEL;
3555
  int n, i;
3556
  crc = crc ^ (((hexaddr >> 12) & 0xfff) << 12);
3557
  for (i = 0; i < 12; i++) {
3558
    crc <<= 1;
3559
    if (crc & 0x1000000)
3560
      crc ^= 0xCFB864;
3561
  }
3562
  crc = crc ^ ((hexaddr & 0xfff) << 12);
3563
  for (i = 0; i < 12; i++) {
3564
    crc <<= 1;
3565
    if (crc & 0x1000000)
3566
      crc ^= 0xCFB864;
3567
  }
3568
  for (n = 0; --count >= 0; n++) {
3569
    crc = crc ^ (hexbuffer[n] << 12);
3570
    for (i = 0; i < 12; i++) {
3571
      crc <<= 1;
3572
      if (crc & 0x1000000)
3573
        crc ^= 0xCFB864;
3574
    }
3575
  }
3576
  return (crc);
3577
}
3578
 
3579 4 robfinch
/*****************************************************************************/
3580 22 robfinch
/* flushhex : write Finitron c-records  */
3581 4 robfinch
/* Flushes using 12-bit bytes */
3582
/*****************************************************************************/
3583
 
3584
void flushhex()
3585
{
3586
int i;
3587
 
3588
if (hexcount)
3589
  {
3590
  if (objfile)
3591
    {
3592 22 robfinch
    fprintf(objfile, "C1%03X%06X", (hexcount + 3) & 0xfff, hexaddr & 0xffffff);
3593 4 robfinch
    for (i = 0; i < hexcount; i++)
3594
      fprintf(objfile, "%03X", hexbuffer[i] & 0xfff);
3595 22 robfinch
//    chksum += (hexaddr & 0xfff) + ((hexaddr >> 12) & 0xfff) + hexcount + 3;
3596
//    fprintf(objfile, "%03X\n", 0xfff - (chksum & 0xfff));
3597
    fprintf(objfile, "%06X\n", crc24(hexcount) & 0xffffff);
3598 4 robfinch
    }
3599
  hexaddr += hexcount;
3600
  hexcount = 0;
3601
  chksum = 0;
3602
  }
3603
}
3604
 
3605
/*****************************************************************************/
3606
/* flushihex : write Intel hex record                                        */
3607
/*****************************************************************************/
3608
 
3609
void flushihex()
3610
{
3611
int i;
3612
unsigned char  *j;
3613
 
3614
if (hexcount)
3615
  {
3616
  if (objfile)
3617
    {
3618
    j = &hexbuffer[0];
3619
    fprintf(objfile, ":%03X%06X00", hexcount, hexaddr & 0xffffff);
3620
    chksum = hexcount + ((hexaddr >> 12) & 0xfff) + (hexaddr & 0xfff);
3621
    for (i = 0; i < hexcount; i++, j++)
3622
      {
3623
      chksum += (*j) & 0xfff;
3624
      fprintf(objfile, "%03X", (*j) & 0xfff);
3625
      }
3626
    fprintf(objfile, "%03X\n", (-(signed)chksum) & 0xfff);
3627
    }
3628
  hexaddr += hexcount;
3629
  hexcount = 0;
3630
  chksum = 0;
3631
  }
3632
}
3633
 
3634
/*****************************************************************************/
3635
/* flushflex : write FLEX binary record                                      */
3636
/*****************************************************************************/
3637
 
3638
void flushflex()
3639
{
3640
int i;
3641
unsigned short *j;
3642
 
3643
if (hexcount)
3644
  {
3645
  j = &hexbuffer[0];
3646
  if (objfile)
3647
    {
3648
    fputc(0x02, objfile);               /* start of record indicator         */
3649
    fputc((hexaddr >> 32) & 0xf,        /* load address high part            */
3650
      objfile);
3651
    fputc((hexaddr >> 24) & 0xff,        /* load address high part            */
3652
          objfile);
3653
    fputc((hexaddr >> 20) & 0xf,        /* load address high part            */
3654
      objfile);
3655
    fputc((hexaddr >> 12) & 0xff,        /* load address high part            */
3656
          objfile);
3657
    fputc((hexaddr >> 8) & 0xf, objfile);     /* load address low part             */
3658
    fputc(hexaddr & 0xff, objfile);     /* load address low part             */
3659
    fputc((hexcount >> 8) & 0xf, objfile);    /* # following data bytes            */
3660
    fputc(hexcount & 0xff, objfile);    /* # following data bytes            */
3661
    for (i = 0; i < hexcount; i++, j++) { /* then put all data bytes           */
3662
      fputc(((*j)>>8)&0xff, objfile);
3663
      fputc(*j, objfile);
3664
    }
3665
    }
3666
  hexaddr += hexcount;                  /* set new address                   */
3667
  hexcount = 0;                         /* reset counter                     */
3668
  }
3669
}
3670
 
3671
/*****************************************************************************/
3672
/* outver : add a byte to verilog output                           */
3673
/*****************************************************************************/
3674
 
3675
void outver (unsigned short x)
3676
{
3677 22 robfinch
        if (hexcount==16)
3678 4 robfinch
                flushver();
3679
        hexbuffer[hexcount] = x;
3680
        hexcount++;
3681
chksum += x;
3682
}
3683
 
3684
/*****************************************************************************/
3685
/* outhex : add a byte to motorola s-record output                           */
3686
/*****************************************************************************/
3687
 
3688
void outhex (unsigned short x)
3689
{
3690
if (hexcount == 16)
3691
  flushhex();
3692
hexbuffer[hexcount++] = x;
3693
chksum += x;
3694
}
3695
 
3696
/*****************************************************************************/
3697
/* outihex : add a byte to intel hex output                                  */
3698
/*****************************************************************************/
3699
 
3700
void outihex (unsigned short x)
3701
{
3702
if (hexcount == 32)
3703
  flushihex();
3704
hexbuffer[hexcount++] = x;
3705
chksum += x;
3706
}
3707
 
3708
/*****************************************************************************/
3709
/* outflex : adds a byte to FLEX output                                      */
3710
/*****************************************************************************/
3711
 
3712
void outflex(unsigned short x)
3713
{
3714
if (hexcount == 255)                    /* if buffer full                    */
3715
  flushflex();                          /* flush it                          */
3716
hexbuffer[hexcount++] = x;              /* then put byte into buffer         */
3717
}
3718
 
3719
/*****************************************************************************/
3720
/* outbyte : writes one byte to the output in the selected format            */
3721
/*****************************************************************************/
3722
 
3723
void outbyte(unsigned short uc, int off)
3724
{
3725
int nByte = (loccounter + off) / 8;
3726
unsigned short nBitMask = (unsigned short) (1 << ((loccounter + off) % 12));
3727
 
3728
//if (bUsedBytes[nByte] & nBitMask)       /* if address already used           */
3729
//  warning |= WRN_AREA;                  /* set warning code                  */
3730
//else                                    /* otherwise                         */
3731
//  bUsedBytes[nByte] |= nBitMask;        /* mark it as used                   */
3732
 
3733
switch (outmode)
3734
  {
3735
  case OUT_BIN :                        /* binary file                       */
3736
    fputc((uc >> 8) & 0xf, objfile);
3737
    fputc(uc, objfile);
3738
    break;
3739
  case OUT_REL :                        /* FLEX Relocatable                  */
3740
    fputc((uc >> 8) & 0xf, objfile);
3741
    fputc(uc, objfile);
3742
    break;
3743
  case OUT_SREC :                       /* Motorola S-records                */
3744
    outhex(uc);
3745
    break;
3746
  case OUT_IHEX :                       /* Intel Hex                         */
3747
    outihex(uc);
3748
    break;
3749
  case OUT_FLEX :                       /* FLEX                              */
3750
    outflex(uc);
3751
    break;
3752
  case OUT_VER:
3753
          outver(uc);
3754
          break;
3755
  }
3756
}
3757
 
3758
/*****************************************************************************/
3759
/* outbuffer : writes the output to a file in the selected format            */
3760
/*****************************************************************************/
3761
 
3762
void outbuffer()
3763
{
3764
int i;
3765
for (i = 0; i < codeptr; i++)
3766
  outbyte(codebuf[i], i);
3767
}
3768
 
3769
/*****************************************************************************/
3770
/* report : reports an error                                                 */
3771
/*****************************************************************************/
3772
 
3773
void report()
3774
{
3775
int i;
3776
 
3777
for (i = 0; i < 16; i++)
3778
  {
3779
  if (error & 1)
3780
    {
3781
    printf("%s(%ld) : error %d: %s in \"%s\"\n",
3782
           expandfn(curline->fn), curline->ln, i + 1,
3783
           errormsg[i], curline->txt);
3784
    if (((dwOptions & OPTION_LP1) || pass == MAX_PASSNO) && (listing & LIST_ON))
3785
      putlist( "*** Error %d: %s\n", i + 1, errormsg[i]);
3786
    errors++;
3787
    }
3788
  error >>= 1;
3789
  }
3790
 
3791
if ((dwOptions & OPTION_TSC))           /* suppress warning 1 in TSC mode    */
3792
  warning &= ~WRN_OPT;
3793
 
3794
if (!(dwOptions & OPTION_WAR))          /* reset warnings if not wanted      */
3795
  warning = WRN_OK;
3796
 
3797
for (i = 0; i < 16; i++)
3798
  {
3799
  if (warning & 1)
3800
    {
3801
    printf("%s(%ld) : warning %d: %s in \"%s\"\n",
3802
           expandfn(curline->fn), curline->ln, i + 1, warningmsg[i], curline->txt);
3803
    if (((dwOptions & OPTION_LP1) || pass == MAX_PASSNO) && (listing & LIST_ON))
3804
      putlist( "*** warning %d: %s\n", i + 1, warningmsg[i]);
3805
    warnings++;
3806
    }
3807
  warning >>= 1;
3808
  }
3809
}
3810
 
3811
/*****************************************************************************/
3812
/* outlist : lists the code bytes for an instruction                         */
3813
/*****************************************************************************/
3814
 
3815
void outlist(struct oprecord *op)
3816
{
3817
int i;
3818
 
3819
if ((curline->lvl & LINCAT_INVISIBLE) &&/* don't list invisible lines       */
3820
    !(dwOptions & OPTION_INV))
3821
  return;
3822
 
3823
if ((curline->lvl & LINCAT_MACEXP) &&   /* don't list macro expansions if   */
3824
    !(dwOptions & OPTION_EXP))          /* not explicitly requested         */
3825
  return;
3826
 
3827
if ((curline->lvl & LINCAT_LVLMASK) &&  /* if level 1..31                    */
3828
    !(dwOptions & OPTION_LLL))          /* and this is not to be listed      */
3829
  return;
3830
 
3831
if ((suppress || nSkipCount) &&         /* if this is conditionally skipped  */
3832
    !(dwOptions & OPTION_CON))          /* and this is not to be listed      */
3833
  return;
3834
if ((condline) &&                       /* if this is a condition line       */
3835
    !(dwOptions & OPTION_CON))          /* and this is not to be listed      */
3836
  return;
3837
 
3838
if (dwOptions & OPTION_NUM)             /* if number output                  */
3839
  putlist("%4d ", curline->ln);         /* print out the line number         */
3840
 
3841
if (!absmode)                           /* if in relocating assembler mode   */
3842
  putlist("%c", curline->rel);          /* output relocation information     */
3843
 
3844
if (dwOptions & OPTION_LPA)             /* if in patch mode                  */
3845
  {
3846
  if ((op) && (op->cat == OPCAT_PSEUDO))
3847
    {
3848
    switch (op->code)
3849
      {
3850
      case PSEUDO_SETDP :
3851
        if (dpsetting >= 0)
3852
          putlist("setdp %02X\n", dpsetting);
3853
        break;
3854
      case PSEUDO_ORG :
3855
        putlist("insert %08X \\        ORG $%08X\n", loccounter, loccounter);
3856
        break;
3857
      case PSEUDO_FCB :
3858
      case PSEUDO_FCC :
3859
        putlist("data %04X", oldlc);
3860
        if (codeptr > 1)
3861
          putlist("-%04X", oldlc + codeptr - 1);
3862
        putlist("\n");
3863
        break;
3864
      case PSEUDO_FCW :
3865
        putlist("word %04x", oldlc);
3866
        if (codeptr > 2)
3867
          putlist("-%04X", oldlc + codeptr - 1);
3868
        putlist("\n");
3869
        break;
3870
      case PSEUDO_FCDW :
3871
        putlist("dword %08x", oldlc);
3872
        if (codeptr > 2)
3873
          putlist("-%08X", oldlc + codeptr - 1);
3874
        putlist("\n");
3875
        break;
3876
      }
3877
    }
3878
  if (codeptr > 0)                      /* if there are code bytes           */
3879
    {
3880
    char *name = findsymat(oldlc);
3881
    if (name)
3882
      putlist("label %04X %s\n", oldlc, name);
3883
    putlist("patch ");                  /* write "patch"                     */
3884
    }
3885
  else if (*curline->txt)
3886
    putlist("      ");
3887
  else
3888
    putlist("comment %04X", oldlc);
3889
  }
3890
else if ((warning & WRN_OPT) &&         /* excessive branch, TSC style       */
3891
    (dwOptions & OPTION_TSC) &&
3892
    (dwOptions & OPTION_WAR))
3893
  putlist(">");
3894
else if (curline->lvl & LINCAT_MACDEF)  /* if in macro definition            */
3895
  putlist("#");                         /* prefix line with #                */
3896
else if (curline->lvl & LINCAT_MACEXP)  /* if in macro expansion             */
3897
  putlist("+");                         /* prefix line with +                */
3898
else if (curline->lvl & LINCAT_INVISIBLE)
3899
  putlist("-");
3900
else if (curline->txt)                  /* otherwise                         */
3901
  putlist(" ");                         /* prefix line with blank            */
3902
 
3903
if (codeptr > 0)
3904
  putlist("%08X ", oldlc);
3905
else if (*curline->txt)
3906
  putlist("     ");
3907
else
3908
  {
3909
  putlist( "\n");
3910
  return;
3911
  }
3912
 
3913
for (i = 0; i < codeptr && i < MAXLISTBYTES; i++)
3914
  {
3915
  if (dwOptions & OPTION_LPA)
3916
    putlist("%03X ", codebuf[i]&0xfff);
3917
  else
3918
    putlist("%03X", codebuf[i]&0xfff);
3919
  }
3920
for (; i <= MAXLISTBYTES; i++)
3921
  {
3922
  if (dwOptions & OPTION_LPA)
3923
    putlist("    ");
3924
  else
3925
    putlist("   ");
3926
  }
3927
 
3928
if ((dwOptions & OPTION_LPA) &&
3929
    (*curline->txt))
3930
  putlist("* ");
3931
 
3932
if (strcmp(curline->txt, srcline) &&    /* if text inserted                  */
3933
    (dwOptions & OPTION_EXP))           /* and expansion activated           */
3934
  putlist("%s", curline->txt);          /* just print out the source line    */
3935
else                                    /* otherwise                         */
3936
  putlist("%s", srcline);               /* print possibly expanded line      */
3937
 
3938
putlist("\n");                          /* send newline                      */
3939
 
3940
if (codeptr > MAXLISTBYTES &&           /* if there are additional bytes,    */
3941
    (dwOptions & OPTION_MUL))
3942
  {                                     /* print them.                       */
3943
  if (dwOptions & OPTION_LPA)           /* if in patch mode                  */
3944
    putlist("patch");                   /* write "patch"                     */
3945
  for (i = MAXLISTBYTES; i < codeptr; i++)
3946
    {
3947
    if (!(i % MAXLISTBYTES))
3948
      {
3949
      if (i != MAXLISTBYTES)
3950
        putlist("\n");
3951
      if (dwOptions & OPTION_NUM)       /* if number output                  */
3952
        putlist("     ");
3953
      if (!absmode)
3954
        putlist(" ");
3955
      putlist(" %08X ", oldlc + i);
3956
      }
3957
    if (dwOptions & OPTION_LPA)         /* if in patch mode                  */
3958
      putlist("%03X ", codebuf[i]&0xfff);
3959
    else
3960
      putlist("%03X", codebuf[i]&0xfff);
3961
    }
3962
  putlist("\n");
3963
  }
3964
 
3965
if (strcmp(curline->txt, srcline) &&    /* if text inserted                  */
3966
    (dwOptions & OPTION_EXP))           /* and expansion activated           */
3967
  {
3968
  if (dwOptions & OPTION_NUM)
3969
    putlist("%4d ", curline->ln);
3970
  if (!absmode)
3971
    putlist(" ");
3972
  putlist("+                   ( %s )\n", srcline);
3973
  }
3974
}
3975
 
3976
/*****************************************************************************/
3977
/* setlabel : sets a label                                                   */
3978
/*****************************************************************************/
3979
 
3980
void setlabel(struct symrecord * lp)
3981
{
3982
if (lp)
3983
  {
3984
          lp->isFar = isFar;
3985
          lp->isFarkw = isFarkw;
3986
  if (lp->cat == SYMCAT_PUBLICUNDEF)
3987
    {
3988
    lp->cat = SYMCAT_PUBLIC;
3989
    lp->value = loccounter;
3990
    }
3991
  else if (lp->cat == SYMCAT_EMPTYLOCAL)
3992
    {
3993
    lp->cat = SYMCAT_LOCALLABEL;
3994
    }
3995
  else if (lp->cat == SYMCAT_LOCALLABEL)
3996
    ;
3997
  else if (lp->cat != SYMCAT_EMPTY && lp->cat != SYMCAT_UNRESOLVED)
3998
    {
3999
    if ((lp->cat != SYMCAT_LABEL && lp->cat != SYMCAT_PUBLIC) ||
4000
                lp->value != loccounter) {
4001
                lp->value = loccounter;
4002
                if (pass==MAX_PASSNO)
4003
                        error |= ERR_LABEL_MULT;
4004
                }
4005
    }
4006
  else
4007
    {
4008
    lp->cat = (global) ? SYMCAT_PUBLIC : SYMCAT_LABEL;
4009
    lp->value = loccounter;
4010
    }
4011
  }
4012
}
4013
 
4014
/*****************************************************************************/
4015
/* putbyte : adds a byte to the instruction code buffer                      */
4016
/*****************************************************************************/
4017
 
4018
void putbyte(unsigned short b)
4019
{
4020
codebuf[codeptr++] = b;                 /* and finally put the byte there.   */
4021
}
4022
 
4023
/*****************************************************************************/
4024
/* putword : adds a word to the instruction code buffer                      */
4025
/*****************************************************************************/
4026
 
4027
void putword(unsigned w)
4028
{
4029
putbyte((unsigned short)((w >> 12L) & 0xfffL));
4030
putbyte((unsigned short)(w & 0xfff));
4031
}
4032
 
4033
/*****************************************************************************/
4034
/* putdword : adds a doubleword to the instruction code buffer               */
4035
/*****************************************************************************/
4036
 
4037
void putdword(unsigned __int64 d)
4038
{
4039
putbyte((unsigned short)((d >> 36LL) & 0xfffLL));
4040
putbyte((unsigned short)((d >> 24LL) & 0xfffLL));
4041
putbyte((unsigned short)((d >> 12LL) & 0xfffLL));
4042
putbyte((unsigned short)(d & 0xfffLL));
4043
}
4044
 
4045
/*****************************************************************************/
4046
/* doaddress : assemble the right addressing bytes for an instruction        */
4047
/*****************************************************************************/
4048
 
4049
void doaddress(struct relocrecord *p)
4050
{
4051
int offs;
4052
int addrelocation = 0;
4053
int isNear = 0;
4054
if (p)                                  /* create relocation record          */
4055
  p->addr = (unsigned)(loccounter + codeptr);
4056
 
4057
switch (mode)
4058
  {
4059
  case ADRMODE_IMM :
4060
    if (opsize == 2)
4061
      putbyte((unsigned short)operand);
4062
    else if (opsize == 5)               /* LDQ special                       */
4063
      putdword(operand);
4064
    else
4065
      {
4066
      putword((unsigned)operand);
4067
      addrelocation = 1;
4068
      }
4069
    break;
4070
  case ADRMODE_DIR :
4071
    putbyte((unsigned short)operand);
4072
    break;
4073
  case ADRMODE_EXT :
4074
    if (((codebuf[0] == 0x07e) ||        /* special for JMP                   */
4075
         (codebuf[0] == 0x0bd) ||
4076
                 (codebuf[0] == 0x015 && (codebuf[1]==0x07E || codebuf[1]==0x0bd))
4077
                 ) &&       /* and JSR                           */
4078
        pass > 1)
4079
      {
4080
      int nDiff = (int)operand - (int)loccounter - 3;
4081
          isNear = (operand & 0xFF0000L) == (loccounter & 0xff0000L);
4082
      if (((nDiff & 0xff80) == 0x0000) ||
4083
           ((nDiff & 0xff80) == 0xff80))
4084
           warning |= (certain) ? WRN_OPT : 0;
4085
      }
4086
          if (codebuf[0]==0x015 && codebuf[1]==0x0bd && isFar) {
4087
                  if (isNear && !isFarkw) {
4088
                          codebuf[0]=0x0bd;
4089
                          isFar = 0;
4090
                  }
4091
                  else
4092
                          codebuf[0]=0x0cf;
4093
                  codeptr--;
4094
          }
4095
          if (codebuf[0]==0x015 && codebuf[1]==0x07E && isFar) {
4096
                  if (isNear && !isFarkw) {
4097
                        codebuf[0]=0x07E;
4098
                        isFar = 0;
4099
                  }
4100
                  else
4101
                        codebuf[0]=0x08f;
4102
                  codeptr--;
4103
          }
4104
          if (isFar) {
4105
                  putbyte((unsigned short)(operand >> 24));
4106
          }
4107
    putword((unsigned)operand);
4108
    addrelocation = 1;
4109
    break;
4110
  case ADRMODE_IDX :
4111
    putbyte((unsigned short)operand);
4112
    break;
4113
  case ADRMODE_POST :
4114
  case ADRMODE_IND :
4115
  case ADRMODE_DBL_IND:
4116
    putbyte(postbyte);
4117
    switch (opsize)
4118
      {
4119
      case 2:
4120
        putbyte((unsigned short)operand);
4121
        break;
4122
      case 3:
4123
        putword((unsigned)operand);
4124
        addrelocation = 1;
4125
                break;
4126
      case 4:
4127
        putbyte((unsigned short)(operand>>24));
4128
        putword((unsigned)operand);
4129
        addrelocation = 1;
4130
                break;
4131
      case 5:
4132
        putword((unsigned short)(operand>>24));
4133
        putword((unsigned)operand);
4134
        addrelocation = 1;
4135
                break;
4136
      }
4137
    break;
4138
  case ADRMODE_PCR :
4139
  case ADRMODE_PIN :
4140
    offs = (unsigned)operand - loccounter - codeptr - 2;
4141
    if (offs < -2048 || offs >= 2048 || opsize == 3 || unknown || !certain)
4142
      {
4143
      if ((!unknown) && opsize == 2)
4144
        error |= ERR_RANGE;
4145
      offs--;
4146
      opsize = 3;
4147
      postbyte++;
4148
      }
4149
    putbyte(postbyte);
4150
    if (opsize == 3)
4151
      {
4152
      putword((unsigned)offs);
4153
      addrelocation = 1;
4154
      }
4155
    else
4156
      putbyte((unsigned short)offs);
4157
  }
4158
 
4159
if (addrelocation)
4160
  addreloc(p);
4161
}
4162
 
4163
/*****************************************************************************/
4164
/* onebyte : saves integer as one instruction byte                           */
4165
/*****************************************************************************/
4166
 
4167
void onebyte(int co)
4168
{
4169
putbyte((unsigned short)co);
4170
}
4171
 
4172
/*****************************************************************************/
4173
/* twobyte : saves integer as two instruction bytes                          */
4174
/*****************************************************************************/
4175
 
4176
void twobyte(int co)
4177
{
4178
putword((unsigned)co);
4179
}
4180
 
4181
/*****************************************************************************/
4182
/* threebyte : saves long integer as three instruction bytes                 */
4183
/*****************************************************************************/
4184
 
4185
void threebyte(unsigned __int64 co)
4186
{
4187
putbyte((unsigned short)((co >> 24LL) & 0xfffLL));
4188
putbyte((unsigned short)((co >> 12LL) & 0xfffLL));
4189
putbyte((unsigned short)(co & 0xfffL));
4190
}
4191
 
4192
/*****************************************************************************/
4193
/* fourbyte : saves long integer as four instruction bytes                   */
4194
/*****************************************************************************/
4195
 
4196
void fourbyte(unsigned __int64 co)
4197
{
4198
  putbyte((unsigned short)((co >> 36LL) & 0xfffLL));
4199
  putbyte((unsigned short)((co >> 24LL) & 0xfffLL));
4200
  putbyte((unsigned short)((co >> 12LL) & 0xfffLL));
4201
  putbyte((unsigned short)(co & 0xfffL));
4202
}
4203
 
4204
/*****************************************************************************/
4205
/* oneimm : saves one immediate value                                        */
4206
/*****************************************************************************/
4207
 
4208
void oneimm(int co)
4209
{
4210
struct relocrecord p = {0};
4211
 
4212
scanoperands(&p);
4213
if (mode >= ADRMODE_POST)
4214
  error |= ERR_ILLEGAL_ADDR;
4215
putbyte((unsigned short)co);
4216
 
4217
/* addreloc(0, 2, p); */                /* no relocation for immediate op's  */
4218
 
4219
putbyte((unsigned short)operand);
4220
}
4221
 
4222
/*****************************************************************************/
4223
/* lea :                                                                     */
4224
/*****************************************************************************/
4225
 
4226
void lea(int co)
4227
{
4228
struct relocrecord p = {0};
4229
 
4230
scanoperands(&p);
4231
if (isFar)
4232
        onebyte(0x015);
4233
onebyte((unsigned short)co);
4234
if (mode == ADRMODE_IMM)
4235
  error |= ERR_ILLEGAL_ADDR;
4236
if (mode < ADRMODE_POST)
4237
  {
4238
          if (isFar)
4239
                  opsize = 4;
4240
          else
4241
                opsize = 3;
4242
  postbyte = 0x80f;
4243
  mode = ADRMODE_POST;
4244
  }
4245
doaddress(&p);
4246
}
4247
 
4248
/*****************************************************************************/
4249
/* sbranch : processes a short branch                                        */
4250
/*****************************************************************************/
4251
 
4252
void sbranch(int co)
4253
{
4254
struct relocrecord p = {0};
4255
int offs;
4256
 
4257
scanoperands(&p);
4258
if (mode != ADRMODE_DIR && mode != ADRMODE_EXT)
4259
  error |= ERR_ILLEGAL_ADDR;
4260
offs = operand - loccounter - 2;
4261
if (!unknown && (offs < -2048 || offs >= 2048))
4262
  error |= ERR_RANGE;
4263
if (pass > 1 && unknown)
4264
  error |= ERR_LABEL_UNDEF;
4265
putbyte((unsigned short)co);
4266
putbyte((unsigned short)offs);
4267
}
4268
 
4269
/*****************************************************************************/
4270
/* lbra : does a long branch                                                 */
4271
/*****************************************************************************/
4272
 
4273
void lbra(int co)
4274
{
4275
struct relocrecord p = {0};
4276
int nDiff;
4277
 
4278
scanoperands(&p);
4279
if (mode != ADRMODE_DIR && mode != ADRMODE_EXT)
4280
  error |= ERR_ILLEGAL_ADDR;
4281
putbyte((unsigned short)co);
4282
 
4283
nDiff = operand - loccounter - 3;
4284
putword((unsigned)nDiff);
4285
if (((nDiff & 0xff8000) == 0x000000) ||
4286
    ((nDiff & 0xff8000) == 0xff8000))
4287
  warning |= (certain) ? WRN_OPT : 0;
4288
}
4289
 
4290
/*****************************************************************************/
4291
/* lbranch : does a long branch                                              */
4292
/*****************************************************************************/
4293
 
4294
void lbranch(int co)
4295
{
4296
struct relocrecord p = {0};
4297
int nDiff;
4298
 
4299
scanoperands(&p);
4300
if (mode != ADRMODE_DIR && mode != ADRMODE_EXT)
4301
  error |= ERR_ILLEGAL_ADDR;
4302
putword((unsigned)co);
4303
nDiff = operand - loccounter - 4;
4304
putword((unsigned)nDiff);
4305
if (((nDiff & 0xff8000) == 0x000000) ||
4306
    ((nDiff & 0xff8000) == 0xff8000))
4307
  warning |= (certain) ? WRN_OPT : 0;
4308
}
4309
 
4310
/*****************************************************************************/
4311
/* arith : process arithmetic operation                                      */
4312
/*****************************************************************************/
4313
 
4314
void arith(int co, char noimm)
4315
{
4316
struct relocrecord p = {0};
4317
 
4318
scanoperands(&p);
4319
switch (mode)
4320
  {
4321
  case ADRMODE_IMM :
4322
    if (noimm)
4323
      error |= ERR_ILLEGAL_ADDR;
4324
    opsize = 2;
4325
    putbyte((unsigned short)co);
4326
    break;
4327
  case ADRMODE_DIR :
4328
    putbyte((unsigned short)(co + 0x010));
4329
    break;
4330
  case ADRMODE_EXT :
4331
          if (isFar)
4332
                  putbyte(0x015);
4333
    putbyte((unsigned short)(co + 0x030));
4334
    break;
4335
  default:
4336
          if (isFar)
4337
                  putbyte(0x015);
4338 12 robfinch
    if (isPostIndexed) {
4339
      //putbyte(0x01B);
4340
      postbyte |= 0x80;
4341
    }
4342 4 robfinch
    putbyte((unsigned short)(co + 0x020));
4343
  }
4344
doaddress(&p);
4345
}
4346
 
4347
/*****************************************************************************/
4348
/* accarith : process arithmetic operation with explicit accumulator         */
4349
/*****************************************************************************/
4350
 
4351
void accarith(int co, char noimm, char ignore)
4352
{
4353
char *s = srcptr;                       /* remember current offset           */
4354
char correct = 1;                       /* flag whether correct              */
4355
 
4356
skipspace();                            /* skip space                        */
4357
scanname();                             /* get following name                */
4358
 
4359
if (strcmp(unamebuf, "A") &&            /* has to be followed by A or B      */
4360
    strcmp(unamebuf, "B"))
4361
  correct = 0;
4362
 
4363
#if 1
4364
if (*srcptr == ',')                     /* if directly followed by a comma   */
4365
  srcptr++;                             /* skip it                           */
4366
#else
4367
if (!(dwOptions & OPTION_TSC))
4368
  skipspace();
4369
if (*srcptr++ != ',')                   /* and a comma                       */
4370
  correct = 0;
4371
#endif
4372
 
4373
if (!correct)                           /* if NOT followed by "A," or "B,"   */
4374
  {
4375
  if (ignore)                           /* if ignoring that,                 */
4376
    srcptr = s;                         /* go back to parm start             */
4377
  else                                  /* otherwise                         */
4378
    error |= ERR_EXPR;                  /* flag as an error                  */
4379
  }
4380
else if (unamebuf[0] == 'B')            /* eventually transform to acc.B     */
4381
  co |= 0x40;
4382
arith(co, noimm);                       /* then process as arithmetic        */
4383
}
4384
 
4385
/*****************************************************************************/
4386
/* idxextarith : indexed / extended arithmetic, 6800 style                   */
4387
/*****************************************************************************/
4388
 
4389
void idxextarith(int co)
4390
{
4391
struct relocrecord p = {0};
4392
 
4393
scanoperands(&p);
4394
switch (mode)
4395
  {
4396
  case ADRMODE_IMM :
4397
    error |= ERR_ILLEGAL_ADDR;
4398
    opsize = 3;
4399
    putbyte((unsigned short)co);
4400
    break;
4401
  case ADRMODE_DIR :
4402
    mode = ADRMODE_EXT;                 /* implicitly convert to extended    */
4403
    putbyte((unsigned short)(co + 0x030));
4404
    break;
4405
  case ADRMODE_EXT :
4406
        if (isFar)
4407
                putbyte(0x015);
4408
    putbyte((unsigned short)(co + 0x030));
4409
    break;
4410
  default:
4411
        if (isFar)
4412
                putbyte(0x015);
4413
        if (isPostIndexed)
4414 12 robfinch
                //putbyte(0x01B);
4415 4 robfinch
    putbyte((unsigned short)(co + 0x020));
4416
    break;
4417
 }
4418
doaddress(&p);
4419
}
4420
 
4421
/*****************************************************************************/
4422
/* darith : process direct arithmetic                                        */
4423
/*****************************************************************************/
4424
 
4425
void darith(int co, char noimm, char tgt)
4426
{
4427
struct relocrecord p = {0};
4428
 
4429
scanoperands(&p);
4430
switch (mode)
4431
  {
4432
  case ADRMODE_IMM :
4433
    if (noimm)
4434
      error |= ERR_ILLEGAL_ADDR;
4435
        if (isX32 && tgt)
4436
                opsize = 5;
4437
        else
4438
                opsize = 3;
4439
    putbyte((unsigned short)co);
4440
    break;
4441
  case ADRMODE_DIR :
4442
    putbyte((unsigned short)(co + 0x010));
4443
    break;
4444
  case ADRMODE_EXT :
4445
          if (isFar)
4446
                  putbyte(0x015);
4447
    putbyte((unsigned short)(co + 0x030));
4448
    break;
4449
  default:
4450
          if (isFar)
4451
                  putbyte(0x015);
4452 12 robfinch
    if (isPostIndexed) {
4453
      //putbyte(0x01B);
4454
      postbyte |= 0x80;
4455
    }
4456 4 robfinch
    putbyte((unsigned short)(co + 0x020));
4457
    break;
4458
 }
4459
doaddress(&p);
4460
}
4461
 
4462
/*****************************************************************************/
4463
/* d2arith : process direct word arithmetic                                  */
4464
/*****************************************************************************/
4465
 
4466
void d2arith(int co, char noimm, char tgt)
4467
{
4468
struct relocrecord p = {0};
4469
 
4470
scanoperands(&p);
4471
switch (mode)
4472
  {
4473
  case ADRMODE_IMM :
4474
    if (noimm)
4475
      error |= ERR_ILLEGAL_ADDR;
4476
        if (isX32 && tgt)
4477
                opsize = 5;
4478
        else
4479
                opsize = 3;
4480
    putword((unsigned)co);
4481
    break;
4482
  case ADRMODE_DIR :
4483
    putword((unsigned)(co + 0x010));
4484
    break;
4485
  case ADRMODE_EXT :
4486
          if (isFar) {
4487
                  putbyte(0x015);
4488
          }
4489
    putword((unsigned)(co + 0x030));
4490
    break;
4491
  default:
4492
          if (isFar)
4493
                  putbyte(0x015);
4494 12 robfinch
    if (isPostIndexed) {
4495
      //putbyte(0x01B);
4496
      postbyte |= 0x80;
4497
    }
4498 4 robfinch
    putword((unsigned)(co + 0x020));
4499
 }
4500
doaddress(&p);
4501
}
4502
 
4503
/*****************************************************************************/
4504
/* qarith : process direct doubleword arithmetic                             */
4505
/*****************************************************************************/
4506
 
4507
void qarith(int co, char noimm)
4508
{
4509
struct relocrecord p = {0};
4510
 
4511
scanoperands(&p);
4512
switch (mode)
4513
  {
4514
  case ADRMODE_IMM :
4515
    if (noimm)
4516
      error |= ERR_ILLEGAL_ADDR;
4517
    opsize = 5;
4518
    putbyte((unsigned short)0xcd);       /* this can ONLY be LDQ!             */
4519
    break;
4520
  case ADRMODE_DIR :
4521
    putword((unsigned)(co + 0x010));
4522
    break;
4523
  case ADRMODE_EXT :
4524
    putword((unsigned)(co + 0x030));
4525
    break;
4526
  default:
4527
    putword((unsigned)(co + 0x020));
4528
    break;
4529
 }
4530
doaddress(&p);
4531
}
4532
 
4533
/*****************************************************************************/
4534
/* oneaddr :                                                                 */
4535
/*****************************************************************************/
4536
 
4537
void oneaddr(int co)
4538
{
4539
struct relocrecord p = {0};
4540
char *s;
4541
 
4542
skipspace();
4543
if ((dwOptions & OPTION_TSC) &&         /* if TSC mode, check for 6800       */
4544
    (co != 0x0e))                       /* convenience things                */
4545
  {
4546
  s = srcptr;
4547
  scanname();                           /* look whether followed by A or B   */
4548
  if (((!strcmp(unamebuf, "A")) ||
4549
       (!strcmp(unamebuf, "B"))) &&
4550
      (*srcptr != ','))                 /* and NO comma                      */
4551
    {                                   /* if so, replace by 6809 mnemonic   */
4552
    warning |= WRN_AMBIG;               /* ... but not without a warning     */
4553
    onebyte(co | ((unamebuf[0] == 'A') ? 0x40 : 0x50));
4554
    return;
4555
    }
4556
  srcptr = s;
4557
  }
4558
 
4559
scanoperands(&p);
4560
switch (mode)
4561
  {
4562
  case ADRMODE_IMM :
4563
    error |= ERR_ILLEGAL_ADDR;
4564
    break;
4565
  case ADRMODE_DIR :
4566
    if ((dwOptions & OPTION_M00) &&     /* on MC6800, a DIRect JMP is not OK */
4567
        (co == 0x0e))
4568
      error |= ERR_ILLEGAL_ADDR;
4569
    else
4570
      putbyte((unsigned short)co);
4571
    break;
4572
  case ADRMODE_EXT :
4573
          if (isFar)
4574
                  putbyte(0x015);
4575
    putbyte((unsigned short)(co + 0x70));
4576
    break;
4577
  default:
4578
          if (isFar)
4579
                  putbyte(0x015);
4580 12 robfinch
    if (isPostIndexed) {
4581
      //putbyte(0x01B);
4582
      postbyte |= 0x80;
4583
    }
4584 4 robfinch
    putbyte((unsigned short)(co + 0x60));
4585
    break;
4586
  }
4587
doaddress(&p);
4588
}
4589
 
4590
/*****************************************************************************/
4591
/* accaddr :                                                                 */
4592
/*****************************************************************************/
4593
 
4594
void accaddr(int co)
4595
{
4596
struct relocrecord p = {0};
4597
char *s;
4598
 
4599
skipspace();
4600
if (dwOptions & OPTION_TSC)             /* if TSC mode, check for 6800       */
4601
  {
4602
  s = srcptr;
4603
  scanname();                           /* look whether followed by A or B   */
4604
  if (((!strcmp(unamebuf, "A")) ||
4605
       (!strcmp(unamebuf, "B"))) &&
4606
      (*srcptr != ','))                 /* and NO comma                      */
4607
    {                                   /* if so, replace                    */
4608
    onebyte(co | ((unamebuf[0] == 'A') ? 0x40 : 0x50));
4609
    return;
4610
    }
4611
  srcptr = s;
4612
  }
4613
 
4614
scanoperands(&p);
4615
switch (mode)
4616
  {
4617
  case ADRMODE_IMM :
4618
    error |= ERR_ILLEGAL_ADDR;
4619
    break;
4620
  case ADRMODE_DIR :
4621
    mode = ADRMODE_EXT;                 /* silently convert to extended      */
4622
    putbyte((unsigned short)(co + 0x70));
4623
    break;
4624
  case ADRMODE_EXT :
4625
          if (isFar)
4626
                  putbyte(0x15);
4627
    putbyte((unsigned short)(co + 0x70));
4628
    break;
4629
  default:
4630
          if (isFar)
4631
                  putbyte(0x15);
4632 12 robfinch
    if (isPostIndexed) {
4633
      //putbyte(0x1B);
4634
      postbyte |= 0x80;
4635
    }
4636 4 robfinch
    putbyte((unsigned short)(co + 0x60));
4637
    break;
4638
  }
4639
doaddress(&p);
4640
}
4641
 
4642
/*****************************************************************************/
4643
/* tfrexg :                                                                  */
4644
/*****************************************************************************/
4645
 
4646
void tfrexg(int co)
4647
{
4648
struct regrecord * p;
4649
 
4650
putbyte((unsigned char)co);
4651
skipspace();
4652
scanname();
4653
 
4654
if (dwOptions & OPTION_H63)
4655
  p = findreg63(unamebuf);
4656
else
4657
  p = findreg(unamebuf);
4658
if (!p)
4659
  error |= ERR_ILLEGAL_ADDR;
4660
else
4661
 postbyte = (p->tfr) << 4;
4662
skipspace();
4663
if (*srcptr == ',')
4664
  srcptr++;
4665
else
4666
 error |= ERR_ILLEGAL_ADDR;
4667
skipspace();
4668
scanname();
4669
if ((p = findreg(unamebuf)) == 0)
4670
  error |= ERR_ILLEGAL_ADDR;
4671
else
4672
 postbyte |= p->tfr;
4673
putbyte(postbyte);
4674
}
4675
 
4676
/*****************************************************************************/
4677
/* pshpul : operates on PSH / PUL mnemonics                                  */
4678
/*****************************************************************************/
4679
 
4680
void pshpul(int co)
4681
{
4682
struct regrecord *p;
4683
struct relocrecord sp = {0};
4684
 
4685
postbyte = 0;
4686
 
4687
skipspace();
4688
if (*srcptr == '#')
4689
  {
4690
  srcptr++;
4691
  if (!(dwOptions & OPTION_TSC))
4692
    skipspace();
4693
  postbyte = (unsigned short)scanexpr(0, &sp);
4694
  }
4695
else do
4696
  {
4697
  if (*srcptr=='f' || *srcptr=='F') {
4698
          if (srcptr[1]=='a' || srcptr[1]=='A') {
4699
                  if (srcptr[2]=='r' || srcptr[2]=='R') {
4700
                          if (srcptr[3]==' ' || srcptr[3]=='\t') {
4701
                                  isFar = 1;
4702
                                  srcptr += 4;
4703
                          }
4704
                  }
4705
          }
4706
  }
4707
  if (*srcptr == ',')
4708
    srcptr++;
4709
  if (!(dwOptions & OPTION_TSC))
4710
    skipspace();
4711
  scanname();
4712
  if ((p = findreg(unamebuf)) == 0)
4713
    error |= ERR_ILLEGAL_ADDR;
4714
  else
4715
    postbyte |= p->psh;
4716
  if (!(dwOptions & OPTION_TSC))
4717
    skipspace();
4718
  } while (*srcptr == ',');
4719
if (isFar)
4720
        putbyte((unsigned short)0x15);
4721
putbyte((unsigned short)co);
4722
putbyte(postbyte);
4723
}
4724
 
4725
/*****************************************************************************/
4726
/* bitdirect :                                                               */
4727
/*****************************************************************************/
4728
 
4729
void bitdirect(int co)
4730
{
4731
struct relocrecord p = {0};
4732
unsigned short dir;
4733
 
4734
skipspace();
4735
if (*srcptr++ != '#')
4736
  error |= ERR_EXPR;
4737
dir = (unsigned)scanexpr(0, &p);
4738
if (dir & 0xfff000)
4739
  error |= ERR_EXPR;
4740
if (!(dwOptions & OPTION_TSC))
4741
  skipspace();
4742
if (*srcptr++ != ',')
4743
  error |= ERR_EXPR;
4744
scanoperands(&p);
4745
switch (mode)
4746
  {
4747
  case ADRMODE_IMM :
4748
    error |= ERR_ILLEGAL_ADDR;
4749
    break;
4750
  case ADRMODE_DIR :
4751
    putbyte((unsigned short)co);
4752
    break;
4753
  case ADRMODE_EXT :
4754
          if (isFar)
4755
                  putbyte(0x15);
4756
    putbyte((unsigned short)(co + 0x70));
4757
    break;
4758
  default:
4759
          if (isFar)
4760
                  putbyte(0x15);
4761
    putbyte((unsigned short)(co + 0x60));
4762
    break;
4763
  }
4764
putbyte((unsigned short)dir);
4765
doaddress(&p);
4766
}
4767
 
4768
/*****************************************************************************/
4769
/* bittrans :                                                                */
4770
/*****************************************************************************/
4771
 
4772
void bittrans(int co)
4773
{
4774
struct regrecord *p;
4775
struct relocrecord rp = {0};
4776
long t;
4777
 
4778
putword((unsigned)co);
4779
 
4780
skipspace();
4781
scanname();
4782
if ((p = findbitreg(unamebuf)) == 0)
4783
  error |= ERR_ILLEGAL_ADDR;
4784
else
4785
  postbyte = (p->tfr) << 6;
4786
if (!(dwOptions & OPTION_TSC))
4787
  skipspace();
4788
if (*srcptr == ',')
4789
  srcptr++;
4790
else
4791
 error |= ERR_ILLEGAL_ADDR;
4792
if (!(dwOptions & OPTION_TSC))
4793
  skipspace();
4794
t = scanfactor(&rp);
4795
if (t & 0xfffff8)
4796
  error |= ERR_ILLEGAL_ADDR;
4797
else
4798
  postbyte |= (t << 3);
4799
if (!(dwOptions & OPTION_TSC))
4800
  skipspace();
4801
if (*srcptr == ',')
4802
  srcptr++;
4803
else
4804
 error |= ERR_ILLEGAL_ADDR;
4805
t = scanfactor(&rp);
4806
if (t & 0xfffff8)
4807
  error |= ERR_ILLEGAL_ADDR;
4808
else
4809
  postbyte |= t;
4810
putbyte((unsigned short)postbyte);
4811
if (!(dwOptions & OPTION_TSC))
4812
  skipspace();
4813
if (*srcptr == ',')
4814
  srcptr++;
4815
else
4816
 error |= ERR_ILLEGAL_ADDR;
4817
scanoperands(&rp);
4818
switch (mode)
4819
  {
4820
  case ADRMODE_DIR :
4821
    putbyte((unsigned short)operand);
4822
    break;
4823
  default:
4824
    error |= ERR_ILLEGAL_ADDR;
4825
  }
4826
}
4827
 
4828
/*****************************************************************************/
4829
/* blocktrans :                                                              */
4830
/*****************************************************************************/
4831
 
4832
void blocktrans(int co)
4833
{
4834
char reg1,reg2;
4835
char mode[3] = "";
4836
static char regnames[] = "DXYUS";
4837
static char *modes[] =
4838
  {
4839
  "++",
4840
  "--",
4841
  "+",
4842
  ",+"
4843
  };
4844
int i;
4845
 
4846
skipspace();
4847
reg1 = toupper(*srcptr);
4848
for (i = 0; regnames[i]; i++)
4849
  if (reg1 == regnames[i])
4850
    break;
4851
if (!regnames[i])
4852
  error |= ERR_ILLEGAL_ADDR;
4853
else
4854
  reg1 = i;
4855
mode[0] = *++srcptr;
4856
if ((mode[0] != '+') && (mode[0] != '-'))
4857
  {
4858
  if (!(dwOptions & OPTION_TSC))
4859
    skipspace();
4860
  mode[0] = *srcptr;
4861
  }
4862
else
4863
  srcptr++;
4864
if (!(dwOptions & OPTION_TSC))
4865
  skipspace();
4866
if (*srcptr != ',')
4867
  error |= ERR_ILLEGAL_ADDR;
4868
srcptr++;
4869
reg2 = toupper(*srcptr);
4870
for (i = 0; regnames[i]; i++)
4871
  if (reg2 == regnames[i])
4872
    break;
4873
if (!regnames[i])
4874
  error |= ERR_ILLEGAL_ADDR;
4875
else
4876
  reg2 = i;
4877
mode[1] = *++srcptr;
4878
if ((mode[1] != '+') && (mode[1] != '-'))
4879
  {
4880
  if (!(dwOptions & OPTION_TSC))
4881
    skipspace();
4882
  mode[1] = *srcptr;
4883
  }
4884
else
4885
  srcptr++;
4886
if ((mode[1] == ';') || (mode[1] == '*') ||
4887
    (mode[1] == ' ') || (mode[1] == '\t'))
4888
  mode[1] = '\0';
4889
for (i = 0; i < (sizeof(modes) / sizeof(modes[0])); i++)
4890
  if (!strcmp(mode, modes[i]))
4891
    break;
4892
if (i >= (sizeof(modes) / sizeof(modes[0])))
4893
  error |= ERR_ILLEGAL_ADDR;
4894
else
4895
  co |= i;
4896
 
4897
putword((unsigned)co);
4898
putbyte((unsigned short)((reg1 << 4) | reg2));
4899
}
4900
 
4901
/*****************************************************************************/
4902
/* expandline : un-tabify current line                                       */
4903
/*****************************************************************************/
4904
 
4905
void expandline()
4906
{
4907
int i, j = 0, k, j1;
4908
 
4909
for (i = 0; i < LINELEN && j < LINELEN; i++)
4910
  {
4911
  if (inpline[i] == '\n')
4912
    {
4913
    srcline[j] = 0;
4914
    break;
4915
    }
4916
  else if (inpline[i] == '\t')
4917
    {
4918
    j1 = j;
4919
    for (k = 0; k < 8 - j1 % 8 && j < LINELEN; k++)
4920
      srcline[j++] = ' ';
4921
    }
4922
  else if (inpline[i] == '\r')
4923
    {
4924
    continue;
4925
    }
4926
  else
4927
    srcline[j++] = inpline[i];
4928
 }
4929
srcline[LINELEN - 1] = 0;
4930
}
4931
 
4932
/*****************************************************************************/
4933
/* expandtext : expands all texts in a line                                  */
4934
/*****************************************************************************/
4935
 
4936
void expandtext()
4937
{
4938
char *p;
4939
int i, j = 0;
4940
int doit = 1;
4941
 
4942
for (p = curline->txt; (*p) && (j < LINELEN); )
4943
  {
4944
  if (*p == '\"')
4945
    doit = !doit;
4946
 
4947
  if (*p == '\\' && p[1] == '&')
4948
    srcline[j++] = *(++p);
4949
  else if (*p == '&' &&
4950
           (p[1] < '0' || p[1] > '9') &&
4951
           doit)
4952
    {
4953
    struct symrecord *lp;
4954
    srcptr = p + 1;
4955
    scanname();
4956
    lp = findsym(namebuf, 0);
4957
    if ((lp) && (*namebuf) &&           /* if symbol IS a text constant,     */
4958
        (lp->cat == SYMCAT_TEXT))
4959
      {                                 /* insert its content                */
4960
      p = srcptr;
4961
      for (i = 0; j < LINELEN && texts[lp->value][i]; i++)
4962
        srcline[j++] = texts[lp->value][i];
4963
      }
4964
    else                                /* otherwise                         */
4965
      srcline[j++] = *p++;              /* simply use the '&' and go on.     */
4966
    }
4967
  else
4968
    srcline[j++] = *p++;
4969
  }
4970
srcline[j >= LINELEN ? LINELEN - 1 : j] = '\0';
4971
}
4972
 
4973
/*****************************************************************************/
4974
/* readfile : reads in a file and recurses through includes                  */
4975
/*****************************************************************************/
4976
 
4977
struct linebuf *readfile(char *name, unsigned char lvl, struct linebuf *after)
4978
{
4979
FILE *srcfile;
4980
struct linebuf *pNew;
4981
int lineno = 0;
4982
int i;
4983
int nfnidx = -1;
4984
 
4985
for (i = 0; i < nfnms; i++)             /* prohibit recursion                */
4986
  if (!strcmp(name, fnms[i]))
4987
    {
4988
    nfnidx = i;
4989
    break;
4990
    }
4991
if (nfnidx < 0)
4992
  {
4993
  if (nfnms >= (sizeof(fnms) / sizeof(fnms[0])))
4994
    {
4995
    printf("%s(0) : error 21: nesting level too deep\n", name);
4996
    if (((dwOptions & OPTION_LP1) || pass == MAX_PASSNO) && (listing & LIST_ON))
4997
      putlist( "*** Error 21: nesting level too deep\n");
4998
    exit(4);
4999
    }
5000
  nfnidx = nfnms++;
5001
  }
5002
 
5003
if ((srcfile = fopen(name, "r")) == 0)
5004
  {
5005
  printf("%s(0) : error 17: cannot open source file\n", name);
5006
  if (((dwOptions & OPTION_LP1) || pass == MAX_PASSNO) && (listing & LIST_ON))
5007
    putlist( "*** Error 17: cannot open source file\n");
5008
  exit(4);
5009
  }
5010
if (!fnms[nfnidx])                      /* if not yet done,                  */
5011
  fnms[nfnidx] = strdup(name);          /* remember the file name            */
5012
while (fgets(inpline, LINELEN, srcfile))
5013
  {
5014
  expandline();
5015
  pNew = allocline(after, fnms[nfnidx], ++lineno, lvl, srcline);
5016
  if (!pNew)
5017
    {
5018
    printf("%s(%d) : error 22: memory allocation error\n", name, lineno);
5019
    if (((dwOptions & OPTION_LP1) || pass == MAX_PASSNO) && (listing & LIST_ON))
5020
      putlist( "*** Error 22: memory allocation error\n");
5021
    exit(4);
5022
    }
5023
  if (!after)                           /* if 1st line                       */
5024
    rootline = pNew;                    /* remember it as root               */
5025
  after = pNew;                         /* insert behind the new line        */
5026
  }
5027
fclose(srcfile);                        /* then close the file               */
5028
return after;                           /* pass back last line inserted      */
5029
}
5030
 
5031
/*****************************************************************************/
5032
/* readbinary: reads in a binary file and converts to fcw / fcb lines        */
5033
/*****************************************************************************/
5034
 
5035
struct linebuf *readbinary
5036
    (
5037
    char *name,
5038
    unsigned char lvl,
5039
    struct linebuf *after,
5040
    struct symrecord *lp
5041
    )
5042
{
5043
FILE *srcfile;
5044
struct linebuf *pNew;
5045
int lineno = 0;
5046
int i;
5047
int nfnidx = -1;
5048
unsigned char binlin[16];
5049
int binlen;
5050
int fcbstart;
5051
 
5052
for (i = 0; i < nfnms; i++)             /* prohibit recursion                */
5053
  if (!strcmp(name, fnms[i]))
5054
    {
5055
    nfnidx = i;
5056
    break;
5057
    }
5058
if (nfnidx < 0)
5059
  {
5060
  if (nfnms >= (sizeof(fnms) / sizeof(fnms[0])))
5061
    {
5062
    printf("%s(0) : error 21: nesting level too deep\n", name);
5063
    if (((dwOptions & OPTION_LP1) || pass == MAX_PASSNO) && (listing & LIST_ON))
5064
      putlist( "*** Error 21: nesting level too deep\n");
5065
    exit(4);
5066
    }
5067
  nfnidx = nfnms++;
5068
  }
5069
 
5070
if ((srcfile = fopen(name, "rb")) == 0)
5071
  {
5072
  printf("%s(0) : error 17: cannot open source file\n", name);
5073
  if (((dwOptions & OPTION_LP1) || pass == MAX_PASSNO) && (listing & LIST_ON))
5074
    putlist( "*** Error 17: cannot open source file\n");
5075
  exit(4);
5076
  }
5077
if (!fnms[nfnidx])                      /* if not yet done,                  */
5078
  fnms[nfnidx] = strdup(name);          /* remember the file name            */
5079
while ((binlen = (int)fread(binlin, 1, sizeof(binlin), srcfile)) > 0)
5080
  {
5081
  sprintf(inpline, "%s", (lineno || (!lp)) ? "" : lp->name);
5082
  i = 0;
5083
  if ((binlen & (~1)) && (binlen > 7))
5084
    {
5085
    sprintf(inpline + strlen(inpline), "\tFCW\t" /* , (binlen & 1) ? 'B' : 'W' */);
5086
    for (; i < (binlen & ~1); i += 2)
5087
      sprintf(inpline + strlen(inpline), "%s$%02X%02X", (i) ? "," : "",
5088
              binlin[i], binlin[i + 1]);
5089
    expandline();
5090
    pNew = allocline(after, fnms[nfnidx], ++lineno, lvl, srcline);
5091
    if (!pNew)
5092
      {
5093
      printf("%s(%d) : error 22: memory allocation error\n", name, lineno);
5094
      if (((dwOptions & OPTION_LP1) || pass == MAX_PASSNO) && (listing & LIST_ON))
5095
        putlist( "*** Error 22: memory allocation error\n");
5096
      exit(4);
5097
      }
5098
    if (!after)                         /* if 1st line                       */
5099
      rootline = pNew;                  /* remember it as root               */
5100
    after = pNew;                       /* insert behind the new line        */
5101
    inpline[0] = '\0';                  /* reset input line                  */
5102
    }
5103
  if ((binlen & 1) || (binlen <= 7))
5104
    {
5105
    fcbstart = i;
5106
    sprintf(inpline + strlen(inpline), "\tFCB\t");
5107
    for (; i < binlen; i++)
5108
      sprintf(inpline + strlen(inpline), "%s$%02X", (i > fcbstart) ? "," : "",
5109
              binlin[i]);
5110
 
5111
    expandline();
5112
    pNew = allocline(after, fnms[nfnidx], ++lineno, lvl, srcline);
5113
    if (!pNew)
5114
      {
5115
      printf("%s(%d) : error 22: memory allocation error\n", name, lineno);
5116
      if (((dwOptions & OPTION_LP1) || pass == MAX_PASSNO) && (listing & LIST_ON))
5117
        putlist( "*** Error 22: memory allocation error\n");
5118
      exit(4);
5119
      }
5120
    if (!after)                         /* if 1st line                       */
5121
      rootline = pNew;                  /* remember it as root               */
5122
    after = pNew;                       /* insert behind the new line        */
5123
    }
5124
  }
5125
fclose(srcfile);                        /* then close the file               */
5126
return after;                           /* pass back last line inserted      */
5127
}
5128
 
5129
/*****************************************************************************/
5130
/* setoptiontexts : sets up the option text variables                        */
5131
/*****************************************************************************/
5132
 
5133
void setoptiontexts()
5134
{
5135
int i;
5136
                                        /* walk option list                  */
5137
for (i = 0; i < (sizeof(Options) / sizeof(Options[0])); i++)
5138
  {
5139
  if ((dwOptions & Options[i].dwAdd) ||
5140
      (!(dwOptions & ~Options[i].dwRem)))
5141
    settext(Options[i].Name, "1");
5142
  else
5143
    settext(Options[i].Name, "0");
5144
  }
5145
}
5146
 
5147
/*****************************************************************************/
5148
/* setoption : processes an option string                                    */
5149
/*****************************************************************************/
5150
 
5151
int setoption ( char *szOpt )
5152
{
5153
char iopt[4];
5154
int i;
5155
 
5156
for (i = 0; szOpt[i] && i < sizeof(iopt); i++)
5157
  iopt[i] = toupper(szOpt[i]);
5158
if (i >= sizeof(iopt))
5159
  i--;
5160
iopt[i] = '\0';
5161
                                        /* search option list                */
5162
for (i = 0; i < (sizeof(Options) / sizeof(Options[0])); i++)
5163
  {
5164
  if (!strcmp(iopt, Options[i].Name))   /* if option found                   */
5165
    {
5166
    dwOptions |= Options[i].dwAdd;      /* add flags                         */
5167
    dwOptions &= ~Options[i].dwRem;     /* and remove flags                  */
5168
 
5169
    switch (Options[i].dwAdd)           /* afterprocessing for specials:     */
5170
      {
5171
      case OPTION_M09 :                 /* switch to MC6809 processor        */
5172
        optable = optable09;
5173
        optablesize = sizeof(optable09) / sizeof(optable09[0]);
5174
        regtable = regtable09;
5175
        bitregtable = bitregtable09;
5176
        scanoperands = scanoperands09;
5177
        break;
5178
      case OPTION_H63 :                 /* switch to HD6309 processor        */
5179
        optable = optable09;
5180
        optablesize = sizeof(optable09) / sizeof(optable09[0]);
5181
        regtable = regtable63;
5182
        bitregtable = bitregtable09;
5183
        scanoperands = scanoperands09;
5184
        break;
5185
      case OPTION_M00 :                 /* switch to MC6800 processor        */
5186
        optable = optable00;
5187
        optablesize = sizeof(optable00) / sizeof(optable00[0]);
5188
        regtable = regtable00;
5189
        bitregtable = bitregtable00;
5190
        scanoperands = scanoperands00;
5191
        break;
5192
      }
5193
 
5194
    setoptiontexts();
5195
    return 0;                           /* then return OK                    */
5196
    }
5197
  }
5198
 
5199
return 1;                               /* unknown option                    */
5200
}
5201
 
5202
/*****************************************************************************/
5203
/* pseudoop : processes all known pseudo-ops                                 */
5204
/*****************************************************************************/
5205
 
5206
void pseudoop(int co, struct symrecord * lp)
5207
{
5208
int i, j;
5209
char c;
5210
struct relocrecord p = {0};
5211
 
5212
if (common &&                           /* if in COMMON definition mode      */
5213
    (co != PSEUDO_ENDCOM) &&            /* and this is neither ENDCOM        */
5214
    (co != PSEUDO_RMB))                 /* nor RMB                           */
5215
  error |= ERR_EXPR;                    /* this is an error.                 */
5216
 
5217
switch (co)
5218
  {
5219
  case PSEUDO_ABS :                     /* ABS                               */
5220
    absmode = 1;                        /* reset mode to absolute            */
5221
    break;
5222
  case PSEUDO_DEF :                     /* DEFINE                            */
5223
    global++;                           /* all labels from now on are global */
5224
    break;
5225
  case PSEUDO_ENDDEF :                  /* ENDDEF                            */
5226
    if (global)                         /* all labels from now on are local  */
5227
      global--;
5228
    else
5229
      error |= ERR_EXPR;                /* must be paired                    */
5230
    break;
5231
  case PSEUDO_COMMON :                  /* label COMMON                      */
5232
    if (absmode)                        /* if in absolute assembler mode     */
5233
      error |= ERR_RELOCATING;
5234
    if (!lp)
5235
      error |= ERR_LABEL_MISSING;
5236
    else
5237
      lp->cat = SYMCAT_COMMON;
5238
    common++;                           /* go into common mode               */
5239
    commonsym = lp;                     /* remember common symbol            */
5240
    break;
5241
  case PSEUDO_ENDCOM :                  /* ENDCOM                            */
5242
    if (absmode)                        /* if in absolute assembler mode     */
5243
      error |= ERR_RELOCATING;
5244
    if (common)                         /* terminate common mode             */
5245
      common--;
5246
    else
5247
      error |= ERR_EXPR;                /* must be paired                    */
5248
    break;
5249
  case PSEUDO_RMB :                     /* [label] RMB <absolute expression> */
5250
  case PSEUDO_RZB :                     /* [label] RZB <absolute expression> */
5251
    operand = scanexpr(0, &p);
5252
    if (unknown)
5253
      error |= ERR_LABEL_UNDEF;
5254
 
5255
    if (common)                         /* if in common mode                 */
5256
      {
5257
      if ((lp->cat != SYMCAT_EMPTY) &&
5258
          (lp->cat != SYMCAT_UNRESOLVED) &&
5259
          (lp->cat != SYMCAT_COMMONDATA))
5260
        error |= ERR_LABEL_MULT;
5261
      if (lp->cat != SYMCAT_COMMONDATA) /* if not yet done,                  */
5262
        {
5263
        lp->cat = SYMCAT_COMMONDATA;    /* set tymbol type                   */
5264
        lp->u.parent = commonsym;       /* remember COMMON symbol            */
5265
        lp->value = commonsym->value;   /* remember offset from COMMON symbol*/
5266
        commonsym->value +=             /* append # bytes to reserve to -"-  */
5267
            (unsigned short)operand;
5268
        }
5269
      break;
5270
      }
5271
 
5272
    setlabel(lp);
5273
    if (generating && pass == MAX_PASSNO)
5274
      {
5275
      if (co != 0 || outmode == OUT_BIN)
5276
        for (i = 0; i < operand; i++)
5277
          outbyte(0, i);
5278
      else switch (outmode)
5279
        {
5280
        case OUT_SREC :                 /* Motorola S51-09 ?                 */
5281
          flushhex();
5282
          break;
5283
        case OUT_IHEX :                 /* Intel Hex ?                       */
5284
          flushihex();
5285
          break;
5286
        case OUT_FLEX :                 /* FLEX binary ?                     */
5287
          flushflex();
5288
          break;
5289
        }
5290
      }
5291
    loccounter += operand;
5292
    hexaddr = loccounter;
5293
    break;
5294
  case PSEUDO_EQU :                     /* label EQU x                       */
5295
    nRepNext = 0;                       /* reset eventual repeat             */
5296
    operand = scanexpr(0, &p);
5297
    if (!lp)
5298
      error |= ERR_LABEL_MISSING;
5299
    else
5300
      {
5301
      if (lp->cat == SYMCAT_EMPTY ||
5302
          lp->cat == SYMCAT_UNRESOLVED ||
5303
          (lp->value == (unsigned)operand &&
5304
           pass > 1))
5305
        {
5306
        if (exprcat == EXPRCAT_INTADDR)
5307
          lp->cat = SYMCAT_LABEL;
5308
        else
5309
          lp->cat = SYMCAT_CONSTANT;
5310
        lp->value = (unsigned)operand;
5311
        }
5312
      else
5313
        error |= ERR_LABEL_MULT;
5314
      }
5315
    break;
5316
  case PSEUDO_PUB :                     /* PUBLIC a[,b[,c...]]               */
5317
  case PSEUDO_EXT :                     /* EXTERN a[,b[,c...]]               */
5318
    nRepNext = 0;                       /* reset eventual repeat             */
5319
    skipspace();
5320
    while (isalnum(*srcptr))
5321
      {
5322
      scanname();                       /* parse option                      */
5323
      lp = findsym(namebuf, 1);         /* look up the symbol                */
5324
      switch (co)
5325
        {
5326
        case PSEUDO_PUB :               /* PUBLIC a[,b[,c...]]               */
5327
          if (lp->cat == SYMCAT_EMPTY ||
5328
              lp->cat == SYMCAT_UNRESOLVED)
5329
            lp->cat = SYMCAT_PUBLICUNDEF;
5330
          else if (lp->cat == SYMCAT_LABEL)
5331
            lp->cat = SYMCAT_PUBLIC;
5332
          else if (lp->cat == SYMCAT_PUBLICUNDEF)
5333
            error |= ERR_LABEL_UNDEF;
5334
          else if (lp->cat != SYMCAT_PUBLIC)
5335
            error |= ERR_LABEL_MULT;
5336
          break;
5337
        case PSEUDO_EXT :               /* EXTERN a[,b[,c...]]               */
5338
          if (absmode)                  /* if not in relocating asm mode,    */
5339
            error |= ERR_RELOCATING;    /* set error                         */
5340
          if (lp->cat == SYMCAT_EMPTY ||
5341
              lp->cat == SYMCAT_UNRESOLVED)
5342
            lp->cat = SYMCAT_EXTERN;
5343
          else if (lp->cat != SYMCAT_EXTERN)
5344
            error |= ERR_LABEL_MULT;
5345
          break;
5346
        }
5347
      if (*srcptr == ',')
5348
        {
5349
        srcptr++;
5350
        if (!(dwOptions & OPTION_TSC))
5351
          skipspace();
5352
        }
5353
      }
5354
    break;
5355
  case PSEUDO_FCB :                     /* [label] FCB expr[,expr...]        */
5356
    setlabel(lp);
5357
    generating = 1;
5358
    do
5359
      {
5360
      if (*srcptr == ',')
5361
        srcptr++;
5362
      if (!(dwOptions & OPTION_TSC))
5363
        skipspace();
5364
      if (*srcptr == '\"')
5365
        {
5366
        srcptr++;
5367
        while (*srcptr != '\"' && *srcptr)
5368
          putbyte(*srcptr++);
5369
        if (*srcptr == '\"')
5370
          srcptr++;
5371
        }
5372
      else
5373
        {
5374
        putbyte((unsigned short)scanexpr(0, &p));
5375
        if (unknown && pass == MAX_PASSNO)
5376
          error |= ERR_LABEL_UNDEF;
5377
        }
5378
      if (!(dwOptions & OPTION_TSC))
5379
        skipspace();
5380
      } while (*srcptr == ',');
5381
    break;
5382
  case PSEUDO_FCC :                     /* [label] FCC expr[,expr...]        */
5383
    setlabel(lp);
5384
    if (!(dwOptions & OPTION_TSC))
5385
      skipspace();
5386
    if (!(dwOptions & OPTION_TSC))      /* if standard                       */
5387
      {                                 /* accept ONE sequence with an       */
5388
      c = *srcptr++;                    /* arbitrary delimiter character     */
5389
      while (*srcptr != c && *srcptr)
5390
        putbyte(*srcptr++);
5391
      if (*srcptr == c)
5392
        srcptr++;
5393
      }
5394
    else                                /* if TSC extended format            */
5395
      {                                 /* accept MORE sequences             */
5396
      do
5397
        {
5398
        if (*srcptr == ',')
5399
          srcptr++;
5400
        if (!(dwOptions & OPTION_TSC))
5401
          skipspace();
5402
        c = *srcptr;
5403
        if ((c == '$') || isalnum(c))
5404
          {
5405
          putbyte((unsigned short)scanexpr(0, &p));
5406
          if (unknown && pass == MAX_PASSNO)
5407
            error |= ERR_LABEL_UNDEF;
5408
          }
5409
        else
5410
          {
5411
          srcptr++;
5412
          while (*srcptr != c && *srcptr)
5413
            putbyte(*srcptr++);
5414
          if (*srcptr == c)
5415
            srcptr++;
5416
          }
5417
        if (!(dwOptions & OPTION_TSC))
5418
          skipspace();
5419
        } while (*srcptr == ',');
5420
      }
5421
    break;
5422
  case PSEUDO_FCW :                     /* [label] FCW,FDB  expr[,expr...]   */
5423
    setlabel(lp);
5424
    generating = 1;
5425
    do
5426
      {
5427
      if (*srcptr == ',')
5428
        srcptr++;
5429
      if (!(dwOptions & OPTION_TSC))
5430
        skipspace();
5431
      putword((unsigned)scanexpr(0, &p));
5432
      if (unknown && pass == MAX_PASSNO)
5433
        error |= ERR_LABEL_UNDEF;
5434
      if (!(dwOptions & OPTION_TSC))
5435
        skipspace();
5436
      } while (*srcptr == ',');
5437
    break;
5438
  case PSEUDO_FCDW:                     /* [label] FCDW,FDB  expr[,expr...]   */
5439
    setlabel(lp);
5440
    generating = 1;
5441
    do
5442
      {
5443
      if (*srcptr == ',')
5444
        srcptr++;
5445
      if (!(dwOptions & OPTION_TSC))
5446
        skipspace();
5447
      putdword((unsigned __int64)scanexpr(0, &p));
5448
      if (unknown && pass == MAX_PASSNO)
5449
        error |= ERR_LABEL_UNDEF;
5450
      if (!(dwOptions & OPTION_TSC))
5451
        skipspace();
5452
      } while (*srcptr == ',');
5453
    break;
5454
  case PSEUDO_ELSE :                    /* ELSE                              */
5455
    if (inMacro)                        /* don't process if in MACRO def.    */
5456
      break;
5457
    nRepNext = 0;                       /* reset eventual repeat             */
5458
    suppress = 1;
5459
    condline = 1;                       /* this is a conditional line        */
5460
    break;
5461
  case PSEUDO_ENDIF :                   /* ENDIF                             */
5462
    if (inMacro)                        /* don't process if in MACRO def.    */
5463
      break;
5464
    nRepNext = 0;                       /* reset eventual repeat             */
5465
    condline = 1;                       /* this is a conditional line        */
5466
    break;
5467
  case PSEUDO_IF :                      /* IF  <expression>[,<skip>]         */
5468
  case PSEUDO_IFN :                     /* IFN <expression>[,<skip>]         */
5469
    if (inMacro)                        /* don't process if in MACRO def.    */
5470
      break;
5471
    condline = 1;                       /* this is a conditional line        */
5472
    nRepNext = 0;                       /* reset eventual repeat             */
5473
    operand = scanexpr(0, &p);
5474
    if (unknown)
5475
      error |= ERR_LABEL_UNDEF;
5476
    if (co == PSEUDO_IFN)               /* if IFN                            */
5477
      operand = !operand;               /* reverse operand                   */
5478
    if (!(dwOptions & OPTION_TSC))
5479
      skipspace();
5480
    if (*srcptr == ',')                 /* skip count?                       */
5481
      {
5482
      srcptr++;
5483
      if (!(dwOptions & OPTION_TSC))
5484
        skipspace();
5485
      nSkipCount = scanexpr(0, &p);
5486
      if (!operand)
5487
        nSkipCount = 0;
5488
      }
5489
    else if (!operand)
5490
      suppress = 2;
5491
    break;
5492
  case PSEUDO_IFC :                     /* IFC  <string1>,<string2>[,<skip>] */
5493
  case PSEUDO_IFNC :                    /* IFNC <string1>,<string2>[,<skip>] */
5494
    if (inMacro)                        /* don't process if in MACRO def.    */
5495
      break;
5496
    condline = 1;                       /* this is a conditional line        */
5497
    if (!(dwOptions & OPTION_TSC))
5498
      skipspace();
5499
    scanstring(szBuf1, sizeof(szBuf1));
5500
    if (!(dwOptions & OPTION_TSC))
5501
      skipspace();
5502
    if (*srcptr != ',')                 /* if not on comma                   */
5503
      {
5504
      *szBuf2 = '\0';                   /* reset 2nd string                  */
5505
      error |= ERR_EXPR;                /* set error                         */
5506
      }
5507
    else
5508
      {
5509
      srcptr++;
5510
      if (!(dwOptions & OPTION_TSC))
5511
        skipspace();
5512
      scanstring(szBuf2, sizeof(szBuf2));
5513
      if (!(dwOptions & OPTION_TSC))
5514
        skipspace();
5515
      }
5516
    operand = !strcmp(szBuf1, szBuf2);
5517
    if (co == PSEUDO_IFNC)
5518
      operand = !operand;
5519
    if (*srcptr == ',')                 /* if skip count                     */
5520
      {
5521
      srcptr++;
5522
      if (!(dwOptions & OPTION_TSC))
5523
        skipspace();
5524
      nSkipCount = scanexpr(0, &p);
5525
      if (!operand)
5526
        nSkipCount = 0;
5527
      }
5528
    else if (!operand)
5529
      suppress = 2;
5530
    break;
5531
 
5532
  case PSEUDO_IFD :                     /* IFD <symbol>[,skipcount]          */
5533
  case PSEUDO_IFND :                    /* IFND <symbol>[,skipcount]         */
5534
    /* ATTENTION: it is easy to produce phasing errors with these 2,         */
5535
    /*            since symbols are NOT reset when starting pass 2!          */
5536
    if (inMacro)                        /* don't process if in MACRO def.    */
5537
      break;
5538
    skipspace();
5539
    scanname();                         /* parse symbol name                 */
5540
    lp = findsym(namebuf, 0);           /* look up the symbol                */
5541
    if (!(dwOptions & OPTION_TSC))
5542
      skipspace();
5543
    if (*srcptr == ',')                 /* if skip count                     */
5544
      {
5545
      srcptr++;
5546
      if (!(dwOptions & OPTION_TSC))
5547
        skipspace();
5548
      nSkipCount = scanexpr(0, &p);
5549
      if (!lp != (co == PSEUDO_IFND))
5550
        nSkipCount = 0;
5551
      }
5552
                                        /* if no skip count and NOT matched  */
5553
    else if (!lp != (co == PSEUDO_IFND))
5554
      suppress = 2;                     /* suppress until ELSE or ENDIF      */
5555
    condline = 1;                       /* this is a conditional line        */
5556
    break;
5557
 
5558
  case PSEUDO_ORG :                     /* ORG <expression>                  */
5559
    nRepNext = 0;                       /* reset eventual repeat             */
5560
    operand = scanexpr(0, &p);
5561
    if (unknown)
5562
      error |= ERR_LABEL_UNDEF;
5563
    if (relocatable &&                  /* if in relocating assembler mode   */
5564
        (!absmode))
5565
      {
5566
      error |= ERR_RELOCATING;          /* set error                         */
5567
      break;                            /* and ignore                        */
5568
      }
5569
    if (generating && pass == MAX_PASSNO)
5570
      {
5571
      switch (outmode)
5572
        {
5573
        case OUT_BIN :                  /* binary output file                */
5574
          j = (int)(unsigned)operand - (int)loccounter;
5575
          if (j > 0)                    /* if forward gap                    */
5576
            {
5577
            for (i = 0; i < j; i++)     /* seek forward that many bytes      */
5578
              fseek(objfile, 1, SEEK_CUR);
5579
            }
5580
          else                          /* if backward gap                   */
5581
            {
5582
            j = -j;
5583
            for (i = 0; i < j; i++)     /* seek back that many bytes         */
5584
              fseek(objfile, -1, SEEK_CUR);
5585
            }
5586
          break;
5587
                case OUT_VER:
5588
                        flushver();
5589
                        break;
5590
        case OUT_SREC :                 /* motorola s51-09                   */
5591
          flushhex();
5592
          break;
5593
        case OUT_IHEX :                 /* intel hex format                  */
5594
          flushihex();
5595
          break;
5596
        case OUT_FLEX :                 /* FLEX binary                       */
5597
          flushflex();
5598
          break;
5599
        }
5600
      }
5601
    loccounter = operand;
5602
    hexaddr = loccounter;
5603
    break;
5604
  case PSEUDO_SETDP :                   /* SETDP [<abs page value>]          */
5605
    nRepNext = 0;                       /* reset eventual repeat             */
5606
    skipspace();
5607
    if ((!*srcptr) || (*srcptr == '*') || (*srcptr == ';'))
5608
      operand = -1;
5609
    else
5610
      operand = scanexpr(0, &p);
5611
    if (unknown)
5612
      error |= ERR_LABEL_UNDEF;
5613
    if (!(operand & 4095))
5614
      operand = (unsigned)operand >> 12;
5615
    if ((unsigned)operand > 4095)
5616
      operand = -1;
5617
    if (absmode)
5618
      dpsetting = operand;
5619
    else
5620
      error |= ERR_RELOCATING;
5621
    break;
5622
  case PSEUDO_SET :                     /* label SET <non external expr>     */
5623
    nRepNext = 0;                       /* reset eventual repeat             */
5624
    operand = scanexpr(0, &p);
5625
    if (!lp)
5626
      error |= ERR_LABEL_MISSING;
5627
    else
5628
      {
5629
      if (lp->cat & SYMCAT_VARIABLE ||
5630
          lp->cat == SYMCAT_UNRESOLVED)
5631
        {
5632
        if (exprcat == EXPRCAT_INTADDR)
5633
          lp->cat = SYMCAT_VARADDR;
5634
        else
5635
          lp->cat = SYMCAT_VARIABLE;
5636
        lp->value = (unsigned)operand;
5637
        }
5638
      else
5639
        error |= ERR_LABEL_MULT;
5640
      }
5641
    break;
5642
  case PSEUDO_END :                     /* END [loadaddr]                    */
5643
    nRepNext = 0;                       /* reset eventual repeat             */
5644
    if ((curline->lvl & 0x0f) == 0)     /* only in outermost level!          */
5645
      {
5646
      skipspace();                      /* skip blanks                       */
5647
      if (isfactorstart(*srcptr))       /* if possible transfer address      */
5648
        {
5649
        tfradr = (unsigned)       /* get transfer address              */
5650
            scanexpr(0, &p);
5651
        if (error)                      /* if error in here                  */
5652
          tfradr = 0;                   /* reset to zero                     */
5653
        else                            /* otherwise                         */
5654
          tfradrset = 1;                /* remember transfer addr. is set    */
5655
        }
5656
      terminate = 1;
5657
      }
5658
    break;
5659
  case PSEUDO_INCLUDE :                 /* INCLUDE <filename>                */
5660
    nRepNext = 0;                       /* reset eventual repeat             */
5661
    if (inMacro ||                      /* if in macro definition            */
5662
        (curline->lvl & LINCAT_MACEXP)) /* or macro expansion                */
5663
      error |= ERR_EXPR;                /* this is an error.                 */
5664
    else if (pass == 1)                 /* otherwise expand if in pass 1     */
5665
      {
5666
      char fname[FNLEN + 1];
5667
      int instring = 0;
5668
      char *osrc = srcptr;
5669
 
5670
      if ((curline->lvl & 0x0f) == 0x0f)/* if impossible                     */
5671
        {
5672
#if 0
5673
        allocline(curline, "NULL", -1, 0x0f,
5674
                  "Error including file - nesting level too deep");
5675
#endif
5676
        error |= ERR_MALLOC;            /* set OUT OF MEMORY error           */
5677
        break;
5678
        }
5679
      if (!(dwOptions & OPTION_TSC))
5680
        skipspace();
5681
      if (*srcptr == '\"')
5682
        {
5683
        srcptr++;
5684
        instring = 1;
5685
        }
5686
      for (i = 0; i < FNLEN; i++)
5687
        {
5688
        if (*srcptr == 0 ||
5689
            (!instring && *srcptr == ' ') ||
5690
            *srcptr == '"')
5691
          break;
5692
        fname[i] = *srcptr++;
5693
        }
5694
      fname[i] = 0;
5695
      curline->lvl |= LINCAT_INVISIBLE; /* preclude listing of INCLUDE line  */
5696
 
5697
      readfile(fname,                   /* append include after current line */
5698
               (unsigned char)((curline->lvl & 0x0f) + 1),
5699
               curline);
5700
      expandtext();                     /* re-expand current line            */
5701
      srcptr = osrc;
5702
      }
5703
    break;
5704
  case PSEUDO_OPT :                     /* OPT,OPTION  option[,option...]    */
5705
    nRepNext = 0;                       /* reset eventual repeat             */
5706
    skipspace();
5707
    while (isalnum(*srcptr))
5708
      {
5709
      scanname();                       /* parse option                      */
5710
      if (setoption(unamebuf))
5711
        error |= ERR_OPTION_UNK;
5712
      if (*srcptr == ',')
5713
        {
5714
        srcptr++;
5715
        if (!(dwOptions & OPTION_TSC))
5716
          skipspace();
5717
        }
5718
      }
5719
    break;
5720
  case PSEUDO_NAM :                     /* NAM,TTL <text>                    */
5721
  case PSEUDO_STTL :                    /* STTL <text>                       */
5722
    nRepNext = 0;                       /* reset eventual repeat             */
5723
    if (!(dwOptions & OPTION_TSC))
5724
      skipspace();
5725
    if (isalnum(*srcptr))
5726
      {
5727
      char *tgt = (co == PSEUDO_NAM) ? szTitle : szSubtitle;
5728
      char *lnblnk = tgt;
5729
      int nBytes = 0;
5730
      while (*srcptr && nBytes < (sizeof(szTitle) - 1))
5731
        {
5732
        if (*srcptr != ' ')
5733
          lnblnk = tgt;
5734
        *tgt++ = *srcptr++;
5735
        nBytes++;
5736
        }
5737
      lnblnk[1] = '\0';                 /* terminate after last nonblank     */
5738
      while (*srcptr)                   /* skip rest if too long             */
5739
        srcptr++;
5740
      }
5741
    break;
5742
  case PSEUDO_PAG :                     /* PAG [<abs expression>]            */
5743
    if (!(dwOptions & OPTION_TSC))
5744
      skipspace();
5745
    if (isfactorstart(*srcptr))         /* if possible new page number       */
5746
      {
5747
      int nPage = scanexpr(0, &p);      /* get new page #                    */
5748
      if (!error && listfile)           /* if valid and writing listfile     */
5749
        nCurPage = nPage - 1;
5750
      else
5751
        break;
5752
      }
5753
    curline->lvl |= LINCAT_INVISIBLE;
5754
    if ((listing & LIST_ON) && listfile &&
5755
        (dwOptions & OPTION_PAG) &&
5756
        (!(curline->lvl & LINCAT_LVLMASK) || (dwOptions & OPTION_LLL)) &&
5757
        (pass > 1 || (dwOptions & OPTION_LP1)))
5758
      PageFeed();
5759
    break;
5760
  case PSEUDO_SPC :                     /* SPC <n[,keep]>                    */
5761
    {
5762
    int nSpc = 1, nKeep = 0;
5763
    if (!(dwOptions & OPTION_TSC))
5764
      skipspace();
5765
    if (isfactorstart(*srcptr))         /* if possible new page number       */
5766
      {
5767
      nSpc = scanexpr(0, &p);           /* get # space lines                 */
5768
      if (!(dwOptions & OPTION_TSC))
5769
        skipspace();
5770
      if (*srcptr == ',')               /* if followed by ,                  */
5771
        {
5772
        srcptr++;
5773
        if (!(dwOptions & OPTION_TSC))
5774
          skipspace();
5775
        nKeep = scanexpr(0, &p);        /* get # keep lines                  */
5776
        }
5777
      if (error)
5778
        break;
5779
      }
5780
    curline->lvl |= LINCAT_INVISIBLE;
5781
    if (listing & LIST_ON)
5782
      {
5783
      if (nSpc > 0)                     /* if spaces needed                  */
5784
        {
5785
        if ((dwOptions & OPTION_PAG) &&
5786
            (nCurLine + nSpc + nKeep >= nLinesPerPage))
5787
          PageFeed();
5788
        else for (; nSpc; nSpc--)
5789
          putlist("\n");
5790
        }
5791
      else if (nKeep &&
5792
          (dwOptions & OPTION_PAG) &&
5793
          (nCurLine + nKeep >= nLinesPerPage))
5794
        PageFeed();
5795
      }
5796
    }
5797
    break;
5798
  case PSEUDO_REP :                     /* REP n                             */
5799
    if (!(dwOptions & OPTION_TSC))
5800
      skipspace();
5801
    nRepNext = scanexpr(0, &p);         /* get # repetitions                 */
5802
    curline->lvl |= LINCAT_INVISIBLE;
5803
    break;
5804
  case PSEUDO_SETPG :                   /* SETPG pagelen                     */
5805
    if (!(dwOptions & OPTION_TSC))
5806
      skipspace();
5807
    nLinesPerPage = scanexpr(0, &p);    /* get # lines per page              */
5808
    if (nLinesPerPage < 10)             /* adjust to boundary values         */
5809
      nLinesPerPage = 10;
5810
    else if (nLinesPerPage > 1000)
5811
      nLinesPerPage = 1000;
5812
    curline->lvl |= LINCAT_INVISIBLE;
5813
    break;
5814
  case PSEUDO_SETLI :                   /* SETLI linelen                     */
5815
    if (!(dwOptions & OPTION_TSC))
5816
      skipspace();
5817
    nColsPerLine = scanexpr(0, &p);     /* get # columns per line            */
5818
    if (nColsPerLine < 40)              /* adjust to boundary values         */
5819
      nColsPerLine = 40;
5820
    else if (nColsPerLine > 2000)
5821
      nColsPerLine = 2000;
5822
    curline->lvl |= LINCAT_INVISIBLE;
5823
    break;
5824
  case PSEUDO_SYMLEN :                  /* SYMLEN symbollength               */
5825
    if (!(dwOptions & OPTION_TSC))
5826
      skipspace();
5827
    maxidlen = scanexpr(0, &p);         /* get # significant ID places       */
5828
    if (maxidlen < 6)                   /* adjust to boundary values         */
5829
      maxidlen = 6;
5830
    else if ((outmode == OUT_REL) &&
5831
             (maxidlen > 8))
5832
      maxidlen = 8;
5833
    else if (maxidlen > MAXIDLEN)
5834
      maxidlen = MAXIDLEN;
5835
    curline->lvl |= LINCAT_INVISIBLE;
5836
    break;
5837
  case PSEUDO_MACRO :                   /* label MACRO                       */
5838
    if (!lp)                            /* a macro NEEDS a label!            */
5839
      error |= ERR_LABEL_MISSING;
5840
    if (lp->cat == SYMCAT_EMPTY)
5841
      {
5842
      if (nMacros < MAXMACROS)          /* if space for another macro defin. */
5843
        {
5844
        lp->cat = SYMCAT_MACRO;         /* remember it's a macro             */
5845
        macros[nMacros] = curline;      /* remember pointer to start line    */
5846
        lp->value = nMacros++;          /* and remember the macro            */
5847
        }
5848
      else
5849
        error |= ERR_MALLOC;
5850
      }
5851
    else if (lp->cat != SYMCAT_MACRO ||
5852
             macros[lp->value] != curline)
5853
      error |= ERR_LABEL_MULT;
5854
    inMacro++;
5855
    curline->lvl |= LINCAT_MACDEF;
5856
    if (inMacro > 1)
5857
      error |= ERR_NESTING;
5858
    break;
5859
  case PSEUDO_ENDM :                    /* ENDM                              */
5860
    if (!inMacro)
5861
      error |= ERR_EXPR;
5862
    else
5863
      inMacro--;
5864
    break;
5865
  case PSEUDO_EXITM :                   /* EXITM                             */
5866
    if (!inMacro &&                     /* only allowed inside macros        */
5867
         !(curline->lvl & LINCAT_MACEXP))
5868
      error |= ERR_EXPR;
5869
    break;
5870
  case PSEUDO_REG :                     /* label REG <register list>         */
5871
    if (!lp)                            /* label is mandatory!               */
5872
      error |= ERR_LABEL_MISSING;
5873
    {
5874
    struct regrecord *p;
5875
    postbyte = 0;
5876
    do
5877
      {
5878
      if (*srcptr == ',')
5879
        srcptr++;
5880
      if (!(dwOptions & OPTION_TSC))
5881
        skipspace();
5882
      scanname();
5883
      if ((p = findreg(unamebuf)) == 0)
5884
        error |= ERR_ILLEGAL_ADDR;
5885
      else
5886
        postbyte |= p->psh;
5887
      if (!(dwOptions & OPTION_TSC))
5888
        skipspace();
5889
      } while (*srcptr == ',');
5890
    if (lp->cat == SYMCAT_EMPTY)
5891
      {
5892
      lp->cat = SYMCAT_REG;
5893
      lp->value = postbyte;
5894
      }
5895
    else if (lp->cat != SYMCAT_REG ||
5896
             lp->value != postbyte)
5897
      error |= ERR_LABEL_MULT;
5898
    }
5899
    break;
5900
  case PSEUDO_ERR :                     /* ERR text?                         */
5901
    if (!(dwOptions & OPTION_TSC))
5902
      skipspace();
5903
    if (pass != 1)                      /* ignore in pass 1                  */
5904
      {
5905
      errormsg[14] = srcptr;
5906
      error |= ERR_ERRTXT;
5907
      }
5908
    break;
5909
  case PSEUDO_TEXT :                    /* TEXT text ?                       */
5910
    if (!(dwOptions & OPTION_TSC))
5911
      skipspace();
5912
    if (!lp)                            /* label is mandatory!               */
5913
      error |= ERR_LABEL_MISSING;
5914
    else if (lp->cat != SYMCAT_EMPTY && /* and must be text, if there        */
5915
             lp->cat != SYMCAT_TEXT)
5916
      error |= ERR_LABEL_MULT;
5917
    else                                /* if all OK, (re)define text        */
5918
      settext(lp->name, srcptr);
5919
    break;
5920
  case PSEUDO_NAME :                    /* NAME <modulename> ?               */
5921
    if (!(dwOptions & OPTION_TSC))
5922
      skipspace();
5923
    scanname();
5924
    if (!namebuf[0])                    /* name must be given                */
5925
      error |= ERR_EXPR;
5926
    strncpy(modulename, namebuf, 8);
5927
    break;
5928
  case PSEUDO_BINARY :                  /* BIN[ARY] <filename> ?             */
5929
    nRepNext = 0;                       /* reset eventual repeat             */
5930
    if (pass == 1)                      /* expand if in pass 1               */
5931
      {
5932
      char fname[FNLEN + 1];
5933
      int instring = 0;
5934
      char *osrc = srcptr;
5935
 
5936
      if (!(dwOptions & OPTION_TSC))
5937
        skipspace();
5938
      if (*srcptr == '\"')
5939
        {
5940
        srcptr++;
5941
        instring = 1;
5942
        }
5943
      for (i = 0; i < FNLEN; i++)
5944
        {
5945
        if (*srcptr == 0 ||
5946
            (!instring && *srcptr == ' ') ||
5947
            *srcptr == '"')
5948
          break;
5949
        fname[i] = *srcptr++;
5950
        }
5951
      fname[i] = 0;
5952
      curline->lvl |= LINCAT_INVISIBLE; /* preclude listing of BINARY line   */
5953
 
5954
      readbinary(fname,                 /* append binary after current line  */
5955
               (unsigned char)((curline->lvl & 0x0f) + 1),
5956
               curline, lp);
5957
      expandtext();                     /* re-expand current line            */
5958
      srcptr = osrc;
5959
      }
5960
    break;
5961
  }
5962
}
5963
 
5964
/*****************************************************************************/
5965
/* macskip : skips a range of macro lines                                    */
5966
/*****************************************************************************/
5967
 
5968
struct linebuf *macskip(struct linebuf *pmac, int nSkips)
5969
{
5970
if (nSkips < 0)                         /* we need to go to the line BEFORE  */
5971
  nSkips--;                             /* the one we need!                  */
5972
while (nSkips)
5973
  {
5974
  if (nSkips < 0)
5975
    {
5976
    if (!pmac->prev)
5977
      break;
5978
    pmac = pmac->prev;
5979
    nSkips++;
5980
    }
5981
  else
5982
    {
5983
    if (!pmac->next)
5984
      break;
5985
    pmac = pmac->next;
5986
    nSkips--;
5987
    }
5988
  }
5989
return pmac;
5990
}
5991
 
5992
/*****************************************************************************/
5993
/* expandmacro : expands a macro definition below the current line           */
5994
/*****************************************************************************/
5995
 
5996
void expandmacro(struct symrecord *lp, struct symrecord *lpmac)
5997
{
5998
struct oprecord *op;
5999
char szMacInv[LINELEN];                 /* macro invocation line             */
6000
char szLine[LINELEN];                   /* current macro line                */
6001
char *szMacParm[10];
6002
char *s, *d;                            /* source / destination work pointers*/
6003
char *srcsave = srcptr;
6004
struct linebuf *cursave = curline;
6005
int nMacParms = 1;
6006
int nInString = 0;
6007
int nMacLine = 1;                       /* current macro line                */
6008
                                        /* current macro line                */
6009
struct linebuf *pmac = macros[lpmac->value]->next;
6010
struct linebuf *pcur = curline;         /* current expanded macro line       */
6011
struct linebuf *pdup = NULL;            /* DUP start line                    */
6012
int nDup = 0;                           /* # repetitions for DUP             */
6013
int terminate = 0;                      /* terminate macro expansion if set  */
6014
int skipit = 0;                         /* skip this line                    */
6015
int suppress[64] = {0};                 /* internal suppression (max.64 lvl) */
6016
int ifcount = 0;                        /* internal if counter               */
6017
struct relocrecord p = {0};
6018
 
6019
if ((listing & LIST_ON) &&              /* if listing pass 1                 */
6020
    (dwOptions & OPTION_LIS) &&
6021
    (dwOptions & OPTION_LP1))
6022
  outlist(NULL);                        /* show macro invocation BEFORE      */
6023
                                        /* processing the expansions         */
6024
 
6025
skipspace();                            /* skip spaces before macro args     */
6026
 
6027
if (!lp)                                /* if no macro label                 */
6028
  szMacParm[0] = "";                    /* set &0 to blank                   */
6029
else                                    /* otherwise                         */
6030
  szMacParm[0] = lp->name;              /* set &0 to line label              */
6031
                                        /* initialize all parameters to ""   */
6032
for (nMacParms = 1; nMacParms < 10; nMacParms++)
6033
  szMacParm[nMacParms] = "";
6034
nMacParms = 1;                          /* reset # parsed parms to 1         */
6035
 
6036
strcpy(szMacInv, srcptr);               /* copy the current line for mangling*/
6037
srcptr = szMacInv;                      /* set pointer to internal buffer    */
6038
do
6039
  {
6040
  while (*srcptr == ',')                /* skip parameter delimiter(s)       */
6041
    {
6042
    *srcptr++ = '\0';                   /* delimit & advance behind it       */
6043
    if (!(dwOptions & OPTION_TSC))
6044
      skipspace();
6045
    }
6046
                                        /* OK, next string...                */
6047
  if ((*srcptr == '\'') ||              /* if delimited string               */
6048
      (*srcptr == '\"'))
6049
    nInString = 1;                      /* remember we're in delimited strg  */
6050
  szMacParm[nMacParms] = srcptr++;      /* store parameter start pointer     */
6051
  while (*srcptr)                       /* walk to end of parameter          */
6052
    {
6053
    if (!nInString &&
6054
        ((*srcptr == ' ') || (*srcptr == ',')))
6055
      break;
6056
    else if (nInString &&
6057
             *srcptr == *szMacParm[nMacParms])
6058
      {
6059
      srcptr++;
6060
      break;
6061
      }
6062
    srcptr++;
6063
    }
6064
  if (*srcptr && *srcptr != ',')
6065
    {
6066
    *srcptr++ = '\0';
6067
    if (!(dwOptions & OPTION_TSC))
6068
      skipspace();
6069
    }
6070
  nMacParms++;
6071
  if (nMacParms >= 10)
6072
    break;
6073
  } while (*srcptr == ',');
6074
 
6075
/*---------------------------------------------------------------------------*/
6076
/* OK, got macro arguments &0...&9 now                                       */
6077
/*---------------------------------------------------------------------------*/
6078
 
6079
while (pmac)                            /* walk through the macro lines      */
6080
  {
6081
  srcptr = s = pmac->txt;
6082
  d = szLine;
6083
  op = NULL;
6084
  skipit = 0;
6085
 
6086
  while (*s)                            /* first, expand the line            */
6087
    {
6088
    if (*s == '\\' && s[1] == '&')
6089
      {
6090
      s++;
6091
      *d++ = *s++;
6092
      }
6093
    else if (*s == '&' && s[1] >= '0' && s[1] <= '9')
6094
      {
6095
      strcpy(d, szMacParm[s[1] - '0']);
6096
      s += 2;
6097
      d += strlen(d);
6098
      }
6099
    else
6100
      *d++ = *s++;
6101
    }
6102
  *d = '\0';
6103
 
6104
  srcptr = szLine;                      /* then, look whether code or macro  */
6105
  if (isalnum(*srcptr))
6106
    {
6107
    scanname();
6108
    lp = findsym(namebuf, 1);
6109
    if (*srcptr == ':')
6110
      srcptr++;
6111
    }
6112
  skipspace();
6113
  if (isalnum(*srcptr))                 /* then parse opcode                 */
6114
    {
6115
    scanname();
6116
    op = findop(unamebuf);
6117
    }
6118
  skipspace();                          /* and skip to eventual parameter    */
6119
 
6120
  if (op && op->cat == OPCAT_PSEUDO)    /* if pseudo-op                      */
6121
    {
6122
    switch (op->code)                   /* examine for macro expansion       */
6123
      {
6124
      case PSEUDO_ENDM :                /* ENDM ?                            */
6125
        terminate = 1;                  /* terminate macro expansion         */
6126
        break;
6127
      case PSEUDO_EXITM :               /* EXITM ?                           */
6128
        if (!suppress[ifcount])         /* if not suppressed                 */
6129
          terminate = 1;                /* terminate macro expansion         */
6130
        break;
6131
      case PSEUDO_DUP :                 /* DUP ?                             */
6132
        if (pdup != NULL)               /* nesting not allowed               */
6133
          error |= ERR_NESTING;
6134
        else
6135
          {
6136
          nDup = scanexpr(0, &p);       /* scan the expression               */
6137
          pdup = pmac;                  /* remember DUP start line           */
6138
          if (nDup < 1 || nDup > 255)   /* if invalid # repetitions          */
6139
            {
6140
            error |= ERR_EXPR;          /* set error here                    */
6141
            nDup = 1;
6142
            }
6143
          else
6144
            skipit = 1;                 /* skip this line                    */
6145
          }
6146
        break;
6147
      case PSEUDO_ENDD :                /* ENDD ?                            */
6148
        if (!pdup)                      /* if no DUP defined                 */
6149
          error |= ERR_EXPR;            /* can't do that here.               */
6150
        else
6151
          {
6152
          nDup--;                       /* decrement # duplications          */
6153
          if (!nDup)                    /* if done,                          */
6154
            pdup = NULL;                /* reset dup start                   */
6155
          else                          /* otherwise                         */
6156
            pmac = pdup;                /* reset current line to DUP op      */
6157
          skipit = 1;                   /* this line isn't really there      */
6158
          }
6159
        break;
6160
      case PSEUDO_IF :                  /* IF                                */
6161
      case PSEUDO_IFN :                 /* IFN                               */
6162
        ifcount++;                      /* increment # ifs                   */
6163
                                        /* take suppression from higher level*/
6164
        suppress[ifcount] = suppress[ifcount - 1];
6165
        if (suppress[ifcount])          /* if already suppressed             */
6166
          suppress[ifcount]++;          /* inrease # suppressions            */
6167
        else                            /* otherwise evaluate expression     */
6168
          {
6169
          operand = scanexpr(0, &p);
6170
          if (unknown)
6171
            error |= ERR_LABEL_UNDEF;
6172
          if (op->code == PSEUDO_IFN)   /* if IFN                            */
6173
            operand = !operand;         /* invert operand                    */
6174
          if (!operand)                 /* if evaulation to zer0             */
6175
            suppress[ifcount]++;        /* suppress until ELSE or ENDIF      */
6176
          if (!(dwOptions & OPTION_TSC))
6177
            skipspace();
6178
          if (*srcptr == ',')           /* if skip count passed              */
6179
            {
6180
            int nSkips;
6181
            srcptr++;
6182
            if (!(dwOptions & OPTION_TSC))
6183
              skipspace();
6184
            nSkips = scanexpr(0, &p);   /* scan skip count                   */
6185
            ifcount--;                  /* this needs no ENDIF               */
6186
            if (nSkips < -255 || nSkips > 255 || nSkips == 0)
6187
              {
6188
              error |= ERR_EXPR;
6189
              break;
6190
              }
6191
            if (operand)                /* if evaluation is true             */
6192
              pmac = macskip(pmac, nSkips); /* then skip the amount of lines */
6193
            }
6194
          }
6195
        skipit = 1;                     /* don't add this line!              */
6196
        break;
6197
      case PSEUDO_IFC :                 /* IFC                               */
6198
      case PSEUDO_IFNC :                /* IFNC                              */
6199
        ifcount++;                      /* increment # ifs                   */
6200
                                        /* take suppression from higher level*/
6201
        suppress[ifcount] = suppress[ifcount - 1];
6202
        if (suppress[ifcount])          /* if already suppressed             */
6203
          suppress[ifcount]++;          /* inrease # suppressions            */
6204
        else                            /* otherwise evaluate expression     */
6205
          {
6206
          if (!(dwOptions & OPTION_TSC))
6207
            skipspace();
6208
          scanstring(szBuf1, sizeof(szBuf1));
6209
          if (!(dwOptions & OPTION_TSC))
6210
            skipspace();
6211
          if (*srcptr != ',')           /* if not on comma                   */
6212
            {
6213
            *szBuf2 = '\0';             /* reset 2nd string                  */
6214
            error |= ERR_EXPR;          /* set error                         */
6215
            }
6216
          else
6217
            {
6218
            srcptr++;
6219
            if (!(dwOptions & OPTION_TSC))
6220
              skipspace();
6221
            scanstring(szBuf2, sizeof(szBuf2));
6222
            }
6223
          operand = !strcmp(szBuf1, szBuf2);
6224
          if (op->code == PSEUDO_IFNC)
6225
            operand = !operand;
6226
          if (!operand)                 /* if evaulation to zer0             */
6227
            suppress[ifcount]++;        /* suppress until ELSE or ENDIF      */
6228
          if (!(dwOptions & OPTION_TSC))
6229
            skipspace();
6230
          if (*srcptr == ',')           /* if skip count passed              */
6231
            {
6232
            int nSkips;
6233
            srcptr++;
6234
            if (!(dwOptions & OPTION_TSC))
6235
              skipspace();
6236
            nSkips = scanexpr(0, &p);   /* scan skip count                   */
6237
            ifcount--;                  /* this needs no ENDIF               */
6238
            if (nSkips < -255 || nSkips > 255 || nSkips == 0)
6239
              {
6240
              error |= ERR_EXPR;
6241
              break;
6242
              }
6243
            if (operand)                /* if evaluation is true             */
6244
              pmac = macskip(pmac, nSkips); /* then skip the amount of lines */
6245
            }
6246
          }
6247
        if (!error)
6248
          skipit = 1;                   /* don't add this line!              */
6249
        break;
6250
      case PSEUDO_ELSE :                /* ELSE                              */
6251
        if (!suppress[ifcount])         /* if IF not suppressed              */
6252
          suppress[ifcount]++;          /* suppress ELSE clause              */
6253
        else                            /* otherwise                         */
6254
          suppress[ifcount]--;          /* decrement suppression             */
6255
        skipit = 1;                     /* don't add this line!              */
6256
        break;
6257
      case PSEUDO_ENDIF :               /* ENDIF                             */
6258
        if (ifcount)
6259
          ifcount--;
6260
        if (suppress[ifcount])
6261
          suppress[ifcount]--;
6262
        skipit = 1;                     /* don't add this line!              */
6263
        break;
6264
      }
6265
    }
6266
 
6267
  if (terminate)                        /* if macro termination needed       */
6268
    break;                              /* terminate here                    */
6269
 
6270
  if (!skipit && !suppress[ifcount])    /* if not skipping this one          */
6271
    {                                   /* add line to source                */
6272
    pcur = allocline(pcur, curline->fn, curline->ln, LINCAT_MACEXP, szLine);
6273
    if (!pcur)
6274
      {
6275
      error |= ERR_MALLOC;
6276
      break;
6277
      }
6278
    else
6279
      {
6280
      curline = pcur;
6281
      error = ERR_OK;
6282
      warning = WRN_OK;
6283
      expandtext();
6284
      processline();
6285
      }
6286
    }
6287
  pmac = pmac->next;
6288
  }
6289
 
6290
curline = cursave;
6291
expandtext();
6292
srcptr = srcsave;                       /* restore source pointer            */
6293
codeptr = 0;
6294
}
6295
 
6296
/*****************************************************************************/
6297
/* processline : processes a source line                                     */
6298
/*****************************************************************************/
6299
 
6300
void processline()
6301
{
6302
struct symrecord *lp, *lpmac;
6303
struct oprecord *op = NULL;
6304
__int64 co;
6305
short cat;
6306
short c;
6307
char noimm;
6308
 
6309
#if 0
6310
srcptr = curline->txt;
6311
#else
6312
srcptr = srcline;
6313
#endif
6314
 
6315
oldlc = loccounter;
6316
unknown = 0;
6317
certain = 1;
6318
lp = 0;
6319
codeptr = 0;
6320
condline = 0;
6321
isFar = 0;
6322
isFarkw = 0;
6323
 
6324
if (inMacro)
6325
  curline->lvl |= LINCAT_MACDEF;
6326
 
6327
if (isalnum(*srcptr))                   /* look for label on line start      */
6328
  {
6329
  scanname();
6330
  if (stricmp(namebuf, "far")==0) {
6331
          isFar = 1;
6332
          isFarkw = 1;
6333
          while(*srcptr==' ' || *srcptr=='\t') srcptr++;
6334
          scanname();
6335
  }
6336
  lp = findsym(namebuf, 1);
6337
  if (*srcptr == ':')
6338
    srcptr++;
6339
 
6340
  if ((lp) &&
6341
      (lp->cat != SYMCAT_COMMONDATA) &&
6342
      (lp->u.flags & SYMFLAG_FORWARD))
6343
    lp->u.flags |= SYMFLAG_PASSED;
6344
  }
6345
skipspace();
6346
if ((isalnum(*srcptr)) ||
6347
    ((dwOptions & OPTION_GAS) && (*srcptr == '.')))
6348
  {
6349
  scanname();
6350
  if ((dwOptions & OPTION_H63) &&       /* eventually adjust some mnemonics  */
6351
      ((!strcmp(unamebuf, "ASLD")) ||   /* that are available in the 6309    */
6352
       (!strcmp(unamebuf, "ASRD")) ||   /* but are implemented as (slower)   */
6353
       (!strcmp(unamebuf, "LSLD")) ||   /* convenience instructions on the   */
6354
       (!strcmp(unamebuf, "LSRD")) ||   /* 6809                              */
6355
       (!strcmp(unamebuf, "DECD")) ||
6356
       (!strcmp(unamebuf, "INCD")) ||
6357
       (!strcmp(unamebuf, "CLRD"))))
6358
    strcat(unamebuf, "63");
6359
  op = findop(unamebuf);
6360
  if (op)
6361
    {
6362
    if ((dwOptions & OPTION_TSC))       /* if TSC compatible, skip space NOW */
6363
      skipspace();                      /* since it's not allowed inside arg */
6364
    if (op->cat != OPCAT_PSEUDO)
6365
      {
6366
      setlabel(lp);
6367
      generating = 1;
6368
      }
6369
    co = op->code;
6370
    cat = op->cat;
6371
                                        /* only pseudo-ops in common mode!   */
6372
    if (common && (cat != OPCAT_PSEUDO))
6373
      error |= ERR_EXPR;
6374
 
6375
    noimm = cat & OPCAT_NOIMM;          /* isolate "no immediate possible"   */
6376
    cat &= ~OPCAT_NOIMM;
6377
        if (dwOptions & OPTION_X32)
6378
                isX32 = 1;
6379
        else
6380
                isX32 = 0;
6381
    if (dwOptions & OPTION_H63)         /* if in HD6309 mode,                */
6382
      cat &= ~OPCAT_6309;               /* mask out the 6309 flag (=allow)   */
6383
    switch (cat)
6384
      {
6385
      case OPCAT_ONEBYTE :
6386
        onebyte(co);
6387
        break;
6388
      case OPCAT_TWOBYTE :
6389
        twobyte(co);
6390
        break;
6391
      case OPCAT_THREEBYTE :
6392
        threebyte(co);
6393
        break;
6394
      case OPCAT_FOURBYTE :
6395
        fourbyte(co);
6396
        break;
6397
      case OPCAT_2IMMBYTE :             /* 6309 only                         */
6398
        putbyte((unsigned short)(co >> 12LL));
6399
        /* fall thru on purpose! */
6400
      case OPCAT_IMMBYTE :
6401
        oneimm(co);
6402
        break;
6403
      case OPCAT_LEA :
6404
        lea(co);
6405
        break;
6406
      case OPCAT_SBRANCH :
6407
        sbranch(co);
6408
        break;
6409
      case OPCAT_LBR2BYTE :
6410
        lbranch(co);
6411
        break;
6412
      case OPCAT_LBR1BYTE :
6413
        lbra(co);
6414
        break;
6415
      case OPCAT_2ARITH :               /* 6309 only                         */
6416
        putbyte((unsigned short)(co >> 12));
6417
        /* fall thru on purpose! */
6418
      case OPCAT_ARITH :
6419
        arith(co, noimm);
6420
        break;
6421
      case OPCAT_ACCARITH :             /* 6800-style arith                  */
6422
        accarith(co, noimm, 0);
6423
        break;
6424
      case OPCAT_DBLREG1BYTE :
6425
        darith(co, noimm, op->tgtNdx);
6426
        break;
6427
      case OPCAT_DBLREG2BYTE :
6428
        d2arith(co, noimm, op->tgtNdx);
6429
        break;
6430
      case OPCAT_SINGLEADDR :
6431
        oneaddr(co);
6432
        break;
6433
      case OPCAT_IREG :                 /* 6309 only                         */
6434
        putbyte((unsigned short)(co >> 12));
6435
        /* fall thru on purpose! */
6436
      case OPCAT_2REG :
6437
        tfrexg(co);
6438
        break;
6439
      case OPCAT_STACK :
6440
        pshpul(co);
6441
        break;
6442
      case OPCAT_BITDIRECT :            /* 6309 only                         */
6443
        bitdirect(co);
6444
        break;
6445
      case OPCAT_BITTRANS :             /* 6309 only                         */
6446
        bittrans(co);
6447
        break;
6448
      case OPCAT_BLOCKTRANS :           /* 6309 only                         */
6449
        blocktrans(co);
6450
        break;
6451
      case OPCAT_QUADREG1BYTE :
6452
        qarith(co, noimm);
6453
        break;
6454
      case OPCAT_IDXEXT :
6455
        idxextarith(co);
6456
        break;
6457
      case OPCAT_ACCADDR :
6458
        accaddr(co);
6459
        break;
6460
      case OPCAT_PSEUDO :
6461
        pseudoop(co, lp);
6462
        break;
6463
      default :
6464
        error |= ERR_ILLEGAL_MNEM;
6465
        break;
6466
      }
6467
    c = *srcptr;                        /* get current character             */
6468
    if (((dwOptions & OPTION_TSC) && (c == '*')) ||
6469
        ((dwOptions & OPTION_GAS) && (c == '|')) ||
6470
        (c == ';'))
6471
      c = '\0';
6472
    if (c != ' ' &&
6473
        *(srcptr - 1) != ' ' &&
6474
        c != '\0')
6475
      error |= ERR_ILLEGAL_ADDR;
6476
    }
6477
  else
6478
    {
6479
    lpmac = findsym(namebuf, 0);        /* look whether opcode is a macro    */
6480
    if (lpmac && lpmac->cat == SYMCAT_MACRO)
6481
      {
6482
      if (pass == 1)                    /* if in pass 1                      */
6483
        expandmacro(lp, lpmac);         /* expand macro below current line   */
6484
      }
6485
    else
6486
      error |= ERR_ILLEGAL_MNEM;
6487
    }
6488
  }
6489
else
6490
  {
6491
  nRepNext = 0;                         /* reset eventual repeat if no code  */
6492
  setlabel(lp);
6493
  }
6494
 
6495
if (inMacro)                            /* if in macro definition            */
6496
  {
6497
  codeptr = 0;                          /* ignore the code                   */
6498
  error &= (ERR_MALLOC | ERR_NESTING);  /* ignore most errors                */
6499
  warning &= WRN_SYM;                   /* ignore most warnings              */
6500
  }
6501
 
6502
if (pass == MAX_PASSNO)
6503
  {
6504
  outbuffer();
6505
  if ((listing & LIST_ON) &&
6506
      (dwOptions & OPTION_LIS))
6507
    outlist(op);
6508
  }
6509
else if ((listing & LIST_ON) &&
6510
         (dwOptions & OPTION_LIS) &&
6511
         (dwOptions & OPTION_LP1))
6512
  {
6513
  if (curline->lvl & LINCAT_MACEXP ||   /* prevent 2nd listing of macro      */
6514
      !curline->next ||                 /* since this is done in expansion   */
6515
      !(curline->next->lvl & LINCAT_MACEXP))
6516
    outlist(op);
6517
  }
6518
 
6519
if (error || warning)
6520
  report();
6521
loccounter += codeptr;
6522
}
6523
 
6524
/*****************************************************************************/
6525
/* suppressline : suppresses a line                                          */
6526
/*****************************************************************************/
6527
 
6528
void suppressline()
6529
{
6530
struct oprecord * op = NULL;
6531
 
6532
srcptr = srcline;
6533
oldlc = loccounter;
6534
codeptr = 0;
6535
condline = 0;
6536
if (nSkipCount > 0)
6537
  {
6538
  nSkipCount--;
6539
  condline = 1;                         /* this is STILL conditional         */
6540
  }
6541
else
6542
  {
6543
  if (isalnum(*srcptr))
6544
    {
6545
    scanname();
6546
    if (*srcptr == ':')
6547
      srcptr++;
6548
    }
6549
  skipspace();
6550
  scanname();
6551
  op = findop(unamebuf);
6552
  if (op && op->cat == OPCAT_PSEUDO)    /* examine pseudo-ops in detail      */
6553
    {
6554
    if ((op->code == PSEUDO_IF) ||      /* IF variants                       */
6555
        (op->code == PSEUDO_IFN) ||
6556
        (op->code == PSEUDO_IFC) ||
6557
        (op->code == PSEUDO_IFNC) ||
6558
        (op->code == PSEUDO_IFD) ||
6559
        (op->code == PSEUDO_IFND))
6560
      {
6561
      ifcount++;
6562
      condline = 1;                     /* this is a conditional line        */
6563
      }
6564
    else if (op->code == PSEUDO_ENDIF)  /* ENDIF                             */
6565
      {
6566
      if (ifcount > 0)
6567
        ifcount--;
6568
      else if (suppress == 1 || suppress == 2)
6569
        suppress = 0;
6570
      condline = 1;                     /* this is a conditional line        */
6571
      }
6572
    else if (op->code == PSEUDO_ELSE)   /* ELSE                              */
6573
      {
6574
      if (ifcount == 0 && suppress == 2)
6575
        suppress = 0;
6576
      condline = 1;                     /* this is a conditional line        */
6577
      }
6578
    }
6579
  }
6580
 
6581
if (((pass == MAX_PASSNO) || (dwOptions & OPTION_LP1)) &&
6582
    (listing & LIST_ON) &&
6583
    (dwOptions & OPTION_LIS))
6584
  outlist(op);
6585
}
6586
 
6587
/*****************************************************************************/
6588
/* usage : prints out correct usage                                          */
6589
/*****************************************************************************/
6590
 
6591
void usage(char *nm)
6592
{
6593
printf("Usage: %s [-option*] srcname*\n",
6594
       nm ? nm : "a09");
6595
printf("Available options are:\n");
6596
printf("-B[objname] ........ output to binary file (default)\n");
6597
printf("-F[objname] ........ output to FLEX binary file\n");
6598
/* printf("-G[objname] ........ output Gnu .o format file\n"); */
6599
printf("-R[objname] ........ output to FLEX relocatable object file\n");
6600
printf("-S[objname] ........ output to Motorola S51-09 file\n");
6601
printf("-X[objname] ........ output to Intel Hex file\n");
6602
printf("-L[listname] ....... create listing file \n");
6603
printf("-V[objname]......... output Verilog rommem declarations \n");
6604
printf("-C ................. suppress code output\n");
6605
printf("-Dsymbol[=value] ... predefines a symbol\n");
6606
printf("                     for TSC 6809 Assembler compatibility,\n");
6607
printf("                     you should only use symbols A through C\n");
6608
printf("-Ooption ........... sets an option (as in OPT pseudoop)\n");
6609
printf("-W ................. suppress warnings\n");
6610
printf("srcname ............ source file name(s)\n");
6611
 
6612
exit(2);
6613
}
6614
 
6615
/*****************************************************************************/
6616
/* getoptions : retrieves the options from the passed argument array         */
6617
/*****************************************************************************/
6618
 
6619
void getoptions (int argc, char* argv[])
6620
{
6621
int i, j;
6622
char *ld;
6623
 
6624
for (i = 1; i < argc; i++)
6625
  {
6626
#if !UNIX
6627
  /* code for DOS / Windows / OS2 */
6628
  if ((argv[i][0] == '-') ||
6629
      (argv[i][0] == '/'))
6630
#else
6631
  /* code for UNIX derivates */
6632
  if (argv[i][0] == '-')
6633
#endif
6634
    {
6635
    for (j = 1; j < (int)strlen(argv[i]); j++)
6636
      {
6637
      switch (tolower(argv[i][j]))
6638
        {
6639
        case 'c' :                      /* suppress code output              */
6640
          outmode = OUT_NONE;
6641
          break;
6642
        case 'b' :                      /* define binary output file         */
6643
        case 's' :                      /* define Motorola output file       */
6644
        case 'x' :                      /* define Intel Hex output file      */
6645
        case 'f' :                      /* define FLEX output file           */
6646
        case 'r' :                      /* define FLEX relocatable output f. */
6647
                case 'v' :
6648
    /*  case 'g' : */                   /* define GNU output file            */
6649
          strcpy(objname,               /* copy in the name                  */
6650
                  argv[i] + j + 1);
6651
          switch (tolower(argv[i][j]))  /* then set output mode              */
6652
            {
6653
            case 'b' :
6654
              outmode = OUT_BIN;
6655
              break;
6656
            case 's' :
6657
              outmode = OUT_SREC;
6658
              break;
6659
            case 'x' :
6660
              outmode = OUT_IHEX;
6661
              break;
6662
            case 'f' :
6663
              outmode = OUT_FLEX;
6664
              break;
6665
                        case 'v':
6666
                                outmode = OUT_VER;
6667
                                break;
6668
/*
6669
            case 'g' :
6670
              outmode = OUT_GAS;
6671
              relocatable = 1;
6672
              dwOptions |= OPTION_REL;
6673
              break;
6674
*/
6675
            case 'r' :
6676
              outmode = OUT_REL;
6677
              maxidlen = 8;             /* only 8 significant ID chars!      */
6678
              relocatable = 1;
6679
              absmode = 0;
6680
              break;
6681
            }
6682
          j = strlen(argv[i]);          /* advance behind copied name        */
6683
          break;
6684
        case 'l' :                      /* define listing file               */
6685
          strcpy(listname,              /* copy in the name                  */
6686
                  argv[i] + j + 1);
6687
          j = strlen(argv[i]);          /* advance behind copied name        */
6688
          listing = LIST_ON;            /* remember we're listing            */
6689
          break;
6690
        case 'd' :                      /* define a symbol ?                 */
6691
          srcptr = argv[i] + j + 1;     /* parse in the name                 */
6692
          scanname();
6693
          if (!namebuf[0])              /* if no name there                  */
6694
            usage(argv[0]);             /* show usage and get out            */
6695
          if (*srcptr == '=')           /* if followed by value              */
6696
            srcptr++;                   /* advance behind it                 */
6697
          else                          /* otherwise go to ""                */
6698
            srcptr = argv[i] + strlen(argv[i]);
6699
          settext(namebuf, srcptr);     /* define the symbol                 */
6700
          j = strlen(argv[i]);          /* advance behind copied name        */
6701
          break;
6702
        case 'o' :                      /* option                            */
6703
          if (setoption(argv[i] + j + 1))
6704
            usage(argv[0]);
6705
          j = strlen(argv[i]);          /* advance behind option             */
6706
          break;
6707
        }
6708
      }
6709
    for (j = i; j < argc; j++)          /* remove all consumed arguments     */
6710
      argv[j] = argv[j + 1];
6711
    argc--;                             /* reduce # arguments                */
6712
    i--;                                /* and restart with next one         */
6713
    }
6714
  }
6715
 
6716
if (argc < 2)                           /* if not at least one filename left */
6717
  usage(argv[0]);                       /* complain & terminate              */
6718
 
6719
strcpy(srcname, argv[1]);               /* copy it in.                       */
6720
 
6721
if (!objname[0])                        /* if no object name defined         */
6722
  {
6723
  strcpy(objname, srcname);             /* copy in the source name           */
6724
  ld = strrchr(objname, '.');           /* look whether there's a dot in it  */
6725
  if (!ld)                              /* if not                            */
6726
    ld = objname + strlen(objname);     /* append extension                  */
6727
  switch (outmode)                      /* which output mode?                */
6728
    {
6729
    case OUT_BIN :                      /* binary ?                          */
6730
#if !UNIX
6731
      strcpy(ld, ".bin");               /* DOS / Windows / OS2               */
6732
#else
6733
      strcpy(ld, ".b");                 /* UNIX                              */
6734
#endif
6735
      break;
6736
    case OUT_SREC :                     /* Motorola S51-09 ?                 */
6737 22 robfinch
      strcpy(ld, ".c19");
6738 4 robfinch
      break;
6739
    case OUT_IHEX :                     /* Intel Hex ?                       */
6740
      strcpy(ld, ".hex");
6741
      break;
6742
    case OUT_FLEX :                     /* FLEX binary ?                     */
6743
      strcpy(ld, ".bin");
6744
      break;
6745
    case OUT_GAS :                      /* GNU relocatable object ?          */
6746
      strcpy(ld, ".o");
6747
      break;
6748
    case OUT_REL :                      /* Flex9 relocatable object ?        */
6749
      strcpy(ld, ".rel");
6750
      break;
6751
    case OUT_VER :                     /* Verilog texr                     */
6752
      strcpy(ld, ".ver");
6753
      break;
6754
    }
6755
  }
6756
 
6757
if ((listing & LIST_ON) && !listname[0])/* if no list file specified         */
6758
  {
6759
  strcpy(listname, srcname);            /* copy in the source name           */
6760
  ld = strrchr(listname, '.');          /* look whether there's a dot in it  */
6761
  if (!ld)                              /* if not                            */
6762
    ld = listname + strlen(listname);   /* append extension                  */
6763
  strcpy(ld, ".lst");                   /* .lst                              */
6764
  }
6765
}
6766
 
6767
/*****************************************************************************/
6768
/* processfile : processes the input file                                    */
6769
/*****************************************************************************/
6770
 
6771
void processfile(struct linebuf *pline)
6772
{
6773
struct linebuf *plast = pline;
6774
vercount = 0;
6775
while (!terminate && pline)
6776
  {
6777
  curline = pline;
6778
  error = ERR_OK;
6779
  warning = WRN_OK;
6780
  expandtext();                         /* expand text symbols               */
6781
  srcptr = srcline;
6782
  if (suppress || nSkipCount)
6783
    suppressline();
6784
  else
6785
    {
6786
    if (nRepNext)
6787
      {
6788
      for (; nRepNext > 0; nRepNext--)
6789
        {
6790
        processline();
6791
        error = ERR_OK;
6792
        warning = WRN_OK;
6793
        }
6794
      nRepNext = 0;
6795
      }
6796
    else
6797
      {
6798
      if (pass != 1 ||
6799
          !(curline->lvl & LINCAT_MACEXP))
6800
        processline();
6801
      error = ERR_OK;
6802
      warning = WRN_OK;
6803
      }
6804
    }
6805
  plast = pline;
6806
  pline = pline->next;
6807
  }
6808
 
6809
if (suppress)
6810
  {
6811
  printf("%s(%ld) : error 18: improperly nested IF statements\n",
6812
         expandfn(plast->fn), plast->ln);
6813
  if (((dwOptions & OPTION_LP1) || pass == MAX_PASSNO) &&
6814
      (listing & LIST_ON))
6815
    putlist( "*** Error 18: improperly nested IF statements\n");
6816
  errors++;
6817
  suppress = 0;
6818
  }
6819
 
6820
if (common)
6821
  {
6822
  printf("%s(%ld) : error 24: improperly nested COMMON statements\n",
6823
         expandfn(plast->fn), plast->ln);
6824
  if (((dwOptions & OPTION_LP1) || pass == MAX_PASSNO) &&
6825
      (listing & LIST_ON))
6826
    putlist( "*** Error 24: improperly nested COMMON statements\n");
6827
  errors++;
6828
  common = 0;
6829
  }
6830
}
6831
 
6832
void dopass(int passno, int lastpass)
6833
{
6834
        int i;
6835
        char buf[4];
6836
        sprintf(buf, "%d", passno);
6837
pass = passno;
6838
settext("PASS", buf);
6839
loccounter = 0;
6840
errors = 0;
6841
warnings = 0;
6842
generating = 0;
6843
terminate = 0;
6844
 
6845
for (i = 0; i < symcounter; i++)        /* reset all PASSED flags            */
6846
  if (symtable[i].cat != SYMCAT_COMMONDATA)
6847
    symtable[i].u.flags &= ~SYMFLAG_PASSED;
6848
 
6849
if (lastpass) {
6850
        if (listing & LIST_ON)
6851
        {
6852
        if ((dwOptions & OPTION_LP1))
6853
                {
6854
                if (dwOptions & OPTION_PAG)
6855
                PageFeed();
6856
                else
6857
                putlist("\n");
6858
                putlist( "*** Pass 2 ***\n\n");
6859
                }
6860
        else if (nTotErrors || nTotWarnings)
6861
                putlist( "%ld error(s), %ld warning(s) unlisted in pass 1\n",
6862
                                nTotErrors, nTotWarnings);
6863
        }
6864
 
6865
        if ((outmode >= OUT_BIN) &&
6866
                ((objfile = fopen(objname,
6867
                                                ((outmode != OUT_SREC) && (outmode != OUT_IHEX)) ? "wb" : "w"))
6868
                                                == 0))
6869
        {
6870
        printf("%s(0) : error 20: cannot write object file %s\n", srcname, objname);
6871
        if (((dwOptions & OPTION_LP1) || pass == MAX_PASSNO) && (listing & LIST_ON))
6872
                putlist( "*** Error 20: cannot write object file %s\n", objname);
6873
        exit(4);
6874
        }
6875
 
6876
        if (outmode == OUT_REL)                 /* if writing FLEX Relocatable       */
6877
        {
6878
        writerelcommon();                     /* write out common blocks           */
6879
        relhdrfoff = ftell(objfile);
6880
        writerelhdr(0);                       /* write out initial header          */
6881
        }
6882
        }
6883
        processfile(rootline);
6884
 
6885
        if (errors)
6886
        {
6887
        printf("%ld error(s) in pass %d\n", errors, passno);
6888
        nTotErrors += errors;
6889
        }
6890
        if (warnings)
6891
        {
6892
        printf("%ld warning(s) in pass %d\n", warnings, passno);
6893
        nTotWarnings += warnings;
6894
        }
6895
 
6896
}
6897
 
6898
/*****************************************************************************/
6899
/* main : the main function                                                  */
6900
/*****************************************************************************/
6901
 
6902
int main (int argc, char *argv[])
6903
{
6904
int i;
6905
struct linebuf *pLastLine = NULL;
6906
 
6907
settext("ASM", "A09");                  /* initialize predefined texts       */
6908
settext("VERSION", VERSNUM);
6909
settext("PASS", "1");
6910
setoptiontexts();
6911
nPredefinedTexts = nTexts;
6912
 
6913
getoptions(argc, argv);
6914
pass = 1;
6915
error = 0;
6916
warning = 0;
6917
nTotErrors = errors = 0;
6918
nTotWarnings = warnings = 0;
6919
generating = 0;
6920
common = 0;
6921
terminate = 0;
6922
if (!absmode)                           /* in relocating mode                */
6923
  dpsetting = -1;                       /* there IS no Direct Page           */
6924
 
6925
printf("A09 Assembler V" VERSION "\n");
6926
 
6927
if ((listing & LIST_ON) &&
6928
    ((listfile = fopen(listname, "w")) == 0))
6929
  {
6930
  printf("%s(0) : error 19: Cannot open list file %s\n", srcname, listname);
6931
  exit(4);
6932
  }
6933
 
6934
for (i = 1; argv[i]; i++)               /* read in all source files          */
6935
  pLastLine = readfile(argv[i], 0, pLastLine);
6936
if (!rootline)                          /* if no lines in there              */
6937
  {
6938
  printf("%s(0) : error 23: no source lines in file\n", srcname);
6939
  if (((dwOptions & OPTION_LP1) || pass == MAX_PASSNO) &&
6940
      (listing & LIST_ON))
6941
    putlist( "*** Error 23: no source lines in file\n");
6942
  exit(4);
6943
  }
6944
 
6945
                                        /* Pass 1 - parse all symbols        */
6946
if ((listing & LIST_ON) && (dwOptions & OPTION_LP1))
6947
  putlist( "*** Pass 1 ***\n\n");
6948
 
6949
processfile(rootline);
6950
if (errors)
6951
  {
6952
  printf("%ld error(s) in pass 1\n",errors);
6953
  if ((listing & LIST_ON) && (dwOptions & OPTION_LP1))
6954
    putlist( "%ld error(s) in pass 1.\n", errors);
6955
  nTotErrors = errors;
6956
  }
6957
if (warnings)
6958
  {
6959
  printf("%ld warning(s) in pass 1\n", warnings);
6960
  if ((listing & LIST_ON) && (dwOptions & OPTION_LP1))
6961
    putlist(
6962
            "%ld warning(s) in pass 1.\n", warnings);
6963
  nTotWarnings = warnings;
6964
  }
6965
 
6966
// Resolve potential phasing errors by performing multiple passes.
6967
dopass(2,0);
6968
dopass(3,0);
6969
dopass(4,0);
6970
dopass(5,0);
6971
dopass(6,0);
6972
dopass(7,0);
6973
dopass(8,0);
6974
dopass(9,1);
6975
//                                       /* Pass 2 - generate output          */
6976
//settext("PASS", "3");
6977
//loccounter = 0;
6978
//errors = 0;
6979
//warnings = 0;
6980
//generating = 0;
6981
//terminate = 0;
6982
////memset(bUsedBytes, 0, sizeof(bUsedBytes));
6983
//for (i = 0; i < symcounter; i++)        /* reset all PASSED flags            */
6984
//  if (symtable[i].cat != SYMCAT_COMMONDATA)
6985
//    symtable[i].u.flags &= ~SYMFLAG_PASSED;
6986
//
6987
//if (listing & LIST_ON)
6988
//  {
6989
//  if ((dwOptions & OPTION_LP1))
6990
//    {
6991
//    if (dwOptions & OPTION_PAG)
6992
//      PageFeed();
6993
//    else
6994
//      putlist("\n");
6995
//    putlist( "*** Pass 2 ***\n\n");
6996
//    }
6997
//  else if (nTotErrors || nTotWarnings)
6998
//    putlist( "%ld error(s), %ld warning(s) unlisted in pass 1\n",
6999
//            nTotErrors, nTotWarnings);
7000
//  }
7001
//
7002
//if ((outmode >= OUT_BIN) &&
7003
//    ((objfile = fopen(objname,
7004
//                     ((outmode != OUT_SREC) && (outmode != OUT_IHEX)) ? "wb" : "w"))
7005
//                     == 0))
7006
//  {
7007
//  printf("%s(0) : error 20: cannot write object file %s\n", srcname, objname);
7008
//  if (((dwOptions & OPTION_LP1) || pass == 2) && (listing & LIST_ON))
7009
//    putlist( "*** Error 20: cannot write object file %s\n", objname);
7010
//  exit(4);
7011
//  }
7012
//
7013
//if (outmode == OUT_REL)                 /* if writing FLEX Relocatable       */
7014
//  {
7015
//  writerelcommon();                     /* write out common blocks           */
7016
//  relhdrfoff = ftell(objfile);
7017
//  writerelhdr(0);                       /* write out initial header          */
7018
//  }
7019
//
7020
//processfile(rootline);
7021
//
7022
//if (errors)
7023
//  {
7024
//  printf("%ld error(s) in pass 2\n", errors);
7025
//  nTotErrors += errors;
7026
//  }
7027
//if (warnings)
7028
//  {
7029
//  printf("%ld warning(s) in pass 2\n", warnings);
7030
//  nTotWarnings += warnings;
7031
//  }
7032
 
7033
if (listing & LIST_ON)
7034
  {
7035
  if (errors || warnings)
7036
    putlist("\n");
7037
  if (errors)
7038
    putlist( "%ld error(s) in pass 2.\n", errors);
7039
  if (warnings)
7040
    putlist( "%ld warning(s) in pass 2.\n", warnings);
7041
  if (dwOptions & OPTION_SYM)
7042
    outsymtable();
7043
  if ((relocatable) && (dwOptions & OPTION_REL))
7044
    outreltable();
7045
  if ((dwOptions & OPTION_TXT) &&
7046
      (nPredefinedTexts < nTexts))
7047
    outtexttable();
7048
 
7049
  putlist( "\n%ld error(s), %ld warning(s)\n",
7050
          nTotErrors, nTotWarnings);
7051
  fclose(listfile);
7052
  }
7053
else
7054
  printf("Last assembled address: %04X\n", loccounter - 1);
7055
 
7056
switch (outmode)                        /* look whether object cleanup needed*/
7057
  {
7058
case OUT_VER:
7059
        flushver();
7060
        break;
7061
  case OUT_SREC :                       /* Motorola S51-09                   */
7062
    flushhex();
7063 16 robfinch
    chksum = (tfradr & 0xfff) + ((tfradr >> 12) & 0xfff) + 3;
7064 22 robfinch
    fprintf(objfile, "C9003%06X%03X\n", tfradr, 0xfff - (chksum & 0xfff));
7065 4 robfinch
    break;
7066
  case OUT_IHEX :                       /* Intel Hex                         */
7067
    flushihex();
7068
#if 0
7069
    /* put transfer address in here... unfortunately, the official
7070
       Intel documentation doesn't allow this mechanism */
7071
    chksum = ((tfradr >> 8) & 0xff) + (tfradr & 0xff) + 1;
7072
    fprintf(objfile, ":00%04X01%02X\n", tfradr, (-(signed)chksum) & 0xff);
7073
#else
7074
    fprintf(objfile, ":00000001FF\n");
7075
#endif
7076
    break;
7077
  case OUT_FLEX :                       /* FLEX binary                       */
7078
    flushflex();
7079
    if (tfradrset)                      /* if transfer address set           */
7080
      {                                 /* write out transfer address block  */
7081
      fputc(0x16, objfile);
7082
      fputc((tfradr >> 8) & 0xff, objfile);
7083
      fputc(tfradr & 0xff, objfile);
7084
      }
7085
    break;
7086
  case OUT_REL :                        /* FLEX Relocatable                  */
7087
    writerelext();                      /* write out External table          */
7088
    writerelglobal();                   /* write out Global table            */
7089
    writerelmodname();                  /* write out Module Name             */
7090
 
7091
    i = (int)ftell(objfile);            /* fill last sector with zeroes      */
7092
    while (i % 252)
7093
      {
7094
      fputc(0, objfile);
7095
      i++;
7096
      }
7097
                                        /* reposition on header              */
7098
    fseek(objfile, relhdrfoff, SEEK_SET);
7099
    writerelhdr(0);                     /* rewrite completed header          */
7100
    break;
7101
  }
7102
 
7103
if (objfile)
7104
  fclose(objfile);
7105
 
7106
if (errors)
7107
  unlink(objname);
7108
 
7109
return (errors) ? 1 : 0;
7110
}

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.