1 %{
2 /* Clang doesn't like the unreachable code in Bison's generated output. */
3 #ifdef __clang__
4 #pragma clang diagnostic ignored "-Wunreachable-code"
5 #endif
6 
7 #if 0
8 #   define YYDEBUG 1
9 #   define YYERROR_VERBOSE 1
10 #   define YYTOKEN_TABLE   1
11     int yydebug = 1;
12 #endif
13 
14 /*  NOTICE:  This code is based on the Public Domain AS2650.Y that comes
15  *           with the Frankenstein Assembler, by Mark Zenier.  The changes
16  *           that I, Joseph Zbiciak, have made are being placed under GPL.
17  *           See GPL notice immediately below.
18  */
19 
20 /* ======================================================================== */
21 /*  This program is free software; you can redistribute it and/or modify    */
22 /*  it under the terms of the GNU General Public License as published by    */
23 /*  the Free Software Foundation; either version 2 of the License, or       */
24 /*  (at your option) any later version.                                     */
25 /*                                                                          */
26 /*  This program is distributed in the hope that it will be useful,         */
27 /*  but WITHOUT ANY WARRANTY; without even the implied warranty of          */
28 /*  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU       */
29 /*  General Public License for more details.                                */
30 /*                                                                          */
31 /*  You should have received a copy of the GNU General Public License along */
32 /*  with this program; if not, write to the Free Software Foundation, Inc., */
33 /*  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.             */
34 /* ======================================================================== */
35 /*                 Copyright (c) 1998-1999, Joseph Zbiciak                  */
36 /* ======================================================================== */
37 
38 
39 /*
40 HEADER:     ;
41 TITLE:      Frankenstein Cross Assemblers;
42 VERSION:    2.0;
43 DESCRIPTION: "  Reconfigurable Cross-assembler producing Intel (TM)
44                 Hex format object records.  ";
45 KEYWORDS:   cross-assemblers, 1600, 1805, 2650, 6301, 6502, 6805, 6809,
46             6811, tms7000, 8048, 8051, 8096, z8, z80;
47 SYSTEM:     UNIX, MS-Dos ;
48 FILENAME:   as1600.y;
49 WARNINGS:   "This software is in the public domain.
50              Any prior copyright claims are relinquished.
51 
52              This software is distributed with no warranty whatever.
53              The author takes no responsibility for the consequences
54              of its use.
55 
56              Yacc (or Bison) required to compile."  ;
57 SEE-ALSO:   as1600.ps, frasmain.c;
58 AUTHORS:    Mark Zenier; Joe Zbiciak
59 COMPILERS:  GCC
60 */
61 
62 /* 1600 instruction generation file, GI standard syntax */
63 /* September 25, 1999 */
64 
65 /*
66     description frame work parser description for framework cross assemblers
67     history     February 2, 1988
68                 September 11, 1990 - merge table definition
69                 September 12, 1990 - short file names
70                 September 14, 1990 - short variable names
71                 September 17, 1990 - use yylex as external
72 */
73 
74 /* ======================================================================== *\
75 
76 The CP-1610 supports the following basic opcode formats:
77 
78  ---------------------------------------  -------  --------------------------
79   Format                                   Words    Description
80  ---------------------------------------  -------  --------------------------
81   0000 000 0oo                               1      Implied 1-op insns
82   0000 000 100  bbppppppii  pppppppppp       3      Jump insns
83   0000 000 1oo                               1      Implied 1-op insns
84   0000 ooo ddd                               1      1-op insns, comb src/dst
85   0000 110 0dd                               1      GSWD
86   0000 110 1om                               1      NOP(2), SIN(2)
87   0001 ooo mrr                               1      Rotate/Shift insns
88   0ooo sss ddd                               1      2-op arith, reg->reg
89   1000 zxc ccc  pppppppppp                   2      Branch insns
90   1ooo 000 ddd  pppppppppp                   2      2-op arith, direct, reg
91   1ooo mmm ddd                               1*     2-op arith, ind., reg
92   1ooo 111 ddd  iiiiiiiiii                   2*     2-op arith, immed., reg
93  ---------------------------------------  -------  --------------------------
94 
95 
96  -----
97   Key
98  -----
99 
100   oo    -- Opcode field (dependent on format)
101   sss   -- Source register,      R0 ... R7 (binary encoding)
102   ddd   -- Destination register, R0 ... R7 (binary encoding)
103   0dd   -- Destination register, R0 ... R3
104   cccc  -- Condition codes (branches)
105   x     -- External branch condition (0 == internal, 1 == examine BEXT)
106   z     -- Branch displacement direction (1 == negative)
107   m     -- Shift amount (0 == shift by 1, 1 == shift by 2)
108   bb    -- Branch return register
109   ii    -- Branch interrupt flag mode
110 
111  --------------------------------
112   Branch Condition Codes  (cccc)
113  --------------------------------
114            n == 0                    n == 1
115   n000  -- Always                    Never
116   n001  -- Carry set/Greater than    Carry clear/Less than or equal
117   n010  -- Overflow set              Overflow clear
118   n011  -- Positive                  Negative
119   n100  -- Equal                     Not equal
120   n101  -- Less than                 Greater than or equal
121   n110  -- Less than or equal        Greater than
122   n111  -- Unequal sign and carry    Equal sign and carry
123 
124 
125  -------------------------------
126   Branch Return Registers  (bb)
127  -------------------------------
128 
129   00   -- R4
130   01   -- R5
131   10   -- R6
132   11   -- none (do not save return address)
133 
134  -------------------------------
135   Branch Interrupt Modes   (ii)
136  -------------------------------
137 
138   00   -- Do not change interrupt enable state
139   01   -- Enable interrupts
140   10   -- Disable interrupts
141   11   -- Undefined/Reserved ?
142 
143  ------------
144   SDBD notes
145  ------------
146 
147   -- SDBD is supported on "immediate" and "indirect" modes only.
148 
149   -- An SDBD prefix on an immediate instruction sets the immediate constant
150      to be 16 bits, stored in two adjacent 8-bit words.  The ordering is
151      little-endian.
152 
153   -- An SDBD prefix on an indirect instruction causes memory to be
154      accessed twice, bringing in (or out) two 8-bit words, again in
155      little-endian order.  If a non-incrementing data counter is used,
156      both accesses are to the same address.  Otherwise, the counter
157      is post-incremented with each access.  Indirect through R6
158      (stack addressing) is not allowed, although I suspect it works
159      as expected (performing two accesses through R6).
160 
161  ------------------------
162   General encoding notes
163  ------------------------
164 
165   -- "Immediate" mode is encoded the same as "Indirect" mode, except that
166      R7 is given as the indirect register.  I'm guessing R7 is implemented
167      the same as R4 and R5, especially since MVOI does what you'd
168      expect -- it (attempts to) write over its immediate operand!!!
169 
170   -- The PC value (in R7) used for arithmetic always points to the first
171      byte after the instruction for purposes of arithmetic.  This is
172      consistent with the observation that immediate mode is really
173      indirect mode in disguise, with the instruction being only one word
174      long initially.
175 
176   -- Several instructions are just special cases of other instructions,
177      and therefore do not need special decoder treatment:
178 
179       -- TSTR Rx  -->  MOVR Rx, Rx
180       -- JR Rx    -->  MOVR Rx, R7
181       -- CLRR Rx  -->  XORR Rx, Rx
182       -- B        -->  Branch with condition code 0000 ("Always")
183       -- NOPP     -->  Branch with condition code 1000 ("Never")
184       -- PSHR Rx  -->  MVO@ Rx, R6
185       -- PULR Rx  -->  MVI@ R6, Rx
186 
187   -- "Direct" mode is encoded the same as "Indirect" mode, except 000
188      (which corresponds to R0) is encoded in the indirect register field.
189      This is why R0 cannot be used as a data counter, and why it has no
190      "special use."
191 
192   -- Relative branches encode their sign bit in the opcode word, rather
193      than relying on a sign-extended relative offset in their second word.
194      This allows +/- 10-bit range in a 10-bit wide memory, or +/-
195      16-bit range in a 16-bit memory.  To avoid redundant encoding, the
196      offset is calculated slightly differently for negative vs. positive
197      offset:
198 
199       -- Negative: address_of_branch + 1 - offset
200       -- Positive: address_of_branch + 2 + offset
201 
202      I'm guessing it is implemented about like so in hardware:
203 
204       -- offset == pc + (offset ^ (sign ? -1 : 0))
205 
206  ---------------
207   Opcode Spaces
208  ---------------
209 
210   I've divided the CP-1610 opcode map into 12 different opcode
211   spaces.  (I really should merge the two separate Implied 1-op
212   spaces into one space.  Oh well...)  In the descriptions below,
213   "n/i" means "not interruptible".  Defined flags: Sign, Zero, Carry,
214   Overflow, Interrupt-enable, Double-byte-data.  Interrupt-enable and
215   Double-byte-data are not user visible.
216 
217   -- Implied 1-op instructions, part A:     0000 000 0oo
218      Each has a single, implied operand, if any.
219 
220          opcode   mnemonic n/i  SZCOID  description
221       --   00       HLT                 Halts the CPU (until next interrupt?)
222       --   01       SDBD    *        1  Set Double Byte Data
223       --   10       EIS     *       1   Enable Interrupt System
224       --   11       DIS     *       1   Disable Interrupt System
225 
226   -- Implied 1-op instructions, part B:     0000 000 1oo
227      Each has a single, implied operand, if any.
228 
229          opcode   mnemonic n/i  SZCOID  description
230       --   00       n/a                 Aliases the "Jump" opcode space
231       --   01       TCI     *           Terminate Current Interrupt.
232       --   10       CLRC    *           Clear carry flag
233       --   11       SETC    *           Set carry flag
234 
235   -- Jump Instructions:                     0000 000 100 bbppppppii pppppppppp
236      Unconditional jumps with optional return-address save and
237      interrupt enable/disable.
238 
239           bb  ii   mnemonic n/i  SZCOID description
240       --  11  00    J                   Jump.
241       --  xx  00    JSR                 Jump.  Save return address in R4..R6
242       --  11  01    JE              1   Jump and enable ints.
243       --  xx  01    JSRE            1   Jump and enable ints.  Save ret addr.
244       --  11  10    JD              0   Jump and disable ints
245       --  xx  10    JSRD            0   Jump and disable ints.  Save ret addr.
246       --  xx  11    n/a                 Invalid opcode.
247 
248   -- Register 1-op instructions             0000 ooo rrr
249      Each has one register operand, encoded as 000 through 111.
250 
251          opcode   mnemonic n/i  SZCOID  description
252       --   000      n/a                 Aliases "Implied", "Jump" opcode space
253       --   001      INCR        XX      INCrement register
254       --   010      DECR        XX      DECrement register
255       --   011      COMR        XX      COMplement register (1s complement)
256       --   100      NEGR        XXXX    NEGate register     (2s complement)
257       --   101      ADCR        XXXX    ADd Carry to Register
258       --   110      n/a                 Aliases "GSWD", "NOP/SIN" opcode space
259       --   111      RSWD        XXXX    Restore Status Word from Register
260 
261 
262   -- Get Status WorD                        0000 110 0rr
263      This was given its own opcode space due to limited encoding on its
264      destination register and complication with the NOP/SIN encodings.
265 
266   -- NOP/SIN                                0000 110 1om
267      I don't know what the "m" bit is for.  I don't know what to do with SIN.
268 
269          opcode   mnemonic n/i  SZCOID  description
270       --    0       NOP                 No operation
271       --    1       SIN                 Software Interrupt (pulse PCIT pin) ?
272 
273   -- Shift/Rotate 1-op instructions         0001 ooo mrr
274      These can operate only on R0...R3.  The "m" bit specifies whether the
275      operation is performed once or twice.  The overflow bit is used for
276      catching the second bit on the rotates/shifts that use the carry.
277 
278          opcode   mnemonic n/i  SZCOID  description
279       --   000      SWAP    *   XX      Swaps bytes in word once or twice.
280       --   001      SLL     *   XX      Shift Logical Left
281       --   010      RLC     *   XXX2    Rotate Left through Carry/overflow
282       --   011      SLLC    *   XXX2    Shift Logical Left thru Carry/overflow
283       --   100      SLR     *   XX      Shift Logical Right
284       --   101      SAR     *   XX      Shift Arithmetic Right
285       --   110      RRC     *   XXX2    Rotate Left through Carry/overflow
286       --   111      SARC    *   XXX2    Shift Arithmetic Right thru Carry/over
287 
288   -- Register/Register 2-op instructions    0ooo sss ddd
289      Register to register arithmetic.  Second operand acts as src2 and dest.
290 
291          opcode   mnemonic n/i  SZCOID  description
292       --   00x      n/a                 Aliases other opcode spaces
293       --   010      MOVR        XX      Move register to register
294       --   011      ADDR        XXXX    Add src1 to src2->dst
295       --   100      SUBR        XXXX    Sub src1 from src2->dst
296       --   101      CMPR        XXXX    Sub src1 from src2, don't store
297       --   110      ANDR        XX      AND src1 with src2->dst
298       --   111      XORR        XX      XOR src1 with src2->dst
299 
300   -- Conditional Branch instructions        1000 zxn ccc pppppppppppppppp
301      The "z" bit specifies the direction for the offset.  The "x" bit
302      specifies using an external branch condition instead of using flag
303      bits.  Conditional brances are interruptible.  The "n" bit specifies
304      branching on the opposite condition from 'ccc'.
305 
306           cond      n=0         Condition       n=1         Condition
307       --  n000      B           always          NOPP        never
308       --  n001      BC          C = 1           BNC         C = 0
309       --  n010      BOV         O = 1           BNOV        O = 0
310       --  n011      BPL         S = 0           BMI         S = 1
311       --  n100      BZE/BEQ     Z = 1           BNZE/BNEQ   Z = 0
312       --  n101      BLT/BNGE    S^O = 1         BGE/BNLT    S^O = 0
313       --  n110      BLE/BNGT    Z|(S^O) = 1     BGT/BNLE    Z|(S^O) = 0
314       --  n111      BUSC        S^C = 1         BESC        S^C = 0
315 
316   -- Direct/Register 2-op instructions      1ooo 000 rrr  pppppppppppppppp
317      Direct memory to register arithmetic.  MVO uses direct address as
318      a destination, all other operations use it as a source, with
319      the register as the destination.
320 
321          opcode   mnemonic n/i  SZCOID  description
322       --   000      n/a                 Aliases conditional branch opcodes
323       --   001      MVO     *           Move register to direct address
324       --   010      MVI                 Move direct address to register
325       --   011      ADD         XXXX    Add src1 to src2->dst
326       --   100      SUB         XXXX    Sub src1 from src2->dst
327       --   101      CMP         XXXX    Sub src1 from src2, don't store
328       --   110      AND         XX      AND src1 with src2->dst
329       --   111      XOR         XX      XOR src1 with src2->dst
330 
331 
332   -- Indirect/Register 2-op instructions    1ooo sss ddd
333      A source of "000" is actually a Direct/Register opcode.
334      A source of "111" is actually a Immediate/Register opcode.
335      R4, R5 increment after each access.  If the D bit is set, two
336      accesses are made through the indirect register, updating the
337      address if R4 or R5.  R6 increments after writes, decrements
338      before reads.
339 
340          opcode   mnemonic n/i  SZCOID  description
341       --   000      n/a                 Aliases conditional branch opcodes
342       --   001      MVO@    *           Move register to indirect address
343       --   010      MVI@                Move indirect address to register
344       --   011      ADD@        XXXX    Add src1 to src2->dst
345       --   100      SUB@        XXXX    Sub src1 from src2->dst
346       --   101      CMP@        XXXX    Sub src1 from src2, don't store
347       --   110      AND@        XX      AND src1 with src2->dst
348       --   111      XOR@        XX      XOR src1 with src2->dst
349 
350   -- Immediate/Register 2-op instructions   1ooo 111 ddd  pppp
351      If DBD is set, the immediate value spans two adjacent bytes, little
352      endian order.  Otherwise the immediate value spans one word.  This
353      instruction really looks like indirect through R7, and I suspect
354      that's how the silicon implements it.
355 
356          opcode   mnemonic n/i  SZCOID  description
357       --   000      n/a                 Aliases conditional branch opcodes
358       --   001      MVOI    *           Move register to immediate field!
359       --   010      MVII                Move immediate field to register
360       --   011      ADDI        XXXX    Add src1 to src2->dst
361       --   100      SUBI        XXXX    Sub src1 from src2->dst
362       --   101      CMPI        XXXX    Sub src1 from src2, don't store
363       --   110      ANDI        XX      AND src1 with src2->dst
364       --   111      XORI        XX      XOR src1 with src2->dst
365 
366 \* ======================================================================== */
367 
368 #include <stdio.h>
369 #include <string.h>
370 #include "config.h"
371 #include "as1600_types.h"
372 #include "intermed.h"
373 #include "lzoe/lzoe.h"
374 #include "file/file.h"
375 #include "asm/frasmdat.h"
376 #include "asm/fragcon.h"
377 #include "asm/intvec.h"
378 #include "asm/protos.h"
379 #include "asm/as1600.tab.h"
380 #include "asm/memo_string.h"
381 
382 #define yylex lexintercept
383 
384 #define JSR_RG    0x0001
385 #define SHF_RG    0x0002
386 #define IND_RG    0x0004
387 #define SDBD      0x0008
388 
389 #define ST_REGREG 0x0001
390 #define ST_REGEXP 0x0002
391 #define ST_EXPREG 0x0004
392 #define ST_REGCEX 0x0008
393 #define ST_CEXREG 0x0010
394 #define ST_REG    0x0020
395 #define ST_EXP    0x0040
396 #define ST_IMP    0x0080
397 #define ST_EXPEXP 0x0100
398 
399 /* ======================================================================== */
400 /*  R0 .. R7 can be used as general-purpose registers.                      */
401 /*  R0 .. R3 can be used for shifts and GSWD.                               */
402 /*  R1 .. R6 can be used for indirect addressing.                           */
403 /*  R4 .. R6 can be used for JSR.                                           */
404 /* ======================================================================== */
405 static int  reg_type[8] =
406 {
407     SHF_RG,
408     SHF_RG | IND_RG,
409     SHF_RG | IND_RG,
410     SHF_RG | IND_RG,
411     JSR_RG | IND_RG,
412     JSR_RG | IND_RG,
413     JSR_RG | IND_RG,
414     0
415 };
416 
417 /* ======================================================================== */
418 /*  BDEF outputs a number as a ROMW width word directly.  Allowed width is  */
419 /*       determined by argument #2 to the expression.                       */
420 /*  WDEF outputs a 16-bit word as a Double Byte Data.                       */
421 /* ======================================================================== */
422 static char genbdef[] = "[1=].[2#]I$[1=]x";
423 static char genwdef[] = "[1=].10I$[1=].FF&x[1=].8}.FF&x";
424 
425 /*static char gensdbd[] = "0001x";*/
426 
427 char ignosyn[] = "[Xinvalid syntax for instruction";
428 char ignosel[] = "[Xinvalid operands";
429 
430 /* ======================================================================== */
431 /*  Truth table:                                                            */
432 /*                                                                          */
433 /*      ifskip      rptskip     expmac  |   Expand macros   Parse line      */
434 /*      FALSE       FALSE       any     |   TRUE            TRUE            */
435 /*      TRUE        any         FALSE   |   FALSE           FALSE           */
436 /*      TRUE        any         TRUE    |   TRUE            FALSE           */
437 /*      any         TRUE        FALSE   |   FALSE           FALSE           */
438 /*      any         TRUE        TRUE    |   TRUE            FALSE           */
439 /*                                                                          */
440 /*  Only IF/ENDI modify expmac.  RPT 0 does not modify expmac, and the      */
441 /*  default state of expmac is TRUE.  Therefore, by default, macros will    */
442 /*  get expanded in RPT 0 / ENDR blocks.  If you need RPT 0 to terminate    */
443 /*  macro recursion, include an IF / ENDI around it.  Sorry.                */
444 /* ======================================================================== */
445 int fraifskip = FALSE, frarptskip = FALSE, fraexpmac = TRUE;
446 
447 int labelloc;
448 static int satsub;
449 int ifstkpt = 0;
450 int frarptact = 0,     frarptcnt = -1;
451 int struct_locctr = -1;
452 
453 #define MAX_PROC_STK (64)
454 
455 static char *proc_stk[MAX_PROC_STK];
456 static int   proc_stk_depth = 0;
457 
458 extern char *proc;
459 extern int   proc_len;
460 static const char *currmode = "";
461 
462 
463 static int sdbd = 0, is_sdbd = 0;
464 static int romw = 16;
465 static unsigned romm = 0xFFFF;
466 static int first = 1;
467 
468 static int fwd_sdbd = 0;
469 
470 struct symel * endsymbol = SYMNULL;
471 
472 
473 #define SDBD_CHK \
474     if (sdbd) { sdbd = 0; frawarn("SDBD not allowed with this instruction."); }
475 
do_set_equ_(int isequ,int flags,struct symel * sym,int value,const char * equerr)476 LOCAL void do_set_equ_(int isequ, int flags,
477                        struct symel *sym, int value,
478                        const char *equerr)
479 {
480     if (sym->seg == SSG_UNDEF
481         || (sym->seg == SSG_SET && isequ == FALSE))
482     {
483         sym->seg    = isequ ? SSG_EQU : SSG_SET;
484         sym->value  = value;
485         sym->flags |= flags;
486         emit_set_equ(value);
487     } else
488     {
489         fraerror(equerr);
490     }
491 }
492 
do_set_equ_list(int isslice,int isequ,int flags,struct symel * const RESTRICT sym,const intvec_t * const RESTRICT exprs,int firstidx,int lastidx,const char * const RESTRICT ncerr,const char * const RESTRICT equerr)493 LOCAL void do_set_equ_list(int isslice,
494                            int isequ,
495                            int flags,
496                            struct symel   *const RESTRICT sym,
497                            const intvec_t *const RESTRICT exprs,
498                            int firstidx,
499                            int lastidx,
500                            const char *const RESTRICT ncerr,
501                            const char *const RESTRICT equerr)
502 {
503     static long *exprvals = NULL;
504     static int exprvals_size = 0;
505     struct symel *newsym;
506     int i, idx, stp;
507 
508     if (exprvals_size < exprs->len)
509     {
510         exprvals = REALLOC(exprvals, long, exprs->alloc);
511         exprvals_size = exprs->alloc;
512     }
513 
514     for (i = 0; i < exprs->len; i++)
515     {
516         pevalexpr(0, exprs->data[i]);
517 
518         exprvals[i] = evalr[0].value;
519 
520         if (evalr[0].seg != SSG_ABS)
521             fraerror(ncerr);
522     }
523 
524     if (exprs->len == 1 && !isslice)
525     {
526         do_set_equ_(isequ, flags, sym, exprvals[0], equerr);
527     }
528     else if (abs(lastidx - firstidx) + 1 != exprs->len)
529     {
530         fraerror("Array slice length doesn't match expression list length");
531     }
532     else if (sym->seg == SSG_UNDEF || sym->seg == SSG_SET)
533     {
534         if (sym->value < firstidx)
535             sym->value = firstidx;
536 
537         if (sym->value < lastidx)
538             sym->value = lastidx;
539 
540         stp = firstidx > lastidx ? -1 : 1;
541         sym->seg    = SSG_SET;
542         sym->flags |= SFLAG_QUIET;
543 
544         for (i = 0, idx = firstidx; i < exprs->len; i++, idx += stp)
545         {
546             newsym         = symbentryidx(sym->symstr, LABEL, 1, idx);
547             newsym->flags |= SFLAG_QUIET | SFLAG_ARRAY;
548 
549             do_set_equ_(isequ, flags, newsym, exprvals[i], equerr);
550         }
551     } else
552     {
553         fraerror("Cannot convert symbol to array");
554     }
555 }
556 
557 typedef enum { USRERR, USRWARN, USRSTAT, USRCMT } usrmsg;
558 
usr_message(usrmsg type,const char * msg)559 LOCAL void usr_message(usrmsg type, const char *msg)
560 {
561     char *copy = strdup((msg && *msg) ? msg : " "), *s, *ss;
562 
563     /* force all characters to be printing characters */
564     for (s = copy; *s; s++)
565         if (!(isprint(*s) || isspace(*s)))
566             *s = '?';
567 
568     /* Print all the lines of the message, breaking at newlines */
569     for (s = copy; s && *s; s = ss)
570     {
571         ss = strpbrk(s, "\n\r");
572 
573         if (ss)
574             *ss++ = 0;
575 
576         switch (type)
577         {
578             case USRERR:   fraerror(s); break;
579             case USRWARN:  frawarn (s); break;
580             case USRSTAT:  puts(s);     FALLTHROUGH_INTENDED;
581             case USRCMT:   emit_comment(1, "%s", s); break;
582             default:       fraerror("internal error in usr_message");
583         }
584     }
585 
586     free(copy);
587 }
588 
chardef(char * sourcestr,const intvec_t * const RESTRICT defs)589 LOCAL void chardef(char *sourcestr,
590                    const intvec_t *const RESTRICT defs)
591 {
592     int findrv, numret, *charaddr;
593     char *before;
594 
595     if(chtnpoint != (int *)NULL)
596     {
597         for(satsub = 0; satsub < defs->len; satsub++)
598         {
599             before = sourcestr;
600 
601             pevalexpr(0, defs->data[satsub]);
602             findrv = chtcfind(chtnpoint, &sourcestr, &charaddr, &numret);
603 
604             if(findrv == CF_END)
605             {
606                 fraerror("more expressions than characters");
607                 break;
608             }
609 
610             if(evalr[0].seg == SSG_ABS)
611             {
612                 switch(findrv)
613                 {
614                 case CF_UNDEF:
615                     {
616                         if(evalr[0].value < 0 || evalr[0].value > 255)
617                             frawarn("character translation value truncated");
618 
619                         *charaddr = evalr[0].value & 0xff;
620                         emit_set_equ(evalr[0].value);
621                     }
622                     break;
623 
624                 case CF_INVALID:
625                 case CF_NUMBER:
626                     fracherror("invalid character to define",
627                                 before, sourcestr);
628                     break;
629 
630                 case CF_CHAR:
631                     fracherror("character already defined",
632                                before, sourcestr);
633                     break;
634                 }
635             }
636             else
637                 fraerror("noncomputable expression");
638         }
639 
640         if( *sourcestr != '\0')
641             fraerror("more characters than expressions");
642     }
643     else
644         fraerror("no CHARSET statement active");
645 }
646 
chkover(int value,int bias)647 LOCAL int chkover(int value, int bias)
648 {
649     if (value > 0xFFFF + bias || value < 0)
650         fraerror("Address overflow");
651 
652     return value;
653 }
654 
655 #define MAXTEMPSTR (65536)
656 static char tempstr[MAXTEMPSTR];
657 static int  tempstrlen = 0;
658 
659 
660 %}
661 %union {
662     int             intv;
663     int             longv;
664     char            *strng;
665     struct symel    *symb;
666     struct slidx    slidx;
667     intvec_t        *intvec;
668 }
669 
670 %token <intv> CP1600_REG
671 %token <intv> KOC_BDEF
672 %token <intv> KOC_ELSE
673 %token <intv> KOC_END
674 %token <intv> KOC_ENDI
675 %token <intv> KOC_EQU
676 %token <intv> KOC_IF
677 %token <intv> KOC_INCLUDE
678 %token <intv> KOC_ORG
679 %token <intv> KOC_RESM
680 %token <intv> KOC_SDEF
681 %token <intv> KOC_SET
682 %token <intv> KOC_WDEF
683 %token <intv> KOC_CHSET
684 %token <intv> KOC_CHDEF
685 %token <intv> KOC_CHUSE
686 %token <intv> KOC_opcode
687 %token <intv> KOC_opcode_i
688 %token <intv> KOC_relbr
689 %token <intv> KOC_relbr_x
690 %token <intv> KOC_SDBD
691 %token <intv> KOC_ROMW
692 %token <intv> KOC_PROC
693 %token <intv> KOC_ENDP
694 %token <intv> KOC_STRUCT
695 %token <intv> KOC_ENDS
696 %token <intv> KOC_MEMATTR
697 %token <intv> KOC_DDEF
698 %token <intv> KOC_RPT
699 %token <intv> KOC_ENDR
700 %token <intv> KOC_USRERR
701 %token <intv> KOC_LIST
702 %token <intv> KOC_QEQU
703 %token <intv> KOC_QSET
704 %token <intv> KOC_MACERR  /* macro error */
705 %token <intv> KOC_BRKIF
706 %token <intv> KOC_CMSG      /* Comment message inserted into listing        */
707 %token <intv> KOC_SMSG      /* Status message printed to stdout + listing   */
708 %token <intv> KOC_WMSG      /* User warning                                 */
709 %token <intv> KOC_CFGVAR    /* Set a .CFG variable                          */
710 %token <intv> KOC_SRCFILE   /* Set the current source file and line #       */
711 %token <intv> KOC_LISTCOL   /* Control formatting of the listing file.      */
712 %token <intv> KOC_ERR_IF_OVERWRITTEN
713 %token <intv> KOC_FORCE_OVERWRITE
714 
715 %token <longv> CONSTANT
716 %token EOL
717 %token KEOP_AND
718 %token KEOP_DEFINED
719 %token KEOP_EQ
720 %token KEOP_GE
721 %token KEOP_GT
722 %token KEOP_HIGH
723 %token KEOP_LE
724 %token KEOP_LOW
725 %token KEOP_LT
726 %token KEOP_MOD
727 %token KEOP_MUN
728 %token KEOP_NE
729 %token KEOP_NOT
730 %token KEOP_OR
731 %token KEOP_SHL
732 %token KEOP_SHR
733 %token KEOP_SHRU
734 %token <intv> KEOP_ROTL
735 %token <intv> KEOP_ROTR
736 %token KEOP_XOR
737 %token KEOP_locctr
738 %token <longv> KEOP_TODAY_STR
739 %token <longv> KEOP_TODAY_VAL
740 %token <longv> KEOP_STRLEN
741 %token <longv> KEOP_ASC
742 %token <longv> KEOP_CLASSIFY
743 %token <symb>  LABEL
744 %token <strng> STRING
745 %token <longv> QCHAR
746 %token <symb>  SYMBOL
747 %token <longv> FEATURE
748 %token KEOP_EXPMAC   /* _EXPMAC modifier for IF/ENDI.                */
749 
750 %token KTK_invalid
751 
752 %nonassoc EXPRLIST
753 %right  KEOP_HIGH KEOP_LOW
754 %left   KEOP_OR KEOP_XOR
755 %nonassoc FEATURE SYMBOL
756 %left   KEOP_AND
757 %right  KEOP_NOT
758 %nonassoc   KEOP_GT KEOP_GE KEOP_LE KEOP_LT KEOP_NE KEOP_EQ
759 %left   '+' '-'
760 %left   '*' '/' KEOP_MOD KEOP_SHL KEOP_SHR KEOP_SHRU KEOP_ROTL KEOP_ROTR
761 %right  KEOP_MUN
762 %nonassoc ')'
763 %right  KEOP_CLASSIFY
764 
765 
766 %type <intv> expr maybe_expmac
767 %type <intvec> exprlist symslice
768 %type <symb> labelcolon symbol label
769 %type <slidx> labelslice labelslicecolon
770 %type <strng> string
771 
772 %start file
773 
774 %%
775 
776 file    :   file allline
777         |   allline
778         ;
779 
780 allline :   line EOL
781             {
782                 clrexpr();
783                 tempstrlen = 0;
784             }
785         |   EOL
786         |   error EOL
787             {
788                 clrexpr();
789                 tempstrlen = 0;
790                 yyerrok;
791             }
792         ;
793 
794 line    :   labelcolon KOC_END
795             {
796                 endsymbol = $1;
797                 nextreadact = Nra_end;
798             }
799         |   KOC_USRERR string
800             {
801                 usr_message(USRERR, $2);
802             }
803         |   KOC_WMSG string
804             {
805                 usr_message(USRWARN, $2);
806             }
807         |   KOC_SMSG string
808             {
809                 usr_message(USRSTAT, $2);
810             }
811         |   KOC_CMSG string
812             {
813                 usr_message(USRCMT, $2);
814             }
815         |   KOC_MACERR
816             {
817                 fraerror("Unexpected MACRO or ENDM directive");
818             }
819         |   KOC_END
820             {
821                 nextreadact = Nra_end;
822             }
823         |   KOC_INCLUDE STRING
824             {
825                 if(frarptact)
826                 {
827                     fraerror("INCLUDE not permitted inside REPEAT");
828                 } else if(nextfstk >= FILESTKDPTH)
829                 {
830                     fraerror("include file nesting limit exceeded");
831                 }
832                 else
833                 {
834                     infilestk[nextfstk].line = 0;
835                     infilestk[nextfstk].fnm  = memoize_string($2);
836                     if( (infilestk[nextfstk].fpt =
837                         path_fopen(as1600_search_path,$2,"r")) ==(LZFILE*)NULL)
838                     {
839                         static char *incl_file = NULL;
840                         static int   incl_file_size = 0;
841                         int          incl_file_len  = strlen($2) + 80;
842                         if (incl_file_size < incl_file_len)
843                         {
844                             incl_file_size = incl_file_len << 1;
845                             if (incl_file) free(incl_file);
846                             incl_file      = (char *)malloc(incl_file_size);
847                             if (!incl_file)
848                                 incl_file_size = 0;
849                         }
850                         if (incl_file_size == 0)
851                             fraerror("cannot open include file");
852                         else
853                         {
854                             sprintf(incl_file, "cannot open include file "
855                                                "\"%s\"", $2);
856 
857                             fraerror(incl_file);
858                         }
859                     }
860                     else
861                     {
862                         nextreadact = Nra_new;
863                     }
864                 }
865             }
866         |   labelcolon KOC_EQU exprlist
867             {
868                 do_set_equ_list(FALSE, TRUE, 0, $1, $3, 0, $3->len - 1,
869                                "noncomputable expression for EQU",
870                                "cannot change symbol value with EQU");
871                 intvec_delete($3);
872             }
873         |   labelcolon KOC_QEQU exprlist
874             {
875                 do_set_equ_list(FALSE, TRUE, SFLAG_QUIET, $1, $3, 0,
876                                 $3->len - 1,
877                                "noncomputable expression for QEQU",
878                                "cannot change symbol value with QEQU");
879                 intvec_delete($3);
880             }
881         |   labelcolon KOC_SET exprlist
882             {
883                 do_set_equ_list(FALSE, FALSE, 0, $1, $3, 0,
884                                $3->len - 1,
885                                "noncomputable expression for SET",
886                                "cannot change symbol value with SET");
887                 intvec_delete($3);
888             }
889         |   labelcolon KOC_QSET exprlist
890             {
891                 do_set_equ_list(FALSE, FALSE, SFLAG_QUIET, $1, $3, 0,
892                                 $3->len - 1,
893                                "noncomputable expression for QSET",
894                                "cannot change symbol value with QSET");
895                 intvec_delete($3);
896             }
897         |   labelslicecolon KOC_EQU exprlist
898             {
899                 do_set_equ_list(TRUE, TRUE, 0,
900                                 $1.sym, $3, $1.first, $1.last,
901                                "noncomputable expression for EQU",
902                                "cannot change symbol value with EQU");
903                 intvec_delete($3);
904             }
905         |   labelslicecolon KOC_QEQU exprlist
906             {
907                 do_set_equ_list(TRUE, TRUE, SFLAG_QUIET,
908                                 $1.sym, $3, $1.first, $1.last,
909                                "noncomputable expression for QEQU",
910                                "cannot change symbol value with QEQU");
911                 intvec_delete($3);
912             }
913         |   labelslicecolon KOC_SET exprlist
914             {
915                 do_set_equ_list(TRUE, FALSE, 0,
916                                 $1.sym, $3, $1.first, $1.last,
917                                "noncomputable expression for SET",
918                                "cannot change symbol value with SET");
919                 intvec_delete($3);
920             }
921         |   labelslicecolon KOC_QSET exprlist
922             {
923                 do_set_equ_list(TRUE, FALSE, SFLAG_QUIET,
924                                 $1.sym, $3, $1.first, $1.last,
925                                "noncomputable expression for QSET",
926                                "cannot change symbol value with QSET");
927                 intvec_delete($3);
928             }
929         |   KOC_RPT expr
930             {
931                 pevalexpr(0, $2);
932                 if (evalr[0].seg == SSG_ABS)
933                 {
934                     if (evalr[0].value < 0)
935                     {
936                         fraerror("REPEAT count must be >= 0");
937                         frarptpush(0);  /* treat it as a 0 count. */
938                     } else
939                     {
940                         frarptpush(frarptskip ? 0 : evalr[0].value);
941                     }
942                 } else
943                 {
944                     fraerror("Computable expression required for REPEAT block");
945                     frarptpush(0);  /* treat it as a 0 count. */
946                 }
947             }
948         |   KOC_ENDR
949             {
950                 if (frarptact == 0)
951                 {
952                     fraerror("ENDR without REPEAT");
953                     frarptreset();  /* make sure repeat stack is reset. */
954                 } else
955                 {
956                     frarptendr();   /* loop back to most recent REPEAT */
957                 }
958             }
959         |   KOC_BRKIF expr
960             {
961                 if (frarptcnt < 0)
962                     fraerror("BRKIF without REPEAT");
963 
964                 pevalexpr(0, $2);
965                 if (evalr[0].seg == SSG_ABS)
966                 {
967                     if (evalr[0].value != 0)
968                         frarptbreak();  /* skip rest of repeat block */
969                 } else
970                 {
971                     fraerror("Computable expression required for BRKIF");
972                 }
973             }
974         |   KOC_LIST STRING
975             {
976                 if      (stricmp($2, "ON"  )==0) emit_listing_mode(LIST_ON);
977                 else if (stricmp($2, "OFF" )==0) emit_listing_mode(LIST_OFF);
978                 else if (stricmp($2, "CODE")==0) emit_listing_mode(LIST_CODE);
979                 else if (stricmp($2, "PREV")==0) emit_listing_mode(LIST_PREV);
980                 else
981                 {
982                     fraerror("LISTING must be followed by \"ON\", \"OFF\" "
983                              "or \"CODE\"");
984                 }
985             }
986         |   labelcolon KOC_LIST STRING
987             {
988                 if      (stricmp($3, "ON"  )==0) emit_listing_mode(LIST_ON);
989                 else if (stricmp($3, "OFF" )==0) emit_listing_mode(LIST_OFF);
990                 else if (stricmp($3, "CODE")==0) emit_listing_mode(LIST_CODE);
991                 else if (stricmp($3, "PREV")==0) emit_listing_mode(LIST_PREV);
992                 else
993                 {
994                     fraerror("LISTING must be followed by \"ON\", \"OFF\" "
995                              "or \"CODE\"");
996                 }
997 
998                 if($1->seg == SSG_UNDEF)
999                 {
1000                     $1->seg   = SSG_ABS;
1001                     $1->value = labelloc;
1002                 }
1003                 else
1004                     fraerror( "multiple definition of label");
1005             }
1006         |   KOC_IF maybe_expmac expr
1007             {
1008                 if((++ifstkpt) < IFSTKDEPTH)
1009                 {
1010                     pevalexpr(0, $3);
1011                     if(evalr[0].seg == SSG_ABS)
1012                     {
1013                         if(evalr[0].value != 0)
1014                         {
1015                             elseifstk[ifstkpt] = If_Skip;
1016                             endifstk[ifstkpt] = If_Active;
1017                         }
1018                         else
1019                         {
1020                             fraifskip = TRUE;
1021                             elseifstk[ifstkpt] = If_Active;
1022                             endifstk[ifstkpt] = If_Active;
1023                         }
1024                     }
1025                     else
1026                     {
1027                         fraifskip = TRUE;
1028                         elseifstk[ifstkpt] = If_Active;
1029                         endifstk[ifstkpt] = If_Active;
1030                     }
1031                     expmacstk[ifstkpt] = fraexpmac;
1032                     fraexpmac = $2;
1033                 }
1034                 else
1035                 {
1036                     fraerror("IF stack overflow");
1037                 }
1038             }
1039 
1040         |   KOC_IF maybe_expmac
1041             {
1042                 if(fraifskip)
1043                 {
1044                     if((++ifstkpt) < IFSTKDEPTH)
1045                     {
1046                             elseifstk[ifstkpt] = If_Skip;
1047                             endifstk[ifstkpt] = If_Skip;
1048                             expmacstk[ifstkpt] = fraexpmac;
1049                             fraexpmac = $2;
1050                     }
1051                     else
1052                     {
1053                         fraerror("IF stack overflow");
1054                     }
1055                 }
1056                 else
1057                 {
1058                     yyerror("syntax error");
1059                     YYERROR;
1060                 }
1061             }
1062 
1063         |   KOC_ELSE
1064             {
1065                 switch(elseifstk[ifstkpt])
1066                 {
1067                 case If_Active:
1068                     fraifskip = FALSE;
1069                     break;
1070 
1071                 case If_Skip:
1072                     fraifskip = TRUE;
1073                     break;
1074 
1075                 case If_Err:
1076                     fraerror("ELSE with no matching if");
1077                     break;
1078                 }
1079             }
1080 
1081         |   KOC_ENDI
1082             {
1083                 fraexpmac = expmacstk[ifstkpt];
1084                 switch(endifstk[ifstkpt])
1085                 {
1086                 case If_Active:
1087                     fraifskip = FALSE;
1088                     ifstkpt--;
1089                     break;
1090 
1091                 case If_Skip:
1092                     fraifskip = TRUE;
1093                     ifstkpt--;
1094                     break;
1095 
1096                 case If_Err:
1097                     fraerror("ENDI with no matching if");
1098                     break;
1099                 }
1100             }
1101         |   labelcolon KOC_ORG expr
1102             {
1103                 pevalexpr(0, $3);
1104                 if(evalr[0].seg == SSG_ABS)
1105                 {
1106                     locctr   = 2 * chkover(labelloc = evalr[0].value, 0);
1107                     currseg  = 0;
1108                     currpag  = -1;
1109                     currmode = memoize_string("+R");
1110                     if($1->seg == SSG_UNDEF)
1111                     {
1112                         $1->seg   = SSG_ABS;
1113                         $1->value = labelloc;
1114                     }
1115                     else
1116                         fraerror( "multiple definition of label");
1117 
1118                     emit_set_equ(evalr[0].value);
1119                 }
1120                 else
1121                 {
1122                     fraerror( "noncomputable expression for ORG");
1123                 }
1124             }
1125         |   KOC_ORG expr
1126             {
1127                 pevalexpr(0, $2);
1128                 if(evalr[0].seg == SSG_ABS)
1129                 {
1130                     locctr   = 2 * chkover(labelloc = evalr[0].value, 0);
1131                     currseg  = 0;
1132                     currpag  = -1;
1133                     currmode = memoize_string("+R");
1134                     emit_set_equ(evalr[0].value);
1135                 }
1136                 else
1137                 {
1138                     fraerror(
1139                      "noncomputable expression for ORG");
1140                 }
1141             }
1142         |   labelcolon KOC_ORG expr ',' expr
1143             {
1144                 pevalexpr(0, $3);
1145                 pevalexpr(1, $5);
1146                 if(evalr[0].seg == SSG_ABS && evalr[1].seg == SSG_ABS)
1147                 {
1148                     locctr   = 2 * chkover(labelloc = evalr[0].value, 0);
1149                     currseg  = chkover(evalr[1].value, 0) - labelloc;
1150                     currpag  = -1;
1151                     currmode = memoize_string(currseg ? "" : "+R");
1152                     if($1->seg == SSG_UNDEF)
1153                     {
1154                         $1->seg   = SSG_ABS;
1155                         $1->value = labelloc;
1156                     }
1157                     else
1158                         fraerror( "multiple definition of label");
1159 
1160                     emit_set_equ(evalr[0].value);
1161                 }
1162                 else
1163                 {
1164                     fraerror( "noncomputable expression for ORG");
1165                 }
1166             }
1167         |   KOC_ORG expr ',' expr
1168             {
1169                 pevalexpr(0, $2);
1170                 pevalexpr(1, $4);
1171                 if(evalr[0].seg == SSG_ABS && evalr[1].seg == SSG_ABS)
1172                 {
1173                     locctr   = 2 * chkover(labelloc = evalr[0].value, 0);
1174                     currseg  = chkover(evalr[1].value, 0) - labelloc;
1175                     currpag  = -1;
1176                     currmode = memoize_string(currseg ? "" : "+R");
1177                     emit_set_equ(evalr[0].value);
1178                 }
1179                 else
1180                 {
1181                     fraerror(
1182                      "noncomputable expression for ORG");
1183                 }
1184             }
1185         |   labelcolon KOC_ORG expr ',' expr ',' STRING
1186             {
1187                 pevalexpr(0, $3);
1188                 pevalexpr(1, $5);
1189                 if(evalr[0].seg == SSG_ABS && evalr[1].seg == SSG_ABS)
1190                 {
1191                     char *s = $7;
1192 
1193                     locctr   = 2 * chkover(labelloc = evalr[0].value, 0);
1194                     currseg  = chkover(evalr[1].value, 0) - labelloc;
1195                     currpag  = -1;
1196                     currmode = memoize_string(s);
1197 
1198                     if($1->seg == SSG_UNDEF)
1199                     {
1200                         $1->seg = SSG_ABS;
1201                         $1->value = labelloc;
1202                     }
1203                     else
1204                         fraerror( "multiple definition of label");
1205 
1206                     emit_set_equ(evalr[0].value);
1207                 }
1208                 else
1209                 {
1210                     fraerror( "noncomputable expression for ORG");
1211                 }
1212             }
1213         |   KOC_ORG expr ',' expr ',' STRING
1214             {
1215                 pevalexpr(0, $2);
1216                 pevalexpr(1, $4);
1217                 if(evalr[0].seg == SSG_ABS && evalr[1].seg == SSG_ABS)
1218                 {
1219                     char *s = $6;
1220 
1221                     locctr   = 2 * chkover(labelloc = evalr[0].value, 0);
1222                     currseg  = chkover(evalr[1].value, 0) - labelloc;
1223                     currpag  = -1;
1224                     currmode = memoize_string(s);
1225                     emit_set_equ(evalr[0].value);
1226                 }
1227                 else
1228                 {
1229                     fraerror("noncomputable expression for ORG");
1230                 }
1231             }
1232         |   labelcolon KOC_ORG expr ':' expr
1233             {
1234                 pevalexpr(0, $3);
1235                 pevalexpr(1, $5);
1236                 if(evalr[0].seg == SSG_ABS && evalr[1].seg == SSG_ABS)
1237                 {
1238                     locctr   = 2 * chkover(labelloc = evalr[0].value, 0);
1239                     currseg  = 0;
1240                     currpag  = evalr[1].value;
1241                     currmode = memoize_string("=R");
1242                     if($1->seg == SSG_UNDEF)
1243                     {
1244                         $1->seg   = SSG_ABS;
1245                         $1->value = labelloc;
1246                     }
1247                     else
1248                         fraerror( "multiple definition of label");
1249 
1250                     emit_set_equ(evalr[0].value);
1251                 }
1252                 else
1253                 {
1254                     fraerror( "noncomputable expression for ORG");
1255                 }
1256             }
1257         |   KOC_ORG expr ':' expr
1258             {
1259                 pevalexpr(0, $2);
1260                 pevalexpr(1, $4);
1261                 if(evalr[0].seg == SSG_ABS && evalr[1].seg == SSG_ABS)
1262                 {
1263                     locctr   = 2 * chkover(labelloc = evalr[0].value, 0);
1264                     currseg  = 0;
1265                     currpag  = evalr[1].value;
1266                     currmode = memoize_string("=R");
1267                     emit_set_equ(evalr[0].value);
1268                 }
1269                 else
1270                 {
1271                     fraerror("noncomputable expression for ORG");
1272                 }
1273             }
1274         |   labelcolon KOC_ORG expr ':' expr ',' STRING
1275             {
1276                 pevalexpr(0, $3);
1277                 pevalexpr(1, $5);
1278                 if(evalr[0].seg == SSG_ABS && evalr[1].seg == SSG_ABS)
1279                 {
1280                     locctr   = 2 * chkover(labelloc = evalr[0].value, 0);
1281                     currseg  = 0;
1282                     currpag  = evalr[1].value;
1283                     currmode = memoize_string($7);
1284                     if($1->seg == SSG_UNDEF)
1285                     {
1286                         $1->seg   = SSG_ABS;
1287                         $1->value = labelloc;
1288                     }
1289                     else
1290                         fraerror( "multiple definition of label");
1291 
1292                     emit_set_equ(evalr[0].value);
1293                 }
1294                 else
1295                 {
1296                     fraerror( "noncomputable expression for ORG");
1297                 }
1298             }
1299         |   KOC_ORG expr ':' expr ',' STRING
1300             {
1301                 pevalexpr(0, $2);
1302                 pevalexpr(1, $4);
1303                 if(evalr[0].seg == SSG_ABS && evalr[1].seg == SSG_ABS)
1304                 {
1305                     locctr   = 2 * chkover(labelloc = evalr[0].value, 0);
1306                     currseg  = 0;
1307                     currpag  = evalr[1].value;
1308                     currmode = memoize_string($6);
1309                     emit_set_equ(evalr[0].value);
1310                 }
1311                 else
1312                 {
1313                     fraerror("noncomputable expression for ORG");
1314                 }
1315             }
1316         |   KOC_MEMATTR expr ',' expr ',' STRING
1317             {
1318                 pevalexpr(0, $2);
1319                 pevalexpr(1, $4);
1320                 if(evalr[0].seg == SSG_ABS && evalr[1].seg == SSG_ABS)
1321                 {
1322                     const char *s = memoize_string($6);
1323                     chkover(evalr[0].value, 0);
1324                     chkover(evalr[1].value, 0);
1325                     emit_location(0, -1, labelloc, TYPE_HOLE, s);
1326                     emit_mark_with_mode(evalr[0].value, evalr[1].value, s);
1327                     emit_location(currseg, currpag, labelloc, TYPE_HOLE,
1328                                   currmode);
1329                 }
1330                 else
1331                 {
1332                     fraerror("noncomputable expression for MEMATTR");
1333                 }
1334             }
1335         |   KOC_CFGVAR string KEOP_EQ string
1336             {
1337                 const char *var   = memoize_string($2);
1338                 const char *value = memoize_string($4);
1339                 emit_cfgvar_str(var, value);
1340             }
1341         |   KOC_CFGVAR string KEOP_EQ expr
1342             {
1343                 pevalexpr(0, $4);
1344                 if(evalr[0].seg == SSG_ABS)
1345                 {
1346                     const char *var = memoize_string($2);
1347                     emit_cfgvar_int(var, evalr[0].value);
1348                 }
1349                 else
1350                 {
1351                     fraerror("noncomputable expression for CFGVAR");
1352                 }
1353             }
1354         |   KOC_SRCFILE string ',' expr
1355             {
1356                 /* set the current source file override and line number */
1357                 pevalexpr(0, $4);
1358                 if ( evalr[0].seg == SSG_ABS )
1359                 {
1360                     if ( strlen( $2 ) == 0 || evalr[0].value < 1 )
1361                     {
1362                         emit_srcfile_override( NULL, 0 );
1363                     } else
1364                     {
1365                         emit_srcfile_override( memoize_string( $2 ),
1366                                                evalr[0].value );
1367                     }
1368                 }
1369                 else
1370                 {
1371                     fraerror("noncomputable expression for SRCFILE");
1372                 }
1373             }
1374         |   KOC_LISTCOL expr ',' expr ',' expr
1375             {
1376                 pevalexpr(0, $2);   /* Hex per line w/ source */
1377                 pevalexpr(1, $4);   /* Hex per line w/out source */
1378                 pevalexpr(2, $6);   /* Starting column of source */
1379                 if ( evalr[0].seg != SSG_ABS || evalr[1].seg != SSG_ABS ||
1380                      evalr[2].seg != SSG_ABS )
1381                 {
1382                     fraerror("noncomputable expression for LISTCOL");
1383                 } else
1384                 {
1385                     const int new_hex_source = evalr[0].value;
1386                     const int new_hex_no_src = evalr[1].value;
1387                     const int new_source_ofs = evalr[2].value;
1388                     const int new_source_ofs_min = 7 + 5*new_hex_source;
1389 
1390                     if (new_hex_source < 1 || new_hex_source > 256 ||
1391                         new_hex_no_src < 1 || new_hex_no_src > 256 ||
1392                         new_source_ofs < 1 || new_source_ofs > 2048)
1393                     {
1394                         fraerror("value out of range value for LISTCOL");
1395                     } else
1396                     {
1397                         if (new_source_ofs < new_source_ofs_min)
1398                         {
1399                             fraerror("source column too small compared to "
1400                                      "hex-per-source-line for LISTCOL");
1401                         } else
1402                         {
1403                             emit_listing_column(new_hex_source,
1404                                                 new_hex_no_src,
1405                                                 new_source_ofs);
1406                         }
1407                     }
1408                 }
1409             }
1410         |   KOC_ERR_IF_OVERWRITTEN expr
1411             {
1412                 pevalexpr(0, $2);
1413                 if ( evalr[0].seg != SSG_ABS )
1414                 {
1415                     fraerror("noncomputable expression for ERR_IF_OVERWITTEN");
1416                 } else
1417                 {
1418                     emit_err_if_overwritten(evalr[0].value != 0);
1419                 }
1420             }
1421         |   KOC_FORCE_OVERWRITE expr
1422             {
1423                 pevalexpr(0, $2);
1424                 if ( evalr[0].seg != SSG_ABS )
1425                 {
1426                     fraerror("noncomputable expression for FORCE_OVERWRITE");
1427                 } else
1428                 {
1429                     emit_force_overwrite(evalr[0].value != 0);
1430                 }
1431             }
1432         |   labelcolon KOC_CHSET
1433             {
1434                 if($1->seg == SSG_UNDEF)
1435                 {
1436                     $1->seg = SSG_EQU;
1437                     if( ($1->value = chtcreate()) <= 0)
1438                     {
1439                         fraerror("cannot create character translation table");
1440                     }
1441                     emit_set_equ($1->value);
1442                 }
1443                 else
1444                 {
1445                     fraerror("multiple definition of label");
1446                 }
1447             }
1448         |   KOC_CHUSE
1449             {
1450                 chtcpoint = (int *) NULL;
1451                 emit_set_equ(0L);
1452             }
1453         |   KOC_CHUSE expr
1454             {
1455                 pevalexpr(0, $2);
1456                 if( evalr[0].seg == SSG_ABS)
1457                 {
1458                     if( evalr[0].value == 0)
1459                     {
1460                         chtcpoint = (int *)NULL;
1461                         emit_set_equ(0L);
1462                     }
1463                     else if(evalr[0].value < chtnxalph)
1464                     {
1465                         chtcpoint = chtatab[evalr[0].value];
1466                         emit_set_equ(evalr[0].value);
1467                     }
1468                     else
1469                     {
1470                         fraerror("nonexistent character translation table");
1471                     }
1472                 }
1473                 else
1474                 {
1475                     fraerror("noncomputable expression");
1476                 }
1477             }
1478         |   KOC_CHDEF string ',' exprlist
1479             {
1480                 chardef($2, $4);
1481                 intvec_delete($4);
1482             }
1483         |   KOC_CHDEF QCHAR ',' exprlist
1484             {
1485                 char st[2] = { $2, 0 };
1486                 chardef(st, $4);
1487                 intvec_delete($4);
1488             }
1489         |   labelcolon
1490             {
1491                 if($1->seg == SSG_UNDEF)
1492                 {
1493                     $1->seg = SSG_ABS;
1494                     $1->value = chkover(labelloc, 0);
1495                     emit_set_equ(labelloc);
1496 
1497                 }
1498                 else
1499                     fraerror("multiple definition of label");
1500             }
1501         |   labeledline
1502         ;
1503 
1504 maybe_expmac:   KEOP_EXPMAC { $$ = 1; }
1505             |               { $$ = 0; }
1506             ;
1507 
1508 labeledline :   labelcolon genline
1509             {
1510                 if (sdbd)
1511                     frawarn("label between SDBD and instruction");
1512 
1513                 if($1->seg == SSG_UNDEF)
1514                 {
1515                     $1->seg   = SSG_ABS;
1516                     $1->value = chkover(labelloc, 0);
1517                 }
1518                 else
1519                     fraerror("multiple definition of label");
1520 
1521                 if (locctr & 1) fraerror("internal error: PC misaligned.");
1522 
1523                 labelloc = locctr >> 1;
1524 
1525                 sdbd    = is_sdbd;
1526                 is_sdbd = 0;
1527                 first   = 0;
1528             }
1529         |   genline
1530             {
1531                 if (locctr & 1) fraerror("internal error: PC misaligned.");
1532                 labelloc = locctr >> 1;
1533 
1534                 sdbd    = is_sdbd;
1535                 is_sdbd = 0;
1536                 first   = 0;
1537             }
1538         ;
1539 
1540 genline :   KOC_BDEF exprlist
1541             {
1542                 emit_location(currseg, currpag, labelloc, TYPE_DATA, currmode);
1543                 evalr[2].seg   = SSG_ABS;
1544                 evalr[2].value = 8;
1545                 for( satsub = 0; satsub < $2->len; satsub++)
1546                 {
1547                     pevalexpr(1, $2->data[satsub]);
1548                     locctr += geninstr(genbdef);
1549                 }
1550                 chkover( locctr >> 1 , 1);
1551                 intvec_delete($2);
1552             }
1553         |   KOC_DDEF exprlist
1554             {
1555                 emit_location(currseg, currpag, labelloc, TYPE_DATA, currmode);
1556                 evalr[2].seg   = SSG_ABS;
1557                 evalr[2].value = romw;
1558                 for( satsub = 0; satsub < $2->len; satsub++)
1559                 {
1560                     pevalexpr(1, $2->data[satsub]);
1561                     locctr += geninstr(genbdef);
1562                 }
1563                 chkover( locctr >> 1 , 1);
1564                 intvec_delete($2);
1565             }
1566 
1567         |   KOC_SDEF exprlist
1568             {
1569                 emit_location(currseg, currpag, labelloc, TYPE_STRING, currmode);
1570                 evalr[2].seg   = SSG_ABS;
1571                 evalr[2].value = romw;
1572                 for( satsub = 0; satsub < $2->len; satsub++)
1573                 {
1574                     pevalexpr(1, $2->data[satsub]);
1575                     locctr += geninstr(genbdef);
1576                 }
1577                 chkover( locctr >> 1 , 1);
1578                 intvec_delete($2);
1579             }
1580         |   KOC_WDEF exprlist
1581             {
1582                 emit_location(currseg, currpag, labelloc,
1583                               TYPE_DBDATA|TYPE_DATA, currmode);
1584                 for( satsub = 0; satsub < $2->len; satsub++)
1585                 {
1586                     pevalexpr(1, $2->data[satsub]);
1587                     locctr += geninstr(genwdef);
1588                 }
1589                 chkover( locctr >> 1 , 1);
1590                 intvec_delete($2);
1591             }
1592         |   KOC_RESM expr
1593             {
1594                 pevalexpr(0, $2);
1595                 if(evalr[0].seg == SSG_ABS)
1596                 {
1597                     locctr = 2 * chkover(labelloc + evalr[0].value, 1);
1598                     emit_set_equ(labelloc);
1599                     emit_location(currseg, currpag, labelloc, TYPE_HOLE,
1600                                   currmode);
1601                     emit_reserve(labelloc + evalr[0].value - 1);
1602                 }
1603                 else
1604                 {
1605                     fraerror("noncomputable expression for RMB");
1606                 }
1607             }
1608         ;
1609 
1610 labelcolon: label
1611         |   label ':'
1612         ;
1613 
1614 labelslicecolon: labelslice
1615              |   labelslice ':'
1616             ;
1617 
1618 exprlist :  exprlist ',' expr
1619             {
1620                 intvec_push($1, $3);
1621                 $$ = $1;
1622             }
1623         |   exprlist ',' string
1624             {
1625                 char *s = $3;
1626                 int  accval = 0;
1627 
1628                 while (*s)
1629                 {
1630                     accval = chtran(&s);
1631                     intvec_push($1,
1632                         exprnode(PCCASE_CONS,0,IGP_CONSTANT,0,accval,SYMNULL));
1633                 }
1634                 $$ = $1;
1635             }
1636         |   expr %prec EXPRLIST
1637             {
1638                 intvec_t *const RESTRICT iv = intvec_new();
1639                 intvec_push(iv, $1);
1640                 $$ = iv;
1641             }
1642         |   string
1643             {
1644                 intvec_t *const RESTRICT iv = intvec_new();
1645                 char *s = $1;
1646                 int  accval = 0;
1647 
1648                 while (*s)
1649                 {
1650                     accval = chtran(&s);
1651                     intvec_push(iv,
1652                         exprnode(PCCASE_CONS,0,IGP_CONSTANT,0,accval,SYMNULL));
1653                 }
1654                 $$ = iv;
1655             }
1656         |   KEOP_TODAY_VAL '(' string ')'
1657             {
1658                 const struct tm *t = $1 ? &asm_time_gmt : &asm_time_local;
1659                 $$ = unpack_time_exprs(t, &asm_time_gmt, $3);
1660             }
1661         |   exprlist ',' symslice
1662             {
1663                 intvec_concat($1, $3);
1664                 intvec_delete($3);
1665                 $$ = $1;
1666             }
1667         |   symslice
1668             {
1669                 $$ = $1;
1670             }
1671         ;
1672 
1673 string  :   STRING
1674         |   '$' '(' exprlist ')'
1675             {
1676                 char *s = &tempstr[tempstrlen];
1677 
1678                 if (chtcpoint != NULL)
1679                 {
1680                     frawarn("Stringifying expression list while character "
1681                             "translation active");
1682                 }
1683 
1684                 tempstrlen += $3->len + 1;
1685 
1686                 if (tempstrlen > MAXTEMPSTR)
1687                 {
1688                     fraerror("Temporary string buffer overflow");
1689                     $$ = "";
1690                 } else
1691                 {
1692                     int i;
1693                     $$ = s;
1694                     for (i = 0; i < $3->len; i++)
1695                     {
1696                         pevalexpr(0, $3->data[i]);
1697 
1698                         if (evalr[0].seg == SSG_ABS)
1699                             *s++ = evalr[0].value;
1700                         else
1701                             *s++ = '?';
1702                     }
1703                     *s = 0;
1704                 }
1705                 intvec_delete($3);
1706             }
1707         |   '$' '#' '(' expr ')'
1708             {
1709                 char *s = &tempstr[tempstrlen];
1710 
1711                 if (tempstrlen + 32 > MAXTEMPSTR)
1712                 {
1713                     fraerror("Temporary string buffer overflow");
1714                     $$ = "";
1715                 } else
1716                 {
1717                     $$ = s;
1718                     pevalexpr(0, $4);
1719 
1720                     if (evalr[0].seg == SSG_ABS)
1721                         sprintf(s, "%d", (int)evalr[0].value);
1722                     else
1723                     {
1724                         s[0] = '?';
1725                         s[1] = 0;
1726                     }
1727                     tempstrlen += strlen(s) + 1;
1728                 }
1729             }
1730         |   '$' '$' '(' expr ')'
1731             {
1732                 char *s = &tempstr[tempstrlen];
1733 
1734                 if (tempstrlen + 5 > MAXTEMPSTR)
1735                 {
1736                     fraerror("Temporary string buffer overflow");
1737                     $$ = "";
1738                 } else
1739                 {
1740                     $$ = s;
1741                     pevalexpr(0, $4);
1742 
1743                     if (evalr[0].seg == SSG_ABS)
1744                         sprintf(s, "%4.4X",
1745                                 (unsigned int)(0xFFFF & evalr[0].value));
1746                     else
1747                     {
1748                         s[0] = '?';
1749                         s[1] = '?';
1750                         s[2] = '?';
1751                         s[3] = '?';
1752                         s[4] = 0;
1753                     }
1754                     tempstrlen += 5;
1755                 }
1756             }
1757         |   '$' '%' '(' expr ')'
1758             {
1759                 char *s = &tempstr[tempstrlen];
1760 
1761                 if (tempstrlen + 5 > MAXTEMPSTR)
1762                 {
1763                     fraerror("Temporary string buffer overflow");
1764                     $$ = "";
1765                 } else
1766                 {
1767                     $$ = s;
1768                     pevalexpr(0, $4);
1769 
1770                     if (evalr[0].seg == SSG_ABS)
1771                         sprintf(s, "%8.8X",
1772                                 (unsigned int)(0xFFFFFFFF & evalr[0].value));
1773                     else
1774                     {
1775                         s[0] = '?';
1776                         s[1] = '?';
1777                         s[2] = '?';
1778                         s[3] = '?';
1779                         s[4] = '?';
1780                         s[5] = '?';
1781                         s[6] = '?';
1782                         s[7] = '?';
1783                         s[8] = 0;
1784                     }
1785                     tempstrlen += 5;
1786                 }
1787             }
1788         |   KEOP_TODAY_STR '(' string ')'
1789             {
1790                 const struct tm *t = $1 ? &asm_time_gmt : &asm_time_local;
1791                 char *const bufbeg = &tempstr[tempstrlen];
1792                 const int avail = MAXTEMPSTR - tempstrlen;
1793                 const int len = format_time_string(t, &asm_time_gmt,
1794                                                    $3, bufbeg, avail);
1795                 tempstrlen += len;
1796                 $$ = bufbeg;
1797             }
1798         ;
1799 
1800 /* ======================================================================== */
1801 /*  PROC/ENDP pseudo-ops                                                    */
1802 /* ======================================================================== */
1803 genline : labelcolon KOC_PROC
1804             {
1805                 if (proc && struct_locctr != -1)
1806                     fraerror("PROC cannot nest inside STRUCT.");
1807                 else if (proc && proc_stk_depth == MAX_PROC_STK)
1808                     fraerror("PROC nesting limit reached.");
1809                 else if (($1->flags & SFLAG_ARRAY) != 0)
1810                     fraerror("array element can not be defined by PROC");
1811                 else if ($1->seg != SSG_UNDEF)
1812                     fraerror("multiple definition of label");
1813                 else
1814                 {
1815                     if (proc)
1816                     {
1817                         char *old_proc     = proc;
1818                         int   old_proc_len = proc_len;
1819                         proc_stk[proc_stk_depth++] = proc;
1820                         proc_len = strlen(proc) + strlen($1->symstr) + 1;
1821                         proc     = (char *)malloc(proc_len + 1);
1822                         strcpy(proc, old_proc);
1823                         proc[old_proc_len] = '.';
1824                         strcpy(proc + old_proc_len + 1, $1->symstr);
1825                     } else
1826                     {
1827                         proc     = strdup($1->symstr);
1828                         proc_len = strlen(proc);
1829                     }
1830 
1831                     $1->seg   = SSG_ABS;
1832                     $1->value = labelloc;
1833                     emit_set_equ(labelloc);
1834                 }
1835             }
1836         ;
1837 genline : KOC_ENDP
1838             {
1839                 if (!proc || struct_locctr != -1)
1840                     fraerror("ENDP w/out PROC.");
1841 
1842                 free(proc);
1843 
1844                 if (proc_stk_depth > 0)
1845                 {
1846                     proc     = proc_stk[--proc_stk_depth];
1847                     proc_len = strlen(proc);
1848                 } else
1849                 {
1850                     proc     = NULL;
1851                     proc_len = 0;
1852                 }
1853             }
1854         ;
1855 /* ======================================================================== */
1856 /*  STRUCT/ENDS pseudo-ops                                                  */
1857 /* ======================================================================== */
1858 genline : labelcolon KOC_STRUCT expr
1859             {
1860                 pevalexpr(0, $3);
1861 
1862                 if (proc)
1863                     fraerror("STRUCT can not nest inside other STRUCTs or PROCs.");
1864                 else if (($1->flags & SFLAG_ARRAY) != 0)
1865                     fraerror("array element can not be defined by STRUCT");
1866                 else if (evalr[0].seg != SSG_ABS)
1867                     fraerror( "noncomputable expression for ORG");
1868                 else if ($1->seg != SSG_UNDEF)
1869                     fraerror( "multiple definition of label");
1870                 else
1871                 {
1872                     proc     = strdup($1->symstr);
1873                     proc_len = strlen(proc);
1874                     struct_locctr = locctr;
1875 
1876                     locctr = 2 * chkover(labelloc = evalr[0].value, 0);
1877 
1878                     $1->seg = SSG_ABS;
1879                     $1->value = labelloc;
1880 
1881                     emit_set_equ(evalr[0].value);
1882                 }
1883             }
1884         ;
1885 genline : KOC_ENDS
1886             {
1887                 if (!proc || struct_locctr == -1)
1888                     fraerror("ENDS w/out STRUCT.");
1889                 else
1890                 {
1891                     free(proc);
1892                     proc     = NULL;
1893                     proc_len = 0;
1894                     locctr = struct_locctr;
1895                     struct_locctr = -1;
1896                 }
1897             }
1898         ;
1899 /* ======================================================================== */
1900 /*  ROMWIDTH pseudo-op                                                      */
1901 /* ======================================================================== */
1902 genline : KOC_ROMW expr
1903             {
1904                 emit_location(currseg, currpag, labelloc, TYPE_HOLE, currmode);
1905                 pevalexpr(0, $2);
1906                 if(evalr[0].seg == SSG_ABS)
1907                 {
1908                     romw = evalr[0].value;
1909 
1910                     if (romw < 8 || romw > 16)
1911                         fraerror("ROMWIDTH out of range");
1912 
1913                     romm = 0xFFFFU >> (16 - romw);
1914                 }
1915                 else
1916                 {
1917                     fraerror("noncomputable expression for ROMWIDTH");
1918                 }
1919 
1920                 if (!first)
1921                 {
1922                     frawarn("Code appears before ROMW directive.");
1923                 }
1924 
1925                 fwd_sdbd = 0;
1926             }
1927         | KOC_ROMW expr ',' expr
1928             {
1929                 emit_location(currseg, currpag, labelloc, TYPE_HOLE, currmode);
1930                 pevalexpr(0, $2);
1931                 pevalexpr(1, $4);
1932                 if(evalr[0].seg == SSG_ABS)
1933                 {
1934                     romw = evalr[0].value;
1935 
1936                     if (romw < 8 || romw > 16)
1937                         fraerror("ROMWIDTH out of range");
1938 
1939                     romm = 0xFFFFU >> (16 - romw);
1940                 }
1941                 else
1942                     fraerror("noncomputable expression for ROMWIDTH");
1943 
1944                 if (!first)
1945                 {
1946                     frawarn("Code appears before ROMW directive.");
1947                 }
1948 
1949                 if (evalr[1].seg == SSG_ABS)
1950                 {
1951                     fwd_sdbd = evalr[1].value;
1952 
1953                     if (fwd_sdbd > 1 || fwd_sdbd < 0)
1954                         fraerror("SDBD mode flag must be 0 or 1.");
1955                 } else
1956                     fraerror("noncomputable expression for ROMWIDTH");
1957 
1958             }
1959         ;
1960 
1961 /* ======================================================================== */
1962 /*  SDBD instruction.                                                       */
1963 /* ======================================================================== */
1964 genline : KOC_SDBD
1965             {
1966                 if (sdbd)
1967                     frawarn("Two SDBDs in a row.");
1968 
1969                 emit_location(currseg, currpag, labelloc, TYPE_CODE, currmode);
1970                 locctr += geninstr(findgen($1, ST_IMP, 0));
1971                 chkover(locctr >> 1, 1);
1972                 is_sdbd = SDBD;
1973             }
1974         ;
1975 
1976 /* ======================================================================== */
1977 /*  Relative Branch instructions.                                           */
1978 /* ======================================================================== */
1979 genline : KOC_relbr expr
1980             {
1981                 /*unsigned rel_addr = labelloc + 2;*/
1982                 /*int dir;*/
1983 
1984                 SDBD_CHK
1985 
1986                 emit_location(currseg, currpag, labelloc, TYPE_CODE, currmode);
1987                 pevalexpr(1, $2);
1988 
1989                 evalr[3].seg   = SSG_ABS;
1990                 evalr[3].value = romw;
1991 
1992                 locctr += geninstr(findgen($1, ST_EXP, sdbd));
1993                 chkover(locctr >> 1, 1);
1994             }
1995         ;
1996 genline : KOC_relbr_x expr ',' expr
1997             {
1998                 /*unsigned rel_addr = labelloc + 2;*/
1999                 /*int dir;*/
2000 
2001                 SDBD_CHK
2002 
2003                 emit_location(currseg, currpag, labelloc, TYPE_CODE, currmode);
2004                 pevalexpr(1, $2);
2005                 pevalexpr(4, $4);
2006 
2007                 if (evalr[4].seg != SSG_ABS)
2008                     fraerror("Must have constant expr for BEXT condition");
2009 
2010                 evalr[3].seg   = SSG_ABS;
2011                 evalr[3].value = romw;
2012 
2013                 locctr += geninstr(findgen($1, ST_EXPEXP, sdbd));
2014                 chkover(locctr >> 1, 1);
2015             }
2016         ;
2017 
2018 
2019 /* ======================================================================== */
2020 /*  Implied Operand instructions.                                           */
2021 /* ======================================================================== */
2022 genline : KOC_opcode
2023             {
2024                 SDBD_CHK
2025                 emit_location(currseg, currpag, labelloc, TYPE_CODE, currmode);
2026                 locctr += geninstr(findgen($1, ST_IMP, sdbd));
2027                 chkover(locctr >> 1, 1);
2028             }
2029         ;
2030 
2031 /* ======================================================================== */
2032 /*  Constant Operand instructions.                                          */
2033 /* ======================================================================== */
2034 genline : KOC_opcode  expr
2035             {
2036                 SDBD_CHK
2037                 emit_location(currseg, currpag, labelloc, TYPE_CODE, currmode);
2038                 pevalexpr(1, $2);
2039                 locctr += geninstr(findgen($1, ST_EXP, sdbd));
2040                 chkover(locctr >> 1, 1);
2041             }
2042         ;
2043 
2044 /* ======================================================================== */
2045 /*  Register, Direct instructions (MVO)                                     */
2046 /*  Register, 2 instructions (shifts)                                       */
2047 /* ======================================================================== */
2048 genline : KOC_opcode  CP1600_REG ',' expr
2049             {
2050                 SDBD_CHK
2051                 emit_location(currseg, currpag, labelloc, TYPE_CODE, currmode);
2052                 evalr[1].value = $2;
2053                 pevalexpr(2, $4);
2054                 evalr[3].seg    = SSG_ABS;
2055                 evalr[3].value  = romw;
2056                 locctr += geninstr(findgen($1, ST_REGEXP, reg_type[$2]|sdbd));
2057                 chkover(locctr >> 1, 1);
2058             }
2059         ;
2060 
2061 /* ======================================================================== */
2062 /*  Register, Immediate --> MVOI                                            */
2063 /* ======================================================================== */
2064 genline : KOC_opcode  CP1600_REG ',' '#' expr
2065             {
2066                 SDBD_CHK
2067                 emit_location(currseg, currpag, labelloc, TYPE_CODE, currmode);
2068                 evalr[1].value  = $2;
2069                 evalr[3].seg    = SSG_ABS;
2070                 evalr[3].value  = romw;
2071                 pevalexpr(2, $5);
2072                 locctr += geninstr(findgen($1, ST_REGCEX, reg_type[$2]|sdbd));
2073                 chkover(locctr >> 1, 1);
2074             }
2075         ;
2076 
2077 /* ======================================================================== */
2078 /*  Direct, Register instructions                                           */
2079 /* ======================================================================== */
2080 genline : KOC_opcode  expr ',' CP1600_REG
2081             {
2082                 SDBD_CHK
2083                 emit_location(currseg, currpag, labelloc, TYPE_CODE, currmode);
2084                 pevalexpr(1, $2);
2085                 evalr[2].value = $4;
2086                 evalr[3].seg   = SSG_ABS;
2087                 evalr[3].value = romw;
2088                 locctr += geninstr(findgen($1, ST_EXPREG, reg_type[$4]|sdbd));
2089                 chkover(locctr >> 1, 1);
2090             }
2091         ;
2092 
2093 /* ======================================================================== */
2094 /*  Immediate, Register instructions                                        */
2095 /* ======================================================================== */
2096 genline : KOC_opcode  '#' expr ',' CP1600_REG
2097             {
2098                 emit_location(currseg, currpag, labelloc, TYPE_CODE, currmode);
2099                 pevalexpr(1, $3);
2100                 evalr[2].value = $5;
2101 
2102                 evalr[3].seg   = SSG_ABS;
2103                 evalr[3].value = romw;
2104 
2105                 if (sdbd == 0 && romw != 16)
2106                 {
2107                     if (evalr[1].seg == SSG_ABS &&
2108                         (0xFFFF & evalr[1].value & ~romm) != 0)
2109                     {
2110                         /*frawarn("Constant is wider than ROM width.  "
2111                                 "Inserting SDBD.");*/
2112                         locctr += geninstr("0001x");
2113                         sdbd = SDBD;
2114                     }
2115 
2116                     if (evalr[1].seg != SSG_ABS && fwd_sdbd)
2117                     {
2118                         frawarn("Inserting SDBD due to forward reference.");
2119                         locctr += geninstr("0001x");
2120                         sdbd = SDBD;
2121                     }
2122                 }
2123 
2124                 locctr += geninstr(findgen($1, ST_CEXREG, reg_type[$5]|sdbd));
2125                 chkover(locctr >> 1, 1);
2126             }
2127         ;
2128 
2129 /* ======================================================================== */
2130 /*  Single-register instructions.                                           */
2131 /* ======================================================================== */
2132 genline : KOC_opcode  CP1600_REG
2133             {
2134                 SDBD_CHK
2135                 emit_location(currseg, currpag, labelloc, TYPE_CODE, currmode);
2136                 evalr[1].value = $2;
2137                 locctr += geninstr(findgen($1, ST_REG, reg_type[$2]|sdbd));
2138                 chkover(locctr >> 1, 1);
2139             }
2140         ;
2141 
2142 /* ======================================================================== */
2143 /*  Register, Register instructions.                                        */
2144 /* ======================================================================== */
2145 genline : KOC_opcode  CP1600_REG ',' CP1600_REG
2146             {
2147                 SDBD_CHK
2148                 emit_location(currseg, currpag, labelloc, TYPE_CODE, currmode);
2149                 evalr[1].value = $2;
2150                 evalr[2].value = $4;
2151                 locctr += geninstr(findgen($1, ST_REGREG, reg_type[$2]|sdbd));
2152                 chkover(locctr >> 1, 1);
2153             }
2154         ;
2155 
2156 /* ======================================================================== */
2157 /*  Register, Register instructions, indirect via first register.           */
2158 /* ======================================================================== */
2159 genline : KOC_opcode_i  CP1600_REG ',' CP1600_REG
2160             {
2161                 emit_location(currseg, currpag, labelloc, TYPE_CODE, currmode);
2162                 evalr[1].value = $2;
2163                 evalr[2].value = $4;
2164                 locctr += geninstr(findgen($1, ST_REGREG, reg_type[$2]|sdbd));
2165                 chkover(locctr >> 1, 1);
2166             }
2167         ;
2168 
2169 
2170 /* ======================================================================== */
2171 /*  Expression definition.                                                  */
2172 /* ======================================================================== */
2173 expr    :   '+' expr %prec KEOP_MUN
2174             {
2175                 $$ = $2;
2176             }
2177         |   '-' expr %prec KEOP_MUN
2178             {
2179                 $$ = exprnode(PCCASE_UN,$2,IFC_NEG,0,0L, SYMNULL);
2180             }
2181         |   KEOP_NOT expr
2182             {
2183                 $$ = exprnode(PCCASE_UN,$2,IFC_NOT,0,0L, SYMNULL);
2184             }
2185         |   KEOP_HIGH expr
2186             {
2187                 $$ = exprnode(PCCASE_UN,$2,IFC_HIGH,0,0L, SYMNULL);
2188             }
2189         |   KEOP_LOW expr
2190             {
2191                 $$ = exprnode(PCCASE_UN,$2,IFC_LOW,0,0L, SYMNULL);
2192             }
2193         |   expr '*' expr
2194             {
2195                 $$ = exprnode(PCCASE_BIN,$1,IFC_MUL,$3,0L, SYMNULL);
2196             }
2197         |   expr '/' expr
2198             {
2199                 $$ = exprnode(PCCASE_BIN,$1,IFC_DIV,$3,0L, SYMNULL);
2200             }
2201         |   expr '+' expr
2202             {
2203                 $$ = exprnode(PCCASE_BIN,$1,IFC_ADD,$3,0L, SYMNULL);
2204             }
2205         |   expr '-' expr
2206             {
2207                 $$ = exprnode(PCCASE_BIN,$1,IFC_SUB,$3,0L, SYMNULL);
2208             }
2209         |   expr KEOP_MOD expr
2210             {
2211                 $$ = exprnode(PCCASE_BIN,$1,IFC_MOD,$3,0L, SYMNULL);
2212             }
2213         |   expr KEOP_SHL expr
2214             {
2215                 $$ = exprnode(PCCASE_BIN,$1,IFC_SHL,$3,0L, SYMNULL);
2216             }
2217         |   expr KEOP_SHR expr
2218             {
2219                 $$ = exprnode(PCCASE_BIN,$1,IFC_SHR,$3,0L, SYMNULL);
2220             }
2221         |   expr KEOP_SHRU expr
2222             {
2223                 $$ = exprnode(PCCASE_BIN,$1,IFC_SHRU,$3,0L, SYMNULL);
2224             }
2225         |   expr KEOP_ROTL expr
2226             {
2227                 const int ifc = $2 == 16 ? IFC_ROTL16 : IFC_ROTL32;
2228                 $$ = exprnode(PCCASE_BIN,$1,ifc,$3,0L, SYMNULL);
2229             }
2230         |   expr KEOP_ROTR expr
2231             {
2232                 const int ifc = $2 == 16 ? IFC_ROTL16 : IFC_ROTL32;
2233                 const int neg = exprnode(PCCASE_UN,$3,IFC_NEG,0,0L, SYMNULL);
2234                 $$ = exprnode(PCCASE_BIN,$1,ifc,neg,0L, SYMNULL);
2235             }
2236         |   expr KEOP_GT expr
2237             {
2238                 $$ = exprnode(PCCASE_BIN,$1,IFC_GT,$3,0L, SYMNULL);
2239             }
2240         |   expr KEOP_GE expr
2241             {
2242                 $$ = exprnode(PCCASE_BIN,$1,IFC_GE,$3,0L, SYMNULL);
2243             }
2244         |   expr KEOP_LT expr
2245             {
2246                 $$ = exprnode(PCCASE_BIN,$1,IFC_LT,$3,0L, SYMNULL);
2247             }
2248         |   expr KEOP_LE expr
2249             {
2250                 $$ = exprnode(PCCASE_BIN,$1,IFC_LE,$3,0L, SYMNULL);
2251             }
2252         |   expr KEOP_NE expr
2253             {
2254                 $$ = exprnode(PCCASE_BIN,$1,IFC_NE,$3,0L, SYMNULL);
2255             }
2256         |   expr KEOP_EQ expr
2257             {
2258                 $$ = exprnode(PCCASE_BIN,$1,IFC_EQ,$3,0L, SYMNULL);
2259             }
2260         |   expr KEOP_AND expr
2261             {
2262                 $$ = exprnode(PCCASE_BIN,$1,IFC_AND,$3,0L, SYMNULL);
2263             }
2264         |   expr KEOP_OR expr
2265             {
2266                 $$ = exprnode(PCCASE_BIN,$1,IFC_OR,$3,0L, SYMNULL);
2267             }
2268         |   expr KEOP_XOR expr
2269             {
2270                 $$ = exprnode(PCCASE_BIN,$1,IFC_XOR,$3,0L, SYMNULL);
2271             }
2272         |   KEOP_DEFINED symbol
2273             {
2274                 $$ = exprnode(PCCASE_DEF,0,IGP_DEFINED,0,0L,$2);
2275             }
2276         |   symbol %prec SYMBOL
2277             {
2278                 $$ = exprnode(PCCASE_SYMB,0,IFC_SYMB,0,0L,$1);
2279             }
2280         |   KEOP_DEFINED FEATURE
2281             {
2282                 $$ = exprnode(PCCASE_CONS,0,IGP_CONSTANT,0,$2, SYMNULL);
2283             }
2284         |   FEATURE
2285             {
2286                 $$ = exprnode(PCCASE_CONS,0,IGP_CONSTANT,0,$1, SYMNULL);
2287             }
2288         |   '$'
2289             {
2290                 $$ = exprnode(PCCASE_PROGC,0,IFC_PROGCTR,0,labelloc,SYMNULL);
2291             }
2292         |   CONSTANT
2293             {
2294                 $$ = exprnode(PCCASE_CONS,0,IGP_CONSTANT,0,$1, SYMNULL);
2295             }
2296         |   QCHAR
2297             {
2298                 char st[2] = { $1, 0 }, *s = st;
2299                 int  accval = chtran(&s);
2300                 $$ = exprnode(PCCASE_CONS,0,IGP_CONSTANT,0,accval,SYMNULL);
2301             }
2302         |   KEOP_CLASSIFY '(' ')' %prec KEOP_CLASSIFY
2303             {
2304                 $$ = exprnode(PCCASE_CONS,0,IGP_CONSTANT,0,CLASS_EMPTY,SYMNULL);
2305             }
2306         |   KEOP_CLASSIFY '(' CP1600_REG ')' %prec KEOP_CLASSIFY
2307             {
2308                 $$ = exprnode(PCCASE_CONS,0,IGP_CONSTANT,0, $3, SYMNULL);
2309             }
2310         |   KEOP_CLASSIFY '(' FEATURE ')' %prec KEOP_CLASSIFY
2311             {
2312                 $$ = exprnode(PCCASE_CONS,0,IGP_CONSTANT,0,CLASS_FEATURE,
2313                              SYMNULL);
2314             }
2315         |   KEOP_CLASSIFY '(' keyword ')' %prec KEOP_CLASSIFY
2316             {
2317                 $$ = exprnode(PCCASE_CONS,0,IGP_CONSTANT,0,CLASS_RESV,SYMNULL);
2318             }
2319         |   KEOP_CLASSIFY '(' string ')' %prec KEOP_CLASSIFY
2320             {
2321                 $$ = exprnode(PCCASE_CONS,0,IGP_CONSTANT,0,CLASS_STRING,
2322                               SYMNULL);
2323             }
2324         |   KEOP_CLASSIFY '(' symbol ')' %prec KEOP_CLASSIFY
2325             {
2326                 $$ = exprnode(PCCASE_CLASSSYM,0,IFC_CLASSIFY,0,0L,$3);
2327             }
2328         |   KEOP_CLASSIFY '(' expr ')' %prec KEOP_CLASSIFY
2329             {
2330                 $$ = exprnode(PCCASE_UN,$3,IFC_CLASSIFY,0,0L, SYMNULL);
2331             }
2332         |   KEOP_STRLEN '(' string ')'
2333             {
2334                 char *s = $3;
2335                 int  accval = 0;
2336                 int  length = 0;
2337 
2338                 while (*s)
2339                 {
2340                     accval = chtran(&s);
2341                     length++;
2342                 }
2343                 (void)accval;
2344                 $$ = exprnode(PCCASE_CONS,0,IGP_CONSTANT,0,length++,SYMNULL);
2345             }
2346         |   KEOP_STRLEN '(' QCHAR ')'
2347             {
2348                 $$ = exprnode(PCCASE_CONS,0,IGP_CONSTANT,0,1,SYMNULL);
2349             }
2350         |   KEOP_ASC '(' string ',' expr ')'
2351             {
2352                 char *s = $3;
2353                 int  accval = 0;
2354                 int  sindex = 0;
2355 
2356                 pevalexpr(0, $5);
2357                 if(evalr[0].seg == SSG_ABS)
2358                 {
2359                     sindex = evalr[0].value;
2360                     while (*s && sindex >= 0)
2361                     {
2362                         accval = chtran(&s);
2363                         sindex--;
2364                     }
2365                     if (sindex >= 0)
2366                         accval = 0;
2367 
2368                     $$ = exprnode(PCCASE_CONS,0,IGP_CONSTANT,0,accval,SYMNULL);
2369                 }
2370                 else
2371                 {
2372                     fraerror("noncomputable expression for index to ASC");
2373                 }
2374             }
2375         |   KEOP_ASC '(' QCHAR ',' expr ')'
2376             {
2377                 char st[2] = { $3, 0 }, *s = st;
2378                 int  accval = 0;
2379 
2380                 pevalexpr(0, $5);
2381                 if(evalr[0].seg == SSG_ABS)
2382                 {
2383                     accval = evalr[0].value == 0 ? chtran(&s) : 0;
2384                     $$ = exprnode(PCCASE_CONS,0,IGP_CONSTANT,0,accval,SYMNULL);
2385                 }
2386                 else
2387                 {
2388                     fraerror("noncomputable expression for index to ASC");
2389                 }
2390             }
2391         |   '(' expr ')' { $$ = $2; }
2392         |   '(' exprlist ')' '[' expr ']' %prec '('
2393             {
2394                 pevalexpr(0, $5);
2395                 if (evalr[0].seg == SSG_ABS)
2396                 {
2397                     const int idx = evalr[0].value;
2398                     if (idx < $2->len)
2399                         $$ = $2->data[idx];
2400                     else
2401                         $$ = exprnode(PCCASE_CONS,0,IGP_CONSTANT,0,0,SYMNULL);
2402                 }
2403                 else
2404                 {
2405                     fraerror("noncomputable expression for expr-list index");
2406                 }
2407                 intvec_delete($2);
2408             }
2409         ;
2410 
2411 /* ======================================================================== */
2412 /*  Array-indexed labels and symbols                                        */
2413 /* ======================================================================== */
2414 label:      LABEL
2415         |   label '[' expr ']'
2416             {
2417                 pevalexpr(0, $3);
2418                 if (evalr[0].seg == SSG_ABS)
2419                 {
2420                     $$ = symbentryidx($1->symstr, LABEL, 1, evalr[0].value);
2421                     $$->flags |= SFLAG_QUIET | SFLAG_ARRAY;
2422 
2423                     /* track "high water mark" in LABEL's own value */
2424                     $1->seg    = SSG_SET;
2425                     $1->flags |= SFLAG_QUIET;
2426                     if ($1->value < evalr[0].value)
2427                         $1->value = evalr[0].value;
2428                 } else
2429                 {
2430                     fraerror("noncomputable expression for label array index");
2431                 }
2432             }
2433         ;
2434 
2435 symbol:     SYMBOL
2436         |   symbol '[' expr ']'
2437             {
2438                 pevalexpr(0, $3);
2439                 if (evalr[0].seg == SSG_ABS)
2440                 {
2441                     $$ = symbentryidx($1->symstr, LABEL, 1, evalr[0].value);
2442                     $$->flags |= SFLAG_QUIET | SFLAG_ARRAY;
2443 
2444                     /* track "high water mark" in LABEL's own value */
2445                     $1->seg    = SSG_SET;
2446                     $1->flags |= SFLAG_QUIET;
2447                     if ($1->value < evalr[0].value)
2448                         $1->value = evalr[0].value;
2449                 } else
2450                 {
2451                     fraerror("noncomputable expression for symbol array index");
2452                 }
2453             }
2454         ;
2455 
2456 
2457 symslice:   symbol '[' expr ',' expr ']'
2458             {
2459                 intvec_t *const RESTRICT iv = intvec_new();
2460                 pevalexpr(0, $3);
2461                 pevalexpr(1, $5);
2462 
2463                 if (evalr[0].seg != SSG_ABS || evalr[1].seg != SSG_ABS)
2464                 {
2465                     fraerror("noncomputable expression for symbol slice index");
2466                     $$ = iv;
2467                 } else
2468                 {
2469                     int i, s;
2470 
2471                     s = evalr[0].value > evalr[1].value ? -1 : 1;
2472 
2473                     for (i = evalr[0].value; i != evalr[1].value + s; i += s)
2474                     {
2475                         struct symel *sym;
2476                         intvec_push(iv,
2477                             exprnode(PCCASE_SYMB,0,IFC_SYMB,0,0L,
2478                                 sym = symbentryidx($1->symstr, LABEL, 1, i)));
2479 
2480                         sym->flags |= SFLAG_ARRAY | SFLAG_QUIET;
2481                     }
2482                     $$ = iv;
2483                 }
2484             }
2485         |   '(' exprlist ')' '[' expr ',' expr ']' %prec '('
2486             {
2487                 pevalexpr(0, $5);
2488                 pevalexpr(1, $7);
2489                 if (evalr[0].seg != SSG_ABS || evalr[1].seg != SSG_ABS)
2490                 {
2491                     fraerror(
2492                         "noncomputable expression for expr-list slice index");
2493                     intvec_resize($2, 0);
2494                     $$ = $2;
2495                 } else if (evalr[0].value >= $2->len ||
2496                            evalr[1].value >= $2->len)
2497                 {
2498                     fraerror("out of range index for expr-list slice");
2499                     intvec_resize($2, 0);
2500                     $$ = $2;
2501                 } else
2502                 {
2503                     const int rev = evalr[0].value > evalr[1].value;
2504                     const int lo = rev ? evalr[1].value : evalr[0].value;
2505                     const int hi = rev ? evalr[0].value : evalr[1].value;
2506                     const int cnt = hi - lo + 1;
2507                     int *const data = $2->data;
2508 
2509                     memmove(&data[0], &data[lo], sizeof(data[0]) * cnt);
2510 
2511                     if (rev)
2512                     {
2513                         int i, j;
2514                         for (i = 0, j = cnt - 1; i < j; i++, j--)
2515                         {
2516                             const int tmp = $2->data[i];
2517                             $2->data[i] = $2->data[j];
2518                             $2->data[j] = tmp;
2519                         }
2520                     }
2521                     $2->len = cnt;
2522                     $$ = $2;
2523                 }
2524             }
2525         |   symslice '[' expr ']'
2526             {
2527                 fraerror("array slice allowed on last index only");
2528                 $$ = intvec_new();
2529             }
2530         |   symslice '[' expr ',' expr ']'
2531             {
2532                 fraerror("array slice allowed on last index only");
2533                 $$ = intvec_new();
2534             }
2535         ;
2536 
2537 
2538 labelslice: label '[' expr ',' expr ']'
2539             {
2540                 pevalexpr(0, $3);
2541                 pevalexpr(1, $5);
2542 
2543                 if (evalr[0].seg != SSG_ABS || evalr[1].seg != SSG_ABS)
2544                 {
2545                     fraerror("noncomputable expression for label slice index");
2546                 } else
2547                 {
2548                     $$.first = evalr[0].value;
2549                     $$.last  = evalr[1].value;
2550                     $$.sym   = $1;
2551                 }
2552             }
2553         |   labelslice '[' expr ']'
2554             {
2555                 fraerror("array slice allowed on last index only");
2556             }
2557         |   labelslice '[' expr ',' expr ']'
2558             {
2559                 fraerror("array slice allowed on last index only");
2560             }
2561         ;
2562 
2563 /* Keyword catch-all for CLASSIFY operator */
2564 keyword :   KEOP_AND
2565         |   KEOP_DEFINED
2566         |   KEOP_EQ
2567         |   KEOP_GE
2568         |   KEOP_GT
2569         |   KEOP_HIGH
2570         |   KEOP_LE
2571         |   KEOP_LOW
2572         |   KEOP_LT
2573         |   KEOP_MOD
2574         |   KEOP_MUN
2575         |   KEOP_NE
2576         |   KEOP_NOT
2577         |   KEOP_OR
2578         |   KEOP_SHL
2579         |   KEOP_SHR
2580         |   KEOP_SHRU
2581         |   KEOP_XOR
2582         |   KEOP_locctr
2583         |   KEOP_STRLEN
2584         |   KEOP_ASC
2585         |   KEOP_CLASSIFY
2586         ;
2587 %%
2588 
2589 int lexintercept(void)
2590 /*
2591     description intercept the call to yylex (the lexical analyzer)
2592             and filter out all unnecessary tokens when skipping
2593             the input between a failed IF and its matching ENDI or
2594             ELSE
2595     globals     fraifskip   the enable flag
2596 */
2597 {
2598 #undef yylex
2599     int rv;
2600 
2601     if (!(frarptskip | fraifskip))
2602     {
2603         int token = yylex();
2604         return token;
2605     }
2606 
2607     if(frarptskip)
2608     {
2609         for(;;)
2610         {
2611 
2612             switch(rv = yylex())
2613             {
2614             case 0:
2615             case KOC_END:
2616             case KOC_ENDR:
2617             case EOL:
2618                 return rv;
2619             case KOC_RPT:
2620                 frarptpush(0);  /* push a dummy loop */
2621             default:
2622                 break;
2623             }
2624         }
2625     } else if(fraifskip)
2626     {
2627         for(;;)
2628         {
2629 
2630             switch(rv = yylex())
2631             {
2632             case 0:
2633             case KOC_END:
2634             case KOC_IF:
2635             case KOC_ELSE:
2636             case KOC_ENDI:
2637             case KEOP_EXPMAC:
2638             case EOL:
2639                 return rv;
2640             default:
2641                 break;
2642             }
2643         }
2644     } else
2645     {
2646         int token = yylex();
2647         return token;
2648     }
2649 
2650 #define yylex lexintercept
2651 }
2652 
2653 
2654 
setreserved(void)2655 void setreserved(void)
2656 {
2657     reservedsym("and",           KEOP_AND,       0);
2658     reservedsym("defined",       KEOP_DEFINED,   0);
2659     reservedsym("ge",            KEOP_GE,        0);
2660     reservedsym("high",          KEOP_HIGH,      0);
2661     reservedsym("le",            KEOP_LE,        0);
2662     reservedsym("low",           KEOP_LOW,       0);
2663     reservedsym("mod",           KEOP_MOD,       0);
2664     reservedsym("ne",            KEOP_NE,        0);
2665     reservedsym("not",           KEOP_NOT,       0);
2666     reservedsym("or",            KEOP_OR,        0);
2667     reservedsym("shl",           KEOP_SHL,       0);
2668     reservedsym("shr",           KEOP_SHR,       0);
2669     reservedsym("shru",          KEOP_SHRU,      0);
2670     reservedsym("xor",           KEOP_XOR,       0);
2671     reservedsym("AND",           KEOP_AND,       0);
2672     reservedsym("DEFINED",       KEOP_DEFINED,   0);
2673     reservedsym("GE",            KEOP_GE,        0);
2674     reservedsym("HIGH",          KEOP_HIGH,      0);
2675     reservedsym("LE",            KEOP_LE,        0);
2676     reservedsym("LOW",           KEOP_LOW,       0);
2677     reservedsym("MOD",           KEOP_MOD,       0);
2678     reservedsym("NE",            KEOP_NE,        0);
2679     reservedsym("NOT",           KEOP_NOT,       0);
2680     reservedsym("OR",            KEOP_OR,        0);
2681     reservedsym("SHL",           KEOP_SHL,       0);
2682     reservedsym("SHR",           KEOP_SHR,       0);
2683     reservedsym("SHRU",          KEOP_SHRU,      0);
2684     reservedsym("_ROTL16",       KEOP_ROTL,      16);
2685     reservedsym("_ROTL32",       KEOP_ROTL,      32);
2686     reservedsym("_ROTR16",       KEOP_ROTR,      16);
2687     reservedsym("_ROTR32",       KEOP_ROTR,      32);
2688     reservedsym("XOR",           KEOP_XOR,       0);
2689     reservedsym("STRLEN",        KEOP_STRLEN,    0);
2690     reservedsym("ASC",           KEOP_ASC,       0);
2691     reservedsym("CLASSIFY",      KEOP_CLASSIFY,  0);
2692     reservedsym("TODAY_STR_LOC", KEOP_TODAY_STR, 0);
2693     reservedsym("TODAY_STR_GMT", KEOP_TODAY_STR, 1);
2694     reservedsym("TODAY_VAL_LOC", KEOP_TODAY_VAL, 0);
2695     reservedsym("TODAY_VAL_GMT", KEOP_TODAY_VAL, 1);
2696     reservedsym("_EXPMAC",       KEOP_EXPMAC,    1);
2697 
2698     /* machine specific token definitions */
2699     reservedsym("r0",       CP1600_REG,     0);
2700     reservedsym("r1",       CP1600_REG,     1);
2701     reservedsym("r2",       CP1600_REG,     2);
2702     reservedsym("r3",       CP1600_REG,     3);
2703     reservedsym("r4",       CP1600_REG,     4);
2704     reservedsym("r5",       CP1600_REG,     5);
2705     reservedsym("r6",       CP1600_REG,     6);
2706     reservedsym("r7",       CP1600_REG,     7);
2707     reservedsym("sp",       CP1600_REG,     6);
2708     reservedsym("pc",       CP1600_REG,     7);
2709     reservedsym("R0",       CP1600_REG,     0);
2710     reservedsym("R1",       CP1600_REG,     1);
2711     reservedsym("R2",       CP1600_REG,     2);
2712     reservedsym("R3",       CP1600_REG,     3);
2713     reservedsym("R4",       CP1600_REG,     4);
2714     reservedsym("R5",       CP1600_REG,     5);
2715     reservedsym("R6",       CP1600_REG,     6);
2716     reservedsym("R7",       CP1600_REG,     7);
2717     reservedsym("SP",       CP1600_REG,     6);
2718     reservedsym("PC",       CP1600_REG,     7);
2719 
2720     reservedsym("__FEATURE.MACRO",     FEATURE, 99);
2721     reservedsym("__FEATURE.CFGVAR",    FEATURE, 99);
2722     reservedsym("__FEATURE.SRCFILE",   FEATURE, 99);
2723     reservedsym("__FEATURE.CLASSIFY",  FEATURE, 99);
2724     reservedsym("__FEATURE.TODAY",     FEATURE, 99);
2725     reservedsym("__FEATURE.ROTATE",    FEATURE, 99);
2726     reservedsym("__FEATURE.EXPMAC",    FEATURE, 99);
2727     reservedsym("__FEATURE.LISTCOL",   FEATURE, 99);
2728     reservedsym("__FEATURE.OVERWRITE", FEATURE, 99);
2729     reservedsym("MACRO",               FEATURE, 99);
2730     reservedsym("ENDM",                FEATURE, 99);
2731 }
2732 
cpumatch(char * str)2733 int cpumatch(char *str)
2734 {
2735     (void)str;
2736     return TRUE;
2737 }
2738 
2739 
2740 /* ======================================================================== */
2741 /*  Opcode and Instruction Generation Tables                                */
2742 /*                                                                          */
2743 /*  These tables are used by the assembler framework to generate            */
2744 /*  instructions from the parsed input.                                     */
2745 /*                                                                          */
2746 /*  OPTAB    -- OPcode TABle.  Contains the set of supported mnemonics.     */
2747 /*  OSTAB    -- Opcode Syntax TABle.  Syntax definition sets for instrs.    */
2748 /*  IGTAB    -- Instruction Generation TABle.  Contains RPN code for        */
2749 /*              generating the instructions.                                */
2750 /* ======================================================================== */
2751 
2752 
2753 
2754 /* ======================================================================== */
2755 /*  OPTAB    -- OPcode TABle.  Contains the set of supported mnemonics.     */
2756 /* ======================================================================== */
2757 struct opsym optab[] =
2758 {
2759     {   "invalid",  KOC_opcode,     2,  0   },
2760 
2761     {   "MVO",      KOC_opcode,     1,  2   },
2762     {   "MVI",      KOC_opcode,     1,  3   },
2763     {   "ADD",      KOC_opcode,     1,  4   },
2764     {   "SUB",      KOC_opcode,     1,  5   },
2765     {   "CMP",      KOC_opcode,     1,  6   },
2766     {   "AND",      KOC_opcode,     1,  7   },
2767     {   "XOR",      KOC_opcode,     1,  8   },
2768 
2769     {   "MVO@",     KOC_opcode,     1,  9   },
2770     {   "MVI@",     KOC_opcode_i,   1,  10  },
2771     {   "ADD@",     KOC_opcode_i,   1,  11  },
2772     {   "SUB@",     KOC_opcode_i,   1,  12  },
2773     {   "CMP@",     KOC_opcode_i,   1,  13  },
2774     {   "AND@",     KOC_opcode_i,   1,  14  },
2775     {   "XOR@",     KOC_opcode_i,   1,  15  },
2776 
2777     {   "MVOI",     KOC_opcode,     1,  16  },
2778     {   "MVII",     KOC_opcode,     1,  17  },
2779     {   "ADDI",     KOC_opcode,     1,  18  },
2780     {   "SUBI",     KOC_opcode,     1,  19  },
2781     {   "CMPI",     KOC_opcode,     1,  20  },
2782     {   "ANDI",     KOC_opcode,     1,  21  },
2783     {   "XORI",     KOC_opcode,     1,  22  },
2784 
2785     {   "MOVR",     KOC_opcode,     1,  24  },
2786     {   "ADDR",     KOC_opcode,     1,  25  },
2787     {   "SUBR",     KOC_opcode,     1,  26  },
2788     {   "CMPR",     KOC_opcode,     1,  27  },
2789     {   "ANDR",     KOC_opcode,     1,  28  },
2790     {   "XORR",     KOC_opcode,     1,  29  },
2791 
2792     {   "B",        KOC_relbr,      1,  30  },
2793     {   "BC",       KOC_relbr,      1,  31  },
2794     {   "BOV",      KOC_relbr,      1,  32  },
2795     {   "BPL",      KOC_relbr,      1,  33  },
2796     {   "BZE",      KOC_relbr,      1,  34  },
2797     {   "BEQ",      KOC_relbr,      1,  34  },
2798     {   "BLT",      KOC_relbr,      1,  35  },
2799     {   "BNGE",     KOC_relbr,      1,  35  },
2800     {   "BLE",      KOC_relbr,      1,  36  },
2801     {   "BNGT",     KOC_relbr,      1,  36  },
2802     {   "BUSC",     KOC_relbr,      1,  37  },
2803 
2804     {   "NOPP",     KOC_opcode,     2,  92  },
2805     {   "BNC",      KOC_relbr,      1,  39  },
2806     {   "BNOV",     KOC_relbr,      1,  40  },
2807     {   "BMI",      KOC_relbr,      1,  41  },
2808     {   "BNZE",     KOC_relbr,      1,  42  },
2809     {   "BNZ",      KOC_relbr,      1,  42  },
2810     {   "BNEQ",     KOC_relbr,      1,  42  },
2811     {   "BNE",      KOC_relbr,      1,  42  },
2812     {   "BGE",      KOC_relbr,      1,  43  },
2813     {   "BNLT",     KOC_relbr,      1,  43  },
2814     {   "BGT",      KOC_relbr,      1,  44  },
2815     {   "BNLE",     KOC_relbr,      1,  44  },
2816     {   "BESC",     KOC_relbr,      1,  45  },
2817 
2818     {   "BEXT",     KOC_relbr_x,    1,  96  },
2819 
2820     {   "SWAP",     KOC_opcode,     2,  46  },
2821     {   "SLL",      KOC_opcode,     2,  48  },
2822     {   "RLC",      KOC_opcode,     2,  50  },
2823     {   "SLLC",     KOC_opcode,     2,  52  },
2824     {   "SLR",      KOC_opcode,     2,  54  },
2825     {   "SAR",      KOC_opcode,     2,  56  },
2826     {   "RRC",      KOC_opcode,     2,  58  },
2827     {   "SARC",     KOC_opcode,     2,  60  },
2828 
2829     {   "NOP",      KOC_opcode,     1,  62  },
2830     {   "NOP2",     KOC_opcode,     1,  94  },
2831     {   "SIN",      KOC_opcode,     1,  63  },
2832     {   "SIN2",     KOC_opcode,     1,  95  },
2833 
2834     {   "J",        KOC_opcode,     1,  64  },
2835     {   "JE",       KOC_opcode,     1,  65  },
2836     {   "JD",       KOC_opcode,     1,  66  },
2837     {   "JSR",      KOC_opcode,     1,  67  },
2838     {   "JSRE",     KOC_opcode,     1,  68  },
2839     {   "JSRD",     KOC_opcode,     1,  69  },
2840 
2841     {   "INCR",     KOC_opcode,     1,  70  },
2842     {   "DECR",     KOC_opcode,     1,  71  },
2843     {   "COMR",     KOC_opcode,     1,  72  },
2844     {   "NEGR",     KOC_opcode,     1,  73  },
2845     {   "ADCR",     KOC_opcode,     1,  74  },
2846     {   "GSWD",     KOC_opcode,     1,  75  },
2847     {   "RSWD",     KOC_opcode,     1,  76  },
2848 
2849     {   "HLT",      KOC_opcode,     1,  77  },
2850     {   "SDBD",     KOC_SDBD,       1,  78  },
2851     {   "EIS",      KOC_opcode,     1,  79  },
2852     {   "DIS",      KOC_opcode,     1,  80  },
2853     {   "TCI",      KOC_opcode,     1,  81  },
2854     {   "CLRC",     KOC_opcode,     1,  82  },
2855     {   "SETC",     KOC_opcode,     1,  83  },
2856 
2857     {   "TSTR",     KOC_opcode,     1,  84  },  /*  MOVR  Rx, Rx    */
2858     {   "CLRR",     KOC_opcode,     1,  85  },  /*  XORR  Rx, Rx    */
2859     {   "PSHR",     KOC_opcode,     1,  86  },  /*  MVO@  Rx, SP    */
2860     {   "PULR",     KOC_opcode,     1,  87  },  /*  MVI@  SP, Rx    */
2861     {   "JR",       KOC_opcode,     1,  88  },  /*  MOVR  Rx, PC    */
2862     {   "CALL",     KOC_opcode,     1,  89  },  /*  JSR   R5, addr  */
2863     {   "BEGIN",    KOC_opcode,     1,  90  },  /*  MVO@  R5, SP    */
2864     {   "RETURN",   KOC_opcode,     1,  91  },  /*  MVI@  SP, PC    */
2865 
2866     {   "DECLE",    KOC_DDEF,       0,  0   },  /* Generates ROMW values  */
2867     {   "DCW",      KOC_DDEF,       0,  0   },  /* Generates ROMW values  */
2868     {   "BIDECLE",  KOC_WDEF,       0,  0   },  /* Generates SDBD values  */
2869     {   "ROMWIDTH", KOC_ROMW,       0,  0   },
2870     {   "ROMW",     KOC_ROMW,       0,  0   },
2871     {   "PROC",     KOC_PROC,       0,  0   },
2872     {   "ENDP",     KOC_ENDP,       0,  0   },
2873 
2874     {   "BYTE",     KOC_BDEF,       0,  0   },  /* Generates 8-bit values */
2875     {   "CHARDEF",  KOC_CHDEF,      0,  0   },
2876     {   "CHARSET",  KOC_CHSET,      0,  0   },
2877     {   "CHARUSE",  KOC_CHUSE,      0,  0   },
2878     {   "CHD",      KOC_CHDEF,      0,  0   },
2879     {   "DATA",     KOC_DDEF,       0,  0   },  /* Generates ROMW values  */
2880     {   "DB",       KOC_BDEF,       0,  0   },  /* Generates 8-bit values */
2881     {   "DW",       KOC_WDEF,       0,  0   },  /* Generates SDBD values  */
2882     {   "ELSE",     KOC_ELSE,       0,  0   },
2883     {   "END",      KOC_END,        0,  0   },
2884     {   "ENDI",     KOC_ENDI,       0,  0   },
2885     {   "EQU",      KOC_EQU,        0,  0   },
2886     {   "FCB",      KOC_BDEF,       0,  0   },  /* Generates 8-bit values */
2887     {   "FCC",      KOC_SDEF,       0,  0   },
2888     {   "FDB",      KOC_WDEF,       0,  0   },  /* Generates SDBD values  */
2889     {   "IF",       KOC_IF,         0,  0   },
2890     {   "INCL",     KOC_INCLUDE,    0,  0   },
2891     {   "INCLUDE",  KOC_INCLUDE,    0,  0   },
2892     {   "ORG",      KOC_ORG,        0,  0   },
2893     {   "RES",      KOC_RESM,       0,  0   },
2894     {   "RESERVE",  KOC_RESM,       0,  0   },
2895     {   "RMB",      KOC_RESM,       0,  0   },
2896     {   "SET",      KOC_SET,        0,  0   },
2897     {   "STRING",   KOC_SDEF,       0,  0   },
2898     {   "WORD",     KOC_WDEF,       0,  0   },  /* Generates SDBD values  */
2899 
2900     {   "STRUCT",   KOC_STRUCT,     0,  0   },  /* Opens a struct def'n */
2901     {   "ENDS",     KOC_ENDS,       0,  0   },  /* Closes a struct def'n */
2902 
2903     {   "MEMATTR",  KOC_MEMATTR,    0,  0   },  /* Set memory attributes */
2904 
2905     {   "RPT",      KOC_RPT,        0,  0   },  /* Repeat a block of code */
2906     {   "REPEAT",   KOC_RPT,        0,  0   },  /* Repeat a block of code */
2907     {   "ENDR",     KOC_ENDR,       0,  0   },  /* End repeated block     */
2908 
2909     {   "ERR",      KOC_USRERR,     0,  0   },  /* User-designated error */
2910 
2911     {   "STRLEN",   KEOP_STRLEN,    0,  0   },  /* Returns length of string */
2912     {   "ASC",      KEOP_ASC,       0,  0   },  /* ASCII val of char in str */
2913 
2914     {   "LISTING",  KOC_LIST,       0,  0   },  /* Assembler listing control */
2915     {   "QEQU",     KOC_QEQU,       0,  0   },  /* EQU and mark as "quiet" */
2916     {   "QSET",     KOC_QSET,       0,  0   },  /* SET and mark as "quiet" */
2917 
2918     {   "MACRO",    KOC_MACERR,     0,  0   },  /* We shouldn't see MACRO   */
2919     {   "ENDM",     KOC_MACERR,     0,  0   },  /* We shouldn't see ENDM    */
2920 
2921     {   "BRKIF",    KOC_BRKIF,      0,  0   },  /* Break out of RPT if true */
2922 
2923     {   "CMSG",     KOC_CMSG,       0,  0   },  /* Comment message in listing */
2924     {   "SMSG",     KOC_SMSG,       0,  0   },  /* Status message to stdout */
2925     {   "WMSG",     KOC_WMSG,       0,  0   },  /* Warning message */
2926 
2927     {   "CFGVAR",   KOC_CFGVAR,     0,  0   },  /* Configuration variable */
2928 
2929     {   "SRCFILE",  KOC_SRCFILE,    0,  0   },  /* HLL source file / line */
2930     {   "LISTCOL",  KOC_LISTCOL,    0,  0   },  /* Listing formatting */
2931     {   "ERR_IF_OVERWRITTEN",
2932           KOC_ERR_IF_OVERWRITTEN,   0,  0   },  /* ROM overwrite control */
2933     {   "FORCE_OVERWRITE",
2934           KOC_FORCE_OVERWRITE,      0,  0   },  /* ROM overwrite control */
2935     {   "",         0,              0,  0   }
2936 };
2937 
2938 
2939 /* ======================================================================== */
2940 /*  OSTAB    -- Opcode Syntax TABle.  Syntax definition sets for instrs.    */
2941 /*                                                                          */
2942 /*  Legend:                                                                 */
2943 /*      REG      Register.                                                  */
2944 /*      EXP      EXPression                                                 */
2945 /*      CEX      Constant EXpression (eg. exp. prefixed w/ #).              */
2946 /*      IMP      Implied operand.                                           */
2947 /* ======================================================================== */
2948 struct opsynt ostab[] =
2949 {
2950     /*  invalid 0   */  {   0,          1,  0   },
2951     /*  invalid 1   */  {   0xFFFF,     1,  1   },
2952 
2953     /*  MVO     2   */  {   ST_REGEXP,  1,  2   },
2954     /*  MVI     3   */  {   ST_EXPREG,  1,  3   },
2955     /*  ADD     4   */  {   ST_EXPREG,  1,  4   },
2956     /*  SUB     5   */  {   ST_EXPREG,  1,  5   },
2957     /*  CMP     6   */  {   ST_EXPREG,  1,  6   },
2958     /*  AND     7   */  {   ST_EXPREG,  1,  7   },
2959     /*  XOR     8   */  {   ST_EXPREG,  1,  8   },
2960 
2961     /*  MVO@    9   */  {   ST_REGREG,  1,  9   },
2962     /*  MVI@    10  */  {   ST_REGREG,  1,  10  },
2963     /*  ADD@    11  */  {   ST_REGREG,  1,  11  },
2964     /*  SUB@    12  */  {   ST_REGREG,  1,  12  },
2965     /*  CMP@    13  */  {   ST_REGREG,  1,  13  },
2966     /*  AND@    14  */  {   ST_REGREG,  1,  14  },
2967     /*  XOR@    15  */  {   ST_REGREG,  1,  15  },
2968 
2969     /*  MVOI    16  */  {   ST_REGCEX,  1,  16  },
2970     /*  MVII    17  */  {   ST_CEXREG,  2,  17  },
2971     /*  ADDI    18  */  {   ST_CEXREG,  2,  19  },
2972     /*  SUBI    19  */  {   ST_CEXREG,  2,  21  },
2973     /*  CMPI    20  */  {   ST_CEXREG,  2,  23  },
2974     /*  ANDI    21  */  {   ST_CEXREG,  2,  25  },
2975     /*  XORI    22  */  {   ST_CEXREG,  2,  27  },
2976 
2977     /*  unused  23  */  {   0,          1,  0   },  /* oops */
2978     /*  MOVR    24  */  {   ST_REGREG,  1,  29  },
2979     /*  ADDR    25  */  {   ST_REGREG,  1,  30  },
2980     /*  SUBR    26  */  {   ST_REGREG,  1,  31  },
2981     /*  CMPR    27  */  {   ST_REGREG,  1,  32  },
2982     /*  ANDR    28  */  {   ST_REGREG,  1,  33  },
2983     /*  XORR    29  */  {   ST_REGREG,  1,  34  },
2984 
2985     /*  B       30  */  {   ST_EXP,     1,  35  },
2986     /*  BC      31  */  {   ST_EXP,     1,  36  },
2987     /*  BOV     32  */  {   ST_EXP,     1,  37  },
2988     /*  BPL     33  */  {   ST_EXP,     1,  38  },
2989     /*  BEQ     34  */  {   ST_EXP,     1,  39  },
2990     /*  BLT     35  */  {   ST_EXP,     1,  40  },
2991     /*  BLE     36  */  {   ST_EXP,     1,  41  },
2992     /*  BUSC    37  */  {   ST_EXP,     1,  42  },
2993 
2994     /*  unused  38  */  {   0,          1,  0   },  /* oops */
2995     /*  BNC     39  */  {   ST_EXP,     1,  44  },
2996     /*  BNOV    40  */  {   ST_EXP,     1,  45  },
2997     /*  BMI     41  */  {   ST_EXP,     1,  46  },
2998     /*  BNEQ    42  */  {   ST_EXP,     1,  47  },
2999     /*  BGE     43  */  {   ST_EXP,     1,  48  },
3000     /*  BGT     44  */  {   ST_EXP,     1,  49  },
3001     /*  BESC    45  */  {   ST_EXP,     1,  50  },
3002 
3003     /*  SWAP    46  */  {   ST_REG,     1,  51  },
3004     /*  SWAP    47  */  {   ST_REGEXP,  1,  52  },
3005     /*  SLL     48  */  {   ST_REG,     1,  53  },
3006     /*  SLL     49  */  {   ST_REGEXP,  1,  54  },
3007     /*  RLC     50  */  {   ST_REG,     1,  55  },
3008     /*  RLC     51  */  {   ST_REGEXP,  1,  56  },
3009     /*  SLLC    52  */  {   ST_REG,     1,  57  },
3010     /*  SLLC    53  */  {   ST_REGEXP,  1,  58  },
3011     /*  SLR     54  */  {   ST_REG,     1,  59  },
3012     /*  SLR     55  */  {   ST_REGEXP,  1,  60  },
3013     /*  SAR     56  */  {   ST_REG,     1,  61  },
3014     /*  SAR     57  */  {   ST_REGEXP,  1,  62  },
3015     /*  RRC     58  */  {   ST_REG,     1,  63  },
3016     /*  RRC     59  */  {   ST_REGEXP,  1,  64  },
3017     /*  SARC    60  */  {   ST_REG,     1,  65  },
3018     /*  SARC    61  */  {   ST_REGEXP,  1,  66  },
3019 
3020     /*  NOP     62  */  {   ST_IMP,     1,  67  },
3021     /*  SIN     63  */  {   ST_IMP,     1,  68  },
3022 
3023     /*  J       64  */  {   ST_EXP,     1,  69  },
3024     /*  JE      65  */  {   ST_EXP,     1,  70  },
3025     /*  JD      66  */  {   ST_EXP,     1,  71  },
3026     /*  JSR     67  */  {   ST_REGEXP,  1,  72  },
3027     /*  JSRE    68  */  {   ST_REGEXP,  1,  73  },
3028     /*  JSRD    69  */  {   ST_REGEXP,  1,  74  },
3029 
3030     /*  INCR    70  */  {   ST_REG,     1,  75  },
3031     /*  DECR    71  */  {   ST_REG,     1,  76  },
3032     /*  COMR    72  */  {   ST_REG,     1,  77  },
3033     /*  NEGR    73  */  {   ST_REG,     1,  78  },
3034     /*  ADCR    74  */  {   ST_REG,     1,  79  },
3035     /*  GSWD    75  */  {   ST_REG,     1,  80  },
3036     /*  RSWD    76  */  {   ST_REG,     1,  81  },
3037 
3038     /*  HLT     77  */  {   ST_IMP,     1,  82  },
3039     /*  SDBD    78  */  {   ST_IMP,     1,  83  },
3040     /*  EIS     79  */  {   ST_IMP,     1,  84  },
3041     /*  DIS     80  */  {   ST_IMP,     1,  85  },
3042     /*  TCI     81  */  {   ST_IMP,     1,  86  },
3043     /*  CLRC    82  */  {   ST_IMP,     1,  87  },
3044     /*  SETC    83  */  {   ST_IMP,     1,  88  },
3045 
3046     /*  TSTR    84  */  {   ST_REG,     1,  89  },
3047     /*  CLRR    85  */  {   ST_REG,     1,  90  },
3048     /*  PSHR    86  */  {   ST_REG,     1,  91  },
3049     /*  PULR    87  */  {   ST_REG,     1,  92  },
3050     /*  JR      88  */  {   ST_REG,     1,  93  },
3051     /*  CALL    89  */  {   ST_EXP,     1,  94  },
3052     /*  BEGIN   90  */  {   ST_IMP,     1,  95  },
3053     /*  RETURN  91  */  {   ST_IMP,     1,  96  },
3054 
3055     /*  NOPP    92  */  {   ST_EXP,     1,  43  },
3056     /*  NOPP    93  */  {   ST_IMP,     1,  97  },
3057 
3058     /*  NOP2    94  */  {   ST_IMP,     1,  98  },
3059     /*  SIN2    95  */  {   ST_IMP,     1,  99  },
3060 
3061     /*  BEXT    95  */  {   ST_EXPEXP,  1,  100 },
3062 
3063     /*  end         */  {   0,          0,  0   }
3064 };
3065 
3066 
3067 /* ======================================================================== */
3068 /*  Helper macros.                                                          */
3069 /*  MVO_OK  Tests arg 2 to make sure it's R1 .. R6.                         */
3070 /*  SH_OK   Tests if shift amount is ok.                                    */
3071 /*  CST_OK  Tests if constant is ok (within field width).                   */
3072 /*  DBD     Generate double-byte-data.                                      */
3073 /*  RR      Register/Register generator. Reused for Direct, Immediate.      */
3074 /*  BR      Branch Relative generator.                                      */
3075 /*  SH      Shift generator.                                                */
3076 /*  SR      Single-register generator                                       */
3077 /*  JSR     Jump/JSR generator                                              */
3078 /*  CST     Constant arg generator (eg. immediate argument)                 */
3079 /* ======================================================================== */
3080 #define MVO_OK      "[2#].0=.[2#].7=+T$"
3081 #define SH_OK(n)    #n ".1>T$" #n ".<0T$"
3082 #define CST_OK(w,c) #c "." #w"I$"
3083 #define DBD(x)      #x ".FF&x" #x ".8}.FF&x"
3084 #define RR(o,x,y)   #o "." #x ".3{|." #y "|x"
3085 #define BRDIR(a)    "P.2+." #a ">."
3086 #define BROFS(a)    #a ".P.2+-." BRDIR(a) "!_^"
3087 #define BR(c,a,w)   "0200." #c "|." BRDIR(a) "5{|x" BROFS(a) "~x" #w "I$"
3088 #define BX(c,a,w)   #c ".4I$" \
3089                     "0210." #c "|." BRDIR(a) "5{|x" BROFS(a) "~x" #w "I$"
3090 /*#define BR(c,a,m)   "0200." #c "|." BRDIR(a) "5{|x" #a "x"*/
3091 #define CST(c,m)    CST_OK(m,c) #c "x"
3092 #define SH(o,n,r)   SH_OK(n) "0040." #o ".3{|." #n ".1&.2{|." #r "|x"
3093 #define SR(o,r)     "0000." #o ".3{|." #r "|x"
3094 #define JSR(r,e,a)  "0004x" #r ".3&.8{." #a ".8}.FC&|." #e "|x" #a ".3FF&x"
3095 
3096 
3097 /* ======================================================================== */
3098 /*  IGTAB    -- Instruction Generator Table.                                */
3099 /* ======================================================================== */
3100 struct igel igtab[] =
3101 {
3102     /* inv  0   */  {   SDBD,       0,      "[Xnullentry"                   },
3103     /* inv  1   */  {   SDBD,       0,      "[Xinvalid opcode"              },
3104 
3105     /* MVO  2   */  {   SDBD,       0,      RR(0240,0,[1#]) CST([2=],[3#])  },
3106     /* MVI  3   */  {   SDBD,       0,      RR(0280,0,[2#]) CST([1=],[3#])  },
3107     /* ADD  4   */  {   SDBD,       0,      RR(02C0,0,[2#]) CST([1=],[3#])  },
3108     /* SUB  5   */  {   SDBD,       0,      RR(0300,0,[2#]) CST([1=],[3#])  },
3109     /* CMP  6   */  {   SDBD,       0,      RR(0340,0,[2#]) CST([1=],[3#])  },
3110     /* AND  7   */  {   SDBD,       0,      RR(0380,0,[2#]) CST([1=],[3#])  },
3111     /* XOR  8   */  {   SDBD,       0,      RR(03C0,0,[2#]) CST([1=],[3#])  },
3112 
3113     /* MVO@ 9   */  {   SDBD,       0,      MVO_OK
3114                                             RR(0240,[2#],[1#])              },
3115     /* MVI@ 10  */  {   IND_RG,     IND_RG, RR(0280,[1#],[2#])              },
3116     /* ADD@ 11  */  {   IND_RG,     IND_RG, RR(02C0,[1#],[2#])              },
3117     /* SUB@ 12  */  {   IND_RG,     IND_RG, RR(0300,[1#],[2#])              },
3118     /* CMP@ 13  */  {   IND_RG,     IND_RG, RR(0340,[1#],[2#])              },
3119     /* AND@ 14  */  {   IND_RG,     IND_RG, RR(0380,[1#],[2#])              },
3120     /* XOR@ 15  */  {   IND_RG,     IND_RG, RR(03C0,[1#],[2#])              },
3121 
3122     /* MVOI 16  */  {   SDBD,       0,      RR(0240,7,[1#]) CST([2=],[3#])  },
3123     /* MVII 17  */  {   SDBD,       0,      RR(0280,7,[2#]) CST([1=],[3#])  },
3124     /* MVII 18  */  {   SDBD,       SDBD,   RR(0280,7,[2#]) DBD([1=])       },
3125     /* ADDI 19  */  {   SDBD,       0,      RR(02C0,7,[2#]) CST([1=],[3#])  },
3126     /* ADDI 20  */  {   SDBD,       SDBD,   RR(02C0,7,[2#]) DBD([1=])       },
3127     /* SUBI 21  */  {   SDBD,       0,      RR(0300,7,[2#]) CST([1=],[3#])  },
3128     /* SUBI 22  */  {   SDBD,       SDBD,   RR(0300,7,[2#]) DBD([1=])       },
3129     /* CMPI 23  */  {   SDBD,       0,      RR(0340,7,[2#]) CST([1=],[3#])  },
3130     /* CMPI 24  */  {   SDBD,       SDBD,   RR(0340,7,[2#]) DBD([1=])       },
3131     /* ANDI 25  */  {   SDBD,       0,      RR(0380,7,[2#]) CST([1=],[3#])  },
3132     /* ANDI 26  */  {   SDBD,       SDBD,   RR(0380,7,[2#]) DBD([1=])       },
3133     /* XORI 27  */  {   SDBD,       0,      RR(03C0,7,[2#]) CST([1=],[3#])  },
3134     /* XORI 28  */  {   SDBD,       SDBD,   RR(03C0,7,[2#]) DBD([1=])       },
3135 
3136     /* MOVR 29  */  {   SDBD,       0,      RR(0080,[1#],[2#])              },
3137     /* ADDR 30  */  {   SDBD,       0,      RR(00C0,[1#],[2#])              },
3138     /* SUBR 31  */  {   SDBD,       0,      RR(0100,[1#],[2#])              },
3139     /* CMPR 32  */  {   SDBD,       0,      RR(0140,[1#],[2#])              },
3140     /* ANDR 33  */  {   SDBD,       0,      RR(0180,[1#],[2#])              },
3141     /* XORR 34  */  {   SDBD,       0,      RR(01C0,[1#],[2#])              },
3142 
3143     /* B    35  */  {   SDBD,       0,      BR(0,[1=],[3#])                 },
3144     /* BC   36  */  {   SDBD,       0,      BR(1,[1=],[3#])                 },
3145     /* BOV  37  */  {   SDBD,       0,      BR(2,[1=],[3#])                 },
3146     /* BPL  38  */  {   SDBD,       0,      BR(3,[1=],[3#])                 },
3147     /* BEQ  39  */  {   SDBD,       0,      BR(4,[1=],[3#])                 },
3148     /* BLT  40  */  {   SDBD,       0,      BR(5,[1=],[3#])                 },
3149     /* BLE  41  */  {   SDBD,       0,      BR(6,[1=],[3#])                 },
3150     /* BUSC 42  */  {   SDBD,       0,      BR(7,[1=],[3#])                 },
3151     /* NOPP 43  */  {   SDBD,       0,      BR(8,[1=],[3#])                 },
3152     /* BNC  44  */  {   SDBD,       0,      BR(9,[1=],[3#])                 },
3153     /* BNOV 45  */  {   SDBD,       0,      BR(A,[1=],[3#])                 },
3154     /* BMI  46  */  {   SDBD,       0,      BR(B,[1=],[3#])                 },
3155     /* BNEQ 47  */  {   SDBD,       0,      BR(C,[1=],[3#])                 },
3156     /* BGE  48  */  {   SDBD,       0,      BR(D,[1=],[3#])                 },
3157     /* BGT  49  */  {   SDBD,       0,      BR(E,[1=],[3#])                 },
3158     /* BESC 50  */  {   SDBD,       0,      BR(F,[1=],[3#])                 },
3159 
3160     /* SWAP 51  */  {   SDBD|SHF_RG,SHF_RG, SH(0,0,[1#])                    },
3161     /* SWAP 52  */  {   SDBD|SHF_RG,SHF_RG, SH(0,[2=].1-,[1#])              },
3162     /* SLL  53  */  {   SDBD|SHF_RG,SHF_RG, SH(1,0,[1#])                    },
3163     /* SLL  54  */  {   SDBD|SHF_RG,SHF_RG, SH(1,[2=].1-,[1#])              },
3164     /* RLC  55  */  {   SDBD|SHF_RG,SHF_RG, SH(2,0,[1#])                    },
3165     /* RLC  56  */  {   SDBD|SHF_RG,SHF_RG, SH(2,[2=].1-,[1#])              },
3166     /* SLLC 57  */  {   SDBD|SHF_RG,SHF_RG, SH(3,0,[1#])                    },
3167     /* SLLC 58  */  {   SDBD|SHF_RG,SHF_RG, SH(3,[2=].1-,[1#])              },
3168     /* SLR  59  */  {   SDBD|SHF_RG,SHF_RG, SH(4,0,[1#])                    },
3169     /* SLR  60  */  {   SDBD|SHF_RG,SHF_RG, SH(4,[2=].1-,[1#])              },
3170     /* SAR  61  */  {   SDBD|SHF_RG,SHF_RG, SH(5,0,[1#])                    },
3171     /* SAR  62  */  {   SDBD|SHF_RG,SHF_RG, SH(5,[2=].1-,[1#])              },
3172     /* RRC  63  */  {   SDBD|SHF_RG,SHF_RG, SH(6,0,[1#])                    },
3173     /* RRC  64  */  {   SDBD|SHF_RG,SHF_RG, SH(6,[2=].1-,[1#])              },
3174     /* SARC 65  */  {   SDBD|SHF_RG,SHF_RG, SH(7,0,[1#])                    },
3175     /* SARC 66  */  {   SDBD|SHF_RG,SHF_RG, SH(7,[2=].1-,[1#])              },
3176 
3177     /* NOP  67  */  {   SDBD,       0,      "0034x"                         },
3178     /* SIN  68  */  {   SDBD,       0,      "0036x"                         },
3179 
3180     /* J    69  */  {   SDBD,       0,      JSR(3,0,[1=])                   },
3181     /* JE   70  */  {   SDBD,       0,      JSR(3,1,[1=])                   },
3182     /* JD   71  */  {   SDBD,       0,      JSR(3,2,[1=])                   },
3183     /* JSR  72  */  {   SDBD|JSR_RG,JSR_RG, JSR([1#],0,[2=])                },
3184     /* JSRE 73  */  {   SDBD|JSR_RG,JSR_RG, JSR([1#],1,[2=])                },
3185     /* JSRD 74  */  {   SDBD|JSR_RG,JSR_RG, JSR([1#],2,[2=])                },
3186 
3187     /* INCR 75  */  {   SDBD,       0,      SR(1,[1#])                      },
3188     /* DECR 76  */  {   SDBD,       0,      SR(2,[1#])                      },
3189     /* COMR 77  */  {   SDBD,       0,      SR(3,[1#])                      },
3190     /* NEGR 78  */  {   SDBD,       0,      SR(4,[1#])                      },
3191     /* ADCR 79  */  {   SDBD,       0,      SR(5,[1#])                      },
3192     /* GSWD 80  */  {   SDBD|SHF_RG,SHF_RG, SR(6,[1#])                      },
3193     /* RSWD 81  */  {   SDBD,       0,      SR(7,[1#])                      },
3194 
3195     /* HLT  82  */  {   SDBD,       0,      "0000x"                         },
3196     /* SDBD 83  */  {   SDBD,       0,      "0001x"                         },
3197     /* EIS  84  */  {   SDBD,       0,      "0002x"                         },
3198     /* DIS  85  */  {   SDBD,       0,      "0003x"                         },
3199     /* TCI  86  */  {   SDBD,       0,      "0005x"                         },
3200     /* CLRC 87  */  {   SDBD,       0,      "0006x"                         },
3201     /* SETC 88  */  {   SDBD,       0,      "0007x"                         },
3202 
3203     /* TSTR 89  */  {   SDBD,       0,      RR(0080,[1#],[1#])              },
3204     /* CLRR 90  */  {   SDBD,       0,      RR(01C0,[1#],[1#])              },
3205     /* PSHR 91  */  {   SDBD,       0,      RR(0240,6,[1#])                 },
3206     /* PULR 92  */  {   0,          0,      RR(0280,6,[1#])                 },
3207     /* JR   93  */  {   SDBD,       0,      RR(0080,[1#],7)                 },
3208     /* CALL 94  */  {   SDBD,       0,      JSR(5,0,[1=])                   },
3209     /* BEGIN 95 */  {   SDBD,       0,      RR(0240,6,5)                    },
3210     /* RETURN 96*/  {   SDBD,       0,      RR(0280,6,7)                    },
3211 
3212     /* NOPP 97  */  {   SDBD,       0,      "0208x0000x"                    },
3213     /* NOP2 98  */  {   SDBD,       0,      "0035x"                         },
3214     /* SIN2 99  */  {   SDBD,       0,      "0037x"                         },
3215 
3216     /* BESC 100 */  {   SDBD,       0,      BX([4#],[1=],[3#])              },
3217 
3218     /* end      */  {   0,          0,      "[Xinvalid opcode"              },
3219 };
3220 
3221 #define NUMOPCODE (sizeof(optab)/sizeof(struct opsym))
3222 
3223 int gnumopcode = NUMOPCODE;
3224 int ophashlnk[NUMOPCODE];
3225 
3226 /* ======================================================================== */
3227 /*  End of file:  fraptabdef.c                                              */
3228 /* ======================================================================== */
3229