1 /*
2  * Copyright (c) 2007-2009 Dominic Morris <dom /at/ suborbital.org.uk>
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  *
14  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
15  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
16  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
17  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
18  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
19  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
20  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
21  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
23  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24  */
25 
26 /* z80 backend for vasm */
27 
28 
29 #include "vasm.h"
30 
31 
32 
33 /*
34  * TODO: Undocumented ld a,rlc(ix+d) style unstructions
35  * TODO: Finish off rcm4000 opcodes
36  *
37  * Note: All z80 opcodes work as expected
38  */
39 mnemonic mnemonics[] = {
40     "adc",  { OP_HL|OP_INDEX|OP_RALT, OP_ARITH16 },             { TYPE_ARITH16, 0xed4a, CPU_ZILOG|CPU_RABBIT, F_ALTD },
41     "adc",  { OP_REG8|OP_INDEX },                               { TYPE_ARITH8,  0x88, CPU_ALL, F_ALL, 0, 0, RCM_EMU_INCREMENT },
42     "adc",  { OP_REG8|OP_INDEX },                               { TYPE_ARITH8,  0x7f88, CPU_RCM4000, F_ALL },
43     "adc",  { OP_A|OP_RALT, OP_REG8 | OP_INDEX },               { TYPE_ARITH8,  0x88, CPU_ALL, F_ALTD, 0, 0, RCM_EMU_INCREMENT },
44     "adc",  { OP_A|OP_RALT, OP_REG8 | OP_INDEX },               { TYPE_ARITH8,  0x7f88, CPU_RCM4000, F_ALTD, },
45     "adc",  { OP_ABS },                                         { TYPE_NONE,  0xce, CPU_ALL, F_ALTD },
46     "adc",  { OP_A|OP_RALT, OP_ABS },                           { TYPE_NONE,  0xce, CPU_ALL, F_ALTD },
47 
48     "add",  { OP_REG8 },                                        { TYPE_ARITH8,  0x80, CPU_ALL, F_ALTD, 0, 0, RCM_EMU_INCREMENT },
49     "add",  { OP_REG8 },                                        { TYPE_ARITH8,  0x7f80, CPU_RCM4000, F_ALTD },
50     "add",  { OP_HL|OP_RALT, OP_JK },                           { TYPE_NONE, 0x65, CPU_RCM4000, F_ALTD },
51 
52     "add",  { OP_HL|OP_INDEX|OP_RALT, OP_INDEX|OP_ARITH16},     { TYPE_ARITH16, 0x09, CPU_ALL, F_ALTD },
53 
54     "add",  { OP_A|OP_RALT, OP_REG8 },                          { TYPE_ARITH8,  0x80, CPU_ALL, F_ALL, 0, 0, RCM_EMU_INCREMENT },
55     "add",  { OP_A|OP_RALT, OP_REG8 },                          { TYPE_ARITH8,  0x7f80,  CPU_RCM4000, F_ALL }, /* add a,r for RCM4000 */
56     "add",  { OP_A|OP_RALT, OP_ABS },                           { TYPE_NONE,  0xc6, CPU_ALL, F_ALTD },
57     "add",  { OP_SP, OP_ABS },                                  { TYPE_NONE, 0x27, CPU_RABBIT|CPU_GB80, 0, 0, 0, 0, RCM_EMU_INCREMENT }, /* add sp,xx */
58     "add",  { OP_SP, OP_ABS },                                  { TYPE_NONE, 0xe8, CPU_GB80, 0 }, /* add sp,xx */
59     "add",  { OP_JKHL|OP_RALT, OP_BCDE },                        { TYPE_NONE, 0xedc6, CPU_RCM4000, F_ALTD },
60     "add",  { OP_ABS },                                         { TYPE_NONE,  0xc6, CPU_ALL, F_ALTD },
61 
62     "and",  { OP_HL|OP_INDEX|OP_RALT, OP_DE },                  { TYPE_NONE, 0xDC, CPU_RABBIT, F_ALTD }, /* and hl/ix/iy,de */
63     "and",  { OP_JKHL|OP_RALT, OP_BCDE },                       { TYPE_NONE, 0xede6, CPU_RCM4000, F_ALTD },
64     "and",  { OP_REG8|OP_INDEX },                               { TYPE_ARITH8, 0xa0, CPU_ALL, F_ALL, 0, 0, RCM_EMU_INCREMENT },
65     "and",  { OP_REG8|OP_INDEX },                               { TYPE_ARITH8, 0x7fa0, CPU_RCM4000, F_ALL,  }, /* and a,r  */
66     "and",  { OP_A|OP_RALT, OP_REG8|OP_INDEX },                 { TYPE_ARITH8, 0xa0, CPU_ALL, F_ALTD, 0, 0, RCM_EMU_INCREMENT },
67     "and",  { OP_A|OP_RALT, OP_REG8|OP_INDEX },                 { TYPE_ARITH8, 0x7fa0, CPU_RCM4000, F_ALTD },
68     "and",  { OP_A|OP_RALT, OP_ABS },                           { TYPE_NONE, 0xE6, CPU_ALL, F_ALTD },
69     "and",  { OP_ABS },                                         { TYPE_NONE, 0xE6, CPU_ALL, F_ALTD },
70 
71 
72 
73     "bit",  { OP_NUMBER, OP_REG8|OP_INDEX|OP_RALT|OP_RALTHL},   { TYPE_BIT, 0xCB40, CPU_NOT8080, F_ALL },
74     "bool", { OP_HL|OP_INDEX|OP_RALT},                          { TYPE_NONE, 0xCC, CPU_RABBIT, F_ALTD }, /* bool hl,ix,iy */
75 
76 
77     "call", { OP_FLAGS, OP_ABS16 },                             { TYPE_FLAGS, 0xc4, CPU_ALL },  /* We use emulation on RCM */
78     "call", { OP_HL|OP_INDIR|OP_INDEX },                        { TYPE_NONE, 0xEA, CPU_RCM4000, 0 }, /* call (hl/ix/iy) */
79     "call", { OP_ABS16 },                                       { TYPE_NONE, 0xcd, CPU_ALL, 0 },
80 
81     "cbm",  { OP_ABS },                                         { TYPE_NONE, 0xed00, CPU_RCM4000, F_IO }, /* cbm x */
82 
83 
84     "ccf",  { OP_NONE, },                                       { TYPE_NONE, 0x3f, CPU_ALL, F_ALTD },
85 
86     "clr",  { OP_HL|OP_RALT },                                  { TYPE_NONE, 0xBF, CPU_RCM4000, F_ALTD },
87 
88     "copy", { OP_NONE },                                        { TYPE_NONE, 0xed80, CPU_RCM4000, 0 },
89     "copyr",{ OP_NONE },                                        { TYPE_NONE, 0xed88, CPU_RCM4000, 0 },
90 
91 
92     "cp",   { OP_REG8 | OP_INDEX },                             { TYPE_ARITH8, 0xb8, CPU_ALL, F_ALL, 0, 0, RCM_EMU_INCREMENT },
93     "cp",   { OP_REG8 | OP_INDEX },                             { TYPE_ARITH8, 0x7fb8, CPU_RCM4000,F_ALL },
94     "cp",   { OP_A|OP_RALT, OP_REG8 | OP_INDEX },               { TYPE_ARITH8, 0xb8, CPU_ALL, F_ALL, 0, 0, RCM_EMU_INCREMENT },
95     "cp",   { OP_A|OP_RALT, OP_REG8 | OP_INDEX },               { TYPE_ARITH8, 0x7fb8, CPU_RCM4000, F_ALL },
96     "cp",   { OP_A|OP_RALT, OP_ABS },                           { TYPE_NONE, 0xfe, CPU_ALL, F_ALL },
97     "cp",   { OP_ABS },                                         { TYPE_NONE, 0xfe, CPU_ALL, F_ALTD },
98     "cp",   { OP_JKHL|OP_RALT, OP_BCDE },                       { TYPE_NONE, 0xed58, CPU_RCM4000, F_ALTD },
99     "cp",   { OP_HL|OP_RALT, OP_DE },                           { TYPE_NONE, 0xED48, CPU_RCM4000, F_ALTD }, /* cp hl,de */
100     "cp",   { OP_HL|OP_RALT, OP_ABS },                          { TYPE_NONE, 0x48, CPU_RCM4000, F_ALTD }, /* cp hl,de */
101 
102     "cpd",  { OP_NONE, },                                       { TYPE_NONE, 0xeda9, CPU_RABBIT|CPU_ZILOG, 0, RCM_EMU_LIBRARY, RCM_EMU_LIBRARY, RCM_EMU_LIBRARY, 0 },
103     "cpdr", { OP_NONE, },                                       { TYPE_NONE, 0xedb9, CPU_RABBIT|CPU_ZILOG, 0, RCM_EMU_LIBRARY, RCM_EMU_LIBRARY, RCM_EMU_LIBRARY, 0 },
104     "cpi",  { OP_NONE, },                                       { TYPE_NONE, 0xeda1, CPU_RABBIT|CPU_ZILOG, 0, RCM_EMU_LIBRARY, RCM_EMU_LIBRARY, RCM_EMU_LIBRARY, 0 },
105     "cpir", { OP_NONE, },                                       { TYPE_NONE, 0xedb1, CPU_RABBIT|CPU_ZILOG, 0, RCM_EMU_LIBRARY, RCM_EMU_LIBRARY, RCM_EMU_LIBRARY, 0 },
106     "cpl",  { OP_NONE, },                                       { TYPE_NONE, 0x2f,   CPU_ALL, F_ALTD },
107     "daa",  { OP_NONE, },                                       { TYPE_NONE, 0x27,   CPU_ZILOG|CPU_8080|CPU_GB80, 0 },
108     "dec",  { OP_REG8 | OP_INDEX|OP_RALT },                     { TYPE_MISC8, 0x05,  CPU_ALL, F_ALL },
109     "dec",  { OP_ARITH16 | OP_INDEX|OP_RALT },                  { TYPE_ARITH16, 0x0b,   CPU_ALL, F_ALTD },
110     "di",   { OP_NONE, },                                       { TYPE_NONE, 0xf3,   CPU_ZILOG|CPU_8080|CPU_GB80, F_ALTD },
111 
112     "djnz", { OP_ABS },                                         { TYPE_RELJUMP, 0x10, CPU_NOTGB80, F_ALTD },
113     "dwjnz",{ OP_ABS },                                         { TYPE_RELJUMP, 0xed10, CPU_RCM4000, F_ALTD },
114 
115 
116     "ei",   { OP_NONE, },                                       { TYPE_NONE, 0xfb,   CPU_ZILOG|CPU_8080|CPU_GB80, 0 },
117     "ex",   { OP_AF, OP_AF | OP_ALT },                          { TYPE_NONE, 0x08, CPU_ZILOG|CPU_RABBIT, F_ALTDW }, /* ex af,af' */
118     "ex",   { OP_BC, OP_HL },                                   { TYPE_NONE, 0xb3, CPU_RCM4000, 0 },
119     "ex",   { OP_BC, OP_HL|OP_ALT },                            { TYPE_NONE, 0x76b3, CPU_RCM4000, 0 },
120     "ex",   { OP_BC|OP_ALT, OP_HL },                            { TYPE_NONE, 0xed74, CPU_RCM4000, 0 },
121     "ex",   { OP_BC|OP_ALT, OP_HL|OP_ALT },                     { TYPE_NONE, 0x76ed74, CPU_RCM4000, 0 },
122 
123 
124     "ex",   { OP_DE, OP_HL|OP_RALT },                           { TYPE_NONE, 0xEB, CPU_NOTGB80, F_ALTD }, /* ex de,hl */
125     "ex",   { OP_DE, OP_HL|OP_ALT },                            { TYPE_NONE, 0x76Eb, CPU_RABBIT, F_ALTDW }, /* ex de,hl' (is this right?) */
126     "ex",   { OP_DE|OP_ALT, OP_HL|OP_RALT },                    { TYPE_NONE, 0xe3, CPU_RABBIT, F_ALTD }, /* ex de',hl */
127     "ex",   { OP_DE|OP_ALT, OP_HL|OP_ALT },                     { TYPE_NONE, 0x76e3, CPU_RABBIT, F_ALTDW }, /* ex de',hl */
128 
129     "ex",   { OP_JKHL, OP_BCDE },                               { TYPE_NONE, 0xb4, CPU_RCM4000, 0 }, /* ex jkhl,bcde */
130     "ex",   { OP_JK|OP_ALT, OP_HL },                            { TYPE_NONE, 0xed7c, CPU_RCM4000, 0 }, /* ex jk',hl */
131     "ex",   { OP_JK, OP_HL },                                   { TYPE_NONE, 0xb9, CPU_RCM4000, F_ALTD }, /* ex jk,hl */
132 
133 
134 
135     "ex",   { OP_SP|OP_INDIR, OP_HL|OP_INDEX|OP_RALT},          { TYPE_NONE, 0xe3, CPU_ALL, F_ALTD, RCM_EMU_INCREMENT, RCM_EMU_INCREMENT, RCM_EMU_INCREMENT  },
136     "ex",   { OP_SP|OP_INDIR, OP_HL|OP_INDEX|OP_RALT},          { TYPE_NONE, 0xed54, CPU_RABBIT, F_ALTD}, /* Must be after standard ex for rabbit compat */
137 
138     "exp",  { OP_NONE },                                        { TYPE_NONE, 0xedd9, CPU_RCM4000, 0 },
139 
140     "exx",  { OP_NONE, },                                       { TYPE_NONE, 0xd9,   CPU_ZILOG|CPU_RABBIT, F_ALTDW },
141 
142     "flag", { OP_FLAGS, OP_HL },                                { TYPE_FLAGS, 0xedc4, CPU_RCM4000, 0 }, /* flag cc,hl */
143     "flag", { OP_FLAGS_RCM, OP_HL },                            { TYPE_FLAGS, 0xeda4, CPU_RCM4000, 0 }, /* flag cc,hl */
144 
145     "fsyscall",{ OP_NONE },                                     { TYPE_NONE, 0xed55, CPU_RCM4000, 0 },
146 
147     "halt", { OP_NONE, },                                       { TYPE_NONE, 0x76,   CPU_ZILOG|CPU_8080|CPU_GB80, 0},
148 
149     "ibox", { OP_A|OP_RALT },                                   { TYPE_NONE, 0xed12, CPU_RCM4000, F_ALTD },
150     "idet", { OP_NONE },                                        { TYPE_NONE, 0x5b, CPU_RCM3000|CPU_RCM4000, 0 },
151 
152     "im",   { OP_NUMBER },                                      { TYPE_IM,   0xED46, CPU_ZILOG, 0 },
153 
154     "in",   { OP_REG8, OP_PORT },                               { TYPE_MISC8, 0xed40, CPU_ZILOG, 0 }, /* in r,(c) */
155     "in",   { OP_A, OP_ADDR8 },                                 { TYPE_NONE, 0xDB, CPU_8080|CPU_ZILOG, 0 },  /* in a,(xx) */
156     "in",   { OP_PORT },                                        { TYPE_NONE, 0xed70, CPU_ZILOG, 0 }, /* in (c) */
157     "in",   { OP_F, OP_PORT },                                  { TYPE_NONE, 0xed70, CPU_ZILOG, 0 }, /* in f,(c) */
158 
159     "in0",  { OP_REG8, OP_ADDR8 },                              { TYPE_MISC8, 0xed00, CPU_Z180|CPU_EZ80, 0 }, /* in0 r,(xx) */
160 
161     "inc",  { OP_REG8 | OP_INDEX },                             { TYPE_MISC8, 0x04,   CPU_ALL, F_ALTD },
162     "inc",  { OP_ARITH16 | OP_INDEX },                          { TYPE_ARITH16, 0x03,   CPU_ALL, F_ALTD },
163     "ind",  { OP_NONE, },                                       { TYPE_NONE, 0xedaa, CPU_ZILOG , 0},
164     "indr", { OP_NONE, },                                       { TYPE_NONE, 0xedba, CPU_ZILOG, 0 },
165     "ini",  { OP_NONE, },                                       { TYPE_NONE, 0xeda2, CPU_ZILOG, 0 },
166     "inir", { OP_NONE, },                                       { TYPE_NONE, 0xedb2, CPU_ZILOG, 0 },
167 
168 
169     "ipres",{ OP_NONE },                                        { TYPE_NONE, 0xed54, CPU_RABBIT, 0 },
170     "ipset",{ OP_NUMBER },                                      { TYPE_IPSET, 0xed46, CPU_RABBIT, 0 },
171 
172     "jr",   { OP_FLAGS, OP_ABS },                               { TYPE_RELJUMP, 0x20, CPU_ALL, 0 },
173     "jr",   { OP_FLAGS_RCM, OP_ABS },                           { TYPE_RELJUMP, 0xA0, CPU_RCM4000, 0 },
174     "jr",   { OP_ABS },                                         { TYPE_RELJUMP, 0x18, CPU_ALL, 0 },
175 
176     "jre",  { OP_FLAGS_RCM, OP_ABS16 },                         { TYPE_RELJUMP, 0xeda3, CPU_RCM4000, 0 },
177     "jre",  { OP_FLAGS, OP_ABS16 },                             { TYPE_RELJUMP, 0xedc3, CPU_RCM4000, 0 },
178     "jre",  { OP_ABS16 },                                       { TYPE_RELJUMP, 0x98, CPU_RCM4000, 0 },
179 
180     "jp",   { OP_FLAGS, OP_ABS16 },                             { TYPE_FLAGS, 0xc2, CPU_ALL, 0 },
181     "jp",   { OP_FLAGS_RCM, OP_ABS16 },                         { TYPE_FLAGS, 0xA2, CPU_RCM4000, 0 },
182     "jp",   { OP_HL|OP_INDIR|OP_INDEX },                        { TYPE_NONE, 0xE9, CPU_ALL, 0 },
183     "jp",   { OP_HL|OP_INDEX },                                 { TYPE_NONE, 0xE9, CPU_ALL, 0 },
184     "jp",   { OP_ABS16 },                                       { TYPE_NONE, 0xc3, CPU_ALL, 0 },
185 
186     "lcall",{ OP_ABS24 },                                       { TYPE_NONE, 0xcf, CPU_RABBIT, 0 },
187     "ljp",  { OP_ABS24 },                                       { TYPE_NONE, 0xc7, CPU_RABBIT, 0 },
188 
189 
190     "ld",   { OP_BC|OP_INDIR, OP_A },                           { TYPE_NONE, 0x02, CPU_ALL, F_IO }, /* ld (bc),a */
191     "ld",   { OP_DE|OP_INDIR, OP_A },                           { TYPE_NONE, 0x12, CPU_ALL, F_IO }, /* ld (de),a */
192 
193     "ld",   { OP_REG8|OP_INDEX|OP_RALT, OP_REG8|OP_INDEX},      { TYPE_LD8, 0x40, CPU_ALL, F_ALL|F_ALTDWHL, 0, 0, RCM_EMU_INCREMENT, 0 }, /* ld r8,r8 */
194     "ld",   { OP_REG8|OP_INDEX|OP_RALT, OP_REG8|OP_INDEX},      { TYPE_LD8, 0x7f40, CPU_RCM4000, F_ALL|F_ALTDWHL }, /* ld r8,r8 (only those without a or (hl) */
195 
196     "ld",   { OP_STD16BIT|OP_ALT, OP_BC },                      { TYPE_ARITH16, 0xed49, CPU_RABBIT, 0 }, /* ld [bc|de|hl]',bc */
197     "ld",   { OP_STD16BIT|OP_ALT, OP_DE },                      { TYPE_ARITH16, 0xed41, CPU_RABBIT, 0 }, /* ld [bc|de|hl]',de */
198 
199     "ld",   { OP_HL|OP_RALT, OP_BC },                           { TYPE_NONE, 0x81, CPU_RCM4000, F_ALTD }, /* ld hl,bc */
200     "ld",   { OP_BC|OP_RALT, OP_HL },                           { TYPE_NONE, 0x91, CPU_RCM4000, F_ALTD }, /* ld bc,hl */
201     "ld",   { OP_HL|OP_RALT, OP_DE },                           { TYPE_NONE, 0xA1, CPU_RCM4000, F_ALTD }, /* ld hl,de */
202     "ld",   { OP_DE|OP_RALT, OP_HL },                           { TYPE_NONE, 0xB1, CPU_RCM4000, F_ALTD }, /* ld de,hl */
203 
204     "ld",   { OP_HL|OP_INDEX|OP_RALT,OP_SP|OP_OFFSET|OP_INDIR}, { TYPE_NONE, 0xc4, CPU_RABBIT, F_ALTD }, /* ld hl,(sp+dd) */
205     "ld",   { OP_SP|OP_OFFSET|OP_INDIR, OP_HL|OP_INDEX},        { TYPE_NONE, 0xd4, CPU_RABBIT, 0 }, /* ld (sp+dd),hl */
206 
207     "ld",   { OP_HL|OP_RALT, OP_IX },                           { TYPE_NONE, 0xdd7c, CPU_RABBIT, F_ALTD }, /* ld hl,ix */
208     "ld",   { OP_HL|OP_RALT, OP_IY },                           { TYPE_NONE, 0xfd7c, CPU_RABBIT, F_ALTD }, /* ld hl,iy */
209     "ld",   { OP_IX, OP_HL },                                   { TYPE_NONE, 0xdd7d, CPU_RABBIT, 0 }, /* ld ix,hl */
210     "ld",   { OP_IY, OP_HL },                                   { TYPE_NONE, 0xfd7d, CPU_RABBIT, 0 }, /* ld iy,hl */
211     "ld",   { OP_HL|OP_RALT, OP_IX|OP_OFFSET|OP_INDIR },        { TYPE_NOPREFIX, 0xe4, CPU_RABBIT, F_ALTD },  /* ld hl,(ix+dd) */
212     "ld",   { OP_HL|OP_RALT, OP_IY|OP_OFFSET|OP_INDIR },        { TYPE_NOPREFIX, 0xfde4, CPU_RABBIT, F_ALTD },  /* ld hl,(iy+dd) */
213     "ld",   { OP_HL|OP_RALT, OP_HL|OP_OFFSET|OP_INDIR },        { TYPE_NOPREFIX, 0xdde4, CPU_RABBIT, F_ALTD },  /* ld hl,(hl+dd) */
214     "ld",   { OP_IX|OP_OFFSET|OP_INDIR, OP_HL },                { TYPE_NOPREFIX, 0xf4, CPU_RABBIT, F_IO },  /* ld (ix+dd),hl */
215     "ld",   { OP_IY|OP_OFFSET|OP_INDIR, OP_HL },                { TYPE_NOPREFIX, 0xfdf4, CPU_RABBIT, F_IO },  /* ld (iy+dd),hl */
216     "ld",   { OP_HL|OP_OFFSET|OP_INDIR, OP_HL },                { TYPE_NONE, 0xddf4, CPU_RABBIT, F_IO },  /* ld (hl+dd),hl */
217 
218 
219 
220     "ld",   { OP_HL|OP_INDEX|OP_RALT, OP_ADDR },                { TYPE_NONE, 0x2A, CPU_NOTGB80, F_ALL }, /* ld hl,(xx)  */
221     "ld",   { OP_ARITH16|OP_INDEX|OP_RALT, OP_ADDR },           { TYPE_ARITH16, 0xED4B, CPU_ZILOG|CPU_RABBIT, F_ALL }, /* ld bc,de,sp,(xx) */
222 
223     "ld",   { OP_A|OP_RALT, OP_IDX32|OP_INDIR|OP_OFFSHL },      { TYPE_IDX32, 0x8b, CPU_RCM4000, F_ALTD }, /* ld a,(ps+hl) */
224     "ld",   { OP_A|OP_RALT, OP_IDX32|OP_OFFSET|OP_INDIR },      { TYPE_IDX32, 0x8d, CPU_RCM4000, F_ALTD }, /* ld a,(ps+d) */
225     "ld",   { OP_IDX32|OP_OFFSHL|OP_INDIR,OP_A },               { TYPE_IDX32, 0x8c, CPU_RCM4000, 0 }, /* ld (pd+hl),a */
226     "ld",   { OP_IDX32|OP_OFFSET|OP_INDIR,OP_A },               { TYPE_IDX32, 0x8e, CPU_RCM4000, 0 }, /* ld (pd+d),a */
227     "ld",   { OP_HL|OP_RALT, OP_IDX32|OP_OFFSBC|OP_INDIR },     { TYPE_IDX32, 0xed06, CPU_RCM4000, F_ALTD }, /* ld hl,(ps+bc) */
228     "ld",   { OP_IDX32|OP_OFFSBC|OP_INDIR, OP_HL },             { TYPE_IDX32, 0xed07, CPU_RCM4000, 0 }, /* ld (pd+bc),hl */
229     "ld",   { OP_HL|OP_RALT, OP_SP|OP_OFFSHL|OP_INDIR },        { TYPE_IDX32, 0xedfe, CPU_RCM4000, F_ALTD }, /* ld hl,(sp+hl) */
230     "ld",   { OP_HL|OP_RALT, OP_IDX32|OP_OFFSET|OP_INDIR },     { TYPE_IDX32, 0x85, CPU_RCM4000, F_ALTD }, /* ld hl,(ps+d) */
231     "ld",   { OP_IDX32|OP_OFFSET|OP_INDIR, OP_HL },             { TYPE_IDX32, 0x86, CPU_RCM4000, 0 }, /* ld (pd+d),hl */
232     "ld",   { OP_IDX32, OP_SP|OP_OFFSET|OP_INDIR },             { TYPE_IDX32, 0xed04, CPU_RCM4000, 0 }, /* ld pd,(sp+n) */
233     "ld",   { OP_SP|OP_OFFSET|OP_INDIR, OP_IDX32 },             { TYPE_NONE, 0xed05, CPU_RCM4000, 0 }, /* ld (sp+dd),pw */
234 
235 
236     "ld",   { OP_BCDE|OP_RALT, OP_HL|OP_INDIR },                { TYPE_NONE, 0xdd1a, CPU_RCM4000, F_ALTD },  /* ld bcde,(hl) */
237     "ld",   { OP_HL|OP_INDIR, OP_BCDE },                        { TYPE_NONE, 0xdd1b, CPU_RCM4000, 0 }, /* ld (hl),bcde */
238     "ld",   { OP_BCDE|OP_RALT, OP_ADDR },                       { TYPE_NONE, 0x93, CPU_RCM4000, F_ALTD },  /* ld bcde,(xx) */
239     "ld",   { OP_ADDR, OP_BCDE },                               { TYPE_NONE, 0x83, CPU_RCM4000, 0 }, /* ld (xx),bcde */
240     "ld",   { OP_BCDE|OP_RALT, OP_ABS },                        { TYPE_NONE, 0xa3, CPU_RCM4000, F_ALTD },  /* ld bcde,dd */
241     "ld",   { OP_BCDE|OP_RALT, OP_SP|OP_OFFSHL|OP_INDIR },      { TYPE_NONE,  0xddfe, CPU_RCM4000, F_ALTD }, /* ld bcde,(sp+hl) */
242     "ld",   { OP_BCDE|OP_RALT, OP_SP|OP_OFFSET|OP_INDIR },      { TYPE_NONE, 0xddee, CPU_RCM4000, F_ALTD },  /* ld bcde,(sp+dd) */
243     "ld",   { OP_BCDE|OP_RALT, OP_IX|OP_OFFSET|OP_INDIR },      { TYPE_NONE, 0xddce, CPU_RCM4000, F_ALTD },  /* ld bcde,(ix+dd) */
244     "ld",   { OP_BCDE|OP_RALT, OP_IY|OP_OFFSET|OP_INDIR },      { TYPE_NONE, 0xddde, CPU_RCM4000, F_ALTD },  /* ld bcde,(iy+dd) */
245     "ld",   { OP_SP|OP_OFFSET|OP_INDIR, OP_BCDE },              { TYPE_NONE, 0xddef, CPU_RCM4000, 0 },  /* ld (sp+dd),bcde */
246     "ld",   { OP_BCDE|OP_RALT, OP_IDX32|OP_OFFSHL|OP_INDIR },   { TYPE_IDX32, 0xdd0c, CPU_RCM4000, F_ALTD }, /* ld bcde,(ps+hl) */
247     "ld",   { OP_BCDE|OP_RALT, OP_IDX32|OP_OFFSET|OP_INDIR },   { TYPE_IDX32, 0xdd0e, CPU_RCM4000, F_ALTD }, /* ld bcde,(ps+d) */
248     "ld",   { OP_BCDE|OP_RALT, OP_IDX32 },                      { TYPE_IDX32, 0xddcd, CPU_RCM4000, F_ALTD }, /* ld bcde,ps */
249     "ld",   { OP_IDX32|OP_OFFSHL|OP_INDIR, OP_BCDE },           { TYPE_IDX32, 0xdd0d, CPU_RCM4000, 0 }, /* ld (pd+hl),bcde */
250     "ld",   { OP_IDX32|OP_OFFSET|OP_INDIR, OP_BCDE },           { TYPE_IDX32, 0xdd0f, CPU_RCM4000, 0 }, /* ld (pd+d),bcde */
251     "ld",   { OP_IDX32, OP_BCDE },                              { TYPE_IDX32, 0xdd8d, CPU_RCM4000, 0 }, /* ld pd,bcde */
252 
253 
254 
255 
256 
257     "ld",   { OP_JKHL|OP_RALT, OP_HL|OP_INDIR },                { TYPE_NONE, 0xfd1a, CPU_RCM4000, F_ALTD },  /* ld jkhl,(hl) */
258     "ld",   { OP_HL|OP_INDIR, OP_JKHL },                        { TYPE_NONE, 0xfd1b, CPU_RCM4000, 0 }, /* ld (hl),jkhl */
259     "ld",   { OP_JKHL|OP_RALT, OP_ADDR },                       { TYPE_NONE, 0x94, CPU_RCM4000, F_ALTD },  /* ld jkhl,(xx) */
260     "ld",   { OP_ADDR, OP_JKHL },                               { TYPE_NONE, 0x84, CPU_RCM4000, 0 }, /* ld (xx),jkhl */
261     "ld",   { OP_JKHL|OP_RALT, OP_ABS },                        { TYPE_NONE, 0xa4, CPU_RCM4000, F_ALTD },  /* ld jkhl,dd */
262     "ld",   { OP_JKHL|OP_RALT, OP_SP|OP_OFFSHL|OP_INDIR },      { TYPE_NONE,  0xddfe, CPU_RCM4000, F_ALTD }, /* ld jkhl,(sp+hl) */
263     "ld",   { OP_JKHL|OP_RALT, OP_SP|OP_OFFSET|OP_INDIR },      { TYPE_NONE, 0xfdee, CPU_RCM4000, F_ALTD },  /* ld jkhl,(sp+dd) */
264     "ld",   { OP_JKHL|OP_RALT, OP_IX|OP_OFFSET|OP_INDIR },      { TYPE_NONE, 0xfdce, CPU_RCM4000, F_ALTD },  /* ld jkhl,(ix+dd) */
265     "ld",   { OP_JKHL|OP_RALT, OP_IY|OP_OFFSET|OP_INDIR },      { TYPE_NONE, 0xfdde, CPU_RCM4000, F_ALTD },  /* ld jkhl,(iy+dd) */
266     "ld",   { OP_SP|OP_OFFSET|OP_INDIR, OP_JKHL },              { TYPE_NONE, 0xfdef, CPU_RCM4000, 0 },  /* ld (sp+dd),jkhl */
267     "ld",   { OP_JKHL|OP_RALT, OP_IDX32|OP_OFFSHL|OP_INDIR },   { TYPE_IDX32, 0xfd0c, CPU_RCM4000, F_ALTD }, /* ld jkhl,(ps+hl) */
268     "ld",   { OP_JKHL|OP_RALT, OP_IDX32|OP_OFFSET|OP_INDIR },   { TYPE_IDX32, 0xfd0e, CPU_RCM4000, F_ALTD }, /* ld jkhl,(ps+d) */
269     "ld",   { OP_JKHL|OP_RALT, OP_IDX32 },                      { TYPE_IDX32, 0xfdcd, CPU_RCM4000, F_ALTD }, /* ld jkhl,ps */
270     "ld",   { OP_IDX32|OP_OFFSHL|OP_INDIR, OP_JKHL },           { TYPE_IDX32, 0xfd0d, CPU_RCM4000, 0 }, /* ld (pd+hl),jkhl */
271     "ld",   { OP_IDX32|OP_OFFSET|OP_INDIR, OP_JKHL },           { TYPE_IDX32, 0xfd0f, CPU_RCM4000, 0 }, /* ld (pd+d),jkhl */
272     "ld",   { OP_IDX32, OP_JKHL },                              { TYPE_IDX32, 0xfd8d, CPU_RCM4000, 0 }, /* ld pd,bcde */
273 
274 
275     "ld",   { OP_IDX32, OP_IDX32|OP_INDIR|OP_OFFSHL },          { TYPE_IDX32R, 0x6d0a, CPU_RCM4000, 0 }, /* ld pd,(ps+hl) */
276     "ld",   { OP_IDX32, OP_IDX32|OP_INDIR|OP_OFFSET },          { TYPE_IDX32R, 0x6d08, CPU_RCM4000, 0 }, /* ld pd,(ps+dd) */
277     "ld",   { OP_IDX32, OP_IDX32|OP_OFFSHL },                   { TYPE_IDX32R, 0x6d0e, CPU_RCM4000, 0 }, /* ld pd,ps+hl */
278     "ld",   { OP_IDX32, OP_IDX32|OP_OFFSDE },                   { TYPE_IDX32R, 0x6d06, CPU_RCM4000, 0 }, /* ld pd,ps+de */
279     "ld",   { OP_IDX32, OP_IDX32|OP_OFFSIX },                   { TYPE_IDX32R, 0x6d04, CPU_RCM4000, 0 }, /* ld pd,ps+ix */
280     "ld",   { OP_IDX32, OP_IDX32|OP_OFFSIY },                   { TYPE_IDX32R, 0x6d05, CPU_RCM4000, 0 }, /* ld pd,ps+iy */
281     "ld",   { OP_IDX32, OP_IDX32 },                             { TYPE_IDX32R, 0x6d07, CPU_RCM4000, 0 }, /* ld pd,ps */
282     "ld",   { OP_IDX32, OP_IDX32|OP_OFFSET },                   { TYPE_IDX32R, 0x6d0c, CPU_RCM4000, 0 }, /* ld pd,ps+dd */
283 
284 
285     "ld",   { OP_BC|OP_RALT, OP_IDX32|OP_INDIR|OP_OFFSHL },     { TYPE_IDX32, 0x6d02, CPU_RCM4000, F_ALTD }, /* ld bc,(ps+hl) */
286     "ld",   { OP_BC|OP_RALT, OP_IDX32|OP_INDIR|OP_OFFSET },     { TYPE_IDX32, 0x6d00, CPU_RCM4000, F_ALTD }, /* ld bc,(ps+dd) */
287     "ld",   { OP_IDX32|OP_INDIR|OP_OFFSHL, OP_BC },             { TYPE_IDX32, 0x6d03, CPU_RCM4000, 0 }, /* ld (pd+hl),bc */
288     "ld",   { OP_IDX32|OP_INDIR|OP_OFFSET, OP_BC },             { TYPE_IDX32, 0x6d01, CPU_RCM4000, 0 }, /* ld (pd+dd),bc */
289     "ld",   { OP_DE|OP_RALT, OP_IDX32|OP_INDIR|OP_OFFSHL },     { TYPE_IDX32, 0x6d42, CPU_RCM4000, F_ALTD }, /* ld de,(ps+hl) */
290     "ld",   { OP_DE|OP_RALT, OP_IDX32|OP_INDIR|OP_OFFSET },     { TYPE_IDX32, 0x6d40, CPU_RCM4000, F_ALTD }, /* ld de,(ps+dd) */
291     "ld",   { OP_IDX32|OP_INDIR|OP_OFFSHL, OP_DE },             { TYPE_IDX32, 0x6d43, CPU_RCM4000, 0 }, /* ld (pd+hl),de */
292     "ld",   { OP_IDX32|OP_INDIR|OP_OFFSET, OP_DE },             { TYPE_IDX32, 0x6d41, CPU_RCM4000, 0 }, /* ld (pd+dd),de */
293     "ld",   { OP_IX, OP_IDX32|OP_INDIR|OP_OFFSHL },             { TYPE_IDX32, 0x6d82, CPU_RCM4000, 0 }, /* ld ix,(ps+hl) */
294     "ld",   { OP_IX, OP_IDX32|OP_INDIR|OP_OFFSET },             { TYPE_IDX32, 0x6d80, CPU_RCM4000, 0 }, /* ld ix,(ps+dd) */
295     "ld",   { OP_IDX32|OP_INDIR|OP_OFFSHL, OP_IX },             { TYPE_IDX32, 0x6d83, CPU_RCM4000, 0 }, /* ld (pd+hl),ix */
296     "ld",   { OP_IDX32|OP_INDIR|OP_OFFSET, OP_IX },             { TYPE_IDX32, 0x6d81, CPU_RCM4000, 0 }, /* ld (pd+dd),ix */
297     "ld",   { OP_IY, OP_IDX32|OP_INDIR|OP_OFFSHL },             { TYPE_IDX32, 0x6dc2, CPU_RCM4000, 0 }, /* ld iy,(ps+hl) */
298     "ld",   { OP_IY, OP_IDX32|OP_INDIR|OP_OFFSET },             { TYPE_IDX32, 0x6dc0, CPU_RCM4000, 0 }, /* ld iy,(ps+dd) */
299     "ld",   { OP_IDX32|OP_INDIR|OP_OFFSHL, OP_IY },             { TYPE_IDX32, 0x6dc3, CPU_RCM4000, 0 }, /* ld (pd+hl),iy */
300     "ld",   { OP_IDX32|OP_INDIR|OP_OFFSET, OP_IY },             { TYPE_IDX32, 0x6dc1, CPU_RCM4000, 0 }, /* ld (pd+dd),iy */
301     "ld",   { OP_IDX32|OP_INDIR|OP_OFFSHL, OP_IDX32 },          { TYPE_IDX32R, 0x6d0b, CPU_RCM4000, 0 }, /* ld (pd+hl),ps */
302     "ld",   { OP_IDX32|OP_INDIR|OP_OFFSET, OP_IDX32 },          { TYPE_IDX32R, 0x6d09, CPU_RCM4000, 0 }, /* ld (pd+dd),ps */
303 
304 
305     "ld",   { OP_IDX32, OP_ABS32 },                             { TYPE_IDX32, 0xed0c, CPU_RCM4000, 0 }, /* ld pd,klmnn */
306 
307 
308 
309     "ld",   { OP_XPC, OP_A },                                   { TYPE_NONE, 0xed67, CPU_RABBIT, 0 }, /* ld xpc,a */
310     "ld",   { OP_A, OP_XPC },                                   { TYPE_NONE, 0xed77, CPU_RABBIT, 0 }, /* ld a,xpc */
311     "ld",   { OP_HTR, OP_A },                                   { TYPE_NONE, 0xed40, CPU_RCM4000, 0 }, /* ld htr,a */
312     "ld",   { OP_A, OP_HTR },                                   { TYPE_NONE, 0xed50, CPU_RCM4000, 0 }, /* ld a,htr */
313 
314     "ld",   { OP_JK|OP_RALT, OP_ABS16 },                        { TYPE_NONE, 0xa9, CPU_RCM4000, F_ALTD },  /* ld jk,xx */
315     "ld",   { OP_ADDR, OP_JK  },                                { TYPE_NONE, 0x89, CPU_RCM4000, F_IO }, /* ld (xx),jk */
316     "ld",   { OP_JK|OP_RALT, OP_ADDR },                         { TYPE_NONE, 0x99, CPU_RCM4000, F_ALL },  /* ld jk,(xx) */
317 
318 
319     "ld",   { OP_A|OP_RALT, OP_BC|OP_INDIR},                    { TYPE_NONE, 0x0a, CPU_ALL, F_ALL }, /* ld a,(bc) */
320     "ld",   { OP_A|OP_RALT, OP_DE|OP_INDIR},                    { TYPE_NONE, 0x1a, CPU_ALL, F_ALL }, /* ld a,(de) */
321 
322     "ld",   { OP_A|OP_RALT, OP_ADDR },                          { TYPE_NONE, 0x3a, CPU_ALL, F_ALL, 0, 0, 0, RCM_EMU_INCREMENT }, /* ld a,(xx) */
323     "ld",   { OP_A, OP_ADDR },                                  { TYPE_NONE, 0xfa, CPU_GB80, F_ALL }, /* ld a,(xx) */
324 
325     "ld",   { OP_A|OP_RALT, OP_I },                             { TYPE_NONE, 0xed57, CPU_ZILOG|CPU_RABBIT, F_ALTD }, /* ld a,i */
326     "ld",   { OP_A|OP_RALT, OP_R },                             { TYPE_NONE, 0xed5f, CPU_ZILOG|CPU_RABBIT, F_ALTD }, /* ld a,r */
327 
328     "ld",   { OP_REG8| OP_INDEX|OP_RALT, OP_ABS },              { TYPE_MISC8, 0x06, CPU_ALL, F_ALL|F_ALTDWHL },  /* ld r8, nn */
329     "ld",   { OP_SP, OP_HL|OP_INDEX},                           { TYPE_NONE, 0xf9, CPU_ALL, 0 }, /* ld sp,hl */
330     "ld",   { OP_ARITH16| OP_INDEX|OP_RALT, OP_ABS16 },         { TYPE_ARITH16, 0x01, CPU_ALL, F_ALTD }, /* ld hl,bc,de,xx */
331     "ld",   { OP_R, OP_A },                                     { TYPE_NONE, 0xed4f, CPU_ZILOG|CPU_RABBIT, F_ALTD }, /* ld r,a */
332     "ld",   { OP_I, OP_A },                                     { TYPE_NONE, 0xed47, CPU_ZILOG|CPU_RABBIT, F_ALTD }, /* ld i,a */
333 
334     "ld",   { OP_PORT, OP_A },                                  { TYPE_NONE, 0xe2, CPU_GB80, 0 }, /* ld (c),a (ff00 + c) */
335 
336 
337     "ld",   { OP_ADDR, OP_SP },                                 { TYPE_NONE, 0xED73, CPU_ZILOG|CPU_RABBIT|CPU_GB80, F_IO, 0, 0, 0, RCM_EMU_INCREMENT }, /* ld (xx),sp */
338     "ld",   { OP_ADDR, OP_SP },                                 { TYPE_NONE, 0x08, CPU_GB80, 0 }, /* ld (xx), sp */
339     "ld",   { OP_ADDR, OP_HL| OP_INDEX },                       { TYPE_NONE, 0x22, CPU_NOTGB80, F_IO }, /* ld (xx),hl */
340     "ld",   { OP_ADDR, OP_ARITH16 },                            { TYPE_ARITH16, 0xED43, CPU_ZILOG|CPU_RABBIT, F_IO }, /* ld (xx),bc,de,sp */
341     "ld",   { OP_ADDR, OP_A },                                  { TYPE_NONE, 0x32, CPU_ALL, F_IO, 0, 0, 0, RCM_EMU_INCREMENT }, /* ld (xx),a */
342     "ld",   { OP_ADDR, OP_A },                                  { TYPE_NONE, 0xea, CPU_GB80, 0 }, /* ld (xx),a (GB) */
343 
344     "ldd",  { OP_NONE, },                                       { TYPE_NONE, 0xeda8, CPU_ZILOG|CPU_RABBIT, F_IO },
345     "ldd",  { OP_A, OP_HL|OP_INDIR },                           { TYPE_NONE, 0x3a, CPU_GB80, 0 },
346     "ldd",  { OP_HL|OP_INDIR,OP_A },                            { TYPE_NONE, 0x32, CPU_GB80, 0 },
347     "lddr", { OP_NONE, },                                       { TYPE_NONE, 0xedb8, CPU_ZILOG|CPU_RABBIT, F_IO },
348     "lddsr",{ OP_NONE },                                        { TYPE_NONE, 0xed98, CPU_RCM3000 | CPU_RCM4000, F_IO },
349 
350     "ldf", { OP_ADDR24, OP_A },                                 { TYPE_NONE, 0x8a, CPU_RCM4000, 0 }, /* ldf (lmn),a */
351     "ldf", { OP_ADDR24, OP_BC },                                { TYPE_NONE, 0xed0b, CPU_RCM4000, 0 }, /* ldf (lmn),bc */
352     "ldf", { OP_ADDR24, OP_DE },                                { TYPE_NONE, 0xed1b, CPU_RCM4000, 0 }, /* ldf (lmn),de */
353     "ldf", { OP_ADDR24, OP_IX },                                { TYPE_NONE, 0xed2b, CPU_RCM4000, 0 }, /* ldf (lmn),ix */
354     "ldf", { OP_ADDR24, OP_IY },                                { TYPE_NONE, 0xed3b, CPU_RCM4000, 0 }, /* ldf (lmn),iy */
355     "ldf", { OP_ADDR24, OP_HL },                                { TYPE_NONE, 0x82, CPU_RCM4000, 0 }, /* ldf (lmn),hl */
356     "ldf", { OP_ADDR24, OP_BCDE },                              { TYPE_NONE, 0xdd0b, CPU_RCM4000, 0 }, /* ldf (lmn),bcde */
357     "ldf", { OP_ADDR24, OP_JKHL },                              { TYPE_NONE, 0xfd0b, CPU_RCM4000, 0 }, /* ldf (lmn),jkhl */
358     "ldf", { OP_A|OP_RALT, OP_ADDR24 },                         { TYPE_NONE, 0x9a, CPU_RCM4000, F_ALTD }, /* ldf a,(lmn) */
359     "ldf", { OP_BC|OP_RALT, OP_ADDR24 },                        { TYPE_NONE, 0xed0a, CPU_RCM4000, F_ALTD }, /* ldf bc,(lmn) */
360     "ldf", { OP_DE|OP_RALT, OP_ADDR24 },                        { TYPE_NONE, 0xed1a, CPU_RCM4000, F_ALTD }, /* ldf de,(lmn) */
361     "ldf", { OP_IX, OP_ADDR24 },                                { TYPE_NONE, 0xed2a, CPU_RCM4000, 0 }, /* ldf ix,(lmn) */
362     "ldf", { OP_IY, OP_ADDR24 },                                { TYPE_NONE, 0xed3a, CPU_RCM4000, 0 }, /* ldf iy,(lmn) */
363     "ldf", { OP_HL|OP_RALT, OP_ADDR24 },                        { TYPE_NONE, 0x92, CPU_RCM4000, F_ALTD }, /* ldf hl,(lmn) */
364     "ldf", { OP_BCDE|OP_RALT, OP_ADDR24 },                      { TYPE_NONE, 0xdd0a, CPU_RCM4000, 0 }, /* ldf bcde,(lmn) */
365     "ldf", { OP_JKHL|OP_RALT, OP_ADDR24 },                      { TYPE_NONE, 0xfd0a, CPU_RCM4000, F_ALTD }, /* ldf jkhl,(lmn) */
366 
367     "ldh",  { OP_ADDR8, OP_A },                                 { TYPE_NONE, 0xe0, CPU_GB80, 0 }, /* ld (xx),a (GB - for ff00 page) */
368     "ldh",  { OP_A, OP_ADDR8 },                                 { TYPE_NONE, 0xf0, CPU_GB80, 0 }, /* ld a,(xx) */
369     "ldhl", { OP_SP, OP_ABS },                                  { TYPE_NONE, 0xf8, CPU_GB80, 0 },
370 
371     "ldi",  { OP_NONE, },                                       { TYPE_NONE, 0xeda0, CPU_ZILOG|CPU_RABBIT, F_IO },
372     "ldi",  { OP_A, OP_HL|OP_INDIR },                           { TYPE_NONE, 0x2a, CPU_GB80, 0 },
373     "ldi",  { OP_HL|OP_INDIR,OP_A },                            { TYPE_NONE, 0x22, CPU_GB80, 0 },
374     "ldir", { OP_NONE, },                                       { TYPE_NONE, 0xedb0, CPU_ZILOG|CPU_RABBIT, F_IO },
375     "ldisr",{ OP_NONE },                                        { TYPE_NONE, 0xed90, CPU_RCM3000 | CPU_RCM4000, F_IO },
376 
377     "ldl",  { OP_IDX32|OP_RALT, OP_DE },                        { TYPE_IDX32, 0xdd8f, CPU_RCM4000, F_ALTD },
378     "ldl",  { OP_IDX32|OP_RALT, OP_HL },                        { TYPE_IDX32, 0xfd8f, CPU_RCM4000, F_ALTD },
379     "ldl",  { OP_IDX32|OP_RALT, OP_IX },                        { TYPE_IDX32, 0xdd8c, CPU_RCM4000, F_ALTD },
380     "ldl",  { OP_IDX32|OP_RALT, OP_IY },                        { TYPE_IDX32, 0xfd8c, CPU_RCM4000, F_ALTD },
381     "ldl",  { OP_IDX32|OP_RALT, OP_ABS16 },                     { TYPE_IDX32, 0xed0d, CPU_RCM4000, F_ALTD },
382     "ldl",  { OP_IDX32|OP_RALT, OP_SP|OP_OFFSET|OP_INDIR },     { TYPE_IDX32, 0xed03, CPU_RCM4000, F_ALTD },
383 
384 
385     "ldp",  { OP_HL|OP_INDEX|OP_INDIR, OP_HL },                 { TYPE_EDPREF, 0xed64, CPU_RABBIT, 0 }, /* ldp (hl),hl */
386     "ldp",  { OP_ADDR, OP_HL|OP_INDEX },                        { TYPE_EDPREF, 0xed65, CPU_RABBIT, 0 }, /* ldp (xx),hl */
387     "ldp",  { OP_HL, OP_HL|OP_INDEX|OP_INDIR },                 { TYPE_EDPREF, 0xed6c, CPU_RABBIT, 0 }, /* ldp hl,(hl) */
388     "ldp",  { OP_HL|OP_INDEX, OP_ADDR },                        { TYPE_EDPREF, 0xed6d, CPU_RABBIT, 0 }, /* ldp hl,(xx) */
389 
390     "llret",{ OP_NONE },                                        { TYPE_NONE, 0xed8b, CPU_RCM4000, 0 },
391     "lret", { OP_NONE },                                        { TYPE_NONE, 0xed45, CPU_RABBIT, 0 },
392 
393     "lsddr",{ OP_NONE },                                        { TYPE_NONE, 0xedd8, CPU_RCM3000 | CPU_RCM4000, F_IO },
394     "lsidr",{ OP_NONE },                                        { TYPE_NONE, 0xedd0, CPU_RCM3000 | CPU_RCM4000, F_IO },
395     "lsir", { OP_NONE },                                        { TYPE_NONE, 0xedf0, CPU_RCM3000 | CPU_RCM4000, F_IO },
396     "lsdr", { OP_NONE },                                        { TYPE_NONE, 0xedf8, CPU_RCM3000 | CPU_RCM4000, F_IO },
397 
398 
399     "mul",  { OP_NONE },                                        { TYPE_NONE, 0xf7, CPU_RABBIT, 0 }, /* mul (hl:bc=bc*de) */
400 
401     "mult", { OP_ARITH16 },                                     { TYPE_ARITH16, 0xed4c, CPU_Z180|CPU_EZ80,0 }, /* mult bc/de/hl/sp */
402     "mulu", { OP_NONE },                                        { TYPE_NONE, 0xa7, CPU_RCM4000, 0 }, /* mulu (hl:bc=bc*de) */
403 
404     "neg",  { OP_NONE, },                                       { TYPE_NONE, 0xed44, CPU_ZILOG|CPU_RABBIT, F_ALTD },
405     "neg",  { OP_HL|OP_RALT, },                                 { TYPE_NONE, 0x44, CPU_RCM4000, F_ALTD },
406     "neg",  { OP_JKHL },                                        { TYPE_NONE, 0xfd4d, CPU_RCM4000, 0 },
407     "neg",  { OP_BCDE },                                        { TYPE_NONE, 0xdd4d, CPU_RCM4000, 0 },
408 
409     "nop",  { OP_NONE, },                                       { TYPE_NONE, 0x00, CPU_ALL, 0 },
410 
411     "or",   { OP_REG8 | OP_INDEX },                             { TYPE_ARITH8, 0xb0, CPU_ALL, F_ALL,0, 0, RCM_EMU_INCREMENT },
412     "or",   { OP_REG8 | OP_INDEX },                             { TYPE_ARITH8, 0x7fb0, CPU_RCM4000, F_ALL },
413     "or",   { OP_A|OP_RALT, OP_REG8 | OP_INDEX },               { TYPE_ARITH8, 0xb0, CPU_ALL, F_ALL,0, 0, RCM_EMU_INCREMENT },
414     "or",   { OP_A|OP_RALT, OP_REG8 | OP_INDEX },               { TYPE_ARITH8, 0x7fb0, CPU_RCM4000, F_ALL },
415     "or",   { OP_A|OP_RALT, OP_ABS },                           { TYPE_NONE,  0xf6, CPU_ALL, F_ALTD },
416     "or",   { OP_ABS },                                         { TYPE_NONE,  0xf6, CPU_ALL, F_ALTD },
417     "or",   { OP_HL|OP_INDEX|OP_RALT, OP_DE },                  { TYPE_NONE, 0xEC, CPU_RABBIT, F_ALTD }, /* or hl/ix/iy,de */
418     "or",   { OP_JKHL|OP_RALT, OP_BCDE },                       { TYPE_NONE, 0xedf6, CPU_RCM4000, F_ALTD },
419 
420     "otdm", { OP_NONE },                                        { TYPE_NONE, 0xed8b, CPU_Z180|CPU_EZ80, 0 },
421     "otdmr",{ OP_NONE },                                        { TYPE_NONE, 0xed9b, CPU_Z180|CPU_EZ80, 0 },
422     "otdr", { OP_NONE, },                                       { TYPE_NONE, 0xedbb, CPU_ZILOG, 0 },
423 
424     "otim", { OP_NONE },                                        { TYPE_NONE, 0xed83, CPU_Z180, 0 },
425     "otimr",{ OP_NONE },                                        { TYPE_NONE, 0xed93, CPU_Z180, 0 },
426 
427     "otir", { OP_NONE, },                                       { TYPE_NONE, 0xedb3, CPU_ZILOG, 0 },
428 
429     "out",  { OP_PORT, OP_REG8},                                { TYPE_MISC8, 0xed41, CPU_ZILOG, 0 },
430     "out",  { OP_PORT       },                                  { TYPE_NONE, 0xed71, CPU_ZILOG, 0 }, /* Undoc out(c) */
431     "out",  { OP_PORT, OP_F },                                  { TYPE_NONE, 0xed71, CPU_ZILOG, 0 }, /* Undoc out (c),f */
432     "out",  { OP_PORT, OP_NUMBER },                             { TYPE_OUT_C_0, 0xed71, CPU_ZILOG, 0 }, /* Undoc out (c),0 */
433     "out",  { OP_ADDR8, OP_A },                                 { TYPE_NONE, 0xD3, CPU_8080|CPU_ZILOG, 0 },   /* out (xx),a */
434     "out0", { OP_ADDR8, OP_REG8 },                              { TYPE_MISC8, 0xed01, CPU_Z180|CPU_EZ80, 0 }, /* out0 (xx),r */
435 
436 
437 
438     "outd", { OP_NONE, },                                       { TYPE_NONE, 0xedab, CPU_ZILOG, 0 },
439     "outi", { OP_NONE, },                                       { TYPE_NONE, 0xeda3, CPU_ZILOG, 0 },
440 
441     "pop",  { OP_PUSHABLE|OP_INDEX|OP_RALT },                   { TYPE_ARITH16, 0xc1, CPU_ALL, F_ALTD },
442     "pop",  { OP_IP },                                          { TYPE_NONE, 0xed7e, CPU_RABBIT, 0 } ,
443     "pop",  { OP_BCDE|OP_RALT },                                { TYPE_NONE, 0xddf1, CPU_RCM4000, F_ALTD },
444     "pop",  { OP_JKHL|OP_RALT },                                { TYPE_NONE, 0xfdf1, CPU_RCM4000, F_ALTD },
445     "pop",  { OP_SU },                                          { TYPE_NONE, 0xed6f, CPU_RCM4000, 0 }, /* pop su */
446     "pop",  { OP_IDX32 },                                       { TYPE_IDX32, 0xedc1, CPU_RCM4000 , 0 },
447 
448     "push", { OP_PUSHABLE|OP_INDEX|OP_RALT },                   { TYPE_ARITH16, 0xc5, CPU_ALL, F_ALTD },
449     "push", { OP_IP },                                          { TYPE_NONE, 0xed76, CPU_RABBIT, 0 } ,
450     "push", { OP_BCDE|OP_RALT },                                { TYPE_NONE, 0xddf5, CPU_RCM4000, F_ALTD },
451     "push", { OP_JKHL|OP_RALT },                                { TYPE_NONE, 0xfdf5, CPU_RCM4000, F_ALTD },
452     "push", { OP_IDX32 },                                       { TYPE_IDX32, 0xedc5, CPU_RCM4000 , 0 },
453     "push", { OP_SU },                                          { TYPE_NONE, 0xed66, CPU_RCM4000, 0 }, /* push su */
454     "push", { OP_ABS16 },                                       { TYPE_NONE, 0xeda5, CPU_RCM4000, 0 },  /* push xx */
455 
456     "rdmode", { OP_NONE },                                      { TYPE_NONE, 0xed7f, CPU_RCM3000|CPU_RCM4000, 0 },
457 
458     "res",  { OP_NUMBER, OP_REG8|OP_INDEX|OP_RALT},             { TYPE_BIT, 0xCB80, CPU_NOT8080, F_ALL|F_ALTDWHL },
459 
460     "ret",  { OP_NONE, },                                       { TYPE_NONE, 0xc9,   CPU_ALL, 0 },
461     "ret",  { OP_FLAGS },                                       { TYPE_FLAGS, 0xc0, CPU_ALL, 0 },
462     "retn", { OP_NONE, },                                       { TYPE_NONE, 0xed45, CPU_ZILOG, 0 },
463     "reti", { OP_NONE, },                                       { TYPE_NONE, 0xed4d, CPU_ZILOG|CPU_RABBIT|CPU_GB80, 0, 0, 0, 0, RCM_EMU_INCREMENT },
464     "reti", { OP_NONE, },                                       { TYPE_NONE, 0xd9,   CPU_GB80, 0 },
465 
466     "rl",   { OP_REG8|OP_RALT },                                { TYPE_ARITH8, 0xcb10, CPU_NOT8080, F_ALL },
467     "rl",   { OP_BC|OP_RALT },                                  { TYPE_NONE, 0x62, CPU_RCM4000, F_ALTD },
468     "rl",   { OP_DE|OP_RALT },                                  { TYPE_NONE, 0xf3, CPU_RABBIT, F_ALTD },
469     "rl",   { OP_HL|OP_RALT },                                  { TYPE_NONE, 0x42, CPU_RCM4000, F_ALTD },
470     "rla",  { OP_NONE, },                                       { TYPE_NONE, 0x17, CPU_ALL, F_ALTD },
471 
472     "rlb",  { OP_A, OP_BCDE },                                  { TYPE_NONE, 0xdd6f, CPU_RCM4000, 0 },
473     "rlb",  { OP_A, OP_JKHL },                                  { TYPE_NONE, 0xfd6f, CPU_RCM4000, 0 },
474 
475     "rlc",  { OP_REG8|OP_RALT },                                { TYPE_ARITH8, 0xcb00, CPU_NOT8080, F_ALTD },
476     "rlc",  { OP_DE|OP_RALT },                                  { TYPE_NONE, 0x50, CPU_RCM4000, F_ALTD },
477     "rlc",  { OP_BC|OP_RALT },                                  { TYPE_NONE, 0x60, CPU_RCM4000, F_ALTD },
478     "rlca", { OP_NONE, },                                       { TYPE_NONE, 0x07,   CPU_ALL, F_ALTD },
479 
480     "rld",  { OP_NONE, },                                       { TYPE_NONE, 0xed6f, CPU_ZILOG|CPU_RABBIT, 0, RCM_EMU_LIBRARY, RCM_EMU_LIBRARY, RCM_EMU_LIBRARY, 0 },
481 
482     "rr",   { OP_REG8|OP_RALT },                                { TYPE_ARITH8, 0xcb18, CPU_NOT8080, F_ALL },
483     "rr",   { OP_DE|OP_RALT },                                  { TYPE_NONE, 0xfb, CPU_RABBIT, F_ALTD },
484     "rr",   { OP_BC|OP_RALT },                                  { TYPE_NONE, 0x63, CPU_RCM4000, F_ALTD },
485     "rr",   { OP_HL|OP_INDEX|OP_RALT},                          { TYPE_NONE, 0xfc, CPU_RABBIT, F_ALTD },
486 
487     "rra",  { OP_NONE, },                                       { TYPE_NONE, 0x1f, CPU_ALL, F_ALTD },
488 
489     "rrb",  { OP_A, OP_BCDE },                                  { TYPE_NONE, 0xdd7f, CPU_RCM4000, 0 },
490     "rrb",  { OP_A, OP_JKHL },                                  { TYPE_NONE, 0xfd7f, CPU_RCM4000, 0 },
491 
492 
493     "rrc",  { OP_REG8|OP_RALT, },                               { TYPE_ARITH8, 0xcb08, CPU_NOT8080, F_ALTD },
494     "rrc",  { OP_BC|OP_RALT, },                                 { TYPE_NONE, 0x61, CPU_RCM4000, F_ALTD },
495     "rrc",  { OP_DE|OP_RALT, },                                 { TYPE_NONE, 0x51, CPU_RCM4000, F_ALTD },
496     "rrca", { OP_NONE, },                                       { TYPE_NONE, 0x0f, CPU_ALL, F_ALTD },
497 
498     "rrd",  { OP_NONE, },                                       { TYPE_NONE, 0xed67, CPU_ZILOG|CPU_RABBIT, 0, RCM_EMU_LIBRARY, RCM_EMU_LIBRARY, RCM_EMU_LIBRARY, 0 },
499     "rst",  { OP_NUMBER },                                      { TYPE_RST,  0xc7, CPU_ALL, 0 },  /* RCM doesn't support 0, 8, 30 */
500 
501     "sbc",  { OP_REG8 | OP_INDEX, },                            { TYPE_ARITH8, 0x98, CPU_ALL, F_ALL, 0, 0, RCM_EMU_INCREMENT },
502     "sbc",  { OP_REG8 | OP_INDEX, },                            { TYPE_ARITH8, 0x7f98, CPU_RCM4000, F_ALL },
503     "sbc",  { OP_A|OP_RALT, OP_REG8 | OP_INDEX },               { TYPE_ARITH8, 0x98, CPU_ALL, F_ALTD, 0, 0, RCM_EMU_INCREMENT },
504     "sbc",  { OP_A|OP_RALT, OP_REG8 | OP_INDEX },               { TYPE_ARITH8, 0x7f98, CPU_RCM4000, F_ALTD },
505     "sbc",  { OP_A|OP_RALT, OP_ABS },                           { TYPE_NONE, 0xde, CPU_ALL , F_ALTD},
506     "sbc",  { OP_ABS },                                         { TYPE_NONE, 0xde, CPU_ALL, F_ALTD },
507     "sbc",  { OP_HL|OP_INDEX|OP_RALT, OP_ARITH16 },             { TYPE_ARITH16, 0xed42, CPU_ZILOG|CPU_RABBIT, F_ALTD },
508 
509     "sbox", { OP_A },                                           { TYPE_NONE, 0xed02, CPU_RCM4000, F_ALTD },
510 
511 
512     "scf",  { OP_NONE, },                                       { TYPE_NONE, 0x37, CPU_ALL, F_ALTD },
513 
514 
515     "set",  { OP_NUMBER, OP_REG8|OP_INDEX|OP_RALT},             { TYPE_BIT, 0xCBC0, CPU_NOT8080, F_ALL|F_ALTDWHL },
516 
517     "setsysp", { OP_ABS16 },                                    { TYPE_NONE, 0xedb1, CPU_RCM4000, 0 },
518     "setusr",  { OP_NONE },                                     { TYPE_NONE, 0xed6f, CPU_RCM3000|CPU_RCM4000 },
519     "setusrp", { OP_ABS16 },                                    { TYPE_NONE, 0xedbf, CPU_RCM4000, 0 },
520 
521     "sla",  { OP_REG8 },                                        { TYPE_ARITH8, 0xcb20, CPU_NOT8080, F_ALTD },
522     "sll",  { OP_REG8, },                                       { TYPE_ARITH8, 0xcb30, CPU_Z80, 0 }, /* Undoc */
523 
524     "slp",  { OP_NONE },                                        { TYPE_NONE, 0xed76, CPU_Z180|CPU_EZ80 },
525 
526     "sra",  { OP_REG8|OP_RALT, },                               { TYPE_ARITH8, 0xcb28, CPU_NOT8080, F_ALTD },
527 
528 
529     "srl",  { OP_REG8|OP_RALT, },                               { TYPE_ARITH8, 0xcb38, CPU_ZILOG|CPU_RABBIT, F_ALTD },
530 
531     "stop", { OP_NONE },                                        { TYPE_NONE, 0x10, CPU_GB80, 0 },
532 
533     "sub",  { OP_HL|OP_RALT, OP_DE },                           { TYPE_NONE, 0x55, CPU_RCM4000, F_ALTD },
534     "sub",  { OP_HL|OP_RALT, OP_JK },                           { TYPE_NONE, 0x45, CPU_RCM4000, F_ALTD },
535     "sub",  { OP_JKHL|OP_RALT, OP_BCDE },                       { TYPE_NONE, 0xedd6, CPU_RCM4000, F_ALTD},
536 
537 
538     "sub",  { OP_REG8|OP_INDEX },                               { TYPE_ARITH8, 0x90, CPU_ALL, F_ALTD, 0, 0, RCM_EMU_INCREMENT },
539     "sub",  { OP_REG8|OP_INDEX },                               { TYPE_ARITH8, 0x7f90, CPU_RCM4000, F_ALTD },
540     "sub",  { OP_A|OP_RALT, OP_REG8|OP_INDEX },                 { TYPE_ARITH8, 0x90, CPU_ALL,F_ALTD,0,0,RCM_EMU_INCREMENT },
541     "sub",  { OP_A|OP_RALT, OP_REG8|OP_INDEX },                 { TYPE_ARITH8, 0x7f90, CPU_RCM4000,F_ALTD },
542     "sub",  { OP_A|OP_RALT, OP_ABS },                           { TYPE_NONE, 0xd6, CPU_ALL, F_ALTD },
543     "sub",  { OP_ABS },                                         { TYPE_NONE, 0xd6, CPU_ALL, F_ALTD },
544 
545     "sures",   { OP_NONE },                                     { TYPE_NONE, 0xed7d, CPU_RCM3000|CPU_RCM4000, 0 },
546 
547     "swap",  { OP_REG8 },                                       { TYPE_ARITH8, 0xcb30, CPU_GB80, 0 },
548 
549     "syscall", { OP_NONE },                                     { TYPE_NONE, 0xed65, CPU_RCM3000|CPU_RCM4000, 0 },
550     "sysret",  { OP_NONE },                                     { TYPE_NONE, 0xed83, CPU_RCM4000, 0 },
551 
552 
553     "test", { OP_HL|OP_INDEX },                                 { TYPE_NONE, 0x4c, CPU_RCM4000, F_ALTD },
554     "test", { OP_BC },                                          { TYPE_NONE, 0xed4c, CPU_RCM4000, F_ALTD },
555     "test", { OP_BCDE },                                        { TYPE_NONE, 0xdd5c, CPU_RCM4000, F_ALTD },
556     "test", { OP_JKHL },                                        { TYPE_NONE, 0xfd5c, CPU_RCM4000, F_ALTD },
557 
558     "tst",  { OP_REG8 },                                        { TYPE_MISC8, 0xed04, CPU_Z180|CPU_EZ80, 0 },  /* Z180 TST r */
559     "tst",  { OP_A, OP_REG8 },                                  { TYPE_MISC8, 0xed04, CPU_Z180|CPU_EZ80, 0 },  /* Z180 TST a,r */
560     "tst",  { OP_A, OP_ABS },                                   { TYPE_NONE, 0xed64, CPU_Z180|CPU_EZ80, 0 },  /* Z180 TST a,xx */
561     "tst",  { OP_ABS },                                         { TYPE_NONE, 0xed64, CPU_Z180|CPU_EZ80, 0 },  /* Z180 TST xx */
562     "tstio",{ OP_ABS },                                         { TYPE_NONE, 0xed74, CPU_Z180|CPU_EZ80, 0 },  /* Z180 TSTIO xx */
563 
564     "uma",  { OP_NONE },                                        { TYPE_NONE, 0xedc0, CPU_RCM3000|CPU_RCM4000, 0 },
565     "ums",  { OP_NONE },                                        { TYPE_NONE, 0xedc8, CPU_RCM3000|CPU_RCM4000, 0 },
566 
567     "xor",  { OP_JKHL|OP_RALT, OP_BCDE },                       { TYPE_NONE, 0xedee, CPU_RCM4000, F_ALTD },
568     "xor",  { OP_REG8|OP_INDEX },                               { TYPE_ARITH8, 0xa8, CPU_ALL, F_ALTD, 0, 0, RCM_EMU_INCREMENT },
569     "xor",  { OP_REG8|OP_INDEX },                               { TYPE_ARITH8, 0x7fa8, CPU_RCM4000, F_ALTD },
570     "xor",  { OP_A|OP_RALT, OP_REG8|OP_INDEX },                 { TYPE_ARITH8, 0xa8, CPU_ALL, F_ALTD, 0, 0, RCM_EMU_INCREMENT },
571     "xor",  { OP_A|OP_RALT, OP_REG8|OP_INDEX },                 { TYPE_ARITH8, 0x7fa8, CPU_RCM4000, F_ALTD },
572     "xor",  { OP_A|OP_RALT, OP_ABS },                           { TYPE_NONE, 0xEE, CPU_ALL, F_ALTD },
573     "xor",  { OP_ABS },                                         { TYPE_NONE, 0xEE, CPU_ALL, F_ALTD },
574     "xor",  { OP_HL|OP_RALT, OP_DE },                           { TYPE_NONE, 0x54, CPU_RCM4000, F_ALTD }, /* xor hl,de */
575 };
576 
577 int mnemonic_cnt=sizeof(mnemonics)/sizeof(mnemonics[0]);
578 
579 char *cpu_copyright="vasm 8080/gbz80/z80/z180/rcmX000 cpu backend 0.2h (c) 2007,2009 Dominic Morris";
580 char *cpuname = "z80";
581 int bitsperbyte = 8;
582 int bytespertaddr = 2;
583 
584 /* Configuration options */
585 static int z80asm_compat = 0;
586 static int cpu_type = CPU_Z80;
587 static int swapixiy = 0;
588 static int rcmemu = 0;
589 
590 /* Variables set by special parsing */
591 static int altd_enabled = 0;
592 static int ioi_enabled = 0;
593 static int ioe_enabled = 0;
594 static int modifier;  /* set by find_base() */
595 
596 
597 struct {
598     char         *name;
599     int           op;
600     int           reg;
601     int           cpu;
602 } registers[] = {
603     { "bc'",  OP_BC|OP_PUSHABLE|OP_STD16BIT|OP_ALT, REG_BC | REG_ALT, CPU_RABBIT },
604     { "de'",  OP_DE|OP_PUSHABLE|OP_STD16BIT|OP_ALT, REG_DE | REG_ALT, CPU_RABBIT },
605     { "hl'",  OP_HL|OP_PUSHABLE|OP_STD16BIT|OP_ALT, REG_HL | REG_ALT, CPU_RABBIT },
606     { "af'",  OP_AF|OP_PUSHABLE|OP_ALT, REG_AF | REG_ALT, CPU_RABBIT },
607 
608     { "bc",   OP_BC|OP_STD16BIT|OP_ARITH16|OP_PUSHABLE, REG_BC, CPU_ALL },
609     { "hl",   OP_HL|OP_STD16BIT|OP_ARITH16|OP_PUSHABLE, REG_HL, CPU_ALL },
610     { "de",   OP_DE|OP_STD16BIT|OP_ARITH16|OP_PUSHABLE, REG_DE, CPU_ALL },
611     { "sp",   OP_SP|OP_ARITH16, REG_SP, CPU_ALL },
612     { "af",   OP_AF|OP_PUSHABLE, REG_AF, CPU_ALL },
613 
614     { "ixl",  OP_REG8|OP_INDEX, REG_L | REG_IX, CPU_ZILOG },
615     { "ixh",  OP_REG8|OP_INDEX, REG_H | REG_IX, CPU_ZILOG },
616     { "iyl",  OP_REG8|OP_INDEX, REG_L | REG_IY, CPU_ZILOG },
617     { "iyh",  OP_REG8|OP_INDEX, REG_H | REG_IY, CPU_ZILOG },
618 
619     { "ix",   OP_HL|OP_ARITH16|OP_PUSHABLE|OP_INDEX, REG_HL | REG_IX, CPU_NOT8080 },
620     { "iy",   OP_HL|OP_ARITH16|OP_PUSHABLE|OP_INDEX, REG_HL | REG_IY, CPU_NOT8080 },
621     { "ip",   OP_IP, REG_IP, CPU_RABBIT }, /* RCM */
622     { "a'",   OP_A|OP_ALT,  REG_A|REG_ALT, CPU_RABBIT },
623     { "b'",   OP_REG8|OP_ALT,  REG_B|REG_ALT, CPU_RABBIT },
624     { "c'",   OP_REG8|OP_ALT,  REG_C|REG_ALT, CPU_RABBIT },
625     { "d'",   OP_REG8|OP_ALT,  REG_D|REG_ALT, CPU_RABBIT },
626     { "e'",   OP_REG8|OP_ALT,  REG_E|REG_ALT, CPU_RABBIT },
627     { "h'",   OP_REG8|OP_ALT,  REG_H|REG_ALT, CPU_RABBIT },
628     { "l'",   OP_REG8|OP_ALT,  REG_L|REG_ALT, CPU_RABBIT },
629     { "a",    OP_A,  REG_A, CPU_ALL },
630     { "b",    OP_REG8,  REG_B, CPU_ALL },
631     { "c",    OP_REG8,  REG_C, CPU_ALL },
632     { "d",    OP_REG8,  REG_D, CPU_ALL },
633     { "e",    OP_REG8,  REG_E, CPU_ALL },
634     { "h",    OP_REG8,  REG_H, CPU_ALL },
635     { "l",    OP_REG8,  REG_L, CPU_ALL },
636     { "r",    OP_R, REG_R, CPU_ZILOG },
637     { "eir",  OP_R, REG_R, CPU_RABBIT },  /* RCM alias */
638     { "i",    OP_I, REG_I, CPU_ZILOG },
639     { "iir",  OP_I, REG_I, CPU_RABBIT },  /* RCM alias */
640     { "f",    OP_F, REG_F, CPU_Z80 },
641     { "xpc",  OP_XPC, REG_XPC, CPU_RABBIT }, /* RCM */
642 
643     /* RCM4000 extra registers + pw, px, py, pz */
644     { "pw'",   OP_IDX32|OP_ALT, REG_PW|REG_ALT, CPU_RCM4000 },
645     { "px'",   OP_IDX32|OP_ALT, REG_PX|REG_ALT, CPU_RCM4000 },
646     { "py'",   OP_IDX32|OP_ALT, REG_PY|REG_ALT, CPU_RCM4000 },
647     { "pz'",   OP_IDX32|OP_ALT, REG_PZ|REG_ALT, CPU_RCM4000 },
648     { "pw",   OP_IDX32, REG_PW, CPU_RCM4000 },
649     { "px",   OP_IDX32, REG_PX, CPU_RCM4000 },
650     { "py",   OP_IDX32, REG_PY, CPU_RCM4000 },
651     { "pz",   OP_IDX32, REG_PZ, CPU_RCM4000 },
652     { "su",   OP_SU, REG_SU, CPU_RCM4000 },
653     { "htr",  OP_HTR, REG_HTR, CPU_RCM4000 },
654     { "jkhl'", OP_JKHL|OP_ALT, REG_JKHL|REG_ALT, CPU_RCM4000 },
655     { "jkhl", OP_JKHL, REG_JKHL, CPU_RCM4000 },
656     { "bcde'", OP_BCDE|OP_ALT, REG_BCDE|REG_ALT, CPU_RCM4000 },
657     { "bcde", OP_BCDE, REG_BCDE, CPU_RCM4000 },
658     { "jk'",   OP_JK|OP_ALT,   REG_JK|REG_ALT,   CPU_RCM4000 },
659     { "jk",   OP_JK,   REG_JK,   CPU_RCM4000 },
660 };
661 
662 struct {
663     char          *name;
664     int            op;
665     int            flags;
666     int            cpu;
667 } flags[] = {
668     { "z",   OP_FLAGS, FLAGS_Z,  CPU_ALL },
669     { "nz",  OP_FLAGS, FLAGS_NZ, CPU_ALL },
670     { "c",   OP_FLAGS, FLAGS_C,  CPU_ALL },
671     { "nc",  OP_FLAGS, FLAGS_NC, CPU_ALL },
672     { "pe",  OP_FLAGS, FLAGS_PE, CPU_ALL },  /* Not for jr, emu for RCM */
673     { "po",  OP_FLAGS, FLAGS_PO, CPU_ALL },  /* Not for jr, emu for RCM */
674     { "p",   OP_FLAGS, FLAGS_P,  CPU_ALL },   /* Not for jr, emu for RCM */
675     { "m",   OP_FLAGS, FLAGS_M,  CPU_ALL },   /* Not for jr, emu for RCM */
676     { "lz",  OP_FLAGS, FLAGS_PO, CPU_RABBIT },  /* RCM alias */
677     { "lo",  OP_FLAGS, FLAGS_PE, CPU_RABBIT },  /* RCM alias */
678     { "gtu", OP_FLAGS_RCM, FLAGS_GTU, CPU_RCM4000 }, /* RCM4000 */
679     { "gt",  OP_FLAGS_RCM, FLAGS_GT,  CPU_RCM4000 },  /* RCM4000 */
680     { "lt",  OP_FLAGS_RCM, FLAGS_LT,  CPU_RCM4000 },  /* RCM4000 */
681     { "v",   OP_FLAGS_RCM, FLAGS_V,   CPU_RCM4000 },   /* RCM4000 */
682 };
683 
684 
685 
686 
ext_unary_eval(int type,taddr val,taddr * result,int cnst)687 int ext_unary_eval(int type,taddr val,taddr *result,int cnst)
688 {
689     switch (type) {
690     case LOBYTE:
691         *result = cnst ? (val & 0xff) : val;
692         return 1;
693     case HIBYTE:
694         *result = cnst ? ((val >> 8) & 0xff) : val;
695         return 1;
696     default:
697         break;
698     }
699     return 0;  /* unknown type */
700 }
701 
ext_find_base(symbol ** base,expr * p,section * sec,taddr pc)702 int ext_find_base(symbol **base,expr *p,section *sec,taddr pc)
703 {
704     if ( p->type==DIV || p->type ==MOD) {
705         if (p->right->type == NUM && p->right->c.val == 256 ) {
706            p->type = p->type == DIV ? HIBYTE : LOBYTE;
707         }
708     } else if ( p->type == BAND && p->right->type == NUM && p->right->c.val == 255 ) {
709         p->type = LOBYTE;
710     }
711     if (p->type==LOBYTE || p->type==HIBYTE) {
712         modifier = p->type;
713         return find_base(p->left,base,sec,pc);
714     }
715     return BASE_ILLEGAL;
716 }
717 
718 
get_flags_info(char ** text,int len,int * flags_ptr,int * op)719 static int get_flags_info(char **text, int len, int *flags_ptr, int *op)
720 {
721     int     i;
722 
723     for ( i = 0; i < sizeof(flags) / sizeof(flags[0]); i++ ) {
724         if ( len != strlen(flags[i].name) ) {
725             continue;
726         }
727         if ( strnicmp(*text, flags[i].name,len) == 0 ) {
728 #if 0
729             if ( (cpu_type & flags[i].cpu) == 0 ) {
730                 continue;
731             }
732 #endif
733             *text += len;
734             *op= flags[i].op;
735             *flags_ptr = flags[i].flags;
736             return 0;
737         }
738     }
739     return -1;
740 }
741 
742 
743 
get_register_info(char ** text,int len,int * reg,int * op)744 static int get_register_info(char **text, int len, int *reg, int *op)
745 {
746     int     i;
747 
748     for ( i = 0; i < sizeof(registers) / sizeof(registers[0]); i++ ) {
749         if ( len != strlen(registers[i].name) ) {
750             continue;
751         }
752         if ( strnicmp(*text, registers[i].name,len) == 0 ) {
753 #if 0
754             if ( (cpu_type & registers[i].cpu) == 0 ) {
755                 continue;
756             }
757 #endif
758             *text += len;
759             *reg = registers[i].reg;
760             *op = registers[i].op;
761             return 0;
762         }
763     }
764     return -1;
765 }
766 
767 
768 #define BASIC_TYPE(x) ((x) & OP_MASK )
769 #define CHECK_INDEXVALID(ot, r) ( ( (ot) & OP_INDEX ) == OP_INDEX || ( ( ((r) & (REG_IX|REG_IY)) == 0 ) ) )
770 #define ONLY_MODIFIER(x, nmod) ((((x) & ~OP_MASK) | (nmod)) == (nmod))
771 #define PERMITTED(c, ot, b ) ( ( (ot) & (b) ) || ( ((ot) & (b)) | ( (c) & (b) ) ) == 0 )
772 #define WANT(c, ot, b ) ( ( (ot) & (b) ) && ( ((c) & (b)) ) ||  ( (ot) & (b) ) == 0 && ( ((c) & (b)) ) == 0 )
773 
774 /* Check whether an alt override is permitted - this is for allowing the first register
775  * operand of rabbit instructions to specify that they want to use altd
776  *
777  * NB: OP_ALT and OP_RALT are mutually exclusive
778  */
alt_override_permitted(int want,int got,int gotreg)779 static int alt_override_permitted(int want, int got, int gotreg)
780 {
781     if ( ( cpu_type & CPU_RABBIT ) ) {
782         if ( ( want & OP_RALT|OP_ALT ) == 0 && ( got & OP_ALT ) ) {
783             /* Not allowed an override or not accepting an alt by default */
784             return 0;
785         }
786         if ( ( want & OP_RALT ) && ( got & OP_ALT) ) {
787             if ( (gotreg & REG_PLAIN) == REG_HLREF && ( want & OP_RALTHL ) == 0 ) {
788                 /* We're not allowed (hl') apart from for bit */
789                 return 0;
790             }
791             /* We wanted an override */
792             return 1;
793         }
794     }
795 
796     if ( ( want & OP_ALT ) && ( got & OP_ALT) == 0 ) {
797         /* We wanted an alt but didn't get one */
798         return 0;
799     }
800 
801     if ( ( got & OP_ALT ) && ( want & OP_ALT ) == 0 ) {
802         /* Not expected an alt by default */
803         return 0;
804     }
805     return 1; /* It is permitted */
806 }
807 
parse_operand(char * p,int len,operand * op,int optype)808 int parse_operand(char *p, int len, operand *op, int optype)
809 {
810     char   *start = p;
811     int     opt = 0;
812     int     regopt = 0;
813     int     second_reg = -1;
814     int     ignore;
815 
816     op->value = NULL;
817     op->reg = 0;
818     op->type = 0;
819     op->flags = 0;
820     op->bit = 0;
821 
822     p = skip(p);
823     /* Here I disable the possiblity to use parentheses around constants
824      * when addressing is not possible. This old behavior created a lot of
825      * inexisting instructions and bugs.
826      */
827     if ( *p == '(' && optype != OP_DATA && check_indir(p,start+len) ) {
828         int   llen;
829         char *end;
830         p++;
831 
832         p = skip(p);
833 
834         /* Search for the first nonmatching character */
835         if ( (end = strpbrk(p, ") +-") ) != NULL ) {
836             llen = end - p;
837         } else {
838             llen = len - (p - start);
839         }
840 
841         /* Search for register */
842         if ( get_register_info(&p, llen, &op->reg, &opt) == 0 ) {
843             char  save;
844             char *save_ptr;
845             int   get_expr = 1;
846             opt |= OP_INDIR;
847             p = skip(p);
848             if ( *p != ')' ) {
849                 if ( *p == '+' ) {
850                     p++;
851                     /* RCM4000 - check for a register here */
852                     if ( (end = strpbrk(p+1, ") \t+-") ) != NULL ) {
853                         llen = end - p;
854                     } else {
855                         llen = len - (p - start);
856                     }
857                     if ( get_register_info(&p, llen, &second_reg, &ignore) == 0 ) {
858                         get_expr = 0;
859                     } else {
860                         p--;
861                     }
862                 }
863 
864                 if ( get_expr ) {
865                     /* We may well have an expression, check for it */
866                     save_ptr = p-1;
867                     save = *save_ptr;
868                     *save_ptr = '(';  /* Create a bracket */
869                     if ( ( op->value = parse_expr(&p) ) != NULL ) {
870                         opt |= OP_OFFSET;
871                     } else {
872                         *save_ptr = save;
873                         return PO_NOMATCH;
874                     }
875                     *save_ptr = save;
876                 }
877             }
878 
879 
880         } else if ( ( op->value = parse_expr(&p) ) != NULL ) {
881             opt = OP_ABS16|OP_INDIR;
882         } else {
883             return PO_NOMATCH;
884         }
885     } else if ( (optype == OP_FLAGS || optype == OP_FLAGS_RCM) &&
886                 get_flags_info(&p, len, &op->flags, &opt ) == 0 ) {
887         /* It's a flag (flag c matches register c */
888     } else if ( get_register_info(&p, len, &op->reg, &opt) == 0 ) {
889         /* It's a register */
890     } else {
891         int   llen;
892         char *end;
893 
894         /* We might have a reg+reg setup */
895         /* Search for the first nonmatching character */
896         if ( (end = strpbrk(p, " \t+-") ) != NULL ) {
897             llen = end - p;
898         } else {
899             llen = len - (p - start);
900         }
901         if ( get_register_info(&p, llen, &op->reg, &opt) == 0 ) {
902             p = skip(p);
903             if ( *p == '+' ) {
904                 p++;
905                 /* RCM4000 - check for a register here */
906                 if ( (end = strpbrk(p+1, ") \t+-") ) != NULL ) {
907                     llen = end - p;
908                 } else {
909                     llen = len - (p - start);
910                 }
911                 if ( get_register_info(&p, llen, &second_reg, &ignore)  ) {
912                     if ( ( op->value = parse_expr(&p) ) != NULL ) {
913                         opt |= OP_OFFSET;
914                     } else {
915                         return PO_NOMATCH;
916                     }
917                 }
918             }
919         } else {
920             if ( z80asm_compat && *p == '#' ) {
921                 p++;  /* Constant identifier - compatibility with z80asm */
922             }
923             if ( ( op->value = parse_expr(&p) ) != NULL ) {
924                 opt = OP_ABS16;
925             } else {
926                 /* It's rubbish and we don't understand it at all */
927                 return PO_NOMATCH;
928             }
929         }
930     }
931 
932     opt |= regopt; /* Setup what we've parsed */
933 
934 
935     if ( optype & OP_ARITH16 ) {
936 
937         if ( (opt & OP_ARITH16) == 0 ||
938              !PERMITTED(opt, optype, OP_INDEX) || !alt_override_permitted(optype,opt,op->reg) ) {
939             goto nomatch;
940         }
941     } else if ( optype & OP_PUSHABLE ) {
942         if ( (opt & OP_PUSHABLE) == 0 ||
943              !PERMITTED(opt, optype, OP_INDEX) || !alt_override_permitted(optype,opt,op->reg) ) {
944             goto nomatch;
945         }
946     } else if ( optype & OP_STD16BIT ) {
947         if ( (opt & OP_STD16BIT) == 0 ||
948              !PERMITTED(opt, optype, OP_INDEX) || !alt_override_permitted(optype,opt,op->reg) ) {
949             goto nomatch;
950         }
951     } else {
952 
953 
954         switch ( BASIC_TYPE(optype) ) {
955         case OP_A:
956         case OP_AF:
957         case OP_BC:
958         case OP_DE:
959         case OP_HL:
960         case OP_SP:
961         case OP_JKHL:
962         case OP_BCDE:
963         case OP_JK:
964         case OP_I:
965         case OP_R:
966         case OP_F:
967         case OP_IP:
968         case OP_XPC:
969         case OP_IDX32:
970         case OP_SU:
971         case OP_HTR:
972             /* Basic type and indirection and index and alt register designation must match */
973             if ( BASIC_TYPE(opt) != BASIC_TYPE(optype) || !PERMITTED(opt, optype, (OP_INDEX)) ||
974                  !WANT(opt,optype,OP_INDIR) || !alt_override_permitted(optype,opt,op->reg) ) {
975                 goto nomatch;
976             }
977             if ( ( optype & OP_OFFSA ) ) {
978                 if ( second_reg != REG_A ) {
979                     goto nomatch;
980                 }
981             } else if ( ( optype & OP_OFFSHL ) ) {
982                 if ( second_reg != REG_HL ) {
983                     goto nomatch;
984                 }
985             } else if ( ( optype & OP_OFFSBC ) ) {
986                 if ( second_reg != REG_BC ) {
987                     goto nomatch;
988                 }
989             } else if ( ( optype & OP_OFFSDE ) ) {
990                 if ( second_reg != REG_DE ) {
991                     goto nomatch;
992                 }
993             } else if ( ( optype & OP_OFFSIX ) ) {
994                 if ( second_reg != (REG_HL|REG_IX) ) {
995                     goto nomatch;
996                 }
997             } else if ( ( optype & OP_OFFSIY ) ) {
998                 if ( second_reg != (REG_HL|REG_IY) ) {
999                     goto nomatch;
1000                 }
1001             } else if ( (optype & OP_OFFSET)  ) {
1002                 if ( op->value == NULL ) {
1003                     char *expr_s = "0";
1004                     op->value = parse_expr(&expr_s);
1005                     opt |= OP_OFFSET;
1006                 }
1007             } else if ( (( optype & OP_OFFSET ) == 0 && op->value) || second_reg != -1 ) {
1008                 goto nomatch;
1009             }
1010             break;
1011         case OP_REG8:
1012             /* Normalise (hl) or (ix+d) to the correct register type */
1013             if ( ( opt & OP_INDIR ) && (op->reg & REG_PLAIN) == REG_HL ) {
1014                 opt = ( opt & (OP_OFFSET|OP_INDEX|OP_ALT) ) | OP_REG8;
1015                 op->reg = ( op->reg & (REG_IX|REG_IY|REG_ALT) ) | REG_HLREF;
1016                 if ( op->reg & ( REG_IX|REG_IY) ) {
1017                     op->reg |= REG_INDEX;
1018                     /* If it's an index, set an expression on it if there's not one already*/
1019                     if ( op->value == NULL ) {
1020                         char *expr_s = "0";
1021                         op->value = parse_expr(&expr_s);
1022                         opt |= OP_OFFSET;
1023                     }
1024                 } else if ( op->value ) {
1025                     goto nomatch;
1026                 }
1027             } else if ( op->value ) {
1028                 goto nomatch;
1029             }
1030             /* If it's OP_A then we're ok */
1031             if ( opt == OP_A ) {
1032                 opt = OP_REG8;
1033             }
1034             /* Final check - check indices */
1035             if ( !CHECK_INDEXVALID(optype, opt) || BASIC_TYPE(opt) != BASIC_TYPE(optype) || !alt_override_permitted(optype,opt,op->reg) || second_reg != -1  ) {
1036                 goto nomatch;
1037             }
1038             break;
1039         case OP_ADDR8:
1040             if ( opt != (OP_ABS16|OP_INDIR) || op->value == NULL ) {
1041                 goto nomatch;
1042             }
1043             opt = OP_ABS;
1044             break;
1045         case OP_ADDR:
1046             if ( opt != (OP_ABS16|OP_INDIR) || op->value == NULL ) {
1047                 goto nomatch;
1048             }
1049             break;
1050         case OP_ADDR24:
1051             if ( opt != (OP_ABS16|OP_INDIR) || op->value == NULL ) {
1052                 goto nomatch;
1053             }
1054             opt = OP_ABS24;
1055             break;
1056         case OP_ADDR32:
1057             if ( opt != (OP_ABS32|OP_INDIR) || op->value == NULL ) {
1058                 goto nomatch;
1059             }
1060             opt = OP_ABS32;
1061             break;
1062         case OP_NUMBER:
1063         case OP_ABS:
1064         case OP_ABS16:
1065         case OP_ABS24:
1066         case OP_ABS32:
1067             if ( !PERMITTED(opt, optype, OP_INDIR) || op->value == NULL ) {
1068                 goto nomatch;
1069             }
1070         case OP_DATA:
1071             opt = optype;
1072             break;
1073         case OP_PORT:
1074             if ( opt != (OP_INDIR|OP_REG8) || op->reg != REG_C || second_reg != -1 ) {
1075                 goto nomatch;
1076             }
1077             break;
1078         case OP_FLAGS:
1079         case OP_FLAGS_RCM:
1080             if ( opt != optype ) {
1081                 goto nomatch;
1082             }
1083             break;
1084         case OP_IX:
1085             if ( BASIC_TYPE(opt) != OP_HL ||  !WANT(opt, optype, OP_INDIR) || op->reg != (REG_HL|REG_IX) || second_reg != -1 ) {
1086                 goto nomatch;
1087             }
1088             opt = optype;
1089             if ( (optype & OP_OFFSET) ) {
1090                 op->reg = REG_HLREF|REG_IX;
1091                 if ( op->value == NULL ) {
1092                     char *expr_s = "0";
1093                     op->value = parse_expr(&expr_s);
1094                     opt |= OP_OFFSET;
1095                 }
1096             }
1097             break;
1098         case OP_IY:
1099             if ( BASIC_TYPE(opt) != OP_HL ||  !WANT(opt, optype, OP_INDIR) || op->reg != (REG_HL|REG_IY) || second_reg != -1 ) {
1100                 goto nomatch;
1101             }
1102             opt = optype;
1103             if ( (optype & OP_OFFSET) ) {
1104                 op->reg = REG_HLREF|REG_IY;
1105                 if ( op->value == NULL ) {
1106                     char *expr_s = "0";
1107                     op->value = parse_expr(&expr_s);
1108                     opt |= OP_OFFSET;
1109                 }
1110             }
1111             break;
1112         case OP_NONE:
1113             if ( opt != 0 ) {
1114                 goto nomatch;
1115             }
1116             break;
1117         default:
1118             cpu_error(20, optype, opt);
1119             goto nomatch;
1120         }
1121     }
1122 
1123     op->type = opt;
1124 
1125     return PO_MATCH;
1126 nomatch:
1127     if ( op->value ) {
1128         free_expr(op->value);
1129     }
1130     return PO_NOMATCH;
1131 
1132 }
1133 
1134 
1135 
init_instruction_ext(instruction_ext * ext)1136 void init_instruction_ext(instruction_ext *ext)
1137 {
1138     ext->altd = altd_enabled;
1139     ext->ioi = ioi_enabled;
1140     ext->ioe = ioe_enabled;
1141 }
1142 
parse_rcm_identifier(char ** sptr)1143 static int parse_rcm_identifier(char **sptr)
1144 {
1145     char *s = *sptr;
1146     char *name = s;
1147 
1148     while (ISIDCHAR(*s))
1149         s++;
1150     if ( s-name == 4 && strnicmp(name, "altd", 4)  == 0 ) {
1151         altd_enabled = 1;
1152     } else if ( s-name == 3 && strnicmp(name,"ioi",3) == 0 ) {
1153         ioi_enabled = 1;
1154     } else if ( s-name == 3 && strnicmp(name,"ioe",3) == 0 ) {
1155         ioe_enabled = 1;
1156     } else {
1157         return -1;
1158     }
1159     *sptr = s;
1160     return 0;
1161 }
1162 
1163 
1164 
1165 /*#include "syntax_extra.c"*/
1166 
1167 /* TODO: z80asm compatibility
1168    defgroup
1169    defvars
1170    call_oz : macros?
1171    pkg_call:
1172    define
1173    undefine
1174 
1175    perhaps defw etc need to come into here?
1176 */
parse_z80asm_pseudo(char * s)1177 char *parse_z80asm_pseudo(char *s)
1178 {
1179     char *name = s;
1180     char *asmpc;
1181 
1182     if ( z80asm_compat == 0 ) {
1183         return s;
1184     }
1185 
1186     /* z80asm uses ASMPC instead of $ for the program counter, so fix it */
1187     asmpc = strstr(s,"ASMPC");
1188     if ( asmpc != NULL ) {
1189         *asmpc++ = '$';
1190         *asmpc++ = ' ';
1191         *asmpc++ = ' ';
1192         *asmpc++ = ' ';
1193         *asmpc = ' ';
1194     }
1195 
1196     while (ISIDCHAR(*s))
1197         s++;
1198     if ( s - name == 6 && strnicmp(name,"module", 6) == 0 ) {
1199         s = skip(s);
1200         parse_name(&s);  /* We throw away the result */
1201         eol(s);
1202     } else {
1203         /* defb, defw, defl, defm, xdef, xref, lib, xlib, defc, defp dealt with by old syntax module */
1204         s = name;
1205     }
1206 
1207     return s;
1208 }
1209 
parse_cpu_special(char * start)1210 char *parse_cpu_special(char *start)
1211 {
1212     char *s = start;
1213     int   i;
1214 
1215 
1216     altd_enabled = ioi_enabled = ioe_enabled = 0;
1217 
1218     if (ISIDSTART(*s)) {
1219         /* Check for standard identifiers */
1220         if ( parse_rcm_identifier(&s) == -1 ) {
1221             /* Not a rabbit one, lets check z80asm versions */
1222             start = parse_z80asm_pseudo(s);
1223         } else {
1224             /* Check for upto 2 rabbit identifiers */
1225             for ( i = 0; i < 2; i++ ) {
1226                 s = skip(s);
1227                 if ( parse_rcm_identifier(&s) == -1 ) {
1228                     return s;
1229                 }
1230                 start = s;
1231             }
1232         }
1233     }
1234     return start;
1235 }
1236 
instruction_size(instruction * ip,section * sec,taddr pc)1237 size_t instruction_size(instruction *ip, section *sec, taddr pc)
1238 {
1239     mnemonic *opcode = &mnemonics[ip->code];
1240     size_t    size;
1241 
1242     /* Try and find the right opcode as necessary */
1243     if ( (opcode->ext.cpus & cpu_type)  ) {
1244         int action = -1;
1245 
1246         if ( cpu_type & CPU_RCM2000 ) {
1247             action = opcode->ext.rabbit2000_action;
1248         } else if ( cpu_type & CPU_RCM4000 ) {
1249             action = opcode->ext.rabbit4000_action;
1250         } else if ( cpu_type & CPU_RCM3000 ) {
1251             action = opcode->ext.rabbit3000_action;
1252         } else if ( cpu_type & CPU_GB80 ) {
1253             action = opcode->ext.gb80_action;
1254         }
1255         switch ( action ) {
1256         case RCM_EMU_INCREMENT:  /* Move to next instruction in table that matches our cpu */
1257             /* We only want to do the increment if we're not dealing with index registers */
1258             if ( ( ip->op[0] == NULL || (ip->op[0] && (ip->op[0]->type & OP_INDEX) == 0) &&
1259                   (ip->op[1] == NULL || (ip->op[1] && (ip->op[1]->type & OP_INDEX) == 0) )) &&
1260                  !(opcode->ext.mode == TYPE_LD8 && (ip->op[1]->reg == REG_A || ip->op[1]->reg == REG_HLREF || ip->op[0]->reg == REG_A || ip->op[0]->reg == REG_HLREF) ) ) {
1261                 do {
1262                     ip->code++;
1263                     opcode = &mnemonics[ip->code];
1264                 } while ( (opcode->ext.cpus &  cpu_type) == 0 );
1265             }
1266             break;
1267         case RCM_EMU_LIBRARY:
1268             return 3;  /* Call (function) */
1269             break;
1270         }
1271     }
1272 
1273     /* Call cc need to be emulated on the rabbit and have a different size */
1274     if ( ( cpu_type & CPU_RABBIT) && opcode->ext.mode == TYPE_FLAGS && opcode->ext.opcode == 0xc4 ) {
1275         if ( ip->op[0]->flags <= FLAGS_C ) {
1276             size = 5;
1277         } else {
1278             size = 6;
1279         }
1280         return size;
1281     }
1282 
1283 
1284 
1285     /* Get the basic size of the opcode */
1286     if ( opcode->ext.opcode & 0xff000000 ) {
1287         size = 4;
1288     } else if ( opcode->ext.opcode & 0x00ff0000 ) {
1289         size = 3;
1290     } else if ( opcode->ext.opcode & 0x0000ff00 ) {
1291         size = 2;
1292     } else {
1293         size = 1;
1294     }
1295 
1296     /* Increase the size for any modifiers */
1297     if ( (( ip->op[0] && ip->op[0]->type & (OP_INDEX ) )  ||
1298           ( ip->op[1] && ip->op[1]->type & (OP_INDEX ) )) && opcode->ext.mode != TYPE_EDPREF ) {
1299         size++;
1300     }
1301 
1302     if ( ( ip->op[0] && ip->op[0]->type == OP_ABS ) ||
1303          ( ip->op[1] && ip->op[1]->type == OP_ABS  ) ) {
1304         size++;
1305     }
1306     if ( ( ip->op[0] && (ip->op[0]->type & OP_OFFSET )) ||
1307          ( ip->op[1] && (ip->op[1]->type & OP_OFFSET)  ) ) {
1308         size++;
1309     }
1310 
1311     if ( ( ip->op[0] && (ip->op[0]->type == (OP_ABS16|OP_INDIR) || ip->op[0]->type == OP_ABS16 )) ||
1312          ( ip->op[1] && (ip->op[1]->type == (OP_ABS16|OP_INDIR) || ip->op[1]->type == OP_ABS16 )) ) {
1313         size += 2;
1314     }
1315     if ( ( ip->op[0] && (ip->op[0]->type == (OP_ABS24|OP_INDIR) || ip->op[0]->type == OP_ABS24 )) ||
1316          ( ip->op[1] && (ip->op[1]->type == (OP_ABS24|OP_INDIR) || ip->op[1]->type == OP_ABS24 )) ) {
1317         size += 3;
1318     }
1319     if ( ( ip->op[0] && (ip->op[0]->type == (OP_ABS32|OP_INDIR) || ip->op[0]->type == OP_ABS32 )) ||
1320          ( ip->op[1] && (ip->op[1]->type == (OP_ABS32|OP_INDIR) || ip->op[1]->type == OP_ABS32 )) ) {
1321         size += 4;
1322     }
1323 
1324 
1325     /* Add on an altd flag if implicitly required by alternate registers */
1326     if ( ((opcode->operand_type[0] & OP_RALT) && ( ip->op[0]->type & OP_ALT) ) ||
1327          ( (opcode->operand_type[1] & OP_RALT) && ( ip->op[1]->type & OP_ALT) ) )  {
1328         ip->ext.altd = 1;
1329     }
1330 
1331 
1332     if  (ip->ext.altd ) {
1333         size++;
1334     }
1335     if ( ip->ext.ioi ) {
1336         size++;
1337     }
1338     if ( ip->ext.ioe ) {
1339         size++;
1340     }
1341 
1342     return size;
1343 }
1344 
1345 
1346 
apply_modifier(rlist * rl,taddr val)1347 static taddr apply_modifier(rlist *rl, taddr val)
1348 {
1349     switch (modifier) {
1350     case LOBYTE:
1351         if (rl)
1352             ((nreloc *)rl->reloc)->mask = 0xff;
1353         val = val & 0xff;
1354         break;
1355     case HIBYTE:
1356         if (rl)
1357             ((nreloc *)rl->reloc)->mask = 0xff00;
1358         val = (val >> 8) & 0xff;
1359         break;
1360     }
1361     return val;
1362 }
1363 
1364 
1365 
write_opcode(mnemonic * opcode,dblock * db,int size,section * sec,taddr pc,operand * op1,operand * op2,int add,instruction_ext * ext)1366 static void write_opcode(mnemonic *opcode, dblock *db, int size, section *sec, taddr pc, operand *op1, operand *op2, int add, instruction_ext *ext)
1367 {
1368     int   reg1 = 0 , reg2 = 0;
1369     operand *indexit = NULL;
1370     int   indexcode = 0;
1371     expr *expr = NULL;
1372     int   exprsize;
1373     unsigned char *d = (unsigned char *)db->data;
1374     unsigned char *start = (unsigned char *)db->data;
1375 
1376     if  (ext->altd ) {
1377         *d++ = 0x76;
1378         size--;
1379     }
1380     if ( ext->ioi ) {
1381         *d++ = 0xd3;
1382         size--;
1383     }
1384     if ( ext->ioe ) {
1385         *d++ = 0xdb;
1386         size--;
1387     }
1388 
1389     if ( op1 ) {
1390         reg1 = op1->reg;
1391         if ( op1->type & OP_OFFSET ) {
1392             indexit = op1;
1393         }
1394         if ( reg1 & REG_IX ) {
1395             indexcode = swapixiy == 0 ? 0xdd : 0xfd;
1396         } else if ( reg1 & REG_IY ) {
1397             indexcode = swapixiy == 0 ? 0xfd : 0xdd;
1398         }
1399         if ( BASIC_TYPE(op1->type) == OP_ABS ) {
1400             expr = op1->value;
1401             exprsize = 1;
1402             --size;
1403         }
1404         if ( BASIC_TYPE(op1->type) == OP_ABS16 ) {
1405             expr = op1->value;
1406             exprsize = 2;
1407             size -= 2;
1408         }
1409         if ( BASIC_TYPE(op1->type) == OP_ABS24 ) {
1410             expr = op1->value;
1411             exprsize = 3;
1412             size -= 3;
1413         }
1414         if ( BASIC_TYPE(op1->type) == OP_ABS32 ) {
1415             expr = op1->value;
1416             exprsize = 4;
1417             size -= 4;
1418         }
1419     }
1420     if ( op2 ) {
1421         reg2 = op2->reg;
1422 
1423         if ( op2->type & OP_OFFSET ) {
1424             indexit = op2;
1425         }
1426         if ( reg2 & REG_IX ) {
1427             indexcode = 0xdd;
1428         } else if ( reg2 & REG_IY ) {
1429             indexcode = 0xfd;
1430         }
1431         if ( BASIC_TYPE(op2->type) == OP_ABS ) {
1432             expr = op2->value;
1433             exprsize = 1;
1434             --size;
1435         }
1436         if ( BASIC_TYPE(op2->type) == OP_ABS16 ) {
1437             expr = op2->value;
1438             exprsize = 2;
1439             size -= 2;
1440         }
1441         if ( BASIC_TYPE(op2->type) == OP_ABS24 ) {
1442             expr = op2->value;
1443             exprsize = 3;
1444             size -= 3;
1445         }
1446         if ( BASIC_TYPE(op2->type) == OP_ABS32 ) {
1447             expr = op2->value;
1448             exprsize = 4;
1449             size -= 4;
1450         }
1451     }
1452 
1453     if ( opcode->ext.mode == TYPE_EDPREF ) {
1454         if ( indexcode == 0 ) {
1455             indexcode = 0xed;
1456         }
1457     } else if ( opcode->ext.mode == TYPE_NOPREFIX || opcode->ext.mode == TYPE_IDX32 ) {
1458         indexcode = 0;
1459     }
1460 
1461     if ( indexcode ) {
1462         *d++ = indexcode;
1463         --size;
1464     }
1465 
1466     if ( indexit ) {
1467         size--;
1468     }
1469 
1470     switch ( size ) {
1471     case 4:
1472         *d++ = ( opcode->ext.opcode & 0xff000000 ) >> 24;
1473         /* Fall through */
1474     case 3:
1475         *d++ = ( opcode->ext.opcode & 0x00ff0000 ) >> 16;
1476         /* Fall through */
1477     case 2:
1478         *d++ = ( opcode->ext.opcode & 0x0000ff00 ) >> 8;
1479         /* Fall through */
1480     case 1:
1481         *d++ = ( ( opcode->ext.opcode & 0x000000ff ) >> 0 ) + add ;
1482     }
1483 
1484     /* Now we can write out the index */
1485     if ( indexit ) {
1486         taddr val = 0;
1487         int cbmode = 0;
1488         /* If it's a CB code then the index isn't last */
1489         if ( (( opcode->ext.opcode & 0xffffff00 ) >> 8) == 0x000000cb )
1490             cbmode = 1;
1491         if ( indexit->value && eval_expr(indexit->value, &val, sec, pc) == 0 ) {
1492             symbol *base;
1493             rlist *rl;
1494             modifier = 0;
1495             if ( find_base(indexit->value, &base, sec, pc) == BASE_OK ) {
1496                 rl = add_extnreloc(&db->relocs, base, val, REL_ABS, 0, 8,
1497                                    cbmode ? ((d-1)-start) : (d-start));
1498                 val = apply_modifier(rl, val);
1499             } else
1500                 general_error(38);  /* illegal relocation */
1501         }
1502         if ( ( (indexit->reg == REG_SP || ( indexit->reg & REG_PLAIN) == REG_HL) && val >= 0 && val <= 255 )
1503              || ( val >= -128 && val <= 127 ) )  {
1504             if ( cbmode ) {
1505                 *d = *(d - 1);
1506                 *(d -1 ) = val;
1507             } else {
1508                 *d++ = val;
1509             }
1510         } else {
1511             cpu_error(0, val);
1512         }
1513     }
1514 
1515     if ( expr != NULL ) {
1516         taddr val;
1517         if ( eval_expr(expr, &val, sec, pc) == 0 ) {
1518             symbol *base;
1519             rlist *rl;
1520             modifier = 0;
1521             if ( find_base(expr, &base, sec, pc) == BASE_OK ) {
1522                 if ( opcode->ext.mode == TYPE_RELJUMP ) {
1523                     add_extnreloc(&db->relocs, base, val -1, REL_PC,
1524                                   0, exprsize * 8, (d - start));
1525                     val -= (pc + db->size);
1526                     if (modifier)
1527                         ierror(0);  /* @@@ Hi/Lo modifier makes no sense here? */
1528                 } else {
1529                     rl = add_extnreloc(&db->relocs, base, val, REL_ABS,
1530                                        0, exprsize * 8, (d - start));
1531                     val = apply_modifier(rl, val);
1532                 }
1533 
1534             } else {
1535                 general_error(38);  /* illegal relocation */
1536             }
1537         } else {
1538             /* It was a constant, if it's relative calculate now */
1539             if ( opcode->ext.mode == TYPE_RELJUMP ) {
1540                 val -= ( pc + db->size );
1541             }
1542         }
1543         if ( exprsize == 1 && ( val < -128 || val >= 256 ||
1544              (opcode->ext.mode == TYPE_RELJUMP && val >= 128 ) ) )
1545             cpu_error(3, val);
1546         else
1547             d = setval(0,d,exprsize,val);
1548     }
1549 }
1550 
1551 
1552 
rabbit_emu_call(instruction * ip,dblock * db,section * sec,taddr pc)1553 static void rabbit_emu_call(instruction *ip,dblock *db,section *sec,taddr pc)
1554 {
1555     unsigned char *d;
1556     unsigned char *start;
1557     taddr          val;
1558 
1559 
1560     myfree(db->data);
1561     db->data = mymalloc(6);  /* Maximum size */
1562     start = d = (unsigned char *)db->data;
1563 
1564     if (  ip->op[0]->flags < FLAGS_PO ) {
1565         switch ( ip->op[0]->flags ) {
1566         case FLAGS_NZ:
1567             *d++ = 0x28; /* jr z */
1568             *d++ = 0x03;
1569             break;
1570         case FLAGS_Z:
1571             *d++ = 0x20; /* jr z */
1572             *d++ = 0x03;
1573             break;
1574         case FLAGS_NC:
1575             *d++ = 0x38;  /* jr c */
1576             *d++ = 0x03;
1577             break;
1578         case FLAGS_C:
1579             *d++ = 0x30;  /* jr nc */
1580             *d++ = 0x03;
1581             break;
1582         }
1583     } else {
1584         expr *expr;
1585         char *t_expr = "$ + 6";
1586         /* These ones need to be jp to get a temporary expression */
1587         switch ( ip->op[0]->flags ) {
1588         case FLAGS_PO:
1589             *d++ = 0xea; /* jp pe */
1590             break;
1591         case FLAGS_PE:
1592             *d++ = 0xe2; /* jp po */
1593             break;
1594         case FLAGS_M:
1595             *d++ = 0xf2; /* jp p */
1596             break;
1597         case FLAGS_P:
1598             *d++ = 0xfa; /* jp m */
1599             break;
1600         }
1601         /* Create a temporary expression */
1602         expr = parse_expr(&t_expr);
1603         if ( eval_expr(expr, &val, sec, pc) == 0 ) {
1604             symbol *base;
1605             if ( find_base(expr, &base, sec, pc) == BASE_OK )
1606                 add_extnreloc(&db->relocs,base, val, REL_ABS,
1607                               0, 8, (d - start));
1608             else
1609                 general_error(38);  /* illegal relocation */
1610         }
1611         free_expr(expr);
1612         *d++ = val % 256;
1613         *d++ = val / 256;
1614     }
1615     *d++ = 0xcd;  /* call */
1616     /* Evaluate the real expression */
1617     if ( eval_expr(ip->op[1]->value, &val, sec, pc) == 0 ) {
1618         symbol *base;
1619         if ( find_base(ip->op[1]->value, &base, sec, pc) == BASE_OK )
1620             add_extnreloc(&db->relocs,base, val, REL_ABS, 0, 8, (d - start));
1621         else
1622             general_error(38);  /* illegal relocation */
1623     }
1624     *d++ = val % 256;
1625     *d++ = val / 256;
1626 
1627     /* Set the size */
1628     db->size= d - start;
1629     return;
1630 }
1631 
1632 /* Check whether an operand is an offset operator and thus affects memory */
is_offset_operand(operand * op)1633 static int is_offset_operand(operand *op)
1634 {
1635     if ( op ) {
1636         if ( BASIC_TYPE(op->type) == OP_REG8 && ( (op->reg & REG_PLAIN) == REG_HLREF) ) {
1637             return 1;
1638         }
1639     }
1640     return 0;
1641 }
1642 
eval_data(operand * op,size_t bitsize,section * sec,taddr pc)1643 dblock *eval_data(operand *op,size_t bitsize,section *sec,taddr pc)
1644 {
1645     dblock *db = new_dblock();
1646     taddr val;
1647 
1648     if (bitsize!=8 && bitsize!=16 && bitsize != 24 && bitsize != 32)
1649         cpu_error(2,bitsize);  /* data size not supported */
1650 
1651     db->size = bitsize >> 3;
1652     db->data = mymalloc(db->size);
1653     if (!eval_expr(op->value,&val,sec,pc)) {
1654         symbol *base;
1655         int btype;
1656         rlist *rl;
1657 
1658         modifier = 0;
1659         btype = find_base(op->value, &base, sec, pc);
1660         if ( btype == BASE_OK || ( btype == BASE_PCREL && modifier == 0 ) ) {
1661             rl = add_extnreloc(&db->relocs, base, val,
1662                                btype==BASE_PCREL ? REL_PC : REL_ABS,
1663                                0, bitsize, 0);
1664             val = apply_modifier(rl, val);
1665         }
1666         else if (btype != BASE_NONE)
1667             general_error(38);  /* illegal relocation */
1668     }
1669     if (bitsize < 16 && (val<-0x80 || val>0xff))
1670         cpu_error(3, val);  /* operand doesn't fit into 8-bits */
1671     setval(0,db->data,db->size,val);
1672 
1673     return db;
1674 }
1675 
eval_instruction(instruction * ip,section * sec,taddr pc)1676 dblock *eval_instruction(instruction *ip,section *sec,taddr pc)
1677 {
1678     dblock *db;
1679     mnemonic *opcode = &mnemonics[ip->code];
1680     symbol *base;
1681     unsigned char *d;
1682     taddr val = 0;
1683     int   size = 0, reg,offs = 0;
1684     int error = 0;
1685 
1686     size = instruction_size(ip, sec, pc);
1687 
1688     if ( (opcode->ext.cpus & cpu_type) == 0 ) {
1689         cpu_error(1, cpuname, opcode->name);
1690         error = 1;
1691     } else {
1692         int action = 0;
1693 
1694 
1695         if ( cpu_type & (CPU_RABBIT|CPU_GB80) ) {
1696             if ( cpu_type & CPU_RCM2000 ) {
1697                 action = opcode->ext.rabbit2000_action;
1698             } else if ( cpu_type & CPU_RCM4000 ) {
1699                 action = opcode->ext.rabbit4000_action;
1700             } else if ( cpu_type & CPU_RCM3000 ) {
1701                 action = opcode->ext.rabbit3000_action;
1702             } else if ( cpu_type & CPU_GB80 ) {
1703                 action = opcode->ext.gb80_action;
1704             }
1705             switch ( action ) { /* INCREMENT dealt with by instruction_size */
1706             case RCM_EMU_LIBRARY:
1707             {
1708                 char    buf[128];
1709                 char   *bufptr = buf;
1710                 symbol *sym;
1711                 expr   *expr;
1712                 taddr   val;
1713 
1714                 /* Emulate by calling a library routine */
1715                 if ( rcmemu ) {
1716                     snprintf(buf,sizeof(buf),"rcmx_%s",opcode->name);
1717 
1718                     if ( (sym = find_symbol(buf)) == NULL ) {
1719                         sym = new_import(buf);
1720                     }
1721                     db = new_dblock();
1722 
1723                     size = db->size = 3;
1724                     db->data = mymalloc(db->size);
1725                     d = (unsigned char *)db->data;
1726                     *d++ = 205; /* Call */
1727 
1728                     /* Create a temporary expression */
1729                     expr = parse_expr(&bufptr);
1730                     if ( eval_expr(expr, &val, sec, pc) == 0 ) {
1731                         if (find_base(expr, &base, sec, pc) == BASE_OK)
1732                             add_extnreloc(&db->relocs,base, val, REL_ABS,
1733                                           0, 8, 1);
1734                         else
1735                             general_error(38);  /* illegal relocation */
1736                     }
1737                     *d++ = val % 256;
1738                     *d++ = val / 256;
1739 
1740                     free_expr(expr);
1741                     return db;
1742                 } else {
1743                     cpu_error(13, cpuname, opcode->name);
1744                     error = 1;
1745                 }
1746             }
1747             }
1748         }
1749     }
1750 
1751 
1752     /* Check altd/ioi on non-rabbit cpus */
1753     if ( (cpu_type & CPU_RABBIT) == 0 ) {
1754         if  ( ip->ext.altd ) {
1755             cpu_error(14,"altd");
1756             error = 1;
1757         }
1758         if  ( ip->ext.ioi ) {
1759             cpu_error(14,"ioi");
1760             error = 1;
1761         }
1762         if  ( ip->ext.ioe ) {
1763             cpu_error(14,"ioe");
1764             error = 1;
1765         }
1766     } else {
1767         if ( ip->ext.ioe && ip->ext.ioi ) {
1768             cpu_error(15);
1769             error = 1;
1770         }
1771         if ( ip->ext.altd ) {
1772             if ( (opcode->ext.modifier_flags & F_ALTDW) == F_ALTDW ) {
1773                 /* Warning, altd not needed */
1774                 cpu_error(17, "altd", opcode->name);
1775             } else if ( (opcode->ext.modifier_flags & F_ALTD) == 0 ) {
1776                 /* Error, altd not supported */
1777                 cpu_error(16, "altd", opcode->name);
1778                 error = 1;
1779             }
1780             if ( (opcode->ext.modifier_flags & F_ALTDWHL ) ) {
1781                 /* Check for (hl) usage and indicate it has no effect */
1782                 if ( ((opcode->operand_type[0] & OP_RALT) && (ip->op[0]->reg & REG_PLAIN) == REG_HLREF) ||
1783                       ((opcode->operand_type[1] & OP_RALT) && (ip->op[1]->reg & REG_PLAIN) == REG_HLREF) ) {
1784                     /* Warning, altd not needed */
1785                     cpu_error(18, "altd", opcode->name);
1786                 }
1787             }
1788             if ( (ip->op[0] && (ip->op[0]->reg == (REG_HL|REG_IX) || ip->op[0]->reg == (REG_HL|REG_IY))) ) {
1789                 cpu_error(12);
1790             }
1791 
1792         }
1793         if ( ip->ext.ioe && (opcode->ext.modifier_flags & F_IO) == 0 ) {
1794             /* If (hl) or (ix+) (iy+) then we shouldn't warn */
1795             if ( is_offset_operand(ip->op[0]) == 0 && is_offset_operand(ip->op[1]) == 0 ) {
1796                 cpu_error(18, "ioe", opcode->name);
1797             }
1798         }
1799         if ( ip->ext.ioi && (opcode->ext.modifier_flags & F_IO) == 0 ) {
1800             if ( is_offset_operand(ip->op[0]) == 0 && is_offset_operand(ip->op[1]) == 0 ) {
1801                 cpu_error(18, "ioi", opcode->name);
1802             }
1803         }
1804 
1805     }
1806 
1807     /* Check for bad register usage */
1808     if ( (cpu_type & (CPU_RABBIT|CPU_Z180)) ) {
1809         /* Rabbit can't use index registers by themselves */
1810         if ( (ip->op[0] && ip->op[0]->type == ( OP_REG8|OP_INDEX ) ) ||
1811              (ip->op[1] && ip->op[1]->type == ( OP_REG8|OP_INDEX ) ) ) {
1812             cpu_error(cpu_type & CPU_RABBIT ? 10 : 11);
1813             error = 1;
1814         }
1815     }
1816     if ( (cpu_type & (CPU_GB80|CPU_8080)) ) {
1817         /* 8080 can't use index registers at all */
1818         if ( (ip->op[0] && ip->op[0]->type & ( OP_INDEX ) ) ||
1819              (ip->op[1] && ip->op[1]->type & ( OP_INDEX ) ) ) {
1820             cpu_error(2, cpuname);
1821             error = 1;
1822         }
1823     }
1824 
1825 
1826     db = new_dblock();
1827 
1828     db->size = size;
1829     db->data = mymalloc(db->size); /* Ed prefix ones are larger in anycase */
1830     d = (unsigned char *)db->data;
1831 
1832     offs = 0;
1833     switch ( opcode->ext.mode ) {
1834     case TYPE_ARITH8:
1835         offs = ip->op[0]->reg & REG_PLAIN;
1836         if ( ip->op[1] && ip->op[0]->reg != OP_A ) {
1837             offs = ip->op[1]->reg & REG_PLAIN;
1838         }
1839         break;
1840     case TYPE_MISC8:
1841         if ( BASIC_TYPE(opcode->operand_type[0]) == OP_REG8 ) {
1842             offs = (ip->op[0]->reg & REG_PLAIN) * 8;
1843         } else if ( BASIC_TYPE(opcode->operand_type[1]) == OP_REG8 ) {
1844             offs = (ip->op[1]->reg & REG_PLAIN) * 8;
1845         }
1846         break;
1847     case TYPE_LD8:
1848         /* ix/iy couples forbidden */
1849         if ( (ip->op[0]->reg & (REG_IX |REG_IY)) &&
1850              (ip->op[1]->reg & (REG_IX|REG_IY)) &&
1851              (((ip->op[0]->reg & REG_IX) && (ip->op[1]->reg & REG_IY)) ||
1852               ((ip->op[1]->reg & REG_IX) && (ip->op[0]->reg & REG_IY)) )){
1853             cpu_error(23,opcode->name);
1854         }
1855         /* forbid ld ixl, (ix+0) */
1856         if ( (ip->op[0]->reg & (REG_IX |REG_IY)) &&
1857              (ip->op[1]->reg & (REG_IX|REG_IY)) &&
1858              (ip->op[1]->type & OP_OFFSET)
1859            ){
1860             cpu_error(23,opcode->name);
1861         }
1862         /* forbid ld ixl,(hl) or similar expressions */
1863         if ( (ip->op[0]->reg & (REG_IX|REG_IY)) &&
1864              (ip->op[1]->reg & REG_PLAIN) == REG_HLREF)
1865         {
1866             cpu_error(24,opcode->name);
1867         }
1868         offs =  ((ip->op[0]->reg & REG_PLAIN) * 8) + ( ip->op[1]->reg & REG_PLAIN);
1869         break;
1870     case TYPE_ARITH16:
1871         /* Forbid instructions of type ld (hl), (memory) */
1872         if ( opcode->operand_type[1] && (opcode->operand_type[1] & (OP_ADDR)) &&
1873              opcode->operand_type[0] && (OP_INDIR) &&
1874              (ip->op[0]->reg & REG_PLAIN) == REG_HL) {
1875             cpu_error(25);
1876         }
1877         /* Forbid instructions of type ld (memory), (hl) */
1878         if (BASIC_TYPE(ip->op[0]->type) == OP_ABS16 &&
1879              BASIC_TYPE(ip->op[1]->type) == OP_HL) {
1880             cpu_error(25);
1881         }
1882         if ( opcode->operand_type[1] && (opcode->operand_type[1] & ( OP_ARITH16)) ) {
1883             offs = (ip->op[1]->reg & REG_PLAIN) * 16;
1884             if ( (ip->op[0]->reg & REG_PLAIN) == REG_HL && (ip->op[1]->reg & REG_PLAIN) == REG_HL &&
1885                 (ip->op[0]->reg & (REG_IX|REG_IY)) != (ip->op[1]->reg & (REG_IX|REG_IY)) ) {
1886                 cpu_error(21,opcode->name);
1887             }
1888         } else {
1889             if ( (ip->op[0]->reg & REG_PLAIN) == REG_AF ) {
1890                 offs = 3 * 16;
1891             } else {
1892                 offs = (ip->op[0]->reg & REG_PLAIN) * 16;
1893             }
1894         }
1895         reg = ip->op[0]->reg & (REG_IX | REG_IY);
1896         break;
1897     case TYPE_IDX32:
1898         offs = 0;
1899         if ( BASIC_TYPE(opcode->operand_type[1]) == OP_IDX32 ) {
1900             offs = 16 * ( ip->op[1]->reg - REG_PW );
1901         } else {
1902             offs = 16 * ( ip->op[0]->reg - REG_PW );
1903         }
1904         break;
1905     case TYPE_IDX32R:
1906         if ( BASIC_TYPE(opcode->operand_type[1]) == OP_IDX32 ) {
1907             offs = 16 * ( ip->op[1]->reg - REG_PW );
1908         }
1909         if ( BASIC_TYPE(opcode->operand_type[0]) == OP_IDX32 ) {
1910             offs += 64 * ( ip->op[0]->reg - REG_PW );
1911         }
1912         break;
1913     case TYPE_FLAGS:
1914     case TYPE_RELJUMP:
1915         if ( opcode->operand_type[0] == OP_FLAGS || opcode->operand_type[0] == OP_FLAGS_RCM ) {
1916 
1917             offs = ip->op[0]->flags * 8;
1918 
1919             if ( ( cpu_type & CPU_GB80 ) && ip->op[0]->flags >= FLAGS_PO ) {
1920                 /* GB80 doesn't support flags po, p, m, pe */
1921                 cpu_error(8, opcode->name);
1922                 error = 1;
1923             } else if (  opcode->ext.opcode == 0xc4 && (cpu_type & CPU_RABBIT ) ) {
1924                 /* If this is a call then we need to do special stuff for the rabbit */
1925                 if ( rcmemu ) {
1926                     rabbit_emu_call(ip,db,sec,pc);
1927                     return db;
1928                 } else {
1929                     cpu_error(13, cpuname, opcode->name);
1930                     error = 1;
1931                 }
1932             } else if ( strcmp(opcode->name,"jr") == 0 || strcmp(opcode->name,"jre") == 0 ) {
1933                 if ( ip->op[0]->flags >= FLAGS_PO ) {
1934                     cpu_error(8, opcode->name);
1935                     error = 1;
1936                 }
1937             }
1938         }
1939         break;
1940     case TYPE_NONE:
1941     case TYPE_EDPREF:
1942     case TYPE_NOPREFIX:
1943         break;
1944     case TYPE_IPSET:
1945         if ( eval_expr(ip->op[0]->value, &val, sec, pc) == 0 ) {
1946             cpu_error(19, opcode->name);
1947             error = 1;
1948         } else  if ( val >= 0 && val <= 3) {  /* ipset has to be between 0 and 3 */
1949             if ( val <= 1 ) {
1950                 offs = val * 16;
1951             } else {
1952                 offs = (val - 2) * 16 + 8;
1953             }
1954         } else {
1955             cpu_error(6,opcode->name,val);  /* ipset out of range */
1956             error = 1 ;
1957         }
1958         break;
1959     case TYPE_BIT:
1960         if ( eval_expr(ip->op[0]->value, &val, sec, pc) == 0 ) {
1961             cpu_error(19, opcode->name);
1962             error = 1;
1963         } else  if ( val >= 0 && val <= 7) {  /* Bit has to be between 0 and 7 */
1964             offs = val * 8 +  (ip->op[1]->reg & REG_PLAIN);
1965         } else {
1966             cpu_error(4,val);  /* Bit count out of range */
1967             error = 1;
1968         }
1969         break;
1970     case TYPE_IM:
1971         if ( eval_expr(ip->op[0]->value, &val, sec, pc) == 0 ) {
1972             cpu_error(19, opcode->name);
1973             error = 1;
1974         } else  if ( val >=0 && val <= 2) {
1975             offs = val * 16;
1976             if ( val == 2 ) { /* More opcode placement oddness */
1977                 offs = 24;
1978             }
1979         } else {
1980             cpu_error(6,opcode->name,val);  /* im out of range */
1981             error = 1;
1982         }
1983         break;
1984     case TYPE_OUT_C_0:
1985         if ( eval_expr(ip->op[1]->value, &val, sec, pc) == 0 ) {
1986             cpu_error(19, opcode->name);
1987             error = 1;
1988         } else if (val != 0){
1989             cpu_error(22,opcode->name);
1990             error = 1;
1991         }
1992         break;
1993     case TYPE_RST:
1994         if ( eval_expr(ip->op[0]->value, &val, sec, pc) == 0 ) {
1995             /* Also allow known labels from an absolute program segment */
1996             if ( find_base(ip->op[0]->value, &base, sec, pc) != BASE_OK ) {
1997                 general_error(38);  /* illegal relocation */
1998                 error = 1;
1999                 break;
2000             }
2001             if ( !( base->sec->flags & ABSOLUTE ) || EXTREF(base) ) {
2002                 cpu_error(19, opcode->name);
2003                 error = 1;
2004                 break;
2005             }
2006             offs = val;
2007         } else if ( (val & ~0x38) == 0 ) {
2008             if ( cpu_type == CPU_RCM2000 ) {
2009                 /* Check for valid rst on Rabbit */
2010                 if ( val == 0 ||  val == 8 || val == 0x30 ) {
2011                     cpu_error(9, val); /* Invalid restart */
2012                     error = 1;
2013                 }
2014             }
2015             offs = val;
2016         } else {
2017             cpu_error(5, val, val);  /* rst out of range */
2018             error = 1;
2019         }
2020         break;
2021     }
2022     if ( error == 0 ) {
2023         write_opcode(opcode, db, size, sec, pc, ip->op[0], ip->op[1], offs, &ip->ext);
2024     }
2025 
2026 
2027     return db;
2028 }
2029 
2030 
new_operand()2031 operand *new_operand()
2032 {
2033   operand *new = mymalloc(sizeof(*new));
2034   new->type = -1;
2035   new->reg = 0;
2036   return new;
2037 }
2038 
2039 
init_cpu()2040 int init_cpu()
2041 {
2042   current_pc_char = '$';
2043   return 1;
2044 }
2045 
2046 
cpu_args(char * p)2047 int cpu_args(char *p)
2048 {
2049 
2050     if ( strcmp(p, "-8080") == 0 ) {
2051         cpu_type = CPU_8080;
2052         cpuname = "8080";
2053         return 1;
2054     } else if ( strcmp(p, "-rcm2000") == 0 ) {
2055         cpu_type = CPU_RCM2000;
2056         cpuname = "Rabbit2000";
2057         return 1;
2058     } else if ( strcmp(p, "-rcm3000") == 0 ) {
2059         cpu_type = CPU_RCM3000;
2060         cpuname = "Rabbit3000";
2061         return 1;
2062     } else if ( strcmp(p, "-rcm4000") == 0 ) {
2063         cpu_type = CPU_RCM4000;
2064         cpuname = "Rabbit4000";
2065         return 1;
2066     } else if ( strcmp(p, "-hd64180") == 0 ) {
2067         cpu_type = CPU_Z180;
2068         cpuname = "hd64180";
2069         return 1;
2070     } else if ( strcmp(p, "-gbz80") == 0 ) {
2071         cpu_type = CPU_GB80;
2072         cpuname = "gbz80";
2073         return 1;
2074     } else if ( strcmp(p, "-swapixiy") == 0 ) {
2075         swapixiy = 1;
2076         return 1;
2077     } else if ( strcmp(p, "-rcmemu" ) == 0 ) {
2078         rcmemu = 1;
2079         return 1;
2080     } else if ( strcmp(p, "-z80asm" ) == 0 ) {
2081         z80asm_compat = 1;
2082         return 1;
2083     }
2084     return 0;
2085 }
2086