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

Subversion Repositories rf6809

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

Go to most recent revision | 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
               OPCAT_IREG,        0x1031, 0 },
383
  { "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
               OPCAT_2ARITH,      0x118b, 0 },
389
  { "ADDF",    OPCAT_6309 |
390
               OPCAT_2ARITH,      0x11cb, 0 },
391
  { "ADDR",    OPCAT_6309 |
392
               OPCAT_IREG,        0x1030, 0 },
393
  { "ADDW",    OPCAT_6309 |
394
               OPCAT_DBLREG2BYTE, 0x108b, 0 },
395
  { "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
               OPCAT_IREG,        0x1034, 0 },
405
  { "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
               OPCAT_TWOBYTE,     0x1048, 0 },
411
  { "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
               OPCAT_TWOBYTE,     0x1047, 0 },
417
  { "BAND",    OPCAT_6309 |
418
               OPCAT_BITTRANS,    0x1130, 0 },
419
  { "BCC",     OPCAT_SBRANCH,     0x24, 0 },
420
  { "BCS",     OPCAT_SBRANCH,     0x25, 0 },
421
  { "BEC",     OPCAT_SBRANCH,     0x24, 0 },
422
  { "BEOR",    OPCAT_6309 |
423
               OPCAT_BITTRANS,    0x1134, 0 },
424
  { "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
               OPCAT_BITTRANS,    0x1131, 0 },
432
  { "BIEOR",   OPCAT_6309 |
433
               OPCAT_BITTRANS,    0x1135, 0 },
434
  { "BIN",     OPCAT_PSEUDO,      PSEUDO_BINARY, 0 },
435
  { "BINARY",  OPCAT_PSEUDO,      PSEUDO_BINARY, 0 },
436
  { "BIOR",    OPCAT_6309 |
437
               OPCAT_BITTRANS,    0x1133, 0 },
438
  { "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
               OPCAT_2IMMBYTE,    0x113c, 0 },
445
  { "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
               OPCAT_BITTRANS,    0x1132, 0 },
453
  { "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
               OPCAT_TWOBYTE,     0x104f, 0 },
470
  { "CLRE",    OPCAT_6309 |
471
               OPCAT_TWOBYTE,     0x114f, 0 },
472
  { "CLRF",    OPCAT_6309 |
473
               OPCAT_TWOBYTE,     0x115f, 0 },
474
  { "CLRW",    OPCAT_6309 |
475
               OPCAT_TWOBYTE,     0x105f, 0 },
476
  { "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
               OPCAT_2ARITH,      0x1181, 0 },
484
  { "CMPF",    OPCAT_6309 |
485
               OPCAT_2ARITH,      0x11c1, 0 },
486
  { "CMPR",    OPCAT_6309 |
487
               OPCAT_IREG,        0x1037, 0 },
488
  { "CMPS",    OPCAT_DBLREG1BYTE, 0x28c, 4 },
489
  { "CMPU",    OPCAT_DBLREG1BYTE, 0x283, 3 },
490
  { "CMPW",    OPCAT_6309 |
491
               OPCAT_DBLREG2BYTE, 0x1081, 0 },
492
  { "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
               OPCAT_TWOBYTE,     0x1143, 0  },
501
  { "COMF",    OPCAT_6309 |
502
               OPCAT_TWOBYTE,     0x1153, 0 },
503
  { "COMW",    OPCAT_6309 |
504
               OPCAT_TWOBYTE,     0x1053, 0 },
505
  { "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
               OPCAT_TWOBYTE,     0x104a, 0 },
517
  { "DECE",    OPCAT_6309 |
518
               OPCAT_TWOBYTE,     0x114a, 0 },
519
  { "DECF",    OPCAT_6309 |
520
               OPCAT_TWOBYTE,     0x115a, 0 },
521
  { "DECW",    OPCAT_6309 |
522
               OPCAT_TWOBYTE,     0x105a, 0 },
523
  { "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
               OPCAT_2ARITH,      0x118d, 0 },
531
  { "DIVQ",    OPCAT_6309 |
532
               OPCAT_DBLREG2BYTE, 0x118e, 0 },
533
  { "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
               OPCAT_IREG,        0x1036, 0 },
550
  { "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
               OPCAT_TWOBYTE,     0x104c, 0 },
574
  { "INCE",    OPCAT_6309 |
575
               OPCAT_TWOBYTE,     0x114c, 0 },
576
  { "INCF",    OPCAT_6309 |
577
               OPCAT_TWOBYTE,     0x115c, 0 },
578
  { "INCLUDE", OPCAT_PSEUDO,      PSEUDO_INCLUDE, 0 },
579
  { "INCW",    OPCAT_6309 |
580
               OPCAT_TWOBYTE,     0x105c, 0 },
581
  { "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
               OPCAT_BITTRANS,    0x1136, 0 },
616
  { "LDD",     OPCAT_DBLREG1BYTE, 0xcc, 0 },
617
  { "LDE",     OPCAT_6309 |
618
               OPCAT_2ARITH,      0x1186, 0 },
619
  { "LDF",     OPCAT_6309 |
620
               OPCAT_2ARITH,      0x11c6, 0 },
621
  { "LDMD",    OPCAT_6309 |
622
               OPCAT_2IMMBYTE,    0x113d, 0 },
623
  { "LDQ",     OPCAT_6309 |
624
               OPCAT_QUADREG1BYTE,0x10cc, 0 },
625
  { "LDS",     OPCAT_DBLREG1BYTE, 0x1ce, 4 },
626
  { "LDU",     OPCAT_DBLREG1BYTE, 0xce, 3 },
627
  { "LDW",     OPCAT_6309 |
628
               OPCAT_DBLREG2BYTE, 0x1086, 0 },
629
  { "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
               OPCAT_TWOBYTE,     0x1048, 0 },
643
  { "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
               OPCAT_TWOBYTE,     0x1044, 0 },
649
  { "LSRW",    OPCAT_6309 |
650
               OPCAT_TWOBYTE,     0x1054, 0 },
651
  { "MACRO",   OPCAT_PSEUDO,      PSEUDO_MACRO, 0 },
652
  { "MUL",     OPCAT_ONEBYTE,     0x3d, 0 },
653
  { "MULD",    OPCAT_6309 |
654
               OPCAT_DBLREG2BYTE, 0x118f, 0 },
655
  { "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
               OPCAT_IREG,        0x1035, 0 },
677
  { "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
               OPCAT_TWOBYTE,     0x1038, 0 },
686
  { "PSHU",    OPCAT_STACK,       0x36, 3 },
687
  { "PSHUW",   OPCAT_6309 |
688
               OPCAT_TWOBYTE,     0x103a, 0 },
689
  { "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
               OPCAT_TWOBYTE,     0x1039, 0 },
700
  { "PULU",    OPCAT_STACK,       0x37, 3 },
701
  { "PULUW",   OPCAT_6309 |
702
               OPCAT_TWOBYTE,     0x103b, 0 },
703
  { "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
               OPCAT_TWOBYTE,     0x1059, 0 },
717
  { "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
               OPCAT_TWOBYTE,     0x1056, 0 },
724
  { "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
               OPCAT_IREG,        0x1033, 0 },
737
  { "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
               OPCAT_BITTRANS,    0x1137, 0 },
763
  { "STD",     OPCAT_NOIMM |
764
               OPCAT_DBLREG1BYTE, 0xcd, 0 },
765
  { "STE",     OPCAT_NOIMM |
766
               OPCAT_6309 |
767
               OPCAT_2ARITH,      0x1187, 0 },
768
  { "STF",     OPCAT_NOIMM |
769
               OPCAT_6309 |
770
               OPCAT_2ARITH,      0x11c7, 0 },
771
  { "STQ",     OPCAT_NOIMM |
772
               OPCAT_6309 |
773
               OPCAT_QUADREG1BYTE,0x10cd, 0 },
774
  { "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
               OPCAT_DBLREG2BYTE, 0x1087, 0 },
782
  { "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
               OPCAT_2ARITH,      0x1180, 0 },
792
  { "SUBF",    OPCAT_6309 |
793
               OPCAT_2ARITH,      0x11c0, 0 },
794
  { "SUBW",    OPCAT_6309 |
795
               OPCAT_DBLREG2BYTE, 0x1080, 0 },
796
  { "SUBR",    OPCAT_6309 |
797
               OPCAT_IREG,        0x1032, 0 },
798
  { "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
               OPCAT_BLOCKTRANS,  0x1138, 0 },
809
  { "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
               OPCAT_TWOBYTE,     0x114d, 0 },
821
  { "TSTF",    OPCAT_6309 |
822
               OPCAT_TWOBYTE,     0x115d, 0 },
823
  { "TSTW",    OPCAT_6309 |
824
               OPCAT_TWOBYTE,     0x105d, 0 },
825
  { "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
unsigned short tfradr = 0;
1467
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
      postbyte += (operand & 511);
2880
      opsize = 0;
2881
      break;
2882
    case 2:
2883
      postbyte += 0x808;
2884
      break;
2885
    case 3:
2886
      postbyte += 0x809;
2887
      break;
2888
        case 4:
2889
          postbyte += 0x80A;
2890
          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
  postbyte += 0x80c;
2911
  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
 
2928
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
  }
2948
switch (toupper(c))
2949
  {
2950
  case 'D':
2951
    accpost = 0x80b;
2952
  accoffset:
2953
    oldsrcptr = srcptr;
2954
    srcptr++;
2955
    if (!(dwOptions & OPTION_TSC))
2956
      skipspace();
2957
    if (*srcptr != ',')
2958
      RESTORE
2959
    else
2960
      {
2961
                  isIndexed = 1;
2962
      if ((h63) && (!(dwOptions & OPTION_H63)))
2963
        error |= ERR_ILLEGAL_ADDR;
2964
      postbyte = accpost;
2965
      srcptr++;
2966
      if (!scanindexreg())
2967
        RESTORE
2968
      else
2969
        {
2970
        srcptr++;
2971
        set3();
2972
        }
2973
      }
2974
    break;
2975
  case 'A':
2976
    accpost = 0x806;
2977
    goto accoffset;
2978
  case 'B':
2979
    accpost = 0x805;
2980
    goto accoffset;
2981
  case 'E':
2982
    accpost = 0x807;
2983
    h63 = 1;
2984
    goto accoffset;
2985
  case 'F':
2986
          if (toupper(srcptr[1])=='A' && toupper(srcptr[2])=='R' && (srcptr[3]==' '||srcptr[3]=='\t')) {
2987
                  isFar = 1;
2988
                  isFarkw = 1;
2989
                  srcptr += 3;
2990
                  goto scano1;
2991
          }
2992
    accpost = 0x80a;
2993
    h63 = 1;
2994
    goto accoffset;
2995
  case 'W' :
2996
    accpost = 0x80e;
2997
    h63 = 1;
2998
    goto accoffset;
2999
  case ',':
3000
    srcptr++;
3001
    scanspecial();
3002
    break;
3003
  case '#':
3004
    if (mode == ADRMODE_IND)
3005
      error |= ERR_ILLEGAL_ADDR;
3006
    else
3007
      mode = ADRMODE_IMM;
3008
    srcptr++;
3009
        if (*srcptr=='>') {
3010
                srcptr++;
3011
            operand = (scanexpr(0, pp) >> 24LL) & 0xffffffLL;
3012
                isFar = 0;
3013
                opsize = 3;
3014
        }
3015
        else if (*srcptr=='<') {
3016
                srcptr++;
3017
            operand = scanexpr(0, pp) & 0xffffffLL;
3018
                isFar = 0;
3019
                opsize = 3;
3020
        }
3021
        else
3022
                operand = scanexpr(0, pp);
3023
    break;
3024
  case '<':
3025
    srcptr++;
3026
    if (*srcptr == '<')
3027
      {
3028
      srcptr++;
3029
      opsize = 1;
3030
      }
3031
    else
3032
      opsize = 2;
3033
    goto dodefault;
3034
  case '>':
3035
    srcptr++;
3036
    opsize = 3;
3037
    /* fall thru on purpose */
3038
  default:
3039
  dodefault:
3040
    operand = scanexpr(0, pp);
3041
    if (!(dwOptions & OPTION_TSC))
3042
      skipspace();
3043
    if (*srcptr == ',')
3044
      {
3045
                  isIndexed = 1;
3046
      srcptr++;
3047
      if (!(dwOptions & OPTION_TSC))
3048
        skipspace();
3049
      if ((operand == 0) &&             /* special for "0,-[-]indexreg       */
3050
          (!unknown) && (certain) &&    /*         and "0,indexreg[+[+]]     */
3051
          (opsize < 3) &&               /* but NOT for ">0,indexreg"!        */
3052
          ((*srcptr == '-') ||
3053
           (scanindexreg() /* && (srcptr[1] == '+') */ )))
3054
        scanspecial();
3055
      else
3056
        scanindexed();
3057
      }
3058
    else
3059
      {
3060
      if (opsize == 0)
3061
        {
3062
        if ((unsigned)operand >= 16777216)
3063
                      opsize = 4;
3064
              else
3065
        if (unknown || !certain || dpsetting == -1 ||
3066
          (unsigned)(operand - dpsetting * 4096) >= 4096)
3067
          opsize = 3;
3068
        else
3069
          opsize = 2;
3070
        }
3071
      /*
3072
      if (opsize == 4) {
3073
        if ((operand & 0xff800000) == 0xff800000)
3074
          opsize = 3;
3075
        else if ((operand & 0xff800000) == 0x0)
3076
          opsize = 3;
3077
      }
3078
      */
3079
      if (opsize == 1)
3080
        opsize = 2;
3081
      if (mode == ADRMODE_IND)
3082
        {
3083
        postbyte = 0x80f;
3084
                // Why is the following set ?
3085
//        opsize = 3;
3086
        }
3087
          else if (mode == ADRMODE_DBL_IND)
3088
                  ;
3089
          else {
3090
                  switch(opsize) {
3091
                case 2: mode = ADRMODE_DIR; break;
3092
                case 3: mode = ADRMODE_EXT; break;
3093
//              case 4:
3094
                case 4: mode = ADRMODE_EXT; isFar = 1; break;
3095
                default: mode = opsize - 1;
3096
                  }
3097
          }
3098
      }
3099
  }
3100
 
3101
if (mode >= ADRMODE_IND)
3102
  {
3103
  if (!(dwOptions & OPTION_TSC))
3104
    skipspace();
3105
  if (mode != ADRMODE_DBL_IND)
3106
        postbyte |= 0x100;
3107
  if (*srcptr != ']')
3108
    error |= ERR_ILLEGAL_ADDR;
3109
  srcptr++;
3110
  if (mode==ADRMODE_DBL_IND) {
3111
          if (*srcptr != ']')
3112
                error |= ERR_ILLEGAL_ADDR;
3113
          srcptr++;
3114
  }
3115
  }
3116
  skipspace();
3117
  if (*srcptr==',') {
3118
          srcptr++;
3119
          isPostIndexed = 1;
3120
      scanindexed();    // scanindexed will reset the postbyte
3121
          postbyte |= 0x100;
3122
  }
3123
  else {
3124
          if (postbyte==0x90F || postbyte==0x80F)
3125
                  opsize = 3;
3126
      if (mode == ADRMODE_IND || mode==ADRMODE_DBL_IND)
3127
        {
3128
/*
3129
                        if ((postbyte & 0xF)==4)        // 0 offset
3130
                                opsize = 0;
3131
                //      else if ((postbyte & 0xf)==8 || (postbyte & 0xF)==
3132
                        else
3133
                                opsize = 3;
3134
*/
3135
        }
3136
  }
3137
if (pass > 1 && unknown)
3138
  error |= ERR_LABEL_UNDEF;
3139
}
3140
 
3141
void scanoperands00(struct relocrecord *pp)
3142
{
3143
char c, *s = srcptr;
3144
 
3145
unknown = 0;
3146
opsize = 0;
3147
certain = 1;
3148
operand = 0;
3149
skipspace();
3150
c = *srcptr;
3151
mode = ADRMODE_IMM;
3152
switch (toupper(c))
3153
  {
3154
  case 'X' :                            /* "X"?                              */
3155
    scanname();
3156
    if (!strcmp(unamebuf, "X"))         /* if it's "X" alone,                */
3157
      goto XWithout;                    /* assume it means "0,X"             */
3158
    srcptr = s;                         /* else restore current offset       */
3159
    goto dodefault;                     /* and treat as label starting with X*/
3160
  case ',':                             /* ","?                              */
3161
  Indexed :
3162
    srcptr++;                           /* must be followed by "X"           */
3163
    if (!(dwOptions & OPTION_TSC))
3164
      skipspace();
3165
    scanname();
3166
    if (strcmp(unamebuf, "X"))          /* if it's NOT "X" alone,            */
3167
      {
3168
      error |= ERR_ILLEGAL_ADDR;
3169
      break;
3170
      }
3171
  XWithout :
3172
    if ((unsigned)operand < 256)
3173
      mode = ADRMODE_IDX;
3174
    else
3175
      error |= ERR_ILLEGAL_ADDR;
3176
    break;
3177
  case '#':
3178
    srcptr++;
3179
    operand = scanexpr(0, pp);
3180
    break;
3181
  case '<':
3182
    srcptr++;
3183
    if (*srcptr == '<')
3184
      {
3185
      srcptr++;
3186
      opsize = 1;
3187
      }
3188
    else
3189
      opsize = 2;
3190
    goto dodefault;
3191
  case '>':
3192
    srcptr++;
3193
    opsize = 3;
3194
    /* fall thru on purpose */
3195
  default:
3196
  dodefault:
3197
    operand = scanexpr(0, pp);
3198
    if (!(dwOptions & OPTION_TSC))
3199
      skipspace();
3200
    if (*srcptr == ',')
3201
      goto Indexed;
3202
    else
3203
      {
3204
      if (opsize == 0)
3205
        {
3206
        if (unknown || !certain ||
3207
          (unsigned short)(operand) >= 256)
3208
          opsize = 3;
3209
        else
3210
          opsize = 2;
3211
        }
3212
      if (opsize == 1)
3213
        opsize = 2;
3214
      mode = opsize - 1;
3215
      }
3216
  }
3217
 
3218
if (pass > 1 && unknown)
3219
  error |= ERR_LABEL_UNDEF;
3220
}
3221
 
3222
/*****************************************************************************/
3223
/* writerelhdr : writes a FLEX Relocatable Format header                     */
3224
/*****************************************************************************/
3225
 
3226
void writerelhdr(char wcommon)
3227
{
3228
int i;
3229
 
3230
#if 0
3231
struct                                  /* Header Layout                     */
3232
  {
3233
  unsigned char Signature;              /* Signature (always $03)            */
3234
  unsigned char flags1;                 /* Flags 1                           */
3235
  unsigned datasize;              /* size of binary data               */
3236
  unsigned char unknown1[4];            /* unknown data                      */
3237
  unsigned short extsize;               /* size of External table            */
3238
  unsigned startaddr;             /* program start address             */
3239
  unsigned char unknown2[2];            /* unknown data                      */
3240
  unsigned short globalsize;            /* size of global table              */
3241
  unsigned char unknown3[2];            /* unknown data                      */
3242
  unsigned short namesize;              /* length of module name             */
3243
  unsigned char flags2;                 /* Flags 2                           */
3244
  unsigned char unknown4[3];            /* unknown data; filler?             */
3245
  } hdr;
3246
memset(&hdr, 0, sizeof(hdr));
3247
#endif
3248
 
3249
fputc(0x04, objfile);                   /* write signature                   */
3250
 
3251
if (wcommon)                            /* if writing common data,           */
3252
  fputc(0x18, objfile);                 /* Flags1 = $18                      */
3253
else if (!absmode)                      /* if writing Relative data,         */
3254
  fputc(0x10, objfile);                 /* Flags1 = $10                      */
3255
else                                    /* if writing Absolute data,         */
3256
  fputc(0x12, objfile);                 /* Flags1 = $12                      */
3257
 
3258
if (wcommon)                            /* if writing common data            */
3259
  {                                     /* write size of data                */
3260
//  fputc((unsigned char)((commonsym->value >> 24) & 0xff), objfile);
3261
  fputc((unsigned char)((commonsym->value >> 16) & 0xff), objfile);
3262
  fputc((unsigned char)((commonsym->value >> 8) & 0xff), objfile);
3263
  fputc((unsigned char)(commonsym->value & 0xFF), objfile);
3264
  }
3265
else                                    /* otherwise                         */
3266
  {                                     /* write size of binary data         */
3267
//  fputc((unsigned char)((loccounter >> 24) & 0xff), objfile);
3268
  fputc((unsigned char)((loccounter >> 16) & 0xff), objfile);
3269
  fputc((unsigned char)((loccounter >> 8) & 0xff), objfile);
3270
  fputc((unsigned char)(loccounter & 0xFF), objfile);
3271
  }
3272
 
3273
//fputc(0, objfile);                      /* unknown data                      */
3274
fputc(0, objfile);
3275
fputc(0, objfile);
3276
fputc(0, objfile);
3277
 
3278
if (wcommon)                            /* if writing common data            */
3279
  {                                     /* external table is empty           */
3280
  fputc(0, objfile);
3281
  fputc(0, objfile);
3282
  }
3283
else
3284
  {
3285
  int extrel = 0;                       /* # external relocation records     */
3286
 
3287
  for (i = 0; i < relcounter; i++)      /* calc # external symbols           */
3288
    if ((reltable[i].sym->cat == SYMCAT_EXTERN) ||
3289
        (reltable[i].sym->cat == SYMCAT_COMMON))
3290
      extrel++;
3291
                                        /* then calculate table size         */
3292
  extrel = (extrel * 8) + (relcounter * 3);
3293
                                        /* and write it out                  */
3294
  fputc((unsigned char)(extrel >> 8), objfile);
3295
  fputc((unsigned char)(extrel & 0xFF), objfile);
3296
  }
3297
 
3298
if (wcommon ||                          /* if writing common data            */
3299
    (!tfradrset))                       /* or no transfer address given      */
3300
  {                                     /* start address is empty            */
3301
//  fputc(0, objfile);
3302
  fputc(0, objfile);
3303
  fputc(0, objfile);
3304
  fputc(0, objfile);
3305
  }
3306
else                                    /* write transfer address            */
3307
  {
3308
//  fputc((unsigned char)((tfradr >> 24) & 0xff), objfile);
3309
  fputc((unsigned char)((tfradr >> 16) & 0xff), objfile);
3310
  fputc((unsigned char)((tfradr >> 8) & 0xff), objfile);
3311
  fputc((unsigned char)(tfradr & 0xFF), objfile);
3312
  }
3313
 
3314
fputc(0, objfile);                      /* unknown data                      */
3315
fputc(0, objfile);
3316
 
3317
if (wcommon)
3318
  {                                     /* always 1 Global - the LABEL       */
3319
  fputc(0, objfile);
3320
  fputc(12, objfile);
3321
  }
3322
else                                    /* calculate & write out global size */
3323
  {
3324
  int globals = 0;
3325
  for (i = 0; i < symcounter; i++)
3326
    if (symtable[i].cat == SYMCAT_PUBLIC)
3327
      globals++;
3328
  globals *= 12;
3329
  fputc((unsigned char)(globals >> 8), objfile);
3330
  fputc((unsigned char)(globals & 0xFF), objfile);
3331
  }
3332
 
3333
fputc(0, objfile);                      /* unknown data                      */
3334
fputc(0, objfile);
3335
 
3336
if (wcommon)
3337
  {                                     /* no name size yet ...              */
3338
  size_t len;
3339
  char name[9] = "";
3340
  sprintf(name, "%-.8s", commonsym->name);
3341
  strupr(name);
3342
  len = strlen(name);
3343
  if (len)                              /* if there,                         */
3344
    len++;                              /* append a $04                      */
3345
  fputc((unsigned char)(len >> 8), objfile);
3346
  fputc((unsigned char)(len & 0xFF), objfile);
3347
  }
3348
else                                    /* write out module name size        */
3349
  {
3350
  size_t len = strlen(modulename);
3351
  if (len)                              /* if there,                         */
3352
    len++;                              /* append a $04                      */
3353
  fputc((unsigned char)(len >> 8), objfile);
3354
  fputc((unsigned char)(len & 0xFF), objfile);
3355
  }
3356
 
3357
if ((!wcommon) && (tfradrset))          /* if transfer address set           */
3358
  fputc(0x80, objfile);                 /* write $80 flag                    */
3359
else
3360
  fputc(0, objfile);
3361
 
3362
fputc(0, objfile);                      /* unknown data                      */
3363
fputc(0, objfile);
3364
fputc(0, objfile);
3365
}
3366
 
3367
/*****************************************************************************/
3368
/* writerelcommon : writes out all common blocks                             */
3369
/*****************************************************************************/
3370
 
3371
void writerelcommon()
3372
{
3373
int i, j;
3374
char name[9];
3375
                                        /* work through symbol list          */
3376
for (i = 0; i < symcounter; i++)
3377
  {
3378
  if (symtable[i].cat == SYMCAT_COMMON) /* if that is a common block         */
3379
    {
3380
    commonsym = symtable + i;           /* write it out                      */
3381
    writerelhdr(1);
3382
                                        /* then write the global definition  */
3383
    sprintf(name, "%-8.8s", symtable[i].name);
3384
    strupr(name);
3385
    fwrite(name, 1, 8, objfile);
3386
        if (symtable[i].value >= 65536)
3387
                fputc(2, objfile);                  /* unknown data                      */
3388
        else
3389
                fputc(1, objfile);                  /* unknown data                      */
3390
//    fputc((unsigned char)(symtable[i].value >> 24), objfile);
3391
    fputc((unsigned char)(symtable[i].value >> 16), objfile);
3392
    fputc((unsigned char)(symtable[i].value >> 8), objfile);
3393
    fputc((unsigned char)(symtable[i].value & 0xFF), objfile);
3394
    fputc(0x13, objfile);               /* unknown flag                      */
3395
 
3396
                                        /* then write the Common name        */
3397
    sprintf(name, "%-.8s", symtable[i].name);
3398
    strupr(name);
3399
    for (j = 0; name[j]; j++)
3400
      fputc(name[j], objfile);
3401
    fputc(0x04, objfile);
3402
 
3403
    j = (int)ftell(objfile);            /* fill last sector with zeroes      */
3404
    while (j % 252)
3405
      {
3406
      fputc(0, objfile);
3407
      j++;
3408
      }
3409
    }
3410
  }
3411
}
3412
 
3413
/*****************************************************************************/
3414
/* writerelext : writes out a FLEX Relocatable External table                */
3415
/*****************************************************************************/
3416
 
3417
void writerelext()
3418
{
3419
int i;
3420
char name[9];
3421
unsigned char flags;
3422
 
3423
for (i = 0; i < relcounter; i++)        /* write out the external data       */
3424
  {
3425
//  fputc((unsigned char)(reltable[i].addr >> 24), objfile);
3426
  fputc((unsigned char)(reltable[i].addr >> 16), objfile);
3427
  fputc((unsigned char)(reltable[i].addr >> 8), objfile);
3428
  fputc((unsigned char)(reltable[i].addr & 0xFF), objfile);
3429
 
3430
  flags = 0x00;                         /* reset flags                       */
3431
  if (reltable[i].exprcat & EXPRCAT_NEGATIVE)
3432
    flags |= 0x20;                      /* eventually add subtraction flag   */
3433
  if ((reltable[i].sym->cat == SYMCAT_EXTERN) ||
3434
      (reltable[i].sym->cat == SYMCAT_COMMON))
3435
    flags |= 0x80;                      /* eventually add External flag      */
3436
  fputc(flags, objfile);                /* write the flag bytes              */
3437
  if (flags & 0x80)                     /* eventually write external symbol  */
3438
    {
3439
    sprintf(name, "%-8.8s", reltable[i].sym->name);
3440
    strupr(name);
3441
    fwrite(name, 1, 8, objfile);
3442
    }
3443
  }
3444
}
3445
 
3446
/*****************************************************************************/
3447
/* writerelglobal : writes out FLEX Relocatable Global table                 */
3448
/*****************************************************************************/
3449
 
3450
void writerelglobal()
3451
{
3452
int i;
3453
char name[9];
3454
 
3455
for (i = 0; i < symcounter; i++)        /* write out the global data         */
3456
  {
3457
  if (symtable[i].cat == SYMCAT_PUBLIC)
3458
    {
3459
    sprintf(name, "%-8.8s", symtable[i].name);
3460
    strupr(name);
3461
    fwrite(name, 1, 8, objfile);
3462
 
3463
    fputc(0, objfile);                  /* unknown data                      */
3464
 
3465
//    fputc((unsigned char)(symtable[i].value >> 24), objfile);
3466
    fputc((unsigned char)(symtable[i].value >> 16), objfile);
3467
    fputc((unsigned char)(symtable[i].value >> 8), objfile);
3468
    fputc((unsigned char)(symtable[i].value & 0xFF), objfile);
3469
 
3470
    fputc(0x02, objfile);               /* unknown flag                      */
3471
    }
3472
  }
3473
}
3474
 
3475
/*****************************************************************************/
3476
/* writerelmodname : writes out FLEX Relocatable Module Name                 */
3477
/*****************************************************************************/
3478
 
3479
void writerelmodname()
3480
{
3481
int i;
3482
 
3483
if (!modulename[0])
3484
  return;
3485
strupr(modulename);
3486
for (i = 0; modulename[i]; i++)
3487
  fputc(modulename[i], objfile);
3488
fputc(0x04, objfile);
3489
}
3490
 
3491
/*****************************************************************************/
3492
/* flushver : write verilog                                       */
3493
/*****************************************************************************/
3494
 
3495
int calcParity(unsigned wd)
3496
{
3497
        int nn;
3498
        int bit;
3499
        int par;
3500
 
3501
        par = 0;
3502
        for (nn = 0; nn < 32; nn++) {
3503
                bit = (wd >> nn) & 1;
3504
                par = par ^ bit;
3505
        }
3506
        return par;
3507
}
3508
 
3509
void flushver()
3510
{
3511
int i;
3512
int chk;
3513
 
3514
if (hexcount)
3515
 {
3516
  if (objfile)
3517
    {
3518
                 for (i = 0; i < hexcount; i++)
3519
        fprintf(objfile, "rommem[%5d] <= 12'h%03X;\r\n", (hexaddr+i) & 0x3fff, hexbuffer[i] & 0xfff);
3520
  hexaddr += hexcount;
3521
  hexcount = 0;
3522
  chksum = 0;
3523
        vercount++;
3524
        }
3525
  }
3526
}
3527
 
3528
/*****************************************************************************/
3529
/* flushhex : write Motorola s-records  */
3530
/* Flushes using 12-bit bytes */
3531
/*****************************************************************************/
3532
 
3533
void flushhex()
3534
{
3535
int i;
3536
 
3537
if (hexcount)
3538
  {
3539
  if (objfile)
3540
    {
3541
    fprintf(objfile, "S1%03X%06X", (hexcount + 3) & 0xfff, hexaddr & 0xffffff);
3542
    for (i = 0; i < hexcount; i++)
3543
      fprintf(objfile, "%03X", hexbuffer[i] & 0xfff);
3544
    chksum += (hexaddr & 0xfff) + ((hexaddr >> 12) & 0xfff) + hexcount + 3;
3545
    fprintf(objfile, "%03X\n", 0xfff - (chksum & 0xfff));
3546
    }
3547
  hexaddr += hexcount;
3548
  hexcount = 0;
3549
  chksum = 0;
3550
  }
3551
}
3552
 
3553
/*****************************************************************************/
3554
/* flushihex : write Intel hex record                                        */
3555
/*****************************************************************************/
3556
 
3557
void flushihex()
3558
{
3559
int i;
3560
unsigned char  *j;
3561
 
3562
if (hexcount)
3563
  {
3564
  if (objfile)
3565
    {
3566
    j = &hexbuffer[0];
3567
    fprintf(objfile, ":%03X%06X00", hexcount, hexaddr & 0xffffff);
3568
    chksum = hexcount + ((hexaddr >> 12) & 0xfff) + (hexaddr & 0xfff);
3569
    for (i = 0; i < hexcount; i++, j++)
3570
      {
3571
      chksum += (*j) & 0xfff;
3572
      fprintf(objfile, "%03X", (*j) & 0xfff);
3573
      }
3574
    fprintf(objfile, "%03X\n", (-(signed)chksum) & 0xfff);
3575
    }
3576
  hexaddr += hexcount;
3577
  hexcount = 0;
3578
  chksum = 0;
3579
  }
3580
}
3581
 
3582
/*****************************************************************************/
3583
/* flushflex : write FLEX binary record                                      */
3584
/*****************************************************************************/
3585
 
3586
void flushflex()
3587
{
3588
int i;
3589
unsigned short *j;
3590
 
3591
if (hexcount)
3592
  {
3593
  j = &hexbuffer[0];
3594
  if (objfile)
3595
    {
3596
    fputc(0x02, objfile);               /* start of record indicator         */
3597
    fputc((hexaddr >> 32) & 0xf,        /* load address high part            */
3598
      objfile);
3599
    fputc((hexaddr >> 24) & 0xff,        /* load address high part            */
3600
          objfile);
3601
    fputc((hexaddr >> 20) & 0xf,        /* load address high part            */
3602
      objfile);
3603
    fputc((hexaddr >> 12) & 0xff,        /* load address high part            */
3604
          objfile);
3605
    fputc((hexaddr >> 8) & 0xf, objfile);     /* load address low part             */
3606
    fputc(hexaddr & 0xff, objfile);     /* load address low part             */
3607
    fputc((hexcount >> 8) & 0xf, objfile);    /* # following data bytes            */
3608
    fputc(hexcount & 0xff, objfile);    /* # following data bytes            */
3609
    for (i = 0; i < hexcount; i++, j++) { /* then put all data bytes           */
3610
      fputc(((*j)>>8)&0xff, objfile);
3611
      fputc(*j, objfile);
3612
    }
3613
    }
3614
  hexaddr += hexcount;                  /* set new address                   */
3615
  hexcount = 0;                         /* reset counter                     */
3616
  }
3617
}
3618
 
3619
/*****************************************************************************/
3620
/* outver : add a byte to verilog output                           */
3621
/*****************************************************************************/
3622
 
3623
void outver (unsigned short x)
3624
{
3625
        if (hexcount==4)
3626
                flushver();
3627
        hexbuffer[hexcount] = x;
3628
        hexcount++;
3629
chksum += x;
3630
}
3631
 
3632
/*****************************************************************************/
3633
/* outhex : add a byte to motorola s-record output                           */
3634
/*****************************************************************************/
3635
 
3636
void outhex (unsigned short x)
3637
{
3638
if (hexcount == 16)
3639
  flushhex();
3640
hexbuffer[hexcount++] = x;
3641
chksum += x;
3642
}
3643
 
3644
/*****************************************************************************/
3645
/* outihex : add a byte to intel hex output                                  */
3646
/*****************************************************************************/
3647
 
3648
void outihex (unsigned short x)
3649
{
3650
if (hexcount == 32)
3651
  flushihex();
3652
hexbuffer[hexcount++] = x;
3653
chksum += x;
3654
}
3655
 
3656
/*****************************************************************************/
3657
/* outflex : adds a byte to FLEX output                                      */
3658
/*****************************************************************************/
3659
 
3660
void outflex(unsigned short x)
3661
{
3662
if (hexcount == 255)                    /* if buffer full                    */
3663
  flushflex();                          /* flush it                          */
3664
hexbuffer[hexcount++] = x;              /* then put byte into buffer         */
3665
}
3666
 
3667
/*****************************************************************************/
3668
/* outbyte : writes one byte to the output in the selected format            */
3669
/*****************************************************************************/
3670
 
3671
void outbyte(unsigned short uc, int off)
3672
{
3673
int nByte = (loccounter + off) / 8;
3674
unsigned short nBitMask = (unsigned short) (1 << ((loccounter + off) % 12));
3675
 
3676
//if (bUsedBytes[nByte] & nBitMask)       /* if address already used           */
3677
//  warning |= WRN_AREA;                  /* set warning code                  */
3678
//else                                    /* otherwise                         */
3679
//  bUsedBytes[nByte] |= nBitMask;        /* mark it as used                   */
3680
 
3681
switch (outmode)
3682
  {
3683
  case OUT_BIN :                        /* binary file                       */
3684
    fputc((uc >> 8) & 0xf, objfile);
3685
    fputc(uc, objfile);
3686
    break;
3687
  case OUT_REL :                        /* FLEX Relocatable                  */
3688
    fputc((uc >> 8) & 0xf, objfile);
3689
    fputc(uc, objfile);
3690
    break;
3691
  case OUT_SREC :                       /* Motorola S-records                */
3692
    outhex(uc);
3693
    break;
3694
  case OUT_IHEX :                       /* Intel Hex                         */
3695
    outihex(uc);
3696
    break;
3697
  case OUT_FLEX :                       /* FLEX                              */
3698
    outflex(uc);
3699
    break;
3700
  case OUT_VER:
3701
          outver(uc);
3702
          break;
3703
  }
3704
}
3705
 
3706
/*****************************************************************************/
3707
/* outbuffer : writes the output to a file in the selected format            */
3708
/*****************************************************************************/
3709
 
3710
void outbuffer()
3711
{
3712
int i;
3713
for (i = 0; i < codeptr; i++)
3714
  outbyte(codebuf[i], i);
3715
}
3716
 
3717
/*****************************************************************************/
3718
/* report : reports an error                                                 */
3719
/*****************************************************************************/
3720
 
3721
void report()
3722
{
3723
int i;
3724
 
3725
for (i = 0; i < 16; i++)
3726
  {
3727
  if (error & 1)
3728
    {
3729
    printf("%s(%ld) : error %d: %s in \"%s\"\n",
3730
           expandfn(curline->fn), curline->ln, i + 1,
3731
           errormsg[i], curline->txt);
3732
    if (((dwOptions & OPTION_LP1) || pass == MAX_PASSNO) && (listing & LIST_ON))
3733
      putlist( "*** Error %d: %s\n", i + 1, errormsg[i]);
3734
    errors++;
3735
    }
3736
  error >>= 1;
3737
  }
3738
 
3739
if ((dwOptions & OPTION_TSC))           /* suppress warning 1 in TSC mode    */
3740
  warning &= ~WRN_OPT;
3741
 
3742
if (!(dwOptions & OPTION_WAR))          /* reset warnings if not wanted      */
3743
  warning = WRN_OK;
3744
 
3745
for (i = 0; i < 16; i++)
3746
  {
3747
  if (warning & 1)
3748
    {
3749
    printf("%s(%ld) : warning %d: %s in \"%s\"\n",
3750
           expandfn(curline->fn), curline->ln, i + 1, warningmsg[i], curline->txt);
3751
    if (((dwOptions & OPTION_LP1) || pass == MAX_PASSNO) && (listing & LIST_ON))
3752
      putlist( "*** warning %d: %s\n", i + 1, warningmsg[i]);
3753
    warnings++;
3754
    }
3755
  warning >>= 1;
3756
  }
3757
}
3758
 
3759
/*****************************************************************************/
3760
/* outlist : lists the code bytes for an instruction                         */
3761
/*****************************************************************************/
3762
 
3763
void outlist(struct oprecord *op)
3764
{
3765
int i;
3766
 
3767
if ((curline->lvl & LINCAT_INVISIBLE) &&/* don't list invisible lines       */
3768
    !(dwOptions & OPTION_INV))
3769
  return;
3770
 
3771
if ((curline->lvl & LINCAT_MACEXP) &&   /* don't list macro expansions if   */
3772
    !(dwOptions & OPTION_EXP))          /* not explicitly requested         */
3773
  return;
3774
 
3775
if ((curline->lvl & LINCAT_LVLMASK) &&  /* if level 1..31                    */
3776
    !(dwOptions & OPTION_LLL))          /* and this is not to be listed      */
3777
  return;
3778
 
3779
if ((suppress || nSkipCount) &&         /* if this is conditionally skipped  */
3780
    !(dwOptions & OPTION_CON))          /* and this is not to be listed      */
3781
  return;
3782
if ((condline) &&                       /* if this is a condition line       */
3783
    !(dwOptions & OPTION_CON))          /* and this is not to be listed      */
3784
  return;
3785
 
3786
if (dwOptions & OPTION_NUM)             /* if number output                  */
3787
  putlist("%4d ", curline->ln);         /* print out the line number         */
3788
 
3789
if (!absmode)                           /* if in relocating assembler mode   */
3790
  putlist("%c", curline->rel);          /* output relocation information     */
3791
 
3792
if (dwOptions & OPTION_LPA)             /* if in patch mode                  */
3793
  {
3794
  if ((op) && (op->cat == OPCAT_PSEUDO))
3795
    {
3796
    switch (op->code)
3797
      {
3798
      case PSEUDO_SETDP :
3799
        if (dpsetting >= 0)
3800
          putlist("setdp %02X\n", dpsetting);
3801
        break;
3802
      case PSEUDO_ORG :
3803
        putlist("insert %08X \\        ORG $%08X\n", loccounter, loccounter);
3804
        break;
3805
      case PSEUDO_FCB :
3806
      case PSEUDO_FCC :
3807
        putlist("data %04X", oldlc);
3808
        if (codeptr > 1)
3809
          putlist("-%04X", oldlc + codeptr - 1);
3810
        putlist("\n");
3811
        break;
3812
      case PSEUDO_FCW :
3813
        putlist("word %04x", oldlc);
3814
        if (codeptr > 2)
3815
          putlist("-%04X", oldlc + codeptr - 1);
3816
        putlist("\n");
3817
        break;
3818
      case PSEUDO_FCDW :
3819
        putlist("dword %08x", oldlc);
3820
        if (codeptr > 2)
3821
          putlist("-%08X", oldlc + codeptr - 1);
3822
        putlist("\n");
3823
        break;
3824
      }
3825
    }
3826
  if (codeptr > 0)                      /* if there are code bytes           */
3827
    {
3828
    char *name = findsymat(oldlc);
3829
    if (name)
3830
      putlist("label %04X %s\n", oldlc, name);
3831
    putlist("patch ");                  /* write "patch"                     */
3832
    }
3833
  else if (*curline->txt)
3834
    putlist("      ");
3835
  else
3836
    putlist("comment %04X", oldlc);
3837
  }
3838
else if ((warning & WRN_OPT) &&         /* excessive branch, TSC style       */
3839
    (dwOptions & OPTION_TSC) &&
3840
    (dwOptions & OPTION_WAR))
3841
  putlist(">");
3842
else if (curline->lvl & LINCAT_MACDEF)  /* if in macro definition            */
3843
  putlist("#");                         /* prefix line with #                */
3844
else if (curline->lvl & LINCAT_MACEXP)  /* if in macro expansion             */
3845
  putlist("+");                         /* prefix line with +                */
3846
else if (curline->lvl & LINCAT_INVISIBLE)
3847
  putlist("-");
3848
else if (curline->txt)                  /* otherwise                         */
3849
  putlist(" ");                         /* prefix line with blank            */
3850
 
3851
if (codeptr > 0)
3852
  putlist("%08X ", oldlc);
3853
else if (*curline->txt)
3854
  putlist("     ");
3855
else
3856
  {
3857
  putlist( "\n");
3858
  return;
3859
  }
3860
 
3861
for (i = 0; i < codeptr && i < MAXLISTBYTES; i++)
3862
  {
3863
  if (dwOptions & OPTION_LPA)
3864
    putlist("%03X ", codebuf[i]&0xfff);
3865
  else
3866
    putlist("%03X", codebuf[i]&0xfff);
3867
  }
3868
for (; i <= MAXLISTBYTES; i++)
3869
  {
3870
  if (dwOptions & OPTION_LPA)
3871
    putlist("    ");
3872
  else
3873
    putlist("   ");
3874
  }
3875
 
3876
if ((dwOptions & OPTION_LPA) &&
3877
    (*curline->txt))
3878
  putlist("* ");
3879
 
3880
if (strcmp(curline->txt, srcline) &&    /* if text inserted                  */
3881
    (dwOptions & OPTION_EXP))           /* and expansion activated           */
3882
  putlist("%s", curline->txt);          /* just print out the source line    */
3883
else                                    /* otherwise                         */
3884
  putlist("%s", srcline);               /* print possibly expanded line      */
3885
 
3886
putlist("\n");                          /* send newline                      */
3887
 
3888
if (codeptr > MAXLISTBYTES &&           /* if there are additional bytes,    */
3889
    (dwOptions & OPTION_MUL))
3890
  {                                     /* print them.                       */
3891
  if (dwOptions & OPTION_LPA)           /* if in patch mode                  */
3892
    putlist("patch");                   /* write "patch"                     */
3893
  for (i = MAXLISTBYTES; i < codeptr; i++)
3894
    {
3895
    if (!(i % MAXLISTBYTES))
3896
      {
3897
      if (i != MAXLISTBYTES)
3898
        putlist("\n");
3899
      if (dwOptions & OPTION_NUM)       /* if number output                  */
3900
        putlist("     ");
3901
      if (!absmode)
3902
        putlist(" ");
3903
      putlist(" %08X ", oldlc + i);
3904
      }
3905
    if (dwOptions & OPTION_LPA)         /* if in patch mode                  */
3906
      putlist("%03X ", codebuf[i]&0xfff);
3907
    else
3908
      putlist("%03X", codebuf[i]&0xfff);
3909
    }
3910
  putlist("\n");
3911
  }
3912
 
3913
if (strcmp(curline->txt, srcline) &&    /* if text inserted                  */
3914
    (dwOptions & OPTION_EXP))           /* and expansion activated           */
3915
  {
3916
  if (dwOptions & OPTION_NUM)
3917
    putlist("%4d ", curline->ln);
3918
  if (!absmode)
3919
    putlist(" ");
3920
  putlist("+                   ( %s )\n", srcline);
3921
  }
3922
}
3923
 
3924
/*****************************************************************************/
3925
/* setlabel : sets a label                                                   */
3926
/*****************************************************************************/
3927
 
3928
void setlabel(struct symrecord * lp)
3929
{
3930
if (lp)
3931
  {
3932
          lp->isFar = isFar;
3933
          lp->isFarkw = isFarkw;
3934
  if (lp->cat == SYMCAT_PUBLICUNDEF)
3935
    {
3936
    lp->cat = SYMCAT_PUBLIC;
3937
    lp->value = loccounter;
3938
    }
3939
  else if (lp->cat == SYMCAT_EMPTYLOCAL)
3940
    {
3941
    lp->cat = SYMCAT_LOCALLABEL;
3942
    }
3943
  else if (lp->cat == SYMCAT_LOCALLABEL)
3944
    ;
3945
  else if (lp->cat != SYMCAT_EMPTY && lp->cat != SYMCAT_UNRESOLVED)
3946
    {
3947
    if ((lp->cat != SYMCAT_LABEL && lp->cat != SYMCAT_PUBLIC) ||
3948
                lp->value != loccounter) {
3949
                lp->value = loccounter;
3950
                if (pass==MAX_PASSNO)
3951
                        error |= ERR_LABEL_MULT;
3952
                }
3953
    }
3954
  else
3955
    {
3956
    lp->cat = (global) ? SYMCAT_PUBLIC : SYMCAT_LABEL;
3957
    lp->value = loccounter;
3958
    }
3959
  }
3960
}
3961
 
3962
/*****************************************************************************/
3963
/* putbyte : adds a byte to the instruction code buffer                      */
3964
/*****************************************************************************/
3965
 
3966
void putbyte(unsigned short b)
3967
{
3968
codebuf[codeptr++] = b;                 /* and finally put the byte there.   */
3969
}
3970
 
3971
/*****************************************************************************/
3972
/* putword : adds a word to the instruction code buffer                      */
3973
/*****************************************************************************/
3974
 
3975
void putword(unsigned w)
3976
{
3977
putbyte((unsigned short)((w >> 12L) & 0xfffL));
3978
putbyte((unsigned short)(w & 0xfff));
3979
}
3980
 
3981
/*****************************************************************************/
3982
/* putdword : adds a doubleword to the instruction code buffer               */
3983
/*****************************************************************************/
3984
 
3985
void putdword(unsigned __int64 d)
3986
{
3987
putbyte((unsigned short)((d >> 36LL) & 0xfffLL));
3988
putbyte((unsigned short)((d >> 24LL) & 0xfffLL));
3989
putbyte((unsigned short)((d >> 12LL) & 0xfffLL));
3990
putbyte((unsigned short)(d & 0xfffLL));
3991
}
3992
 
3993
/*****************************************************************************/
3994
/* doaddress : assemble the right addressing bytes for an instruction        */
3995
/*****************************************************************************/
3996
 
3997
void doaddress(struct relocrecord *p)
3998
{
3999
int offs;
4000
int addrelocation = 0;
4001
int isNear = 0;
4002
if (p)                                  /* create relocation record          */
4003
  p->addr = (unsigned)(loccounter + codeptr);
4004
 
4005
switch (mode)
4006
  {
4007
  case ADRMODE_IMM :
4008
    if (opsize == 2)
4009
      putbyte((unsigned short)operand);
4010
    else if (opsize == 5)               /* LDQ special                       */
4011
      putdword(operand);
4012
    else
4013
      {
4014
      putword((unsigned)operand);
4015
      addrelocation = 1;
4016
      }
4017
    break;
4018
  case ADRMODE_DIR :
4019
    putbyte((unsigned short)operand);
4020
    break;
4021
  case ADRMODE_EXT :
4022
    if (((codebuf[0] == 0x07e) ||        /* special for JMP                   */
4023
         (codebuf[0] == 0x0bd) ||
4024
                 (codebuf[0] == 0x015 && (codebuf[1]==0x07E || codebuf[1]==0x0bd))
4025
                 ) &&       /* and JSR                           */
4026
        pass > 1)
4027
      {
4028
      int nDiff = (int)operand - (int)loccounter - 3;
4029
          isNear = (operand & 0xFF0000L) == (loccounter & 0xff0000L);
4030
      if (((nDiff & 0xff80) == 0x0000) ||
4031
           ((nDiff & 0xff80) == 0xff80))
4032
           warning |= (certain) ? WRN_OPT : 0;
4033
      }
4034
          if (codebuf[0]==0x015 && codebuf[1]==0x0bd && isFar) {
4035
                  if (isNear && !isFarkw) {
4036
                          codebuf[0]=0x0bd;
4037
                          isFar = 0;
4038
                  }
4039
                  else
4040
                          codebuf[0]=0x0cf;
4041
                  codeptr--;
4042
          }
4043
          if (codebuf[0]==0x015 && codebuf[1]==0x07E && isFar) {
4044
                  if (isNear && !isFarkw) {
4045
                        codebuf[0]=0x07E;
4046
                        isFar = 0;
4047
                  }
4048
                  else
4049
                        codebuf[0]=0x08f;
4050
                  codeptr--;
4051
          }
4052
          if (isFar) {
4053
                  putbyte((unsigned short)(operand >> 24));
4054
          }
4055
    putword((unsigned)operand);
4056
    addrelocation = 1;
4057
    break;
4058
  case ADRMODE_IDX :
4059
    putbyte((unsigned short)operand);
4060
    break;
4061
  case ADRMODE_POST :
4062
  case ADRMODE_IND :
4063
  case ADRMODE_DBL_IND:
4064
    putbyte(postbyte);
4065
    switch (opsize)
4066
      {
4067
      case 2:
4068
        putbyte((unsigned short)operand);
4069
        break;
4070
      case 3:
4071
        putword((unsigned)operand);
4072
        addrelocation = 1;
4073
                break;
4074
      case 4:
4075
        putbyte((unsigned short)(operand>>24));
4076
        putword((unsigned)operand);
4077
        addrelocation = 1;
4078
                break;
4079
      case 5:
4080
        putword((unsigned short)(operand>>24));
4081
        putword((unsigned)operand);
4082
        addrelocation = 1;
4083
                break;
4084
      }
4085
    break;
4086
  case ADRMODE_PCR :
4087
  case ADRMODE_PIN :
4088
    offs = (unsigned)operand - loccounter - codeptr - 2;
4089
    if (offs < -2048 || offs >= 2048 || opsize == 3 || unknown || !certain)
4090
      {
4091
      if ((!unknown) && opsize == 2)
4092
        error |= ERR_RANGE;
4093
      offs--;
4094
      opsize = 3;
4095
      postbyte++;
4096
      }
4097
    putbyte(postbyte);
4098
    if (opsize == 3)
4099
      {
4100
      putword((unsigned)offs);
4101
      addrelocation = 1;
4102
      }
4103
    else
4104
      putbyte((unsigned short)offs);
4105
  }
4106
 
4107
if (addrelocation)
4108
  addreloc(p);
4109
}
4110
 
4111
/*****************************************************************************/
4112
/* onebyte : saves integer as one instruction byte                           */
4113
/*****************************************************************************/
4114
 
4115
void onebyte(int co)
4116
{
4117
putbyte((unsigned short)co);
4118
}
4119
 
4120
/*****************************************************************************/
4121
/* twobyte : saves integer as two instruction bytes                          */
4122
/*****************************************************************************/
4123
 
4124
void twobyte(int co)
4125
{
4126
putword((unsigned)co);
4127
}
4128
 
4129
/*****************************************************************************/
4130
/* threebyte : saves long integer as three instruction bytes                 */
4131
/*****************************************************************************/
4132
 
4133
void threebyte(unsigned __int64 co)
4134
{
4135
putbyte((unsigned short)((co >> 24LL) & 0xfffLL));
4136
putbyte((unsigned short)((co >> 12LL) & 0xfffLL));
4137
putbyte((unsigned short)(co & 0xfffL));
4138
}
4139
 
4140
/*****************************************************************************/
4141
/* fourbyte : saves long integer as four instruction bytes                   */
4142
/*****************************************************************************/
4143
 
4144
void fourbyte(unsigned __int64 co)
4145
{
4146
  putbyte((unsigned short)((co >> 36LL) & 0xfffLL));
4147
  putbyte((unsigned short)((co >> 24LL) & 0xfffLL));
4148
  putbyte((unsigned short)((co >> 12LL) & 0xfffLL));
4149
  putbyte((unsigned short)(co & 0xfffL));
4150
}
4151
 
4152
/*****************************************************************************/
4153
/* oneimm : saves one immediate value                                        */
4154
/*****************************************************************************/
4155
 
4156
void oneimm(int co)
4157
{
4158
struct relocrecord p = {0};
4159
 
4160
scanoperands(&p);
4161
if (mode >= ADRMODE_POST)
4162
  error |= ERR_ILLEGAL_ADDR;
4163
putbyte((unsigned short)co);
4164
 
4165
/* addreloc(0, 2, p); */                /* no relocation for immediate op's  */
4166
 
4167
putbyte((unsigned short)operand);
4168
}
4169
 
4170
/*****************************************************************************/
4171
/* lea :                                                                     */
4172
/*****************************************************************************/
4173
 
4174
void lea(int co)
4175
{
4176
struct relocrecord p = {0};
4177
 
4178
scanoperands(&p);
4179
if (isFar)
4180
        onebyte(0x015);
4181
onebyte((unsigned short)co);
4182
if (mode == ADRMODE_IMM)
4183
  error |= ERR_ILLEGAL_ADDR;
4184
if (mode < ADRMODE_POST)
4185
  {
4186
          if (isFar)
4187
                  opsize = 4;
4188
          else
4189
                opsize = 3;
4190
  postbyte = 0x80f;
4191
  mode = ADRMODE_POST;
4192
  }
4193
doaddress(&p);
4194
}
4195
 
4196
/*****************************************************************************/
4197
/* sbranch : processes a short branch                                        */
4198
/*****************************************************************************/
4199
 
4200
void sbranch(int co)
4201
{
4202
struct relocrecord p = {0};
4203
int offs;
4204
 
4205
scanoperands(&p);
4206
if (mode != ADRMODE_DIR && mode != ADRMODE_EXT)
4207
  error |= ERR_ILLEGAL_ADDR;
4208
offs = operand - loccounter - 2;
4209
if (!unknown && (offs < -2048 || offs >= 2048))
4210
  error |= ERR_RANGE;
4211
if (pass > 1 && unknown)
4212
  error |= ERR_LABEL_UNDEF;
4213
putbyte((unsigned short)co);
4214
putbyte((unsigned short)offs);
4215
}
4216
 
4217
/*****************************************************************************/
4218
/* lbra : does a long branch                                                 */
4219
/*****************************************************************************/
4220
 
4221
void lbra(int co)
4222
{
4223
struct relocrecord p = {0};
4224
int nDiff;
4225
 
4226
scanoperands(&p);
4227
if (mode != ADRMODE_DIR && mode != ADRMODE_EXT)
4228
  error |= ERR_ILLEGAL_ADDR;
4229
putbyte((unsigned short)co);
4230
 
4231
nDiff = operand - loccounter - 3;
4232
putword((unsigned)nDiff);
4233
if (((nDiff & 0xff8000) == 0x000000) ||
4234
    ((nDiff & 0xff8000) == 0xff8000))
4235
  warning |= (certain) ? WRN_OPT : 0;
4236
}
4237
 
4238
/*****************************************************************************/
4239
/* lbranch : does a long branch                                              */
4240
/*****************************************************************************/
4241
 
4242
void lbranch(int co)
4243
{
4244
struct relocrecord p = {0};
4245
int nDiff;
4246
 
4247
scanoperands(&p);
4248
if (mode != ADRMODE_DIR && mode != ADRMODE_EXT)
4249
  error |= ERR_ILLEGAL_ADDR;
4250
putword((unsigned)co);
4251
nDiff = operand - loccounter - 4;
4252
putword((unsigned)nDiff);
4253
if (((nDiff & 0xff8000) == 0x000000) ||
4254
    ((nDiff & 0xff8000) == 0xff8000))
4255
  warning |= (certain) ? WRN_OPT : 0;
4256
}
4257
 
4258
/*****************************************************************************/
4259
/* arith : process arithmetic operation                                      */
4260
/*****************************************************************************/
4261
 
4262
void arith(int co, char noimm)
4263
{
4264
struct relocrecord p = {0};
4265
 
4266
scanoperands(&p);
4267
switch (mode)
4268
  {
4269
  case ADRMODE_IMM :
4270
    if (noimm)
4271
      error |= ERR_ILLEGAL_ADDR;
4272
    opsize = 2;
4273
    putbyte((unsigned short)co);
4274
    break;
4275
  case ADRMODE_DIR :
4276
    putbyte((unsigned short)(co + 0x010));
4277
    break;
4278
  case ADRMODE_EXT :
4279
          if (isFar)
4280
                  putbyte(0x015);
4281
    putbyte((unsigned short)(co + 0x030));
4282
    break;
4283
  default:
4284
          if (isFar)
4285
                  putbyte(0x015);
4286
                if (isPostIndexed)
4287
                        putbyte(0x01B);
4288
    putbyte((unsigned short)(co + 0x020));
4289
  }
4290
doaddress(&p);
4291
}
4292
 
4293
/*****************************************************************************/
4294
/* accarith : process arithmetic operation with explicit accumulator         */
4295
/*****************************************************************************/
4296
 
4297
void accarith(int co, char noimm, char ignore)
4298
{
4299
char *s = srcptr;                       /* remember current offset           */
4300
char correct = 1;                       /* flag whether correct              */
4301
 
4302
skipspace();                            /* skip space                        */
4303
scanname();                             /* get following name                */
4304
 
4305
if (strcmp(unamebuf, "A") &&            /* has to be followed by A or B      */
4306
    strcmp(unamebuf, "B"))
4307
  correct = 0;
4308
 
4309
#if 1
4310
if (*srcptr == ',')                     /* if directly followed by a comma   */
4311
  srcptr++;                             /* skip it                           */
4312
#else
4313
if (!(dwOptions & OPTION_TSC))
4314
  skipspace();
4315
if (*srcptr++ != ',')                   /* and a comma                       */
4316
  correct = 0;
4317
#endif
4318
 
4319
if (!correct)                           /* if NOT followed by "A," or "B,"   */
4320
  {
4321
  if (ignore)                           /* if ignoring that,                 */
4322
    srcptr = s;                         /* go back to parm start             */
4323
  else                                  /* otherwise                         */
4324
    error |= ERR_EXPR;                  /* flag as an error                  */
4325
  }
4326
else if (unamebuf[0] == 'B')            /* eventually transform to acc.B     */
4327
  co |= 0x40;
4328
arith(co, noimm);                       /* then process as arithmetic        */
4329
}
4330
 
4331
/*****************************************************************************/
4332
/* idxextarith : indexed / extended arithmetic, 6800 style                   */
4333
/*****************************************************************************/
4334
 
4335
void idxextarith(int co)
4336
{
4337
struct relocrecord p = {0};
4338
 
4339
scanoperands(&p);
4340
switch (mode)
4341
  {
4342
  case ADRMODE_IMM :
4343
    error |= ERR_ILLEGAL_ADDR;
4344
    opsize = 3;
4345
    putbyte((unsigned short)co);
4346
    break;
4347
  case ADRMODE_DIR :
4348
    mode = ADRMODE_EXT;                 /* implicitly convert to extended    */
4349
    putbyte((unsigned short)(co + 0x030));
4350
    break;
4351
  case ADRMODE_EXT :
4352
        if (isFar)
4353
                putbyte(0x015);
4354
    putbyte((unsigned short)(co + 0x030));
4355
    break;
4356
  default:
4357
        if (isFar)
4358
                putbyte(0x015);
4359
        if (isPostIndexed)
4360
                putbyte(0x01B);
4361
    putbyte((unsigned short)(co + 0x020));
4362
    break;
4363
 }
4364
doaddress(&p);
4365
}
4366
 
4367
/*****************************************************************************/
4368
/* darith : process direct arithmetic                                        */
4369
/*****************************************************************************/
4370
 
4371
void darith(int co, char noimm, char tgt)
4372
{
4373
struct relocrecord p = {0};
4374
 
4375
scanoperands(&p);
4376
switch (mode)
4377
  {
4378
  case ADRMODE_IMM :
4379
    if (noimm)
4380
      error |= ERR_ILLEGAL_ADDR;
4381
        if (isX32 && tgt)
4382
                opsize = 5;
4383
        else
4384
                opsize = 3;
4385
    putbyte((unsigned short)co);
4386
    break;
4387
  case ADRMODE_DIR :
4388
    putbyte((unsigned short)(co + 0x010));
4389
    break;
4390
  case ADRMODE_EXT :
4391
          if (isFar)
4392
                  putbyte(0x015);
4393
    putbyte((unsigned short)(co + 0x030));
4394
    break;
4395
  default:
4396
          if (isFar)
4397
                  putbyte(0x015);
4398
          if (isPostIndexed)
4399
                  putbyte(0x01B);
4400
    putbyte((unsigned short)(co + 0x020));
4401
    break;
4402
 }
4403
doaddress(&p);
4404
}
4405
 
4406
/*****************************************************************************/
4407
/* d2arith : process direct word arithmetic                                  */
4408
/*****************************************************************************/
4409
 
4410
void d2arith(int co, char noimm, char tgt)
4411
{
4412
struct relocrecord p = {0};
4413
 
4414
scanoperands(&p);
4415
switch (mode)
4416
  {
4417
  case ADRMODE_IMM :
4418
    if (noimm)
4419
      error |= ERR_ILLEGAL_ADDR;
4420
        if (isX32 && tgt)
4421
                opsize = 5;
4422
        else
4423
                opsize = 3;
4424
    putword((unsigned)co);
4425
    break;
4426
  case ADRMODE_DIR :
4427
    putword((unsigned)(co + 0x010));
4428
    break;
4429
  case ADRMODE_EXT :
4430
          if (isFar) {
4431
                  putbyte(0x015);
4432
          }
4433
    putword((unsigned)(co + 0x030));
4434
    break;
4435
  default:
4436
          if (isFar)
4437
                  putbyte(0x015);
4438
          if (isPostIndexed)
4439
                  putbyte(0x01B);
4440
    putword((unsigned)(co + 0x020));
4441
 }
4442
doaddress(&p);
4443
}
4444
 
4445
/*****************************************************************************/
4446
/* qarith : process direct doubleword arithmetic                             */
4447
/*****************************************************************************/
4448
 
4449
void qarith(int co, char noimm)
4450
{
4451
struct relocrecord p = {0};
4452
 
4453
scanoperands(&p);
4454
switch (mode)
4455
  {
4456
  case ADRMODE_IMM :
4457
    if (noimm)
4458
      error |= ERR_ILLEGAL_ADDR;
4459
    opsize = 5;
4460
    putbyte((unsigned short)0xcd);       /* this can ONLY be LDQ!             */
4461
    break;
4462
  case ADRMODE_DIR :
4463
    putword((unsigned)(co + 0x010));
4464
    break;
4465
  case ADRMODE_EXT :
4466
    putword((unsigned)(co + 0x030));
4467
    break;
4468
  default:
4469
    putword((unsigned)(co + 0x020));
4470
    break;
4471
 }
4472
doaddress(&p);
4473
}
4474
 
4475
/*****************************************************************************/
4476
/* oneaddr :                                                                 */
4477
/*****************************************************************************/
4478
 
4479
void oneaddr(int co)
4480
{
4481
struct relocrecord p = {0};
4482
char *s;
4483
 
4484
skipspace();
4485
if ((dwOptions & OPTION_TSC) &&         /* if TSC mode, check for 6800       */
4486
    (co != 0x0e))                       /* convenience things                */
4487
  {
4488
  s = srcptr;
4489
  scanname();                           /* look whether followed by A or B   */
4490
  if (((!strcmp(unamebuf, "A")) ||
4491
       (!strcmp(unamebuf, "B"))) &&
4492
      (*srcptr != ','))                 /* and NO comma                      */
4493
    {                                   /* if so, replace by 6809 mnemonic   */
4494
    warning |= WRN_AMBIG;               /* ... but not without a warning     */
4495
    onebyte(co | ((unamebuf[0] == 'A') ? 0x40 : 0x50));
4496
    return;
4497
    }
4498
  srcptr = s;
4499
  }
4500
 
4501
scanoperands(&p);
4502
switch (mode)
4503
  {
4504
  case ADRMODE_IMM :
4505
    error |= ERR_ILLEGAL_ADDR;
4506
    break;
4507
  case ADRMODE_DIR :
4508
    if ((dwOptions & OPTION_M00) &&     /* on MC6800, a DIRect JMP is not OK */
4509
        (co == 0x0e))
4510
      error |= ERR_ILLEGAL_ADDR;
4511
    else
4512
      putbyte((unsigned short)co);
4513
    break;
4514
  case ADRMODE_EXT :
4515
          if (isFar)
4516
                  putbyte(0x015);
4517
    putbyte((unsigned short)(co + 0x70));
4518
    break;
4519
  default:
4520
          if (isFar)
4521
                  putbyte(0x015);
4522
          if (isPostIndexed)
4523
                  putbyte(0x01B);
4524
    putbyte((unsigned short)(co + 0x60));
4525
    break;
4526
  }
4527
doaddress(&p);
4528
}
4529
 
4530
/*****************************************************************************/
4531
/* accaddr :                                                                 */
4532
/*****************************************************************************/
4533
 
4534
void accaddr(int co)
4535
{
4536
struct relocrecord p = {0};
4537
char *s;
4538
 
4539
skipspace();
4540
if (dwOptions & OPTION_TSC)             /* if TSC mode, check for 6800       */
4541
  {
4542
  s = srcptr;
4543
  scanname();                           /* look whether followed by A or B   */
4544
  if (((!strcmp(unamebuf, "A")) ||
4545
       (!strcmp(unamebuf, "B"))) &&
4546
      (*srcptr != ','))                 /* and NO comma                      */
4547
    {                                   /* if so, replace                    */
4548
    onebyte(co | ((unamebuf[0] == 'A') ? 0x40 : 0x50));
4549
    return;
4550
    }
4551
  srcptr = s;
4552
  }
4553
 
4554
scanoperands(&p);
4555
switch (mode)
4556
  {
4557
  case ADRMODE_IMM :
4558
    error |= ERR_ILLEGAL_ADDR;
4559
    break;
4560
  case ADRMODE_DIR :
4561
    mode = ADRMODE_EXT;                 /* silently convert to extended      */
4562
    putbyte((unsigned short)(co + 0x70));
4563
    break;
4564
  case ADRMODE_EXT :
4565
          if (isFar)
4566
                  putbyte(0x15);
4567
    putbyte((unsigned short)(co + 0x70));
4568
    break;
4569
  default:
4570
          if (isFar)
4571
                  putbyte(0x15);
4572
                if (isPostIndexed)
4573
                        putbyte(0x1B);
4574
    putbyte((unsigned short)(co + 0x60));
4575
    break;
4576
  }
4577
doaddress(&p);
4578
}
4579
 
4580
/*****************************************************************************/
4581
/* tfrexg :                                                                  */
4582
/*****************************************************************************/
4583
 
4584
void tfrexg(int co)
4585
{
4586
struct regrecord * p;
4587
 
4588
putbyte((unsigned char)co);
4589
skipspace();
4590
scanname();
4591
 
4592
if (dwOptions & OPTION_H63)
4593
  p = findreg63(unamebuf);
4594
else
4595
  p = findreg(unamebuf);
4596
if (!p)
4597
  error |= ERR_ILLEGAL_ADDR;
4598
else
4599
 postbyte = (p->tfr) << 4;
4600
skipspace();
4601
if (*srcptr == ',')
4602
  srcptr++;
4603
else
4604
 error |= ERR_ILLEGAL_ADDR;
4605
skipspace();
4606
scanname();
4607
if ((p = findreg(unamebuf)) == 0)
4608
  error |= ERR_ILLEGAL_ADDR;
4609
else
4610
 postbyte |= p->tfr;
4611
putbyte(postbyte);
4612
}
4613
 
4614
/*****************************************************************************/
4615
/* pshpul : operates on PSH / PUL mnemonics                                  */
4616
/*****************************************************************************/
4617
 
4618
void pshpul(int co)
4619
{
4620
struct regrecord *p;
4621
struct relocrecord sp = {0};
4622
 
4623
postbyte = 0;
4624
 
4625
skipspace();
4626
if (*srcptr == '#')
4627
  {
4628
  srcptr++;
4629
  if (!(dwOptions & OPTION_TSC))
4630
    skipspace();
4631
  postbyte = (unsigned short)scanexpr(0, &sp);
4632
  }
4633
else do
4634
  {
4635
  if (*srcptr=='f' || *srcptr=='F') {
4636
          if (srcptr[1]=='a' || srcptr[1]=='A') {
4637
                  if (srcptr[2]=='r' || srcptr[2]=='R') {
4638
                          if (srcptr[3]==' ' || srcptr[3]=='\t') {
4639
                                  isFar = 1;
4640
                                  srcptr += 4;
4641
                          }
4642
                  }
4643
          }
4644
  }
4645
  if (*srcptr == ',')
4646
    srcptr++;
4647
  if (!(dwOptions & OPTION_TSC))
4648
    skipspace();
4649
  scanname();
4650
  if ((p = findreg(unamebuf)) == 0)
4651
    error |= ERR_ILLEGAL_ADDR;
4652
  else
4653
    postbyte |= p->psh;
4654
  if (!(dwOptions & OPTION_TSC))
4655
    skipspace();
4656
  } while (*srcptr == ',');
4657
if (isFar)
4658
        putbyte((unsigned short)0x15);
4659
putbyte((unsigned short)co);
4660
putbyte(postbyte);
4661
}
4662
 
4663
/*****************************************************************************/
4664
/* bitdirect :                                                               */
4665
/*****************************************************************************/
4666
 
4667
void bitdirect(int co)
4668
{
4669
struct relocrecord p = {0};
4670
unsigned short dir;
4671
 
4672
skipspace();
4673
if (*srcptr++ != '#')
4674
  error |= ERR_EXPR;
4675
dir = (unsigned)scanexpr(0, &p);
4676
if (dir & 0xfff000)
4677
  error |= ERR_EXPR;
4678
if (!(dwOptions & OPTION_TSC))
4679
  skipspace();
4680
if (*srcptr++ != ',')
4681
  error |= ERR_EXPR;
4682
scanoperands(&p);
4683
switch (mode)
4684
  {
4685
  case ADRMODE_IMM :
4686
    error |= ERR_ILLEGAL_ADDR;
4687
    break;
4688
  case ADRMODE_DIR :
4689
    putbyte((unsigned short)co);
4690
    break;
4691
  case ADRMODE_EXT :
4692
          if (isFar)
4693
                  putbyte(0x15);
4694
    putbyte((unsigned short)(co + 0x70));
4695
    break;
4696
  default:
4697
          if (isFar)
4698
                  putbyte(0x15);
4699
    putbyte((unsigned short)(co + 0x60));
4700
    break;
4701
  }
4702
putbyte((unsigned short)dir);
4703
doaddress(&p);
4704
}
4705
 
4706
/*****************************************************************************/
4707
/* bittrans :                                                                */
4708
/*****************************************************************************/
4709
 
4710
void bittrans(int co)
4711
{
4712
struct regrecord *p;
4713
struct relocrecord rp = {0};
4714
long t;
4715
 
4716
putword((unsigned)co);
4717
 
4718
skipspace();
4719
scanname();
4720
if ((p = findbitreg(unamebuf)) == 0)
4721
  error |= ERR_ILLEGAL_ADDR;
4722
else
4723
  postbyte = (p->tfr) << 6;
4724
if (!(dwOptions & OPTION_TSC))
4725
  skipspace();
4726
if (*srcptr == ',')
4727
  srcptr++;
4728
else
4729
 error |= ERR_ILLEGAL_ADDR;
4730
if (!(dwOptions & OPTION_TSC))
4731
  skipspace();
4732
t = scanfactor(&rp);
4733
if (t & 0xfffff8)
4734
  error |= ERR_ILLEGAL_ADDR;
4735
else
4736
  postbyte |= (t << 3);
4737
if (!(dwOptions & OPTION_TSC))
4738
  skipspace();
4739
if (*srcptr == ',')
4740
  srcptr++;
4741
else
4742
 error |= ERR_ILLEGAL_ADDR;
4743
t = scanfactor(&rp);
4744
if (t & 0xfffff8)
4745
  error |= ERR_ILLEGAL_ADDR;
4746
else
4747
  postbyte |= t;
4748
putbyte((unsigned short)postbyte);
4749
if (!(dwOptions & OPTION_TSC))
4750
  skipspace();
4751
if (*srcptr == ',')
4752
  srcptr++;
4753
else
4754
 error |= ERR_ILLEGAL_ADDR;
4755
scanoperands(&rp);
4756
switch (mode)
4757
  {
4758
  case ADRMODE_DIR :
4759
    putbyte((unsigned short)operand);
4760
    break;
4761
  default:
4762
    error |= ERR_ILLEGAL_ADDR;
4763
  }
4764
}
4765
 
4766
/*****************************************************************************/
4767
/* blocktrans :                                                              */
4768
/*****************************************************************************/
4769
 
4770
void blocktrans(int co)
4771
{
4772
char reg1,reg2;
4773
char mode[3] = "";
4774
static char regnames[] = "DXYUS";
4775
static char *modes[] =
4776
  {
4777
  "++",
4778
  "--",
4779
  "+",
4780
  ",+"
4781
  };
4782
int i;
4783
 
4784
skipspace();
4785
reg1 = toupper(*srcptr);
4786
for (i = 0; regnames[i]; i++)
4787
  if (reg1 == regnames[i])
4788
    break;
4789
if (!regnames[i])
4790
  error |= ERR_ILLEGAL_ADDR;
4791
else
4792
  reg1 = i;
4793
mode[0] = *++srcptr;
4794
if ((mode[0] != '+') && (mode[0] != '-'))
4795
  {
4796
  if (!(dwOptions & OPTION_TSC))
4797
    skipspace();
4798
  mode[0] = *srcptr;
4799
  }
4800
else
4801
  srcptr++;
4802
if (!(dwOptions & OPTION_TSC))
4803
  skipspace();
4804
if (*srcptr != ',')
4805
  error |= ERR_ILLEGAL_ADDR;
4806
srcptr++;
4807
reg2 = toupper(*srcptr);
4808
for (i = 0; regnames[i]; i++)
4809
  if (reg2 == regnames[i])
4810
    break;
4811
if (!regnames[i])
4812
  error |= ERR_ILLEGAL_ADDR;
4813
else
4814
  reg2 = i;
4815
mode[1] = *++srcptr;
4816
if ((mode[1] != '+') && (mode[1] != '-'))
4817
  {
4818
  if (!(dwOptions & OPTION_TSC))
4819
    skipspace();
4820
  mode[1] = *srcptr;
4821
  }
4822
else
4823
  srcptr++;
4824
if ((mode[1] == ';') || (mode[1] == '*') ||
4825
    (mode[1] == ' ') || (mode[1] == '\t'))
4826
  mode[1] = '\0';
4827
for (i = 0; i < (sizeof(modes) / sizeof(modes[0])); i++)
4828
  if (!strcmp(mode, modes[i]))
4829
    break;
4830
if (i >= (sizeof(modes) / sizeof(modes[0])))
4831
  error |= ERR_ILLEGAL_ADDR;
4832
else
4833
  co |= i;
4834
 
4835
putword((unsigned)co);
4836
putbyte((unsigned short)((reg1 << 4) | reg2));
4837
}
4838
 
4839
/*****************************************************************************/
4840
/* expandline : un-tabify current line                                       */
4841
/*****************************************************************************/
4842
 
4843
void expandline()
4844
{
4845
int i, j = 0, k, j1;
4846
 
4847
for (i = 0; i < LINELEN && j < LINELEN; i++)
4848
  {
4849
  if (inpline[i] == '\n')
4850
    {
4851
    srcline[j] = 0;
4852
    break;
4853
    }
4854
  else if (inpline[i] == '\t')
4855
    {
4856
    j1 = j;
4857
    for (k = 0; k < 8 - j1 % 8 && j < LINELEN; k++)
4858
      srcline[j++] = ' ';
4859
    }
4860
  else if (inpline[i] == '\r')
4861
    {
4862
    continue;
4863
    }
4864
  else
4865
    srcline[j++] = inpline[i];
4866
 }
4867
srcline[LINELEN - 1] = 0;
4868
}
4869
 
4870
/*****************************************************************************/
4871
/* expandtext : expands all texts in a line                                  */
4872
/*****************************************************************************/
4873
 
4874
void expandtext()
4875
{
4876
char *p;
4877
int i, j = 0;
4878
int doit = 1;
4879
 
4880
for (p = curline->txt; (*p) && (j < LINELEN); )
4881
  {
4882
  if (*p == '\"')
4883
    doit = !doit;
4884
 
4885
  if (*p == '\\' && p[1] == '&')
4886
    srcline[j++] = *(++p);
4887
  else if (*p == '&' &&
4888
           (p[1] < '0' || p[1] > '9') &&
4889
           doit)
4890
    {
4891
    struct symrecord *lp;
4892
    srcptr = p + 1;
4893
    scanname();
4894
    lp = findsym(namebuf, 0);
4895
    if ((lp) && (*namebuf) &&           /* if symbol IS a text constant,     */
4896
        (lp->cat == SYMCAT_TEXT))
4897
      {                                 /* insert its content                */
4898
      p = srcptr;
4899
      for (i = 0; j < LINELEN && texts[lp->value][i]; i++)
4900
        srcline[j++] = texts[lp->value][i];
4901
      }
4902
    else                                /* otherwise                         */
4903
      srcline[j++] = *p++;              /* simply use the '&' and go on.     */
4904
    }
4905
  else
4906
    srcline[j++] = *p++;
4907
  }
4908
srcline[j >= LINELEN ? LINELEN - 1 : j] = '\0';
4909
}
4910
 
4911
/*****************************************************************************/
4912
/* readfile : reads in a file and recurses through includes                  */
4913
/*****************************************************************************/
4914
 
4915
struct linebuf *readfile(char *name, unsigned char lvl, struct linebuf *after)
4916
{
4917
FILE *srcfile;
4918
struct linebuf *pNew;
4919
int lineno = 0;
4920
int i;
4921
int nfnidx = -1;
4922
 
4923
for (i = 0; i < nfnms; i++)             /* prohibit recursion                */
4924
  if (!strcmp(name, fnms[i]))
4925
    {
4926
    nfnidx = i;
4927
    break;
4928
    }
4929
if (nfnidx < 0)
4930
  {
4931
  if (nfnms >= (sizeof(fnms) / sizeof(fnms[0])))
4932
    {
4933
    printf("%s(0) : error 21: nesting level too deep\n", name);
4934
    if (((dwOptions & OPTION_LP1) || pass == MAX_PASSNO) && (listing & LIST_ON))
4935
      putlist( "*** Error 21: nesting level too deep\n");
4936
    exit(4);
4937
    }
4938
  nfnidx = nfnms++;
4939
  }
4940
 
4941
if ((srcfile = fopen(name, "r")) == 0)
4942
  {
4943
  printf("%s(0) : error 17: cannot open source file\n", name);
4944
  if (((dwOptions & OPTION_LP1) || pass == MAX_PASSNO) && (listing & LIST_ON))
4945
    putlist( "*** Error 17: cannot open source file\n");
4946
  exit(4);
4947
  }
4948
if (!fnms[nfnidx])                      /* if not yet done,                  */
4949
  fnms[nfnidx] = strdup(name);          /* remember the file name            */
4950
while (fgets(inpline, LINELEN, srcfile))
4951
  {
4952
  expandline();
4953
  pNew = allocline(after, fnms[nfnidx], ++lineno, lvl, srcline);
4954
  if (!pNew)
4955
    {
4956
    printf("%s(%d) : error 22: memory allocation error\n", name, lineno);
4957
    if (((dwOptions & OPTION_LP1) || pass == MAX_PASSNO) && (listing & LIST_ON))
4958
      putlist( "*** Error 22: memory allocation error\n");
4959
    exit(4);
4960
    }
4961
  if (!after)                           /* if 1st line                       */
4962
    rootline = pNew;                    /* remember it as root               */
4963
  after = pNew;                         /* insert behind the new line        */
4964
  }
4965
fclose(srcfile);                        /* then close the file               */
4966
return after;                           /* pass back last line inserted      */
4967
}
4968
 
4969
/*****************************************************************************/
4970
/* readbinary: reads in a binary file and converts to fcw / fcb lines        */
4971
/*****************************************************************************/
4972
 
4973
struct linebuf *readbinary
4974
    (
4975
    char *name,
4976
    unsigned char lvl,
4977
    struct linebuf *after,
4978
    struct symrecord *lp
4979
    )
4980
{
4981
FILE *srcfile;
4982
struct linebuf *pNew;
4983
int lineno = 0;
4984
int i;
4985
int nfnidx = -1;
4986
unsigned char binlin[16];
4987
int binlen;
4988
int fcbstart;
4989
 
4990
for (i = 0; i < nfnms; i++)             /* prohibit recursion                */
4991
  if (!strcmp(name, fnms[i]))
4992
    {
4993
    nfnidx = i;
4994
    break;
4995
    }
4996
if (nfnidx < 0)
4997
  {
4998
  if (nfnms >= (sizeof(fnms) / sizeof(fnms[0])))
4999
    {
5000
    printf("%s(0) : error 21: nesting level too deep\n", name);
5001
    if (((dwOptions & OPTION_LP1) || pass == MAX_PASSNO) && (listing & LIST_ON))
5002
      putlist( "*** Error 21: nesting level too deep\n");
5003
    exit(4);
5004
    }
5005
  nfnidx = nfnms++;
5006
  }
5007
 
5008
if ((srcfile = fopen(name, "rb")) == 0)
5009
  {
5010
  printf("%s(0) : error 17: cannot open source file\n", name);
5011
  if (((dwOptions & OPTION_LP1) || pass == MAX_PASSNO) && (listing & LIST_ON))
5012
    putlist( "*** Error 17: cannot open source file\n");
5013
  exit(4);
5014
  }
5015
if (!fnms[nfnidx])                      /* if not yet done,                  */
5016
  fnms[nfnidx] = strdup(name);          /* remember the file name            */
5017
while ((binlen = (int)fread(binlin, 1, sizeof(binlin), srcfile)) > 0)
5018
  {
5019
  sprintf(inpline, "%s", (lineno || (!lp)) ? "" : lp->name);
5020
  i = 0;
5021
  if ((binlen & (~1)) && (binlen > 7))
5022
    {
5023
    sprintf(inpline + strlen(inpline), "\tFCW\t" /* , (binlen & 1) ? 'B' : 'W' */);
5024
    for (; i < (binlen & ~1); i += 2)
5025
      sprintf(inpline + strlen(inpline), "%s$%02X%02X", (i) ? "," : "",
5026
              binlin[i], binlin[i + 1]);
5027
    expandline();
5028
    pNew = allocline(after, fnms[nfnidx], ++lineno, lvl, srcline);
5029
    if (!pNew)
5030
      {
5031
      printf("%s(%d) : error 22: memory allocation error\n", name, lineno);
5032
      if (((dwOptions & OPTION_LP1) || pass == MAX_PASSNO) && (listing & LIST_ON))
5033
        putlist( "*** Error 22: memory allocation error\n");
5034
      exit(4);
5035
      }
5036
    if (!after)                         /* if 1st line                       */
5037
      rootline = pNew;                  /* remember it as root               */
5038
    after = pNew;                       /* insert behind the new line        */
5039
    inpline[0] = '\0';                  /* reset input line                  */
5040
    }
5041
  if ((binlen & 1) || (binlen <= 7))
5042
    {
5043
    fcbstart = i;
5044
    sprintf(inpline + strlen(inpline), "\tFCB\t");
5045
    for (; i < binlen; i++)
5046
      sprintf(inpline + strlen(inpline), "%s$%02X", (i > fcbstart) ? "," : "",
5047
              binlin[i]);
5048
 
5049
    expandline();
5050
    pNew = allocline(after, fnms[nfnidx], ++lineno, lvl, srcline);
5051
    if (!pNew)
5052
      {
5053
      printf("%s(%d) : error 22: memory allocation error\n", name, lineno);
5054
      if (((dwOptions & OPTION_LP1) || pass == MAX_PASSNO) && (listing & LIST_ON))
5055
        putlist( "*** Error 22: memory allocation error\n");
5056
      exit(4);
5057
      }
5058
    if (!after)                         /* if 1st line                       */
5059
      rootline = pNew;                  /* remember it as root               */
5060
    after = pNew;                       /* insert behind the new line        */
5061
    }
5062
  }
5063
fclose(srcfile);                        /* then close the file               */
5064
return after;                           /* pass back last line inserted      */
5065
}
5066
 
5067
/*****************************************************************************/
5068
/* setoptiontexts : sets up the option text variables                        */
5069
/*****************************************************************************/
5070
 
5071
void setoptiontexts()
5072
{
5073
int i;
5074
                                        /* walk option list                  */
5075
for (i = 0; i < (sizeof(Options) / sizeof(Options[0])); i++)
5076
  {
5077
  if ((dwOptions & Options[i].dwAdd) ||
5078
      (!(dwOptions & ~Options[i].dwRem)))
5079
    settext(Options[i].Name, "1");
5080
  else
5081
    settext(Options[i].Name, "0");
5082
  }
5083
}
5084
 
5085
/*****************************************************************************/
5086
/* setoption : processes an option string                                    */
5087
/*****************************************************************************/
5088
 
5089
int setoption ( char *szOpt )
5090
{
5091
char iopt[4];
5092
int i;
5093
 
5094
for (i = 0; szOpt[i] && i < sizeof(iopt); i++)
5095
  iopt[i] = toupper(szOpt[i]);
5096
if (i >= sizeof(iopt))
5097
  i--;
5098
iopt[i] = '\0';
5099
                                        /* search option list                */
5100
for (i = 0; i < (sizeof(Options) / sizeof(Options[0])); i++)
5101
  {
5102
  if (!strcmp(iopt, Options[i].Name))   /* if option found                   */
5103
    {
5104
    dwOptions |= Options[i].dwAdd;      /* add flags                         */
5105
    dwOptions &= ~Options[i].dwRem;     /* and remove flags                  */
5106
 
5107
    switch (Options[i].dwAdd)           /* afterprocessing for specials:     */
5108
      {
5109
      case OPTION_M09 :                 /* switch to MC6809 processor        */
5110
        optable = optable09;
5111
        optablesize = sizeof(optable09) / sizeof(optable09[0]);
5112
        regtable = regtable09;
5113
        bitregtable = bitregtable09;
5114
        scanoperands = scanoperands09;
5115
        break;
5116
      case OPTION_H63 :                 /* switch to HD6309 processor        */
5117
        optable = optable09;
5118
        optablesize = sizeof(optable09) / sizeof(optable09[0]);
5119
        regtable = regtable63;
5120
        bitregtable = bitregtable09;
5121
        scanoperands = scanoperands09;
5122
        break;
5123
      case OPTION_M00 :                 /* switch to MC6800 processor        */
5124
        optable = optable00;
5125
        optablesize = sizeof(optable00) / sizeof(optable00[0]);
5126
        regtable = regtable00;
5127
        bitregtable = bitregtable00;
5128
        scanoperands = scanoperands00;
5129
        break;
5130
      }
5131
 
5132
    setoptiontexts();
5133
    return 0;                           /* then return OK                    */
5134
    }
5135
  }
5136
 
5137
return 1;                               /* unknown option                    */
5138
}
5139
 
5140
/*****************************************************************************/
5141
/* pseudoop : processes all known pseudo-ops                                 */
5142
/*****************************************************************************/
5143
 
5144
void pseudoop(int co, struct symrecord * lp)
5145
{
5146
int i, j;
5147
char c;
5148
struct relocrecord p = {0};
5149
 
5150
if (common &&                           /* if in COMMON definition mode      */
5151
    (co != PSEUDO_ENDCOM) &&            /* and this is neither ENDCOM        */
5152
    (co != PSEUDO_RMB))                 /* nor RMB                           */
5153
  error |= ERR_EXPR;                    /* this is an error.                 */
5154
 
5155
switch (co)
5156
  {
5157
  case PSEUDO_ABS :                     /* ABS                               */
5158
    absmode = 1;                        /* reset mode to absolute            */
5159
    break;
5160
  case PSEUDO_DEF :                     /* DEFINE                            */
5161
    global++;                           /* all labels from now on are global */
5162
    break;
5163
  case PSEUDO_ENDDEF :                  /* ENDDEF                            */
5164
    if (global)                         /* all labels from now on are local  */
5165
      global--;
5166
    else
5167
      error |= ERR_EXPR;                /* must be paired                    */
5168
    break;
5169
  case PSEUDO_COMMON :                  /* label COMMON                      */
5170
    if (absmode)                        /* if in absolute assembler mode     */
5171
      error |= ERR_RELOCATING;
5172
    if (!lp)
5173
      error |= ERR_LABEL_MISSING;
5174
    else
5175
      lp->cat = SYMCAT_COMMON;
5176
    common++;                           /* go into common mode               */
5177
    commonsym = lp;                     /* remember common symbol            */
5178
    break;
5179
  case PSEUDO_ENDCOM :                  /* ENDCOM                            */
5180
    if (absmode)                        /* if in absolute assembler mode     */
5181
      error |= ERR_RELOCATING;
5182
    if (common)                         /* terminate common mode             */
5183
      common--;
5184
    else
5185
      error |= ERR_EXPR;                /* must be paired                    */
5186
    break;
5187
  case PSEUDO_RMB :                     /* [label] RMB <absolute expression> */
5188
  case PSEUDO_RZB :                     /* [label] RZB <absolute expression> */
5189
    operand = scanexpr(0, &p);
5190
    if (unknown)
5191
      error |= ERR_LABEL_UNDEF;
5192
 
5193
    if (common)                         /* if in common mode                 */
5194
      {
5195
      if ((lp->cat != SYMCAT_EMPTY) &&
5196
          (lp->cat != SYMCAT_UNRESOLVED) &&
5197
          (lp->cat != SYMCAT_COMMONDATA))
5198
        error |= ERR_LABEL_MULT;
5199
      if (lp->cat != SYMCAT_COMMONDATA) /* if not yet done,                  */
5200
        {
5201
        lp->cat = SYMCAT_COMMONDATA;    /* set tymbol type                   */
5202
        lp->u.parent = commonsym;       /* remember COMMON symbol            */
5203
        lp->value = commonsym->value;   /* remember offset from COMMON symbol*/
5204
        commonsym->value +=             /* append # bytes to reserve to -"-  */
5205
            (unsigned short)operand;
5206
        }
5207
      break;
5208
      }
5209
 
5210
    setlabel(lp);
5211
    if (generating && pass == MAX_PASSNO)
5212
      {
5213
      if (co != 0 || outmode == OUT_BIN)
5214
        for (i = 0; i < operand; i++)
5215
          outbyte(0, i);
5216
      else switch (outmode)
5217
        {
5218
        case OUT_SREC :                 /* Motorola S51-09 ?                 */
5219
          flushhex();
5220
          break;
5221
        case OUT_IHEX :                 /* Intel Hex ?                       */
5222
          flushihex();
5223
          break;
5224
        case OUT_FLEX :                 /* FLEX binary ?                     */
5225
          flushflex();
5226
          break;
5227
        }
5228
      }
5229
    loccounter += operand;
5230
    hexaddr = loccounter;
5231
    break;
5232
  case PSEUDO_EQU :                     /* label EQU x                       */
5233
    nRepNext = 0;                       /* reset eventual repeat             */
5234
    operand = scanexpr(0, &p);
5235
    if (!lp)
5236
      error |= ERR_LABEL_MISSING;
5237
    else
5238
      {
5239
      if (lp->cat == SYMCAT_EMPTY ||
5240
          lp->cat == SYMCAT_UNRESOLVED ||
5241
          (lp->value == (unsigned)operand &&
5242
           pass > 1))
5243
        {
5244
        if (exprcat == EXPRCAT_INTADDR)
5245
          lp->cat = SYMCAT_LABEL;
5246
        else
5247
          lp->cat = SYMCAT_CONSTANT;
5248
        lp->value = (unsigned)operand;
5249
        }
5250
      else
5251
        error |= ERR_LABEL_MULT;
5252
      }
5253
    break;
5254
  case PSEUDO_PUB :                     /* PUBLIC a[,b[,c...]]               */
5255
  case PSEUDO_EXT :                     /* EXTERN a[,b[,c...]]               */
5256
    nRepNext = 0;                       /* reset eventual repeat             */
5257
    skipspace();
5258
    while (isalnum(*srcptr))
5259
      {
5260
      scanname();                       /* parse option                      */
5261
      lp = findsym(namebuf, 1);         /* look up the symbol                */
5262
      switch (co)
5263
        {
5264
        case PSEUDO_PUB :               /* PUBLIC a[,b[,c...]]               */
5265
          if (lp->cat == SYMCAT_EMPTY ||
5266
              lp->cat == SYMCAT_UNRESOLVED)
5267
            lp->cat = SYMCAT_PUBLICUNDEF;
5268
          else if (lp->cat == SYMCAT_LABEL)
5269
            lp->cat = SYMCAT_PUBLIC;
5270
          else if (lp->cat == SYMCAT_PUBLICUNDEF)
5271
            error |= ERR_LABEL_UNDEF;
5272
          else if (lp->cat != SYMCAT_PUBLIC)
5273
            error |= ERR_LABEL_MULT;
5274
          break;
5275
        case PSEUDO_EXT :               /* EXTERN a[,b[,c...]]               */
5276
          if (absmode)                  /* if not in relocating asm mode,    */
5277
            error |= ERR_RELOCATING;    /* set error                         */
5278
          if (lp->cat == SYMCAT_EMPTY ||
5279
              lp->cat == SYMCAT_UNRESOLVED)
5280
            lp->cat = SYMCAT_EXTERN;
5281
          else if (lp->cat != SYMCAT_EXTERN)
5282
            error |= ERR_LABEL_MULT;
5283
          break;
5284
        }
5285
      if (*srcptr == ',')
5286
        {
5287
        srcptr++;
5288
        if (!(dwOptions & OPTION_TSC))
5289
          skipspace();
5290
        }
5291
      }
5292
    break;
5293
  case PSEUDO_FCB :                     /* [label] FCB expr[,expr...]        */
5294
    setlabel(lp);
5295
    generating = 1;
5296
    do
5297
      {
5298
      if (*srcptr == ',')
5299
        srcptr++;
5300
      if (!(dwOptions & OPTION_TSC))
5301
        skipspace();
5302
      if (*srcptr == '\"')
5303
        {
5304
        srcptr++;
5305
        while (*srcptr != '\"' && *srcptr)
5306
          putbyte(*srcptr++);
5307
        if (*srcptr == '\"')
5308
          srcptr++;
5309
        }
5310
      else
5311
        {
5312
        putbyte((unsigned short)scanexpr(0, &p));
5313
        if (unknown && pass == MAX_PASSNO)
5314
          error |= ERR_LABEL_UNDEF;
5315
        }
5316
      if (!(dwOptions & OPTION_TSC))
5317
        skipspace();
5318
      } while (*srcptr == ',');
5319
    break;
5320
  case PSEUDO_FCC :                     /* [label] FCC expr[,expr...]        */
5321
    setlabel(lp);
5322
    if (!(dwOptions & OPTION_TSC))
5323
      skipspace();
5324
    if (!(dwOptions & OPTION_TSC))      /* if standard                       */
5325
      {                                 /* accept ONE sequence with an       */
5326
      c = *srcptr++;                    /* arbitrary delimiter character     */
5327
      while (*srcptr != c && *srcptr)
5328
        putbyte(*srcptr++);
5329
      if (*srcptr == c)
5330
        srcptr++;
5331
      }
5332
    else                                /* if TSC extended format            */
5333
      {                                 /* accept MORE sequences             */
5334
      do
5335
        {
5336
        if (*srcptr == ',')
5337
          srcptr++;
5338
        if (!(dwOptions & OPTION_TSC))
5339
          skipspace();
5340
        c = *srcptr;
5341
        if ((c == '$') || isalnum(c))
5342
          {
5343
          putbyte((unsigned short)scanexpr(0, &p));
5344
          if (unknown && pass == MAX_PASSNO)
5345
            error |= ERR_LABEL_UNDEF;
5346
          }
5347
        else
5348
          {
5349
          srcptr++;
5350
          while (*srcptr != c && *srcptr)
5351
            putbyte(*srcptr++);
5352
          if (*srcptr == c)
5353
            srcptr++;
5354
          }
5355
        if (!(dwOptions & OPTION_TSC))
5356
          skipspace();
5357
        } while (*srcptr == ',');
5358
      }
5359
    break;
5360
  case PSEUDO_FCW :                     /* [label] FCW,FDB  expr[,expr...]   */
5361
    setlabel(lp);
5362
    generating = 1;
5363
    do
5364
      {
5365
      if (*srcptr == ',')
5366
        srcptr++;
5367
      if (!(dwOptions & OPTION_TSC))
5368
        skipspace();
5369
      putword((unsigned)scanexpr(0, &p));
5370
      if (unknown && pass == MAX_PASSNO)
5371
        error |= ERR_LABEL_UNDEF;
5372
      if (!(dwOptions & OPTION_TSC))
5373
        skipspace();
5374
      } while (*srcptr == ',');
5375
    break;
5376
  case PSEUDO_FCDW:                     /* [label] FCDW,FDB  expr[,expr...]   */
5377
    setlabel(lp);
5378
    generating = 1;
5379
    do
5380
      {
5381
      if (*srcptr == ',')
5382
        srcptr++;
5383
      if (!(dwOptions & OPTION_TSC))
5384
        skipspace();
5385
      putdword((unsigned __int64)scanexpr(0, &p));
5386
      if (unknown && pass == MAX_PASSNO)
5387
        error |= ERR_LABEL_UNDEF;
5388
      if (!(dwOptions & OPTION_TSC))
5389
        skipspace();
5390
      } while (*srcptr == ',');
5391
    break;
5392
  case PSEUDO_ELSE :                    /* ELSE                              */
5393
    if (inMacro)                        /* don't process if in MACRO def.    */
5394
      break;
5395
    nRepNext = 0;                       /* reset eventual repeat             */
5396
    suppress = 1;
5397
    condline = 1;                       /* this is a conditional line        */
5398
    break;
5399
  case PSEUDO_ENDIF :                   /* ENDIF                             */
5400
    if (inMacro)                        /* don't process if in MACRO def.    */
5401
      break;
5402
    nRepNext = 0;                       /* reset eventual repeat             */
5403
    condline = 1;                       /* this is a conditional line        */
5404
    break;
5405
  case PSEUDO_IF :                      /* IF  <expression>[,<skip>]         */
5406
  case PSEUDO_IFN :                     /* IFN <expression>[,<skip>]         */
5407
    if (inMacro)                        /* don't process if in MACRO def.    */
5408
      break;
5409
    condline = 1;                       /* this is a conditional line        */
5410
    nRepNext = 0;                       /* reset eventual repeat             */
5411
    operand = scanexpr(0, &p);
5412
    if (unknown)
5413
      error |= ERR_LABEL_UNDEF;
5414
    if (co == PSEUDO_IFN)               /* if IFN                            */
5415
      operand = !operand;               /* reverse operand                   */
5416
    if (!(dwOptions & OPTION_TSC))
5417
      skipspace();
5418
    if (*srcptr == ',')                 /* skip count?                       */
5419
      {
5420
      srcptr++;
5421
      if (!(dwOptions & OPTION_TSC))
5422
        skipspace();
5423
      nSkipCount = scanexpr(0, &p);
5424
      if (!operand)
5425
        nSkipCount = 0;
5426
      }
5427
    else if (!operand)
5428
      suppress = 2;
5429
    break;
5430
  case PSEUDO_IFC :                     /* IFC  <string1>,<string2>[,<skip>] */
5431
  case PSEUDO_IFNC :                    /* IFNC <string1>,<string2>[,<skip>] */
5432
    if (inMacro)                        /* don't process if in MACRO def.    */
5433
      break;
5434
    condline = 1;                       /* this is a conditional line        */
5435
    if (!(dwOptions & OPTION_TSC))
5436
      skipspace();
5437
    scanstring(szBuf1, sizeof(szBuf1));
5438
    if (!(dwOptions & OPTION_TSC))
5439
      skipspace();
5440
    if (*srcptr != ',')                 /* if not on comma                   */
5441
      {
5442
      *szBuf2 = '\0';                   /* reset 2nd string                  */
5443
      error |= ERR_EXPR;                /* set error                         */
5444
      }
5445
    else
5446
      {
5447
      srcptr++;
5448
      if (!(dwOptions & OPTION_TSC))
5449
        skipspace();
5450
      scanstring(szBuf2, sizeof(szBuf2));
5451
      if (!(dwOptions & OPTION_TSC))
5452
        skipspace();
5453
      }
5454
    operand = !strcmp(szBuf1, szBuf2);
5455
    if (co == PSEUDO_IFNC)
5456
      operand = !operand;
5457
    if (*srcptr == ',')                 /* if skip count                     */
5458
      {
5459
      srcptr++;
5460
      if (!(dwOptions & OPTION_TSC))
5461
        skipspace();
5462
      nSkipCount = scanexpr(0, &p);
5463
      if (!operand)
5464
        nSkipCount = 0;
5465
      }
5466
    else if (!operand)
5467
      suppress = 2;
5468
    break;
5469
 
5470
  case PSEUDO_IFD :                     /* IFD <symbol>[,skipcount]          */
5471
  case PSEUDO_IFND :                    /* IFND <symbol>[,skipcount]         */
5472
    /* ATTENTION: it is easy to produce phasing errors with these 2,         */
5473
    /*            since symbols are NOT reset when starting pass 2!          */
5474
    if (inMacro)                        /* don't process if in MACRO def.    */
5475
      break;
5476
    skipspace();
5477
    scanname();                         /* parse symbol name                 */
5478
    lp = findsym(namebuf, 0);           /* look up the symbol                */
5479
    if (!(dwOptions & OPTION_TSC))
5480
      skipspace();
5481
    if (*srcptr == ',')                 /* if skip count                     */
5482
      {
5483
      srcptr++;
5484
      if (!(dwOptions & OPTION_TSC))
5485
        skipspace();
5486
      nSkipCount = scanexpr(0, &p);
5487
      if (!lp != (co == PSEUDO_IFND))
5488
        nSkipCount = 0;
5489
      }
5490
                                        /* if no skip count and NOT matched  */
5491
    else if (!lp != (co == PSEUDO_IFND))
5492
      suppress = 2;                     /* suppress until ELSE or ENDIF      */
5493
    condline = 1;                       /* this is a conditional line        */
5494
    break;
5495
 
5496
  case PSEUDO_ORG :                     /* ORG <expression>                  */
5497
    nRepNext = 0;                       /* reset eventual repeat             */
5498
    operand = scanexpr(0, &p);
5499
    if (unknown)
5500
      error |= ERR_LABEL_UNDEF;
5501
    if (relocatable &&                  /* if in relocating assembler mode   */
5502
        (!absmode))
5503
      {
5504
      error |= ERR_RELOCATING;          /* set error                         */
5505
      break;                            /* and ignore                        */
5506
      }
5507
    if (generating && pass == MAX_PASSNO)
5508
      {
5509
      switch (outmode)
5510
        {
5511
        case OUT_BIN :                  /* binary output file                */
5512
          j = (int)(unsigned)operand - (int)loccounter;
5513
          if (j > 0)                    /* if forward gap                    */
5514
            {
5515
            for (i = 0; i < j; i++)     /* seek forward that many bytes      */
5516
              fseek(objfile, 1, SEEK_CUR);
5517
            }
5518
          else                          /* if backward gap                   */
5519
            {
5520
            j = -j;
5521
            for (i = 0; i < j; i++)     /* seek back that many bytes         */
5522
              fseek(objfile, -1, SEEK_CUR);
5523
            }
5524
          break;
5525
                case OUT_VER:
5526
                        flushver();
5527
                        break;
5528
        case OUT_SREC :                 /* motorola s51-09                   */
5529
          flushhex();
5530
          break;
5531
        case OUT_IHEX :                 /* intel hex format                  */
5532
          flushihex();
5533
          break;
5534
        case OUT_FLEX :                 /* FLEX binary                       */
5535
          flushflex();
5536
          break;
5537
        }
5538
      }
5539
    loccounter = operand;
5540
    hexaddr = loccounter;
5541
    break;
5542
  case PSEUDO_SETDP :                   /* SETDP [<abs page value>]          */
5543
    nRepNext = 0;                       /* reset eventual repeat             */
5544
    skipspace();
5545
    if ((!*srcptr) || (*srcptr == '*') || (*srcptr == ';'))
5546
      operand = -1;
5547
    else
5548
      operand = scanexpr(0, &p);
5549
    if (unknown)
5550
      error |= ERR_LABEL_UNDEF;
5551
    if (!(operand & 4095))
5552
      operand = (unsigned)operand >> 12;
5553
    if ((unsigned)operand > 4095)
5554
      operand = -1;
5555
    if (absmode)
5556
      dpsetting = operand;
5557
    else
5558
      error |= ERR_RELOCATING;
5559
    break;
5560
  case PSEUDO_SET :                     /* label SET <non external expr>     */
5561
    nRepNext = 0;                       /* reset eventual repeat             */
5562
    operand = scanexpr(0, &p);
5563
    if (!lp)
5564
      error |= ERR_LABEL_MISSING;
5565
    else
5566
      {
5567
      if (lp->cat & SYMCAT_VARIABLE ||
5568
          lp->cat == SYMCAT_UNRESOLVED)
5569
        {
5570
        if (exprcat == EXPRCAT_INTADDR)
5571
          lp->cat = SYMCAT_VARADDR;
5572
        else
5573
          lp->cat = SYMCAT_VARIABLE;
5574
        lp->value = (unsigned)operand;
5575
        }
5576
      else
5577
        error |= ERR_LABEL_MULT;
5578
      }
5579
    break;
5580
  case PSEUDO_END :                     /* END [loadaddr]                    */
5581
    nRepNext = 0;                       /* reset eventual repeat             */
5582
    if ((curline->lvl & 0x0f) == 0)     /* only in outermost level!          */
5583
      {
5584
      skipspace();                      /* skip blanks                       */
5585
      if (isfactorstart(*srcptr))       /* if possible transfer address      */
5586
        {
5587
        tfradr = (unsigned)       /* get transfer address              */
5588
            scanexpr(0, &p);
5589
        if (error)                      /* if error in here                  */
5590
          tfradr = 0;                   /* reset to zero                     */
5591
        else                            /* otherwise                         */
5592
          tfradrset = 1;                /* remember transfer addr. is set    */
5593
        }
5594
      terminate = 1;
5595
      }
5596
    break;
5597
  case PSEUDO_INCLUDE :                 /* INCLUDE <filename>                */
5598
    nRepNext = 0;                       /* reset eventual repeat             */
5599
    if (inMacro ||                      /* if in macro definition            */
5600
        (curline->lvl & LINCAT_MACEXP)) /* or macro expansion                */
5601
      error |= ERR_EXPR;                /* this is an error.                 */
5602
    else if (pass == 1)                 /* otherwise expand if in pass 1     */
5603
      {
5604
      char fname[FNLEN + 1];
5605
      int instring = 0;
5606
      char *osrc = srcptr;
5607
 
5608
      if ((curline->lvl & 0x0f) == 0x0f)/* if impossible                     */
5609
        {
5610
#if 0
5611
        allocline(curline, "NULL", -1, 0x0f,
5612
                  "Error including file - nesting level too deep");
5613
#endif
5614
        error |= ERR_MALLOC;            /* set OUT OF MEMORY error           */
5615
        break;
5616
        }
5617
      if (!(dwOptions & OPTION_TSC))
5618
        skipspace();
5619
      if (*srcptr == '\"')
5620
        {
5621
        srcptr++;
5622
        instring = 1;
5623
        }
5624
      for (i = 0; i < FNLEN; i++)
5625
        {
5626
        if (*srcptr == 0 ||
5627
            (!instring && *srcptr == ' ') ||
5628
            *srcptr == '"')
5629
          break;
5630
        fname[i] = *srcptr++;
5631
        }
5632
      fname[i] = 0;
5633
      curline->lvl |= LINCAT_INVISIBLE; /* preclude listing of INCLUDE line  */
5634
 
5635
      readfile(fname,                   /* append include after current line */
5636
               (unsigned char)((curline->lvl & 0x0f) + 1),
5637
               curline);
5638
      expandtext();                     /* re-expand current line            */
5639
      srcptr = osrc;
5640
      }
5641
    break;
5642
  case PSEUDO_OPT :                     /* OPT,OPTION  option[,option...]    */
5643
    nRepNext = 0;                       /* reset eventual repeat             */
5644
    skipspace();
5645
    while (isalnum(*srcptr))
5646
      {
5647
      scanname();                       /* parse option                      */
5648
      if (setoption(unamebuf))
5649
        error |= ERR_OPTION_UNK;
5650
      if (*srcptr == ',')
5651
        {
5652
        srcptr++;
5653
        if (!(dwOptions & OPTION_TSC))
5654
          skipspace();
5655
        }
5656
      }
5657
    break;
5658
  case PSEUDO_NAM :                     /* NAM,TTL <text>                    */
5659
  case PSEUDO_STTL :                    /* STTL <text>                       */
5660
    nRepNext = 0;                       /* reset eventual repeat             */
5661
    if (!(dwOptions & OPTION_TSC))
5662
      skipspace();
5663
    if (isalnum(*srcptr))
5664
      {
5665
      char *tgt = (co == PSEUDO_NAM) ? szTitle : szSubtitle;
5666
      char *lnblnk = tgt;
5667
      int nBytes = 0;
5668
      while (*srcptr && nBytes < (sizeof(szTitle) - 1))
5669
        {
5670
        if (*srcptr != ' ')
5671
          lnblnk = tgt;
5672
        *tgt++ = *srcptr++;
5673
        nBytes++;
5674
        }
5675
      lnblnk[1] = '\0';                 /* terminate after last nonblank     */
5676
      while (*srcptr)                   /* skip rest if too long             */
5677
        srcptr++;
5678
      }
5679
    break;
5680
  case PSEUDO_PAG :                     /* PAG [<abs expression>]            */
5681
    if (!(dwOptions & OPTION_TSC))
5682
      skipspace();
5683
    if (isfactorstart(*srcptr))         /* if possible new page number       */
5684
      {
5685
      int nPage = scanexpr(0, &p);      /* get new page #                    */
5686
      if (!error && listfile)           /* if valid and writing listfile     */
5687
        nCurPage = nPage - 1;
5688
      else
5689
        break;
5690
      }
5691
    curline->lvl |= LINCAT_INVISIBLE;
5692
    if ((listing & LIST_ON) && listfile &&
5693
        (dwOptions & OPTION_PAG) &&
5694
        (!(curline->lvl & LINCAT_LVLMASK) || (dwOptions & OPTION_LLL)) &&
5695
        (pass > 1 || (dwOptions & OPTION_LP1)))
5696
      PageFeed();
5697
    break;
5698
  case PSEUDO_SPC :                     /* SPC <n[,keep]>                    */
5699
    {
5700
    int nSpc = 1, nKeep = 0;
5701
    if (!(dwOptions & OPTION_TSC))
5702
      skipspace();
5703
    if (isfactorstart(*srcptr))         /* if possible new page number       */
5704
      {
5705
      nSpc = scanexpr(0, &p);           /* get # space lines                 */
5706
      if (!(dwOptions & OPTION_TSC))
5707
        skipspace();
5708
      if (*srcptr == ',')               /* if followed by ,                  */
5709
        {
5710
        srcptr++;
5711
        if (!(dwOptions & OPTION_TSC))
5712
          skipspace();
5713
        nKeep = scanexpr(0, &p);        /* get # keep lines                  */
5714
        }
5715
      if (error)
5716
        break;
5717
      }
5718
    curline->lvl |= LINCAT_INVISIBLE;
5719
    if (listing & LIST_ON)
5720
      {
5721
      if (nSpc > 0)                     /* if spaces needed                  */
5722
        {
5723
        if ((dwOptions & OPTION_PAG) &&
5724
            (nCurLine + nSpc + nKeep >= nLinesPerPage))
5725
          PageFeed();
5726
        else for (; nSpc; nSpc--)
5727
          putlist("\n");
5728
        }
5729
      else if (nKeep &&
5730
          (dwOptions & OPTION_PAG) &&
5731
          (nCurLine + nKeep >= nLinesPerPage))
5732
        PageFeed();
5733
      }
5734
    }
5735
    break;
5736
  case PSEUDO_REP :                     /* REP n                             */
5737
    if (!(dwOptions & OPTION_TSC))
5738
      skipspace();
5739
    nRepNext = scanexpr(0, &p);         /* get # repetitions                 */
5740
    curline->lvl |= LINCAT_INVISIBLE;
5741
    break;
5742
  case PSEUDO_SETPG :                   /* SETPG pagelen                     */
5743
    if (!(dwOptions & OPTION_TSC))
5744
      skipspace();
5745
    nLinesPerPage = scanexpr(0, &p);    /* get # lines per page              */
5746
    if (nLinesPerPage < 10)             /* adjust to boundary values         */
5747
      nLinesPerPage = 10;
5748
    else if (nLinesPerPage > 1000)
5749
      nLinesPerPage = 1000;
5750
    curline->lvl |= LINCAT_INVISIBLE;
5751
    break;
5752
  case PSEUDO_SETLI :                   /* SETLI linelen                     */
5753
    if (!(dwOptions & OPTION_TSC))
5754
      skipspace();
5755
    nColsPerLine = scanexpr(0, &p);     /* get # columns per line            */
5756
    if (nColsPerLine < 40)              /* adjust to boundary values         */
5757
      nColsPerLine = 40;
5758
    else if (nColsPerLine > 2000)
5759
      nColsPerLine = 2000;
5760
    curline->lvl |= LINCAT_INVISIBLE;
5761
    break;
5762
  case PSEUDO_SYMLEN :                  /* SYMLEN symbollength               */
5763
    if (!(dwOptions & OPTION_TSC))
5764
      skipspace();
5765
    maxidlen = scanexpr(0, &p);         /* get # significant ID places       */
5766
    if (maxidlen < 6)                   /* adjust to boundary values         */
5767
      maxidlen = 6;
5768
    else if ((outmode == OUT_REL) &&
5769
             (maxidlen > 8))
5770
      maxidlen = 8;
5771
    else if (maxidlen > MAXIDLEN)
5772
      maxidlen = MAXIDLEN;
5773
    curline->lvl |= LINCAT_INVISIBLE;
5774
    break;
5775
  case PSEUDO_MACRO :                   /* label MACRO                       */
5776
    if (!lp)                            /* a macro NEEDS a label!            */
5777
      error |= ERR_LABEL_MISSING;
5778
    if (lp->cat == SYMCAT_EMPTY)
5779
      {
5780
      if (nMacros < MAXMACROS)          /* if space for another macro defin. */
5781
        {
5782
        lp->cat = SYMCAT_MACRO;         /* remember it's a macro             */
5783
        macros[nMacros] = curline;      /* remember pointer to start line    */
5784
        lp->value = nMacros++;          /* and remember the macro            */
5785
        }
5786
      else
5787
        error |= ERR_MALLOC;
5788
      }
5789
    else if (lp->cat != SYMCAT_MACRO ||
5790
             macros[lp->value] != curline)
5791
      error |= ERR_LABEL_MULT;
5792
    inMacro++;
5793
    curline->lvl |= LINCAT_MACDEF;
5794
    if (inMacro > 1)
5795
      error |= ERR_NESTING;
5796
    break;
5797
  case PSEUDO_ENDM :                    /* ENDM                              */
5798
    if (!inMacro)
5799
      error |= ERR_EXPR;
5800
    else
5801
      inMacro--;
5802
    break;
5803
  case PSEUDO_EXITM :                   /* EXITM                             */
5804
    if (!inMacro &&                     /* only allowed inside macros        */
5805
         !(curline->lvl & LINCAT_MACEXP))
5806
      error |= ERR_EXPR;
5807
    break;
5808
  case PSEUDO_REG :                     /* label REG <register list>         */
5809
    if (!lp)                            /* label is mandatory!               */
5810
      error |= ERR_LABEL_MISSING;
5811
    {
5812
    struct regrecord *p;
5813
    postbyte = 0;
5814
    do
5815
      {
5816
      if (*srcptr == ',')
5817
        srcptr++;
5818
      if (!(dwOptions & OPTION_TSC))
5819
        skipspace();
5820
      scanname();
5821
      if ((p = findreg(unamebuf)) == 0)
5822
        error |= ERR_ILLEGAL_ADDR;
5823
      else
5824
        postbyte |= p->psh;
5825
      if (!(dwOptions & OPTION_TSC))
5826
        skipspace();
5827
      } while (*srcptr == ',');
5828
    if (lp->cat == SYMCAT_EMPTY)
5829
      {
5830
      lp->cat = SYMCAT_REG;
5831
      lp->value = postbyte;
5832
      }
5833
    else if (lp->cat != SYMCAT_REG ||
5834
             lp->value != postbyte)
5835
      error |= ERR_LABEL_MULT;
5836
    }
5837
    break;
5838
  case PSEUDO_ERR :                     /* ERR text?                         */
5839
    if (!(dwOptions & OPTION_TSC))
5840
      skipspace();
5841
    if (pass != 1)                      /* ignore in pass 1                  */
5842
      {
5843
      errormsg[14] = srcptr;
5844
      error |= ERR_ERRTXT;
5845
      }
5846
    break;
5847
  case PSEUDO_TEXT :                    /* TEXT text ?                       */
5848
    if (!(dwOptions & OPTION_TSC))
5849
      skipspace();
5850
    if (!lp)                            /* label is mandatory!               */
5851
      error |= ERR_LABEL_MISSING;
5852
    else if (lp->cat != SYMCAT_EMPTY && /* and must be text, if there        */
5853
             lp->cat != SYMCAT_TEXT)
5854
      error |= ERR_LABEL_MULT;
5855
    else                                /* if all OK, (re)define text        */
5856
      settext(lp->name, srcptr);
5857
    break;
5858
  case PSEUDO_NAME :                    /* NAME <modulename> ?               */
5859
    if (!(dwOptions & OPTION_TSC))
5860
      skipspace();
5861
    scanname();
5862
    if (!namebuf[0])                    /* name must be given                */
5863
      error |= ERR_EXPR;
5864
    strncpy(modulename, namebuf, 8);
5865
    break;
5866
  case PSEUDO_BINARY :                  /* BIN[ARY] <filename> ?             */
5867
    nRepNext = 0;                       /* reset eventual repeat             */
5868
    if (pass == 1)                      /* expand if in pass 1               */
5869
      {
5870
      char fname[FNLEN + 1];
5871
      int instring = 0;
5872
      char *osrc = srcptr;
5873
 
5874
      if (!(dwOptions & OPTION_TSC))
5875
        skipspace();
5876
      if (*srcptr == '\"')
5877
        {
5878
        srcptr++;
5879
        instring = 1;
5880
        }
5881
      for (i = 0; i < FNLEN; i++)
5882
        {
5883
        if (*srcptr == 0 ||
5884
            (!instring && *srcptr == ' ') ||
5885
            *srcptr == '"')
5886
          break;
5887
        fname[i] = *srcptr++;
5888
        }
5889
      fname[i] = 0;
5890
      curline->lvl |= LINCAT_INVISIBLE; /* preclude listing of BINARY line   */
5891
 
5892
      readbinary(fname,                 /* append binary after current line  */
5893
               (unsigned char)((curline->lvl & 0x0f) + 1),
5894
               curline, lp);
5895
      expandtext();                     /* re-expand current line            */
5896
      srcptr = osrc;
5897
      }
5898
    break;
5899
  }
5900
}
5901
 
5902
/*****************************************************************************/
5903
/* macskip : skips a range of macro lines                                    */
5904
/*****************************************************************************/
5905
 
5906
struct linebuf *macskip(struct linebuf *pmac, int nSkips)
5907
{
5908
if (nSkips < 0)                         /* we need to go to the line BEFORE  */
5909
  nSkips--;                             /* the one we need!                  */
5910
while (nSkips)
5911
  {
5912
  if (nSkips < 0)
5913
    {
5914
    if (!pmac->prev)
5915
      break;
5916
    pmac = pmac->prev;
5917
    nSkips++;
5918
    }
5919
  else
5920
    {
5921
    if (!pmac->next)
5922
      break;
5923
    pmac = pmac->next;
5924
    nSkips--;
5925
    }
5926
  }
5927
return pmac;
5928
}
5929
 
5930
/*****************************************************************************/
5931
/* expandmacro : expands a macro definition below the current line           */
5932
/*****************************************************************************/
5933
 
5934
void expandmacro(struct symrecord *lp, struct symrecord *lpmac)
5935
{
5936
struct oprecord *op;
5937
char szMacInv[LINELEN];                 /* macro invocation line             */
5938
char szLine[LINELEN];                   /* current macro line                */
5939
char *szMacParm[10];
5940
char *s, *d;                            /* source / destination work pointers*/
5941
char *srcsave = srcptr;
5942
struct linebuf *cursave = curline;
5943
int nMacParms = 1;
5944
int nInString = 0;
5945
int nMacLine = 1;                       /* current macro line                */
5946
                                        /* current macro line                */
5947
struct linebuf *pmac = macros[lpmac->value]->next;
5948
struct linebuf *pcur = curline;         /* current expanded macro line       */
5949
struct linebuf *pdup = NULL;            /* DUP start line                    */
5950
int nDup = 0;                           /* # repetitions for DUP             */
5951
int terminate = 0;                      /* terminate macro expansion if set  */
5952
int skipit = 0;                         /* skip this line                    */
5953
int suppress[64] = {0};                 /* internal suppression (max.64 lvl) */
5954
int ifcount = 0;                        /* internal if counter               */
5955
struct relocrecord p = {0};
5956
 
5957
if ((listing & LIST_ON) &&              /* if listing pass 1                 */
5958
    (dwOptions & OPTION_LIS) &&
5959
    (dwOptions & OPTION_LP1))
5960
  outlist(NULL);                        /* show macro invocation BEFORE      */
5961
                                        /* processing the expansions         */
5962
 
5963
skipspace();                            /* skip spaces before macro args     */
5964
 
5965
if (!lp)                                /* if no macro label                 */
5966
  szMacParm[0] = "";                    /* set &0 to blank                   */
5967
else                                    /* otherwise                         */
5968
  szMacParm[0] = lp->name;              /* set &0 to line label              */
5969
                                        /* initialize all parameters to ""   */
5970
for (nMacParms = 1; nMacParms < 10; nMacParms++)
5971
  szMacParm[nMacParms] = "";
5972
nMacParms = 1;                          /* reset # parsed parms to 1         */
5973
 
5974
strcpy(szMacInv, srcptr);               /* copy the current line for mangling*/
5975
srcptr = szMacInv;                      /* set pointer to internal buffer    */
5976
do
5977
  {
5978
  while (*srcptr == ',')                /* skip parameter delimiter(s)       */
5979
    {
5980
    *srcptr++ = '\0';                   /* delimit & advance behind it       */
5981
    if (!(dwOptions & OPTION_TSC))
5982
      skipspace();
5983
    }
5984
                                        /* OK, next string...                */
5985
  if ((*srcptr == '\'') ||              /* if delimited string               */
5986
      (*srcptr == '\"'))
5987
    nInString = 1;                      /* remember we're in delimited strg  */
5988
  szMacParm[nMacParms] = srcptr++;      /* store parameter start pointer     */
5989
  while (*srcptr)                       /* walk to end of parameter          */
5990
    {
5991
    if (!nInString &&
5992
        ((*srcptr == ' ') || (*srcptr == ',')))
5993
      break;
5994
    else if (nInString &&
5995
             *srcptr == *szMacParm[nMacParms])
5996
      {
5997
      srcptr++;
5998
      break;
5999
      }
6000
    srcptr++;
6001
    }
6002
  if (*srcptr && *srcptr != ',')
6003
    {
6004
    *srcptr++ = '\0';
6005
    if (!(dwOptions & OPTION_TSC))
6006
      skipspace();
6007
    }
6008
  nMacParms++;
6009
  if (nMacParms >= 10)
6010
    break;
6011
  } while (*srcptr == ',');
6012
 
6013
/*---------------------------------------------------------------------------*/
6014
/* OK, got macro arguments &0...&9 now                                       */
6015
/*---------------------------------------------------------------------------*/
6016
 
6017
while (pmac)                            /* walk through the macro lines      */
6018
  {
6019
  srcptr = s = pmac->txt;
6020
  d = szLine;
6021
  op = NULL;
6022
  skipit = 0;
6023
 
6024
  while (*s)                            /* first, expand the line            */
6025
    {
6026
    if (*s == '\\' && s[1] == '&')
6027
      {
6028
      s++;
6029
      *d++ = *s++;
6030
      }
6031
    else if (*s == '&' && s[1] >= '0' && s[1] <= '9')
6032
      {
6033
      strcpy(d, szMacParm[s[1] - '0']);
6034
      s += 2;
6035
      d += strlen(d);
6036
      }
6037
    else
6038
      *d++ = *s++;
6039
    }
6040
  *d = '\0';
6041
 
6042
  srcptr = szLine;                      /* then, look whether code or macro  */
6043
  if (isalnum(*srcptr))
6044
    {
6045
    scanname();
6046
    lp = findsym(namebuf, 1);
6047
    if (*srcptr == ':')
6048
      srcptr++;
6049
    }
6050
  skipspace();
6051
  if (isalnum(*srcptr))                 /* then parse opcode                 */
6052
    {
6053
    scanname();
6054
    op = findop(unamebuf);
6055
    }
6056
  skipspace();                          /* and skip to eventual parameter    */
6057
 
6058
  if (op && op->cat == OPCAT_PSEUDO)    /* if pseudo-op                      */
6059
    {
6060
    switch (op->code)                   /* examine for macro expansion       */
6061
      {
6062
      case PSEUDO_ENDM :                /* ENDM ?                            */
6063
        terminate = 1;                  /* terminate macro expansion         */
6064
        break;
6065
      case PSEUDO_EXITM :               /* EXITM ?                           */
6066
        if (!suppress[ifcount])         /* if not suppressed                 */
6067
          terminate = 1;                /* terminate macro expansion         */
6068
        break;
6069
      case PSEUDO_DUP :                 /* DUP ?                             */
6070
        if (pdup != NULL)               /* nesting not allowed               */
6071
          error |= ERR_NESTING;
6072
        else
6073
          {
6074
          nDup = scanexpr(0, &p);       /* scan the expression               */
6075
          pdup = pmac;                  /* remember DUP start line           */
6076
          if (nDup < 1 || nDup > 255)   /* if invalid # repetitions          */
6077
            {
6078
            error |= ERR_EXPR;          /* set error here                    */
6079
            nDup = 1;
6080
            }
6081
          else
6082
            skipit = 1;                 /* skip this line                    */
6083
          }
6084
        break;
6085
      case PSEUDO_ENDD :                /* ENDD ?                            */
6086
        if (!pdup)                      /* if no DUP defined                 */
6087
          error |= ERR_EXPR;            /* can't do that here.               */
6088
        else
6089
          {
6090
          nDup--;                       /* decrement # duplications          */
6091
          if (!nDup)                    /* if done,                          */
6092
            pdup = NULL;                /* reset dup start                   */
6093
          else                          /* otherwise                         */
6094
            pmac = pdup;                /* reset current line to DUP op      */
6095
          skipit = 1;                   /* this line isn't really there      */
6096
          }
6097
        break;
6098
      case PSEUDO_IF :                  /* IF                                */
6099
      case PSEUDO_IFN :                 /* IFN                               */
6100
        ifcount++;                      /* increment # ifs                   */
6101
                                        /* take suppression from higher level*/
6102
        suppress[ifcount] = suppress[ifcount - 1];
6103
        if (suppress[ifcount])          /* if already suppressed             */
6104
          suppress[ifcount]++;          /* inrease # suppressions            */
6105
        else                            /* otherwise evaluate expression     */
6106
          {
6107
          operand = scanexpr(0, &p);
6108
          if (unknown)
6109
            error |= ERR_LABEL_UNDEF;
6110
          if (op->code == PSEUDO_IFN)   /* if IFN                            */
6111
            operand = !operand;         /* invert operand                    */
6112
          if (!operand)                 /* if evaulation to zer0             */
6113
            suppress[ifcount]++;        /* suppress until ELSE or ENDIF      */
6114
          if (!(dwOptions & OPTION_TSC))
6115
            skipspace();
6116
          if (*srcptr == ',')           /* if skip count passed              */
6117
            {
6118
            int nSkips;
6119
            srcptr++;
6120
            if (!(dwOptions & OPTION_TSC))
6121
              skipspace();
6122
            nSkips = scanexpr(0, &p);   /* scan skip count                   */
6123
            ifcount--;                  /* this needs no ENDIF               */
6124
            if (nSkips < -255 || nSkips > 255 || nSkips == 0)
6125
              {
6126
              error |= ERR_EXPR;
6127
              break;
6128
              }
6129
            if (operand)                /* if evaluation is true             */
6130
              pmac = macskip(pmac, nSkips); /* then skip the amount of lines */
6131
            }
6132
          }
6133
        skipit = 1;                     /* don't add this line!              */
6134
        break;
6135
      case PSEUDO_IFC :                 /* IFC                               */
6136
      case PSEUDO_IFNC :                /* IFNC                              */
6137
        ifcount++;                      /* increment # ifs                   */
6138
                                        /* take suppression from higher level*/
6139
        suppress[ifcount] = suppress[ifcount - 1];
6140
        if (suppress[ifcount])          /* if already suppressed             */
6141
          suppress[ifcount]++;          /* inrease # suppressions            */
6142
        else                            /* otherwise evaluate expression     */
6143
          {
6144
          if (!(dwOptions & OPTION_TSC))
6145
            skipspace();
6146
          scanstring(szBuf1, sizeof(szBuf1));
6147
          if (!(dwOptions & OPTION_TSC))
6148
            skipspace();
6149
          if (*srcptr != ',')           /* if not on comma                   */
6150
            {
6151
            *szBuf2 = '\0';             /* reset 2nd string                  */
6152
            error |= ERR_EXPR;          /* set error                         */
6153
            }
6154
          else
6155
            {
6156
            srcptr++;
6157
            if (!(dwOptions & OPTION_TSC))
6158
              skipspace();
6159
            scanstring(szBuf2, sizeof(szBuf2));
6160
            }
6161
          operand = !strcmp(szBuf1, szBuf2);
6162
          if (op->code == PSEUDO_IFNC)
6163
            operand = !operand;
6164
          if (!operand)                 /* if evaulation to zer0             */
6165
            suppress[ifcount]++;        /* suppress until ELSE or ENDIF      */
6166
          if (!(dwOptions & OPTION_TSC))
6167
            skipspace();
6168
          if (*srcptr == ',')           /* if skip count passed              */
6169
            {
6170
            int nSkips;
6171
            srcptr++;
6172
            if (!(dwOptions & OPTION_TSC))
6173
              skipspace();
6174
            nSkips = scanexpr(0, &p);   /* scan skip count                   */
6175
            ifcount--;                  /* this needs no ENDIF               */
6176
            if (nSkips < -255 || nSkips > 255 || nSkips == 0)
6177
              {
6178
              error |= ERR_EXPR;
6179
              break;
6180
              }
6181
            if (operand)                /* if evaluation is true             */
6182
              pmac = macskip(pmac, nSkips); /* then skip the amount of lines */
6183
            }
6184
          }
6185
        if (!error)
6186
          skipit = 1;                   /* don't add this line!              */
6187
        break;
6188
      case PSEUDO_ELSE :                /* ELSE                              */
6189
        if (!suppress[ifcount])         /* if IF not suppressed              */
6190
          suppress[ifcount]++;          /* suppress ELSE clause              */
6191
        else                            /* otherwise                         */
6192
          suppress[ifcount]--;          /* decrement suppression             */
6193
        skipit = 1;                     /* don't add this line!              */
6194
        break;
6195
      case PSEUDO_ENDIF :               /* ENDIF                             */
6196
        if (ifcount)
6197
          ifcount--;
6198
        if (suppress[ifcount])
6199
          suppress[ifcount]--;
6200
        skipit = 1;                     /* don't add this line!              */
6201
        break;
6202
      }
6203
    }
6204
 
6205
  if (terminate)                        /* if macro termination needed       */
6206
    break;                              /* terminate here                    */
6207
 
6208
  if (!skipit && !suppress[ifcount])    /* if not skipping this one          */
6209
    {                                   /* add line to source                */
6210
    pcur = allocline(pcur, curline->fn, curline->ln, LINCAT_MACEXP, szLine);
6211
    if (!pcur)
6212
      {
6213
      error |= ERR_MALLOC;
6214
      break;
6215
      }
6216
    else
6217
      {
6218
      curline = pcur;
6219
      error = ERR_OK;
6220
      warning = WRN_OK;
6221
      expandtext();
6222
      processline();
6223
      }
6224
    }
6225
  pmac = pmac->next;
6226
  }
6227
 
6228
curline = cursave;
6229
expandtext();
6230
srcptr = srcsave;                       /* restore source pointer            */
6231
codeptr = 0;
6232
}
6233
 
6234
/*****************************************************************************/
6235
/* processline : processes a source line                                     */
6236
/*****************************************************************************/
6237
 
6238
void processline()
6239
{
6240
struct symrecord *lp, *lpmac;
6241
struct oprecord *op = NULL;
6242
__int64 co;
6243
short cat;
6244
short c;
6245
char noimm;
6246
 
6247
#if 0
6248
srcptr = curline->txt;
6249
#else
6250
srcptr = srcline;
6251
#endif
6252
 
6253
oldlc = loccounter;
6254
unknown = 0;
6255
certain = 1;
6256
lp = 0;
6257
codeptr = 0;
6258
condline = 0;
6259
isFar = 0;
6260
isFarkw = 0;
6261
 
6262
if (inMacro)
6263
  curline->lvl |= LINCAT_MACDEF;
6264
 
6265
if (isalnum(*srcptr))                   /* look for label on line start      */
6266
  {
6267
  scanname();
6268
  if (stricmp(namebuf, "far")==0) {
6269
          isFar = 1;
6270
          isFarkw = 1;
6271
          while(*srcptr==' ' || *srcptr=='\t') srcptr++;
6272
          scanname();
6273
  }
6274
  lp = findsym(namebuf, 1);
6275
  if (*srcptr == ':')
6276
    srcptr++;
6277
 
6278
  if ((lp) &&
6279
      (lp->cat != SYMCAT_COMMONDATA) &&
6280
      (lp->u.flags & SYMFLAG_FORWARD))
6281
    lp->u.flags |= SYMFLAG_PASSED;
6282
  }
6283
skipspace();
6284
if ((isalnum(*srcptr)) ||
6285
    ((dwOptions & OPTION_GAS) && (*srcptr == '.')))
6286
  {
6287
  scanname();
6288
  if ((dwOptions & OPTION_H63) &&       /* eventually adjust some mnemonics  */
6289
      ((!strcmp(unamebuf, "ASLD")) ||   /* that are available in the 6309    */
6290
       (!strcmp(unamebuf, "ASRD")) ||   /* but are implemented as (slower)   */
6291
       (!strcmp(unamebuf, "LSLD")) ||   /* convenience instructions on the   */
6292
       (!strcmp(unamebuf, "LSRD")) ||   /* 6809                              */
6293
       (!strcmp(unamebuf, "DECD")) ||
6294
       (!strcmp(unamebuf, "INCD")) ||
6295
       (!strcmp(unamebuf, "CLRD"))))
6296
    strcat(unamebuf, "63");
6297
  op = findop(unamebuf);
6298
  if (op)
6299
    {
6300
    if ((dwOptions & OPTION_TSC))       /* if TSC compatible, skip space NOW */
6301
      skipspace();                      /* since it's not allowed inside arg */
6302
    if (op->cat != OPCAT_PSEUDO)
6303
      {
6304
      setlabel(lp);
6305
      generating = 1;
6306
      }
6307
    co = op->code;
6308
    cat = op->cat;
6309
                                        /* only pseudo-ops in common mode!   */
6310
    if (common && (cat != OPCAT_PSEUDO))
6311
      error |= ERR_EXPR;
6312
 
6313
    noimm = cat & OPCAT_NOIMM;          /* isolate "no immediate possible"   */
6314
    cat &= ~OPCAT_NOIMM;
6315
        if (dwOptions & OPTION_X32)
6316
                isX32 = 1;
6317
        else
6318
                isX32 = 0;
6319
    if (dwOptions & OPTION_H63)         /* if in HD6309 mode,                */
6320
      cat &= ~OPCAT_6309;               /* mask out the 6309 flag (=allow)   */
6321
    switch (cat)
6322
      {
6323
      case OPCAT_ONEBYTE :
6324
        onebyte(co);
6325
        break;
6326
      case OPCAT_TWOBYTE :
6327
        twobyte(co);
6328
        break;
6329
      case OPCAT_THREEBYTE :
6330
        threebyte(co);
6331
        break;
6332
      case OPCAT_FOURBYTE :
6333
        fourbyte(co);
6334
        break;
6335
      case OPCAT_2IMMBYTE :             /* 6309 only                         */
6336
        putbyte((unsigned short)(co >> 12LL));
6337
        /* fall thru on purpose! */
6338
      case OPCAT_IMMBYTE :
6339
        oneimm(co);
6340
        break;
6341
      case OPCAT_LEA :
6342
        lea(co);
6343
        break;
6344
      case OPCAT_SBRANCH :
6345
        sbranch(co);
6346
        break;
6347
      case OPCAT_LBR2BYTE :
6348
        lbranch(co);
6349
        break;
6350
      case OPCAT_LBR1BYTE :
6351
        lbra(co);
6352
        break;
6353
      case OPCAT_2ARITH :               /* 6309 only                         */
6354
        putbyte((unsigned short)(co >> 12));
6355
        /* fall thru on purpose! */
6356
      case OPCAT_ARITH :
6357
        arith(co, noimm);
6358
        break;
6359
      case OPCAT_ACCARITH :             /* 6800-style arith                  */
6360
        accarith(co, noimm, 0);
6361
        break;
6362
      case OPCAT_DBLREG1BYTE :
6363
        darith(co, noimm, op->tgtNdx);
6364
        break;
6365
      case OPCAT_DBLREG2BYTE :
6366
        d2arith(co, noimm, op->tgtNdx);
6367
        break;
6368
      case OPCAT_SINGLEADDR :
6369
        oneaddr(co);
6370
        break;
6371
      case OPCAT_IREG :                 /* 6309 only                         */
6372
        putbyte((unsigned short)(co >> 12));
6373
        /* fall thru on purpose! */
6374
      case OPCAT_2REG :
6375
        tfrexg(co);
6376
        break;
6377
      case OPCAT_STACK :
6378
        pshpul(co);
6379
        break;
6380
      case OPCAT_BITDIRECT :            /* 6309 only                         */
6381
        bitdirect(co);
6382
        break;
6383
      case OPCAT_BITTRANS :             /* 6309 only                         */
6384
        bittrans(co);
6385
        break;
6386
      case OPCAT_BLOCKTRANS :           /* 6309 only                         */
6387
        blocktrans(co);
6388
        break;
6389
      case OPCAT_QUADREG1BYTE :
6390
        qarith(co, noimm);
6391
        break;
6392
      case OPCAT_IDXEXT :
6393
        idxextarith(co);
6394
        break;
6395
      case OPCAT_ACCADDR :
6396
        accaddr(co);
6397
        break;
6398
      case OPCAT_PSEUDO :
6399
        pseudoop(co, lp);
6400
        break;
6401
      default :
6402
        error |= ERR_ILLEGAL_MNEM;
6403
        break;
6404
      }
6405
    c = *srcptr;                        /* get current character             */
6406
    if (((dwOptions & OPTION_TSC) && (c == '*')) ||
6407
        ((dwOptions & OPTION_GAS) && (c == '|')) ||
6408
        (c == ';'))
6409
      c = '\0';
6410
    if (c != ' ' &&
6411
        *(srcptr - 1) != ' ' &&
6412
        c != '\0')
6413
      error |= ERR_ILLEGAL_ADDR;
6414
    }
6415
  else
6416
    {
6417
    lpmac = findsym(namebuf, 0);        /* look whether opcode is a macro    */
6418
    if (lpmac && lpmac->cat == SYMCAT_MACRO)
6419
      {
6420
      if (pass == 1)                    /* if in pass 1                      */
6421
        expandmacro(lp, lpmac);         /* expand macro below current line   */
6422
      }
6423
    else
6424
      error |= ERR_ILLEGAL_MNEM;
6425
    }
6426
  }
6427
else
6428
  {
6429
  nRepNext = 0;                         /* reset eventual repeat if no code  */
6430
  setlabel(lp);
6431
  }
6432
 
6433
if (inMacro)                            /* if in macro definition            */
6434
  {
6435
  codeptr = 0;                          /* ignore the code                   */
6436
  error &= (ERR_MALLOC | ERR_NESTING);  /* ignore most errors                */
6437
  warning &= WRN_SYM;                   /* ignore most warnings              */
6438
  }
6439
 
6440
if (pass == MAX_PASSNO)
6441
  {
6442
  outbuffer();
6443
  if ((listing & LIST_ON) &&
6444
      (dwOptions & OPTION_LIS))
6445
    outlist(op);
6446
  }
6447
else if ((listing & LIST_ON) &&
6448
         (dwOptions & OPTION_LIS) &&
6449
         (dwOptions & OPTION_LP1))
6450
  {
6451
  if (curline->lvl & LINCAT_MACEXP ||   /* prevent 2nd listing of macro      */
6452
      !curline->next ||                 /* since this is done in expansion   */
6453
      !(curline->next->lvl & LINCAT_MACEXP))
6454
    outlist(op);
6455
  }
6456
 
6457
if (error || warning)
6458
  report();
6459
loccounter += codeptr;
6460
}
6461
 
6462
/*****************************************************************************/
6463
/* suppressline : suppresses a line                                          */
6464
/*****************************************************************************/
6465
 
6466
void suppressline()
6467
{
6468
struct oprecord * op = NULL;
6469
 
6470
srcptr = srcline;
6471
oldlc = loccounter;
6472
codeptr = 0;
6473
condline = 0;
6474
if (nSkipCount > 0)
6475
  {
6476
  nSkipCount--;
6477
  condline = 1;                         /* this is STILL conditional         */
6478
  }
6479
else
6480
  {
6481
  if (isalnum(*srcptr))
6482
    {
6483
    scanname();
6484
    if (*srcptr == ':')
6485
      srcptr++;
6486
    }
6487
  skipspace();
6488
  scanname();
6489
  op = findop(unamebuf);
6490
  if (op && op->cat == OPCAT_PSEUDO)    /* examine pseudo-ops in detail      */
6491
    {
6492
    if ((op->code == PSEUDO_IF) ||      /* IF variants                       */
6493
        (op->code == PSEUDO_IFN) ||
6494
        (op->code == PSEUDO_IFC) ||
6495
        (op->code == PSEUDO_IFNC) ||
6496
        (op->code == PSEUDO_IFD) ||
6497
        (op->code == PSEUDO_IFND))
6498
      {
6499
      ifcount++;
6500
      condline = 1;                     /* this is a conditional line        */
6501
      }
6502
    else if (op->code == PSEUDO_ENDIF)  /* ENDIF                             */
6503
      {
6504
      if (ifcount > 0)
6505
        ifcount--;
6506
      else if (suppress == 1 || suppress == 2)
6507
        suppress = 0;
6508
      condline = 1;                     /* this is a conditional line        */
6509
      }
6510
    else if (op->code == PSEUDO_ELSE)   /* ELSE                              */
6511
      {
6512
      if (ifcount == 0 && suppress == 2)
6513
        suppress = 0;
6514
      condline = 1;                     /* this is a conditional line        */
6515
      }
6516
    }
6517
  }
6518
 
6519
if (((pass == MAX_PASSNO) || (dwOptions & OPTION_LP1)) &&
6520
    (listing & LIST_ON) &&
6521
    (dwOptions & OPTION_LIS))
6522
  outlist(op);
6523
}
6524
 
6525
/*****************************************************************************/
6526
/* usage : prints out correct usage                                          */
6527
/*****************************************************************************/
6528
 
6529
void usage(char *nm)
6530
{
6531
printf("Usage: %s [-option*] srcname*\n",
6532
       nm ? nm : "a09");
6533
printf("Available options are:\n");
6534
printf("-B[objname] ........ output to binary file (default)\n");
6535
printf("-F[objname] ........ output to FLEX binary file\n");
6536
/* printf("-G[objname] ........ output Gnu .o format file\n"); */
6537
printf("-R[objname] ........ output to FLEX relocatable object file\n");
6538
printf("-S[objname] ........ output to Motorola S51-09 file\n");
6539
printf("-X[objname] ........ output to Intel Hex file\n");
6540
printf("-L[listname] ....... create listing file \n");
6541
printf("-V[objname]......... output Verilog rommem declarations \n");
6542
printf("-C ................. suppress code output\n");
6543
printf("-Dsymbol[=value] ... predefines a symbol\n");
6544
printf("                     for TSC 6809 Assembler compatibility,\n");
6545
printf("                     you should only use symbols A through C\n");
6546
printf("-Ooption ........... sets an option (as in OPT pseudoop)\n");
6547
printf("-W ................. suppress warnings\n");
6548
printf("srcname ............ source file name(s)\n");
6549
 
6550
exit(2);
6551
}
6552
 
6553
/*****************************************************************************/
6554
/* getoptions : retrieves the options from the passed argument array         */
6555
/*****************************************************************************/
6556
 
6557
void getoptions (int argc, char* argv[])
6558
{
6559
int i, j;
6560
char *ld;
6561
 
6562
for (i = 1; i < argc; i++)
6563
  {
6564
#if !UNIX
6565
  /* code for DOS / Windows / OS2 */
6566
  if ((argv[i][0] == '-') ||
6567
      (argv[i][0] == '/'))
6568
#else
6569
  /* code for UNIX derivates */
6570
  if (argv[i][0] == '-')
6571
#endif
6572
    {
6573
    for (j = 1; j < (int)strlen(argv[i]); j++)
6574
      {
6575
      switch (tolower(argv[i][j]))
6576
        {
6577
        case 'c' :                      /* suppress code output              */
6578
          outmode = OUT_NONE;
6579
          break;
6580
        case 'b' :                      /* define binary output file         */
6581
        case 's' :                      /* define Motorola output file       */
6582
        case 'x' :                      /* define Intel Hex output file      */
6583
        case 'f' :                      /* define FLEX output file           */
6584
        case 'r' :                      /* define FLEX relocatable output f. */
6585
                case 'v' :
6586
    /*  case 'g' : */                   /* define GNU output file            */
6587
          strcpy(objname,               /* copy in the name                  */
6588
                  argv[i] + j + 1);
6589
          switch (tolower(argv[i][j]))  /* then set output mode              */
6590
            {
6591
            case 'b' :
6592
              outmode = OUT_BIN;
6593
              break;
6594
            case 's' :
6595
              outmode = OUT_SREC;
6596
              break;
6597
            case 'x' :
6598
              outmode = OUT_IHEX;
6599
              break;
6600
            case 'f' :
6601
              outmode = OUT_FLEX;
6602
              break;
6603
                        case 'v':
6604
                                outmode = OUT_VER;
6605
                                break;
6606
/*
6607
            case 'g' :
6608
              outmode = OUT_GAS;
6609
              relocatable = 1;
6610
              dwOptions |= OPTION_REL;
6611
              break;
6612
*/
6613
            case 'r' :
6614
              outmode = OUT_REL;
6615
              maxidlen = 8;             /* only 8 significant ID chars!      */
6616
              relocatable = 1;
6617
              absmode = 0;
6618
              break;
6619
            }
6620
          j = strlen(argv[i]);          /* advance behind copied name        */
6621
          break;
6622
        case 'l' :                      /* define listing file               */
6623
          strcpy(listname,              /* copy in the name                  */
6624
                  argv[i] + j + 1);
6625
          j = strlen(argv[i]);          /* advance behind copied name        */
6626
          listing = LIST_ON;            /* remember we're listing            */
6627
          break;
6628
        case 'd' :                      /* define a symbol ?                 */
6629
          srcptr = argv[i] + j + 1;     /* parse in the name                 */
6630
          scanname();
6631
          if (!namebuf[0])              /* if no name there                  */
6632
            usage(argv[0]);             /* show usage and get out            */
6633
          if (*srcptr == '=')           /* if followed by value              */
6634
            srcptr++;                   /* advance behind it                 */
6635
          else                          /* otherwise go to ""                */
6636
            srcptr = argv[i] + strlen(argv[i]);
6637
          settext(namebuf, srcptr);     /* define the symbol                 */
6638
          j = strlen(argv[i]);          /* advance behind copied name        */
6639
          break;
6640
        case 'o' :                      /* option                            */
6641
          if (setoption(argv[i] + j + 1))
6642
            usage(argv[0]);
6643
          j = strlen(argv[i]);          /* advance behind option             */
6644
          break;
6645
        }
6646
      }
6647
    for (j = i; j < argc; j++)          /* remove all consumed arguments     */
6648
      argv[j] = argv[j + 1];
6649
    argc--;                             /* reduce # arguments                */
6650
    i--;                                /* and restart with next one         */
6651
    }
6652
  }
6653
 
6654
if (argc < 2)                           /* if not at least one filename left */
6655
  usage(argv[0]);                       /* complain & terminate              */
6656
 
6657
strcpy(srcname, argv[1]);               /* copy it in.                       */
6658
 
6659
if (!objname[0])                        /* if no object name defined         */
6660
  {
6661
  strcpy(objname, srcname);             /* copy in the source name           */
6662
  ld = strrchr(objname, '.');           /* look whether there's a dot in it  */
6663
  if (!ld)                              /* if not                            */
6664
    ld = objname + strlen(objname);     /* append extension                  */
6665
  switch (outmode)                      /* which output mode?                */
6666
    {
6667
    case OUT_BIN :                      /* binary ?                          */
6668
#if !UNIX
6669
      strcpy(ld, ".bin");               /* DOS / Windows / OS2               */
6670
#else
6671
      strcpy(ld, ".b");                 /* UNIX                              */
6672
#endif
6673
      break;
6674
    case OUT_SREC :                     /* Motorola S51-09 ?                 */
6675
      strcpy(ld, ".s09");
6676
      break;
6677
    case OUT_IHEX :                     /* Intel Hex ?                       */
6678
      strcpy(ld, ".hex");
6679
      break;
6680
    case OUT_FLEX :                     /* FLEX binary ?                     */
6681
      strcpy(ld, ".bin");
6682
      break;
6683
    case OUT_GAS :                      /* GNU relocatable object ?          */
6684
      strcpy(ld, ".o");
6685
      break;
6686
    case OUT_REL :                      /* Flex9 relocatable object ?        */
6687
      strcpy(ld, ".rel");
6688
      break;
6689
    case OUT_VER :                     /* Verilog texr                     */
6690
      strcpy(ld, ".ver");
6691
      break;
6692
    }
6693
  }
6694
 
6695
if ((listing & LIST_ON) && !listname[0])/* if no list file specified         */
6696
  {
6697
  strcpy(listname, srcname);            /* copy in the source name           */
6698
  ld = strrchr(listname, '.');          /* look whether there's a dot in it  */
6699
  if (!ld)                              /* if not                            */
6700
    ld = listname + strlen(listname);   /* append extension                  */
6701
  strcpy(ld, ".lst");                   /* .lst                              */
6702
  }
6703
}
6704
 
6705
/*****************************************************************************/
6706
/* processfile : processes the input file                                    */
6707
/*****************************************************************************/
6708
 
6709
void processfile(struct linebuf *pline)
6710
{
6711
struct linebuf *plast = pline;
6712
vercount = 0;
6713
while (!terminate && pline)
6714
  {
6715
  curline = pline;
6716
  error = ERR_OK;
6717
  warning = WRN_OK;
6718
  expandtext();                         /* expand text symbols               */
6719
  srcptr = srcline;
6720
  if (suppress || nSkipCount)
6721
    suppressline();
6722
  else
6723
    {
6724
    if (nRepNext)
6725
      {
6726
      for (; nRepNext > 0; nRepNext--)
6727
        {
6728
        processline();
6729
        error = ERR_OK;
6730
        warning = WRN_OK;
6731
        }
6732
      nRepNext = 0;
6733
      }
6734
    else
6735
      {
6736
      if (pass != 1 ||
6737
          !(curline->lvl & LINCAT_MACEXP))
6738
        processline();
6739
      error = ERR_OK;
6740
      warning = WRN_OK;
6741
      }
6742
    }
6743
  plast = pline;
6744
  pline = pline->next;
6745
  }
6746
 
6747
if (suppress)
6748
  {
6749
  printf("%s(%ld) : error 18: improperly nested IF statements\n",
6750
         expandfn(plast->fn), plast->ln);
6751
  if (((dwOptions & OPTION_LP1) || pass == MAX_PASSNO) &&
6752
      (listing & LIST_ON))
6753
    putlist( "*** Error 18: improperly nested IF statements\n");
6754
  errors++;
6755
  suppress = 0;
6756
  }
6757
 
6758
if (common)
6759
  {
6760
  printf("%s(%ld) : error 24: improperly nested COMMON statements\n",
6761
         expandfn(plast->fn), plast->ln);
6762
  if (((dwOptions & OPTION_LP1) || pass == MAX_PASSNO) &&
6763
      (listing & LIST_ON))
6764
    putlist( "*** Error 24: improperly nested COMMON statements\n");
6765
  errors++;
6766
  common = 0;
6767
  }
6768
}
6769
 
6770
void dopass(int passno, int lastpass)
6771
{
6772
        int i;
6773
        char buf[4];
6774
        sprintf(buf, "%d", passno);
6775
pass = passno;
6776
settext("PASS", buf);
6777
loccounter = 0;
6778
errors = 0;
6779
warnings = 0;
6780
generating = 0;
6781
terminate = 0;
6782
 
6783
for (i = 0; i < symcounter; i++)        /* reset all PASSED flags            */
6784
  if (symtable[i].cat != SYMCAT_COMMONDATA)
6785
    symtable[i].u.flags &= ~SYMFLAG_PASSED;
6786
 
6787
if (lastpass) {
6788
        if (listing & LIST_ON)
6789
        {
6790
        if ((dwOptions & OPTION_LP1))
6791
                {
6792
                if (dwOptions & OPTION_PAG)
6793
                PageFeed();
6794
                else
6795
                putlist("\n");
6796
                putlist( "*** Pass 2 ***\n\n");
6797
                }
6798
        else if (nTotErrors || nTotWarnings)
6799
                putlist( "%ld error(s), %ld warning(s) unlisted in pass 1\n",
6800
                                nTotErrors, nTotWarnings);
6801
        }
6802
 
6803
        if ((outmode >= OUT_BIN) &&
6804
                ((objfile = fopen(objname,
6805
                                                ((outmode != OUT_SREC) && (outmode != OUT_IHEX)) ? "wb" : "w"))
6806
                                                == 0))
6807
        {
6808
        printf("%s(0) : error 20: cannot write object file %s\n", srcname, objname);
6809
        if (((dwOptions & OPTION_LP1) || pass == MAX_PASSNO) && (listing & LIST_ON))
6810
                putlist( "*** Error 20: cannot write object file %s\n", objname);
6811
        exit(4);
6812
        }
6813
 
6814
        if (outmode == OUT_REL)                 /* if writing FLEX Relocatable       */
6815
        {
6816
        writerelcommon();                     /* write out common blocks           */
6817
        relhdrfoff = ftell(objfile);
6818
        writerelhdr(0);                       /* write out initial header          */
6819
        }
6820
        }
6821
        processfile(rootline);
6822
 
6823
        if (errors)
6824
        {
6825
        printf("%ld error(s) in pass %d\n", errors, passno);
6826
        nTotErrors += errors;
6827
        }
6828
        if (warnings)
6829
        {
6830
        printf("%ld warning(s) in pass %d\n", warnings, passno);
6831
        nTotWarnings += warnings;
6832
        }
6833
 
6834
}
6835
 
6836
/*****************************************************************************/
6837
/* main : the main function                                                  */
6838
/*****************************************************************************/
6839
 
6840
int main (int argc, char *argv[])
6841
{
6842
int i;
6843
struct linebuf *pLastLine = NULL;
6844
 
6845
settext("ASM", "A09");                  /* initialize predefined texts       */
6846
settext("VERSION", VERSNUM);
6847
settext("PASS", "1");
6848
setoptiontexts();
6849
nPredefinedTexts = nTexts;
6850
 
6851
getoptions(argc, argv);
6852
pass = 1;
6853
error = 0;
6854
warning = 0;
6855
nTotErrors = errors = 0;
6856
nTotWarnings = warnings = 0;
6857
generating = 0;
6858
common = 0;
6859
terminate = 0;
6860
if (!absmode)                           /* in relocating mode                */
6861
  dpsetting = -1;                       /* there IS no Direct Page           */
6862
 
6863
printf("A09 Assembler V" VERSION "\n");
6864
 
6865
if ((listing & LIST_ON) &&
6866
    ((listfile = fopen(listname, "w")) == 0))
6867
  {
6868
  printf("%s(0) : error 19: Cannot open list file %s\n", srcname, listname);
6869
  exit(4);
6870
  }
6871
 
6872
for (i = 1; argv[i]; i++)               /* read in all source files          */
6873
  pLastLine = readfile(argv[i], 0, pLastLine);
6874
if (!rootline)                          /* if no lines in there              */
6875
  {
6876
  printf("%s(0) : error 23: no source lines in file\n", srcname);
6877
  if (((dwOptions & OPTION_LP1) || pass == MAX_PASSNO) &&
6878
      (listing & LIST_ON))
6879
    putlist( "*** Error 23: no source lines in file\n");
6880
  exit(4);
6881
  }
6882
 
6883
                                        /* Pass 1 - parse all symbols        */
6884
if ((listing & LIST_ON) && (dwOptions & OPTION_LP1))
6885
  putlist( "*** Pass 1 ***\n\n");
6886
 
6887
processfile(rootline);
6888
if (errors)
6889
  {
6890
  printf("%ld error(s) in pass 1\n",errors);
6891
  if ((listing & LIST_ON) && (dwOptions & OPTION_LP1))
6892
    putlist( "%ld error(s) in pass 1.\n", errors);
6893
  nTotErrors = errors;
6894
  }
6895
if (warnings)
6896
  {
6897
  printf("%ld warning(s) in pass 1\n", warnings);
6898
  if ((listing & LIST_ON) && (dwOptions & OPTION_LP1))
6899
    putlist(
6900
            "%ld warning(s) in pass 1.\n", warnings);
6901
  nTotWarnings = warnings;
6902
  }
6903
 
6904
// Resolve potential phasing errors by performing multiple passes.
6905
dopass(2,0);
6906
dopass(3,0);
6907
dopass(4,0);
6908
dopass(5,0);
6909
dopass(6,0);
6910
dopass(7,0);
6911
dopass(8,0);
6912
dopass(9,1);
6913
//                                       /* Pass 2 - generate output          */
6914
//settext("PASS", "3");
6915
//loccounter = 0;
6916
//errors = 0;
6917
//warnings = 0;
6918
//generating = 0;
6919
//terminate = 0;
6920
////memset(bUsedBytes, 0, sizeof(bUsedBytes));
6921
//for (i = 0; i < symcounter; i++)        /* reset all PASSED flags            */
6922
//  if (symtable[i].cat != SYMCAT_COMMONDATA)
6923
//    symtable[i].u.flags &= ~SYMFLAG_PASSED;
6924
//
6925
//if (listing & LIST_ON)
6926
//  {
6927
//  if ((dwOptions & OPTION_LP1))
6928
//    {
6929
//    if (dwOptions & OPTION_PAG)
6930
//      PageFeed();
6931
//    else
6932
//      putlist("\n");
6933
//    putlist( "*** Pass 2 ***\n\n");
6934
//    }
6935
//  else if (nTotErrors || nTotWarnings)
6936
//    putlist( "%ld error(s), %ld warning(s) unlisted in pass 1\n",
6937
//            nTotErrors, nTotWarnings);
6938
//  }
6939
//
6940
//if ((outmode >= OUT_BIN) &&
6941
//    ((objfile = fopen(objname,
6942
//                     ((outmode != OUT_SREC) && (outmode != OUT_IHEX)) ? "wb" : "w"))
6943
//                     == 0))
6944
//  {
6945
//  printf("%s(0) : error 20: cannot write object file %s\n", srcname, objname);
6946
//  if (((dwOptions & OPTION_LP1) || pass == 2) && (listing & LIST_ON))
6947
//    putlist( "*** Error 20: cannot write object file %s\n", objname);
6948
//  exit(4);
6949
//  }
6950
//
6951
//if (outmode == OUT_REL)                 /* if writing FLEX Relocatable       */
6952
//  {
6953
//  writerelcommon();                     /* write out common blocks           */
6954
//  relhdrfoff = ftell(objfile);
6955
//  writerelhdr(0);                       /* write out initial header          */
6956
//  }
6957
//
6958
//processfile(rootline);
6959
//
6960
//if (errors)
6961
//  {
6962
//  printf("%ld error(s) in pass 2\n", errors);
6963
//  nTotErrors += errors;
6964
//  }
6965
//if (warnings)
6966
//  {
6967
//  printf("%ld warning(s) in pass 2\n", warnings);
6968
//  nTotWarnings += warnings;
6969
//  }
6970
 
6971
if (listing & LIST_ON)
6972
  {
6973
  if (errors || warnings)
6974
    putlist("\n");
6975
  if (errors)
6976
    putlist( "%ld error(s) in pass 2.\n", errors);
6977
  if (warnings)
6978
    putlist( "%ld warning(s) in pass 2.\n", warnings);
6979
  if (dwOptions & OPTION_SYM)
6980
    outsymtable();
6981
  if ((relocatable) && (dwOptions & OPTION_REL))
6982
    outreltable();
6983
  if ((dwOptions & OPTION_TXT) &&
6984
      (nPredefinedTexts < nTexts))
6985
    outtexttable();
6986
 
6987
  putlist( "\n%ld error(s), %ld warning(s)\n",
6988
          nTotErrors, nTotWarnings);
6989
  fclose(listfile);
6990
  }
6991
else
6992
  printf("Last assembled address: %04X\n", loccounter - 1);
6993
 
6994
switch (outmode)                        /* look whether object cleanup needed*/
6995
  {
6996
case OUT_VER:
6997
        flushver();
6998
        break;
6999
  case OUT_SREC :                       /* Motorola S51-09                   */
7000
    flushhex();
7001
    chksum = (tfradr & 0xff) + ((tfradr >> 8) & 0xff) + 3;
7002
    fprintf(objfile, "S903%04X%02X\n", tfradr, 0xff - (chksum & 0xff));
7003
    break;
7004
  case OUT_IHEX :                       /* Intel Hex                         */
7005
    flushihex();
7006
#if 0
7007
    /* put transfer address in here... unfortunately, the official
7008
       Intel documentation doesn't allow this mechanism */
7009
    chksum = ((tfradr >> 8) & 0xff) + (tfradr & 0xff) + 1;
7010
    fprintf(objfile, ":00%04X01%02X\n", tfradr, (-(signed)chksum) & 0xff);
7011
#else
7012
    fprintf(objfile, ":00000001FF\n");
7013
#endif
7014
    break;
7015
  case OUT_FLEX :                       /* FLEX binary                       */
7016
    flushflex();
7017
    if (tfradrset)                      /* if transfer address set           */
7018
      {                                 /* write out transfer address block  */
7019
      fputc(0x16, objfile);
7020
      fputc((tfradr >> 8) & 0xff, objfile);
7021
      fputc(tfradr & 0xff, objfile);
7022
      }
7023
    break;
7024
  case OUT_REL :                        /* FLEX Relocatable                  */
7025
    writerelext();                      /* write out External table          */
7026
    writerelglobal();                   /* write out Global table            */
7027
    writerelmodname();                  /* write out Module Name             */
7028
 
7029
    i = (int)ftell(objfile);            /* fill last sector with zeroes      */
7030
    while (i % 252)
7031
      {
7032
      fputc(0, objfile);
7033
      i++;
7034
      }
7035
                                        /* reposition on header              */
7036
    fseek(objfile, relhdrfoff, SEEK_SET);
7037
    writerelhdr(0);                     /* rewrite completed header          */
7038
    break;
7039
  }
7040
 
7041
if (objfile)
7042
  fclose(objfile);
7043
 
7044
if (errors)
7045
  unlink(objname);
7046
 
7047
return (errors) ? 1 : 0;
7048
}

powered by: WebSVN 2.1.0

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