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