]> git.sur5r.net Git - cc65/blob - src/ca65/instr.c
Fixed ca65's BRK instruction encoding for the 65816.
[cc65] / src / ca65 / instr.c
1 /*****************************************************************************/
2 /*                                                                           */
3 /*                                  instr.c                                  */
4 /*                                                                           */
5 /*             Instruction encoding for the ca65 macroassembler              */
6 /*                                                                           */
7 /*                                                                           */
8 /*                                                                           */
9 /* (C) 1998-2012, Ullrich von Bassewitz                                      */
10 /*                Roemerstrasse 52                                           */
11 /*                D-70794 Filderstadt                                        */
12 /* EMail:         uz@cc65.org                                                */
13 /*                                                                           */
14 /*                                                                           */
15 /* This software is provided 'as-is', without any expressed or implied       */
16 /* warranty.  In no event will the authors be held liable for any damages    */
17 /* arising from the use of this software.                                    */
18 /*                                                                           */
19 /* Permission is granted to anyone to use this software for any purpose,     */
20 /* including commercial applications, and to alter it and redistribute it    */
21 /* freely, subject to the following restrictions:                            */
22 /*                                                                           */
23 /* 1. The origin of this software must not be misrepresented; you must not   */
24 /*    claim that you wrote the original software. If you use this software   */
25 /*    in a product, an acknowledgment in the product documentation would be  */
26 /*    appreciated but is not required.                                       */
27 /* 2. Altered source versions must be plainly marked as such, and must not   */
28 /*    be misrepresented as being the original software.                      */
29 /* 3. This notice may not be removed or altered from any source              */
30 /*    distribution.                                                          */
31 /*                                                                           */
32 /*****************************************************************************/
33
34
35
36 #include <stdlib.h>
37 #include <string.h>
38 #include <ctype.h>
39
40 /* common */
41 #include "addrsize.h"
42 #include "attrib.h"
43 #include "bitops.h"
44 #include "check.h"
45 #include "mmodel.h"
46
47 /* ca65 */
48 #include "asserts.h"
49 #include "ea.h"
50 #include "ea65.h"
51 #include "easw16.h"
52 #include "error.h"
53 #include "expr.h"
54 #include "global.h"
55 #include "instr.h"
56 #include "nexttok.h"
57 #include "objcode.h"
58 #include "spool.h"
59 #include "studyexpr.h"
60 #include "symtab.h"
61
62
63
64 /*****************************************************************************/
65 /*                                 Forwards                                  */
66 /*****************************************************************************/
67
68
69
70 static void PutPCRel8 (const InsDesc* Ins);
71 /* Handle branches with a 8 bit distance */
72
73 static void PutPCRel16 (const InsDesc* Ins);
74 /* Handle branches with an 16 bit distance and PER */
75
76 static void PutPCRel4510 (const InsDesc* Ins);
77 /* Handle branches with a 16 bit distance for 4510 */
78
79 static void PutBlockMove (const InsDesc* Ins);
80 /* Handle the blockmove instructions (65816) */
81
82 static void PutBlockTransfer (const InsDesc* Ins);
83 /* Handle the block transfer instructions (HuC6280) */
84
85 static void PutBitBranch (const InsDesc* Ins);
86 /* Handle 65C02 branch on bit condition */
87
88 static void PutREP (const InsDesc* Ins);
89 /* Emit a REP instruction, track register sizes */
90
91 static void PutSEP (const InsDesc* Ins);
92 /* Emit a SEP instruction (65816), track register sizes */
93
94 static void PutTAMn (const InsDesc* Ins);
95 /* Emit a TAMn instruction (HuC6280). Since this is a two byte instruction with
96 ** implicit addressing mode, the opcode byte in the table is actually the
97 ** second operand byte. The TAM instruction is the more generic form, it takes
98 ** an immediate argument.
99 */
100
101 static void PutTMA (const InsDesc* Ins);
102 /* Emit a TMA instruction (HuC6280) with an immediate argument. Only one bit
103 ** in the argument byte may be set.
104 */
105
106 static void PutTMAn (const InsDesc* Ins);
107 /* Emit a TMAn instruction (HuC6280). Since this is a two byte instruction with
108 ** implicit addressing mode, the opcode byte in the table is actually the
109 ** second operand byte. The TAM instruction is the more generic form, it takes
110 ** an immediate argument.
111 */
112
113 static void PutTST (const InsDesc* Ins);
114 /* Emit a TST instruction (HuC6280). */
115
116 static void PutJMP (const InsDesc* Ins);
117 /* Handle the jump instruction for the 6502. Problem is that these chips have
118 ** a bug: If the address crosses a page, the upper byte gets not corrected and
119 ** the instruction will fail. The PutJmp function will add a linker assertion
120 ** to check for this case and is otherwise identical to PutAll.
121 */
122
123 static void PutRTS (const InsDesc* Ins attribute ((unused)));
124 /* Handle the RTS instruction for the 816. In smart mode emit a RTL opcode if
125 ** the enclosing scope is FAR.
126 */
127
128 static void PutAll (const InsDesc* Ins);
129 /* Handle all other instructions */
130
131 static void Put4510 (const InsDesc* Ins);
132 /* Handle instructions of 4510 not matching any EATab */
133
134 static void PutSweet16 (const InsDesc* Ins);
135 /* Handle a generic sweet16 instruction */
136
137 static void PutSweet16Branch (const InsDesc* Ins);
138 /* Handle a sweet16 branch instruction */
139
140
141
142 /*****************************************************************************/
143 /*                                   Data                                    */
144 /*****************************************************************************/
145
146
147
148 /* Empty instruction table */
149 static const struct {
150     unsigned Count;
151 } InsTabNone = {
152     0
153 };
154
155 /* Instruction table for the 6502 */
156 static const struct {
157     unsigned Count;
158     InsDesc  Ins[56];
159 } InsTab6502 = {
160     sizeof (InsTab6502.Ins) / sizeof (InsTab6502.Ins[0]),
161     {
162         { "ADC",  0x080A26C, 0x60, 0, PutAll },
163         { "AND",  0x080A26C, 0x20, 0, PutAll },
164         { "ASL",  0x000006e, 0x02, 1, PutAll },
165         { "BCC",  0x0020000, 0x90, 0, PutPCRel8 },
166         { "BCS",  0x0020000, 0xb0, 0, PutPCRel8 },
167         { "BEQ",  0x0020000, 0xf0, 0, PutPCRel8 },
168         { "BIT",  0x000000C, 0x00, 2, PutAll },
169         { "BMI",  0x0020000, 0x30, 0, PutPCRel8 },
170         { "BNE",  0x0020000, 0xd0, 0, PutPCRel8 },
171         { "BPL",  0x0020000, 0x10, 0, PutPCRel8 },
172         { "BRK",  0x0000001, 0x00, 0, PutAll },
173         { "BVC",  0x0020000, 0x50, 0, PutPCRel8 },
174         { "BVS",  0x0020000, 0x70, 0, PutPCRel8 },
175         { "CLC",  0x0000001, 0x18, 0, PutAll },
176         { "CLD",  0x0000001, 0xd8, 0, PutAll },
177         { "CLI",  0x0000001, 0x58, 0, PutAll },
178         { "CLV",  0x0000001, 0xb8, 0, PutAll },
179         { "CMP",  0x080A26C, 0xc0, 0, PutAll },
180         { "CPX",  0x080000C, 0xe0, 1, PutAll },
181         { "CPY",  0x080000C, 0xc0, 1, PutAll },
182         { "DEC",  0x000006C, 0x00, 3, PutAll },
183         { "DEX",  0x0000001, 0xca, 0, PutAll },
184         { "DEY",  0x0000001, 0x88, 0, PutAll },
185         { "EOR",  0x080A26C, 0x40, 0, PutAll },
186         { "INC",  0x000006c, 0x00, 4, PutAll },
187         { "INX",  0x0000001, 0xe8, 0, PutAll },
188         { "INY",  0x0000001, 0xc8, 0, PutAll },
189         { "JMP",  0x0000808, 0x4c, 6, PutJMP },
190         { "JSR",  0x0000008, 0x20, 7, PutAll },
191         { "LDA",  0x080A26C, 0xa0, 0, PutAll },
192         { "LDX",  0x080030C, 0xa2, 1, PutAll },
193         { "LDY",  0x080006C, 0xa0, 1, PutAll },
194         { "LSR",  0x000006F, 0x42, 1, PutAll },
195         { "NOP",  0x0000001, 0xea, 0, PutAll },
196         { "ORA",  0x080A26C, 0x00, 0, PutAll },
197         { "PHA",  0x0000001, 0x48, 0, PutAll },
198         { "PHP",  0x0000001, 0x08, 0, PutAll },
199         { "PLA",  0x0000001, 0x68, 0, PutAll },
200         { "PLP",  0x0000001, 0x28, 0, PutAll },
201         { "ROL",  0x000006F, 0x22, 1, PutAll },
202         { "ROR",  0x000006F, 0x62, 1, PutAll },
203         { "RTI",  0x0000001, 0x40, 0, PutAll },
204         { "RTS",  0x0000001, 0x60, 0, PutAll },
205         { "SBC",  0x080A26C, 0xe0, 0, PutAll },
206         { "SEC",  0x0000001, 0x38, 0, PutAll },
207         { "SED",  0x0000001, 0xf8, 0, PutAll },
208         { "SEI",  0x0000001, 0x78, 0, PutAll },
209         { "STA",  0x000A26C, 0x80, 0, PutAll },
210         { "STX",  0x000010c, 0x82, 1, PutAll },
211         { "STY",  0x000002c, 0x80, 1, PutAll },
212         { "TAX",  0x0000001, 0xaa, 0, PutAll },
213         { "TAY",  0x0000001, 0xa8, 0, PutAll },
214         { "TSX",  0x0000001, 0xba, 0, PutAll },
215         { "TXA",  0x0000001, 0x8a, 0, PutAll },
216         { "TXS",  0x0000001, 0x9a, 0, PutAll },
217         { "TYA",  0x0000001, 0x98, 0, PutAll }
218     }
219 };
220
221 /* Instruction table for the 6502 with illegal instructions */
222 static const struct {
223     unsigned Count;
224     InsDesc  Ins[75];
225 } InsTab6502X = {
226     sizeof (InsTab6502X.Ins) / sizeof (InsTab6502X.Ins[0]),
227     {
228         { "ADC",  0x080A26C, 0x60, 0, PutAll },
229         { "ALR",  0x0800000, 0x4B, 0, PutAll },         /* X */
230         { "ANC",  0x0800000, 0x0B, 0, PutAll },         /* X */
231         { "AND",  0x080A26C, 0x20, 0, PutAll },
232         { "ANE",  0x0800000, 0x8B, 0, PutAll },         /* X */
233         { "ARR",  0x0800000, 0x6B, 0, PutAll },         /* X */
234         { "ASL",  0x000006e, 0x02, 1, PutAll },
235         { "AXS",  0x0800000, 0xCB, 0, PutAll },         /* X */
236         { "BCC",  0x0020000, 0x90, 0, PutPCRel8 },
237         { "BCS",  0x0020000, 0xb0, 0, PutPCRel8 },
238         { "BEQ",  0x0020000, 0xf0, 0, PutPCRel8 },
239         { "BIT",  0x000000C, 0x00, 2, PutAll },
240         { "BMI",  0x0020000, 0x30, 0, PutPCRel8 },
241         { "BNE",  0x0020000, 0xd0, 0, PutPCRel8 },
242         { "BPL",  0x0020000, 0x10, 0, PutPCRel8 },
243         { "BRK",  0x0000001, 0x00, 0, PutAll },
244         { "BVC",  0x0020000, 0x50, 0, PutPCRel8 },
245         { "BVS",  0x0020000, 0x70, 0, PutPCRel8 },
246         { "CLC",  0x0000001, 0x18, 0, PutAll },
247         { "CLD",  0x0000001, 0xd8, 0, PutAll },
248         { "CLI",  0x0000001, 0x58, 0, PutAll },
249         { "CLV",  0x0000001, 0xb8, 0, PutAll },
250         { "CMP",  0x080A26C, 0xc0, 0, PutAll },
251         { "CPX",  0x080000C, 0xe0, 1, PutAll },
252         { "CPY",  0x080000C, 0xc0, 1, PutAll },
253         { "DCP",  0x000A26C, 0xC3, 0, PutAll },         /* X */
254         { "DEC",  0x000006C, 0x00, 3, PutAll },
255         { "DEX",  0x0000001, 0xca, 0, PutAll },
256         { "DEY",  0x0000001, 0x88, 0, PutAll },
257         { "EOR",  0x080A26C, 0x40, 0, PutAll },
258         { "INC",  0x000006c, 0x00, 4, PutAll },
259         { "INX",  0x0000001, 0xe8, 0, PutAll },
260         { "INY",  0x0000001, 0xc8, 0, PutAll },
261         { "ISC",  0x000A26C, 0xE3, 0, PutAll },         /* X */
262         { "JAM",  0x0000001, 0x02, 0, PutAll },         /* X */
263         { "JMP",  0x0000808, 0x4c, 6, PutJMP },
264         { "JSR",  0x0000008, 0x20, 7, PutAll },
265         { "LAS",  0x0000200, 0xBB, 0, PutAll },         /* X */
266         { "LAX",  0x080A30C, 0xA3, 11, PutAll },        /* X */
267         { "LDA",  0x080A26C, 0xa0, 0, PutAll },
268         { "LDX",  0x080030C, 0xa2, 1, PutAll },
269         { "LDY",  0x080006C, 0xa0, 1, PutAll },
270         { "LSR",  0x000006F, 0x42, 1, PutAll },
271         { "NOP",  0x080006D, 0x00, 10, PutAll },        /* X */
272         { "ORA",  0x080A26C, 0x00, 0, PutAll },
273         { "PHA",  0x0000001, 0x48, 0, PutAll },
274         { "PHP",  0x0000001, 0x08, 0, PutAll },
275         { "PLA",  0x0000001, 0x68, 0, PutAll },
276         { "PLP",  0x0000001, 0x28, 0, PutAll },
277         { "RLA",  0x000A26C, 0x23, 0, PutAll },         /* X */
278         { "ROL",  0x000006F, 0x22, 1, PutAll },
279         { "ROR",  0x000006F, 0x62, 1, PutAll },
280         { "RRA",  0x000A26C, 0x63, 0, PutAll },         /* X */
281         { "RTI",  0x0000001, 0x40, 0, PutAll },
282         { "RTS",  0x0000001, 0x60, 0, PutAll },
283         { "SAX",  0x000810C, 0x83, 1, PutAll },         /* X */
284         { "SBC",  0x080A26C, 0xe0, 0, PutAll },
285         { "SEC",  0x0000001, 0x38, 0, PutAll },
286         { "SED",  0x0000001, 0xf8, 0, PutAll },
287         { "SEI",  0x0000001, 0x78, 0, PutAll },
288         { "SHA",  0x0002200, 0x93, 1, PutAll },         /* X */
289         { "SHX",  0x0000200, 0x9e, 1, PutAll },         /* X */
290         { "SHY",  0x0000040, 0x9c, 1, PutAll },         /* X */
291         { "SLO",  0x000A26C, 0x03, 0, PutAll },         /* X */
292         { "SRE",  0x000A26C, 0x43, 0, PutAll },         /* X */
293         { "STA",  0x000A26C, 0x80, 0, PutAll },
294         { "STX",  0x000010c, 0x82, 1, PutAll },
295         { "STY",  0x000002c, 0x80, 1, PutAll },
296         { "TAS",  0x0000200, 0x9b, 0, PutAll },         /* X */
297         { "TAX",  0x0000001, 0xaa, 0, PutAll },
298         { "TAY",  0x0000001, 0xa8, 0, PutAll },
299         { "TSX",  0x0000001, 0xba, 0, PutAll },
300         { "TXA",  0x0000001, 0x8a, 0, PutAll },
301         { "TXS",  0x0000001, 0x9a, 0, PutAll },
302         { "TYA",  0x0000001, 0x98, 0, PutAll }
303     }
304 };
305
306 /* Instruction table for the 65SC02 */
307 static const struct {
308     unsigned Count;
309     InsDesc  Ins[66];
310 } InsTab65SC02 = {
311     sizeof (InsTab65SC02.Ins) / sizeof (InsTab65SC02.Ins[0]),
312     {
313         { "ADC",  0x080A66C, 0x60, 0, PutAll },
314         { "AND",  0x080A66C, 0x20, 0, PutAll },
315         { "ASL",  0x000006e, 0x02, 1, PutAll },
316         { "BCC",  0x0020000, 0x90, 0, PutPCRel8 },
317         { "BCS",  0x0020000, 0xb0, 0, PutPCRel8 },
318         { "BEQ",  0x0020000, 0xf0, 0, PutPCRel8 },
319         { "BIT",  0x0A0006C, 0x00, 2, PutAll },
320         { "BMI",  0x0020000, 0x30, 0, PutPCRel8 },
321         { "BNE",  0x0020000, 0xd0, 0, PutPCRel8 },
322         { "BPL",  0x0020000, 0x10, 0, PutPCRel8 },
323         { "BRA",  0x0020000, 0x80, 0, PutPCRel8 },
324         { "BRK",  0x0000001, 0x00, 0, PutAll },
325         { "BVC",  0x0020000, 0x50, 0, PutPCRel8 },
326         { "BVS",  0x0020000, 0x70, 0, PutPCRel8 },
327         { "CLC",  0x0000001, 0x18, 0, PutAll },
328         { "CLD",  0x0000001, 0xd8, 0, PutAll },
329         { "CLI",  0x0000001, 0x58, 0, PutAll },
330         { "CLV",  0x0000001, 0xb8, 0, PutAll },
331         { "CMP",  0x080A66C, 0xc0, 0, PutAll },
332         { "CPX",  0x080000C, 0xe0, 1, PutAll },
333         { "CPY",  0x080000C, 0xc0, 1, PutAll },
334         { "DEA",  0x0000001, 0x00, 3, PutAll },   /* == DEC */
335         { "DEC",  0x000006F, 0x00, 3, PutAll },
336         { "DEX",  0x0000001, 0xca, 0, PutAll },
337         { "DEY",  0x0000001, 0x88, 0, PutAll },
338         { "EOR",  0x080A66C, 0x40, 0, PutAll },
339         { "INA",  0x0000001, 0x00, 4, PutAll },   /* == INC */
340         { "INC",  0x000006f, 0x00, 4, PutAll },
341         { "INX",  0x0000001, 0xe8, 0, PutAll },
342         { "INY",  0x0000001, 0xc8, 0, PutAll },
343         { "JMP",  0x0010808, 0x4c, 6, PutAll },
344         { "JSR",  0x0000008, 0x20, 7, PutAll },
345         { "LDA",  0x080A66C, 0xa0, 0, PutAll },
346         { "LDX",  0x080030C, 0xa2, 1, PutAll },
347         { "LDY",  0x080006C, 0xa0, 1, PutAll },
348         { "LSR",  0x000006F, 0x42, 1, PutAll },
349         { "NOP",  0x0000001, 0xea, 0, PutAll },
350         { "ORA",  0x080A66C, 0x00, 0, PutAll },
351         { "PHA",  0x0000001, 0x48, 0, PutAll },
352         { "PHP",  0x0000001, 0x08, 0, PutAll },
353         { "PHX",  0x0000001, 0xda, 0, PutAll },
354         { "PHY",  0x0000001, 0x5a, 0, PutAll },
355         { "PLA",  0x0000001, 0x68, 0, PutAll },
356         { "PLP",  0x0000001, 0x28, 0, PutAll },
357         { "PLX",  0x0000001, 0xfa, 0, PutAll },
358         { "PLY",  0x0000001, 0x7a, 0, PutAll },
359         { "ROL",  0x000006F, 0x22, 1, PutAll },
360         { "ROR",  0x000006F, 0x62, 1, PutAll },
361         { "RTI",  0x0000001, 0x40, 0, PutAll },
362         { "RTS",  0x0000001, 0x60, 0, PutAll },
363         { "SBC",  0x080A66C, 0xe0, 0, PutAll },
364         { "SEC",  0x0000001, 0x38, 0, PutAll },
365         { "SED",  0x0000001, 0xf8, 0, PutAll },
366         { "SEI",  0x0000001, 0x78, 0, PutAll },
367         { "STA",  0x000A66C, 0x80, 0, PutAll },
368         { "STX",  0x000010c, 0x82, 1, PutAll },
369         { "STY",  0x000002c, 0x80, 1, PutAll },
370         { "STZ",  0x000006c, 0x04, 5, PutAll },
371         { "TAX",  0x0000001, 0xaa, 0, PutAll },
372         { "TAY",  0x0000001, 0xa8, 0, PutAll },
373         { "TRB",  0x000000c, 0x10, 1, PutAll },
374         { "TSB",  0x000000c, 0x00, 1, PutAll },
375         { "TSX",  0x0000001, 0xba, 0, PutAll },
376         { "TXA",  0x0000001, 0x8a, 0, PutAll },
377         { "TXS",  0x0000001, 0x9a, 0, PutAll },
378         { "TYA",  0x0000001, 0x98, 0, PutAll }
379     }
380 };
381
382 /* Instruction table for the 65C02 */
383 static const struct {
384     unsigned Count;
385     InsDesc  Ins[100];
386 } InsTab65C02 = {
387     sizeof (InsTab65C02.Ins) / sizeof (InsTab65C02.Ins[0]),
388     {
389         { "ADC",  0x080A66C, 0x60, 0, PutAll },
390         { "AND",  0x080A66C, 0x20, 0, PutAll },
391         { "ASL",  0x000006e, 0x02, 1, PutAll },
392         { "BBR0", 0x0000000, 0x0F, 0, PutBitBranch },
393         { "BBR1", 0x0000000, 0x1F, 0, PutBitBranch },
394         { "BBR2", 0x0000000, 0x2F, 0, PutBitBranch },
395         { "BBR3", 0x0000000, 0x3F, 0, PutBitBranch },
396         { "BBR4", 0x0000000, 0x4F, 0, PutBitBranch },
397         { "BBR5", 0x0000000, 0x5F, 0, PutBitBranch },
398         { "BBR6", 0x0000000, 0x6F, 0, PutBitBranch },
399         { "BBR7", 0x0000000, 0x7F, 0, PutBitBranch },
400         { "BBS0", 0x0000000, 0x8F, 0, PutBitBranch },
401         { "BBS1", 0x0000000, 0x9F, 0, PutBitBranch },
402         { "BBS2", 0x0000000, 0xAF, 0, PutBitBranch },
403         { "BBS3", 0x0000000, 0xBF, 0, PutBitBranch },
404         { "BBS4", 0x0000000, 0xCF, 0, PutBitBranch },
405         { "BBS5", 0x0000000, 0xDF, 0, PutBitBranch },
406         { "BBS6", 0x0000000, 0xEF, 0, PutBitBranch },
407         { "BBS7", 0x0000000, 0xFF, 0, PutBitBranch },
408         { "BCC",  0x0020000, 0x90, 0, PutPCRel8 },
409         { "BCS",  0x0020000, 0xb0, 0, PutPCRel8 },
410         { "BEQ",  0x0020000, 0xf0, 0, PutPCRel8 },
411         { "BIT",  0x0A0006C, 0x00, 2, PutAll },
412         { "BMI",  0x0020000, 0x30, 0, PutPCRel8 },
413         { "BNE",  0x0020000, 0xd0, 0, PutPCRel8 },
414         { "BPL",  0x0020000, 0x10, 0, PutPCRel8 },
415         { "BRA",  0x0020000, 0x80, 0, PutPCRel8 },
416         { "BRK",  0x0000001, 0x00, 0, PutAll },
417         { "BVC",  0x0020000, 0x50, 0, PutPCRel8 },
418         { "BVS",  0x0020000, 0x70, 0, PutPCRel8 },
419         { "CLC",  0x0000001, 0x18, 0, PutAll },
420         { "CLD",  0x0000001, 0xd8, 0, PutAll },
421         { "CLI",  0x0000001, 0x58, 0, PutAll },
422         { "CLV",  0x0000001, 0xb8, 0, PutAll },
423         { "CMP",  0x080A66C, 0xc0, 0, PutAll },
424         { "CPX",  0x080000C, 0xe0, 1, PutAll },
425         { "CPY",  0x080000C, 0xc0, 1, PutAll },
426         { "DEA",  0x0000001, 0x00, 3, PutAll },   /* == DEC */
427         { "DEC",  0x000006F, 0x00, 3, PutAll },
428         { "DEX",  0x0000001, 0xca, 0, PutAll },
429         { "DEY",  0x0000001, 0x88, 0, PutAll },
430         { "EOR",  0x080A66C, 0x40, 0, PutAll },
431         { "INA",  0x0000001, 0x00, 4, PutAll },   /* == INC */
432         { "INC",  0x000006f, 0x00, 4, PutAll },
433         { "INX",  0x0000001, 0xe8, 0, PutAll },
434         { "INY",  0x0000001, 0xc8, 0, PutAll },
435         { "JMP",  0x0010808, 0x4c, 6, PutAll },
436         { "JSR",  0x0000008, 0x20, 7, PutAll },
437         { "LDA",  0x080A66C, 0xa0, 0, PutAll },
438         { "LDX",  0x080030C, 0xa2, 1, PutAll },
439         { "LDY",  0x080006C, 0xa0, 1, PutAll },
440         { "LSR",  0x000006F, 0x42, 1, PutAll },
441         { "NOP",  0x0000001, 0xea, 0, PutAll },
442         { "ORA",  0x080A66C, 0x00, 0, PutAll },
443         { "PHA",  0x0000001, 0x48, 0, PutAll },
444         { "PHP",  0x0000001, 0x08, 0, PutAll },
445         { "PHX",  0x0000001, 0xda, 0, PutAll },
446         { "PHY",  0x0000001, 0x5a, 0, PutAll },
447         { "PLA",  0x0000001, 0x68, 0, PutAll },
448         { "PLP",  0x0000001, 0x28, 0, PutAll },
449         { "PLX",  0x0000001, 0xfa, 0, PutAll },
450         { "PLY",  0x0000001, 0x7a, 0, PutAll },
451         { "RMB0", 0x0000004, 0x07, 1, PutAll },
452         { "RMB1", 0x0000004, 0x17, 1, PutAll },
453         { "RMB2", 0x0000004, 0x27, 1, PutAll },
454         { "RMB3", 0x0000004, 0x37, 1, PutAll },
455         { "RMB4", 0x0000004, 0x47, 1, PutAll },
456         { "RMB5", 0x0000004, 0x57, 1, PutAll },
457         { "RMB6", 0x0000004, 0x67, 1, PutAll },
458         { "RMB7", 0x0000004, 0x77, 1, PutAll },
459         { "ROL",  0x000006F, 0x22, 1, PutAll },
460         { "ROR",  0x000006F, 0x62, 1, PutAll },
461         { "RTI",  0x0000001, 0x40, 0, PutAll },
462         { "RTS",  0x0000001, 0x60, 0, PutAll },
463         { "SBC",  0x080A66C, 0xe0, 0, PutAll },
464         { "SEC",  0x0000001, 0x38, 0, PutAll },
465         { "SED",  0x0000001, 0xf8, 0, PutAll },
466         { "SEI",  0x0000001, 0x78, 0, PutAll },
467         { "SMB0", 0x0000004, 0x87, 1, PutAll },
468         { "SMB1", 0x0000004, 0x97, 1, PutAll },
469         { "SMB2", 0x0000004, 0xA7, 1, PutAll },
470         { "SMB3", 0x0000004, 0xB7, 1, PutAll },
471         { "SMB4", 0x0000004, 0xC7, 1, PutAll },
472         { "SMB5", 0x0000004, 0xD7, 1, PutAll },
473         { "SMB6", 0x0000004, 0xE7, 1, PutAll },
474         { "SMB7", 0x0000004, 0xF7, 1, PutAll },
475         { "STA",  0x000A66C, 0x80, 0, PutAll },
476         { "STP",  0x0000001, 0xdb, 0, PutAll },
477         { "STX",  0x000010c, 0x82, 1, PutAll },
478         { "STY",  0x000002c, 0x80, 1, PutAll },
479         { "STZ",  0x000006c, 0x04, 5, PutAll },
480         { "TAX",  0x0000001, 0xaa, 0, PutAll },
481         { "TAY",  0x0000001, 0xa8, 0, PutAll },
482         { "TRB",  0x000000c, 0x10, 1, PutAll },
483         { "TSB",  0x000000c, 0x00, 1, PutAll },
484         { "TSX",  0x0000001, 0xba, 0, PutAll },
485         { "TXA",  0x0000001, 0x8a, 0, PutAll },
486         { "TXS",  0x0000001, 0x9a, 0, PutAll },
487         { "TYA",  0x0000001, 0x98, 0, PutAll },
488         { "WAI",  0x0000001, 0xcb, 0, PutAll }
489     }
490 };
491
492 /* Instruction table for the 4510 */
493 static const struct {
494     unsigned Count;
495     InsDesc  Ins[133];
496 } InsTab4510 = {
497     sizeof (InsTab4510.Ins) / sizeof (InsTab4510.Ins[0]),
498     {
499         { "ADC",  0x080A66C, 0x60, 0, PutAll },
500         { "AND",  0x080A66C, 0x20, 0, PutAll },
501         { "ASL",  0x000006e, 0x02, 1, PutAll },
502         { "ASR",  0x0000026, 0x43, 0, Put4510 },
503         { "ASW",  0x0000008, 0xcb, 6, PutAll },
504         { "BBR0", 0x0000000, 0x0F, 0, PutBitBranch },
505         { "BBR1", 0x0000000, 0x1F, 0, PutBitBranch },
506         { "BBR2", 0x0000000, 0x2F, 0, PutBitBranch },
507         { "BBR3", 0x0000000, 0x3F, 0, PutBitBranch },
508         { "BBR4", 0x0000000, 0x4F, 0, PutBitBranch },
509         { "BBR5", 0x0000000, 0x5F, 0, PutBitBranch },
510         { "BBR6", 0x0000000, 0x6F, 0, PutBitBranch },
511         { "BBR7", 0x0000000, 0x7F, 0, PutBitBranch },
512         { "BBS0", 0x0000000, 0x8F, 0, PutBitBranch },
513         { "BBS1", 0x0000000, 0x9F, 0, PutBitBranch },
514         { "BBS2", 0x0000000, 0xAF, 0, PutBitBranch },
515         { "BBS3", 0x0000000, 0xBF, 0, PutBitBranch },
516         { "BBS4", 0x0000000, 0xCF, 0, PutBitBranch },
517         { "BBS5", 0x0000000, 0xDF, 0, PutBitBranch },
518         { "BBS6", 0x0000000, 0xEF, 0, PutBitBranch },
519         { "BBS7", 0x0000000, 0xFF, 0, PutBitBranch },
520         { "BCC",  0x0020000, 0x90, 0, PutPCRel8 },
521         { "BCS",  0x0020000, 0xb0, 0, PutPCRel8 },
522         { "BEQ",  0x0020000, 0xf0, 0, PutPCRel8 },
523         { "BIT",  0x0A0006C, 0x00, 2, PutAll },
524         { "BMI",  0x0020000, 0x30, 0, PutPCRel8 },
525         { "BNE",  0x0020000, 0xd0, 0, PutPCRel8 },
526         { "BPL",  0x0020000, 0x10, 0, PutPCRel8 },
527         { "BRA",  0x0020000, 0x80, 0, PutPCRel8 },
528         { "BRK",  0x0000001, 0x00, 0, PutAll },
529         { "BSR",  0x0040000, 0x63, 0, PutPCRel4510 },
530         { "BVC",  0x0020000, 0x50, 0, PutPCRel8 },
531         { "BVS",  0x0020000, 0x70, 0, PutPCRel8 },
532         { "CLC",  0x0000001, 0x18, 0, PutAll },
533         { "CLD",  0x0000001, 0xd8, 0, PutAll },
534         { "CLE",  0x0000001, 0x02, 0, PutAll },
535         { "CLI",  0x0000001, 0x58, 0, PutAll },
536         { "CLV",  0x0000001, 0xb8, 0, PutAll },
537         { "CMP",  0x080A66C, 0xc0, 0, PutAll },
538         { "CPX",  0x080000C, 0xe0, 1, PutAll },
539         { "CPY",  0x080000C, 0xc0, 1, PutAll },
540         { "CPZ",  0x080000C, 0xd0, 1, Put4510 },
541         { "DEA",  0x0000001, 0x00, 3, PutAll },   /* == DEC */
542         { "DEC",  0x000006F, 0x00, 3, PutAll },
543         { "DEW",  0x0000004, 0xc3, 9, PutAll },
544         { "DEX",  0x0000001, 0xca, 0, PutAll },
545         { "DEY",  0x0000001, 0x88, 0, PutAll },
546         { "DEZ",  0x0000001, 0x3B, 0, PutAll },
547         { "EOM",  0x0000001, 0xea, 0, PutAll },
548         { "EOR",  0x080A66C, 0x40, 0, PutAll },
549         { "INA",  0x0000001, 0x00, 4, PutAll },   /* == INC */
550         { "INC",  0x000006f, 0x00, 4, PutAll },
551         { "INW",  0x0000004, 0xe3, 9, PutAll },
552         { "INX",  0x0000001, 0xe8, 0, PutAll },
553         { "INY",  0x0000001, 0xc8, 0, PutAll },
554         { "INZ",  0x0000001, 0x1B, 0, PutAll },
555         { "JMP",  0x0010808, 0x4c, 6, PutAll },
556         { "JSR",  0x0010808, 0x20, 7, Put4510 },
557         { "LBCC", 0x0040000, 0x93, 0, PutPCRel4510 },
558         { "LBCS", 0x0040000, 0xb3, 0, PutPCRel4510 },
559         { "LBEQ", 0x0040000, 0xf3, 0, PutPCRel4510 },
560         { "LBMI", 0x0040000, 0x33, 0, PutPCRel4510 },
561         { "LBNE", 0x0040000, 0xd3, 0, PutPCRel4510 },
562         { "LBPL", 0x0040000, 0x13, 0, PutPCRel4510 },
563         { "LBRA", 0x0040000, 0x83, 0, PutPCRel4510 },
564         { "LBVC", 0x0040000, 0x53, 0, PutPCRel4510 },
565         { "LBVS", 0x0040000, 0x73, 0, PutPCRel4510 },
566         { "LDA",  0x090A66C, 0xa0, 0, Put4510 },
567         { "LDX",  0x080030C, 0xa2, 1, PutAll },
568         { "LDY",  0x080006C, 0xa0, 1, PutAll },
569         { "LDZ",  0x0800048, 0xa3, 1, Put4510 },
570         { "LSR",  0x000006F, 0x42, 1, PutAll },
571         { "MAP",  0x0000001, 0x5C, 0, PutAll },
572         { "NEG",  0x0000001, 0x42, 0, PutAll },
573         { "NOP",  0x0000001, 0xea, 0, PutAll }, /* == EOM */
574         { "ORA",  0x080A66C, 0x00, 0, PutAll },
575         { "PHA",  0x0000001, 0x48, 0, PutAll },
576         { "PHD",  0x8000008, 0xf4, 1, PutAll }, /* == PHW */
577         { "PHP",  0x0000001, 0x08, 0, PutAll },
578         { "PHW",  0x8000008, 0xf4, 1, PutAll },
579         { "PHX",  0x0000001, 0xda, 0, PutAll },
580         { "PHY",  0x0000001, 0x5a, 0, PutAll },
581         { "PHZ",  0x0000001, 0xdb, 0, PutAll },
582         { "PLA",  0x0000001, 0x68, 0, PutAll },
583         { "PLP",  0x0000001, 0x28, 0, PutAll },
584         { "PLX",  0x0000001, 0xfa, 0, PutAll },
585         { "PLY",  0x0000001, 0x7a, 0, PutAll },
586         { "PLZ",  0x0000001, 0xfb, 0, PutAll },
587         { "RMB0", 0x0000004, 0x07, 1, PutAll },
588         { "RMB1", 0x0000004, 0x17, 1, PutAll },
589         { "RMB2", 0x0000004, 0x27, 1, PutAll },
590         { "RMB3", 0x0000004, 0x37, 1, PutAll },
591         { "RMB4", 0x0000004, 0x47, 1, PutAll },
592         { "RMB5", 0x0000004, 0x57, 1, PutAll },
593         { "RMB6", 0x0000004, 0x67, 1, PutAll },
594         { "RMB7", 0x0000004, 0x77, 1, PutAll },
595         { "ROL",  0x000006F, 0x22, 1, PutAll },
596         { "ROR",  0x000006F, 0x62, 1, PutAll },
597         { "ROW",  0x0000008, 0xeb, 6, PutAll },
598         { "RTI",  0x0000001, 0x40, 0, PutAll },
599         { "RTN",  0x0800000, 0x62, 1, PutAll },
600         { "RTS",  0x0000001, 0x60, 0, PutAll },
601         { "SBC",  0x080A66C, 0xe0, 0, PutAll },
602         { "SEC",  0x0000001, 0x38, 0, PutAll },
603         { "SED",  0x0000001, 0xf8, 0, PutAll },
604         { "SEE",  0x0000001, 0x03, 0, PutAll },
605         { "SEI",  0x0000001, 0x78, 0, PutAll },
606         { "SMB0", 0x0000004, 0x87, 1, PutAll },
607         { "SMB1", 0x0000004, 0x97, 1, PutAll },
608         { "SMB2", 0x0000004, 0xA7, 1, PutAll },
609         { "SMB3", 0x0000004, 0xB7, 1, PutAll },
610         { "SMB4", 0x0000004, 0xC7, 1, PutAll },
611         { "SMB5", 0x0000004, 0xD7, 1, PutAll },
612         { "SMB6", 0x0000004, 0xE7, 1, PutAll },
613         { "SMB7", 0x0000004, 0xF7, 1, PutAll },
614         { "STA",  0x010A66C, 0x80, 0, Put4510 },
615         { "STX",  0x000030c, 0x82, 1, Put4510 },
616         { "STY",  0x000006c, 0x80, 1, Put4510 },
617         { "STZ",  0x000006c, 0x04, 5, PutAll },
618         { "TAB",  0x0000001, 0x5b, 0, PutAll },
619         { "TAX",  0x0000001, 0xaa, 0, PutAll },
620         { "TAY",  0x0000001, 0xa8, 0, PutAll },
621         { "TAZ",  0x0000001, 0x4b, 0, PutAll },
622         { "TBA",  0x0000001, 0x7b, 0, PutAll },
623         { "TRB",  0x000000c, 0x10, 1, PutAll },
624         { "TSB",  0x000000c, 0x00, 1, PutAll },
625         { "TSX",  0x0000001, 0xba, 0, PutAll },
626         { "TSY",  0x0000001, 0x0b, 0, PutAll },
627         { "TXA",  0x0000001, 0x8a, 0, PutAll },
628         { "TXS",  0x0000001, 0x9a, 0, PutAll },
629         { "TYA",  0x0000001, 0x98, 0, PutAll },
630         { "TYS",  0x0000001, 0x2b, 0, PutAll },
631         { "TZA",  0x0000001, 0x6b, 0, PutAll },
632     }
633 };
634
635 /* Instruction table for the 65816 */
636 static const struct {
637     unsigned Count;
638     InsDesc  Ins[99];
639 } InsTab65816 = {
640     sizeof (InsTab65816.Ins) / sizeof (InsTab65816.Ins[0]),
641     {
642         { "ADC",  0x0b8f6fc, 0x60, 0, PutAll },
643         { "AND",  0x0b8f6fc, 0x20, 0, PutAll },
644         { "ASL",  0x000006e, 0x02, 1, PutAll },
645         { "BCC",  0x0020000, 0x90, 0, PutPCRel8 },
646         { "BCS",  0x0020000, 0xb0, 0, PutPCRel8 },
647         { "BEQ",  0x0020000, 0xf0, 0, PutPCRel8 },
648         { "BIT",  0x0a0006c, 0x00, 2, PutAll },
649         { "BMI",  0x0020000, 0x30, 0, PutPCRel8 },
650         { "BNE",  0x0020000, 0xd0, 0, PutPCRel8 },
651         { "BPL",  0x0020000, 0x10, 0, PutPCRel8 },
652         { "BRA",  0x0020000, 0x80, 0, PutPCRel8 },
653         { "BRK",  0x0000005, 0x00, 0, PutAll },
654         { "BRL",  0x0040000, 0x82, 0, PutPCRel16 },
655         { "BVC",  0x0020000, 0x50, 0, PutPCRel8 },
656         { "BVS",  0x0020000, 0x70, 0, PutPCRel8 },
657         { "CLC",  0x0000001, 0x18, 0, PutAll },
658         { "CLD",  0x0000001, 0xd8, 0, PutAll },
659         { "CLI",  0x0000001, 0x58, 0, PutAll },
660         { "CLV",  0x0000001, 0xb8, 0, PutAll },
661         { "CMP",  0x0b8f6fc, 0xc0, 0, PutAll },
662         { "COP",  0x0000004, 0x02, 6, PutAll },
663         { "CPA",  0x0b8f6fc, 0xc0, 0, PutAll },   /* == CMP */
664         { "CPX",  0x0c0000c, 0xe0, 1, PutAll },
665         { "CPY",  0x0c0000c, 0xc0, 1, PutAll },
666         { "DEA",  0x0000001, 0x00, 3, PutAll },   /* == DEC */
667         { "DEC",  0x000006F, 0x00, 3, PutAll },
668         { "DEX",  0x0000001, 0xca, 0, PutAll },
669         { "DEY",  0x0000001, 0x88, 0, PutAll },
670         { "EOR",  0x0b8f6fc, 0x40, 0, PutAll },
671         { "INA",  0x0000001, 0x00, 4, PutAll },   /* == INC */
672         { "INC",  0x000006F, 0x00, 4, PutAll },
673         { "INX",  0x0000001, 0xe8, 0, PutAll },
674         { "INY",  0x0000001, 0xc8, 0, PutAll },
675         { "JML",  0x4000010, 0x5c, 1, PutAll },
676         { "JMP",  0x4010818, 0x4c, 6, PutAll },
677         { "JSL",  0x0000010, 0x20, 7, PutAll },
678         { "JSR",  0x0010018, 0x20, 7, PutAll },
679         { "LDA",  0x0b8f6fc, 0xa0, 0, PutAll },
680         { "LDX",  0x0c0030c, 0xa2, 1, PutAll },
681         { "LDY",  0x0c0006c, 0xa0, 1, PutAll },
682         { "LSR",  0x000006F, 0x42, 1, PutAll },
683         { "MVN",  0x1000000, 0x54, 0, PutBlockMove },
684         { "MVP",  0x1000000, 0x44, 0, PutBlockMove },
685         { "NOP",  0x0000001, 0xea, 0, PutAll },
686         { "ORA",  0x0b8f6fc, 0x00, 0, PutAll },
687         { "PEA",  0x0000008, 0xf4, 6, PutAll },
688         { "PEI",  0x0000400, 0xd4, 1, PutAll },
689         { "PER",  0x0040000, 0x62, 0, PutPCRel16 },
690         { "PHA",  0x0000001, 0x48, 0, PutAll },
691         { "PHB",  0x0000001, 0x8b, 0, PutAll },
692         { "PHD",  0x0000001, 0x0b, 0, PutAll },
693         { "PHK",  0x0000001, 0x4b, 0, PutAll },
694         { "PHP",  0x0000001, 0x08, 0, PutAll },
695         { "PHX",  0x0000001, 0xda, 0, PutAll },
696         { "PHY",  0x0000001, 0x5a, 0, PutAll },
697         { "PLA",  0x0000001, 0x68, 0, PutAll },
698         { "PLB",  0x0000001, 0xab, 0, PutAll },
699         { "PLD",  0x0000001, 0x2b, 0, PutAll },
700         { "PLP",  0x0000001, 0x28, 0, PutAll },
701         { "PLX",  0x0000001, 0xfa, 0, PutAll },
702         { "PLY",  0x0000001, 0x7a, 0, PutAll },
703         { "REP",  0x0800000, 0xc2, 1, PutREP },
704         { "ROL",  0x000006F, 0x22, 1, PutAll },
705         { "ROR",  0x000006F, 0x62, 1, PutAll },
706         { "RTI",  0x0000001, 0x40, 0, PutAll },
707         { "RTL",  0x0000001, 0x6b, 0, PutAll },
708         { "RTS",  0x0000001, 0x60, 0, PutRTS },
709         { "SBC",  0x0b8f6fc, 0xe0, 0, PutAll },
710         { "SEC",  0x0000001, 0x38, 0, PutAll },
711         { "SED",  0x0000001, 0xf8, 0, PutAll },
712         { "SEI",  0x0000001, 0x78, 0, PutAll },
713         { "SEP",  0x0800000, 0xe2, 1, PutSEP },
714         { "STA",  0x018f6fc, 0x80, 0, PutAll },
715         { "STP",  0x0000001, 0xdb, 0, PutAll },
716         { "STX",  0x000010c, 0x82, 1, PutAll },
717         { "STY",  0x000002c, 0x80, 1, PutAll },
718         { "STZ",  0x000006c, 0x04, 5, PutAll },
719         { "SWA",  0x0000001, 0xeb, 0, PutAll },   /* == XBA */
720         { "TAD",  0x0000001, 0x5b, 0, PutAll },   /* == TCD */
721         { "TAS",  0x0000001, 0x1b, 0, PutAll },   /* == TCS */
722         { "TAX",  0x0000001, 0xaa, 0, PutAll },
723         { "TAY",  0x0000001, 0xa8, 0, PutAll },
724         { "TCD",  0x0000001, 0x5b, 0, PutAll },
725         { "TCS",  0x0000001, 0x1b, 0, PutAll },
726         { "TDA",  0x0000001, 0x7b, 0, PutAll },   /* == TDC */
727         { "TDC",  0x0000001, 0x7b, 0, PutAll },
728         { "TRB",  0x000000c, 0x10, 1, PutAll },
729         { "TSA",  0x0000001, 0x3b, 0, PutAll },   /* == TSC */
730         { "TSB",  0x000000c, 0x00, 1, PutAll },
731         { "TSC",  0x0000001, 0x3b, 0, PutAll },
732         { "TSX",  0x0000001, 0xba, 0, PutAll },
733         { "TXA",  0x0000001, 0x8a, 0, PutAll },
734         { "TXS",  0x0000001, 0x9a, 0, PutAll },
735         { "TXY",  0x0000001, 0x9b, 0, PutAll },
736         { "TYA",  0x0000001, 0x98, 0, PutAll },
737         { "TYX",  0x0000001, 0xbb, 0, PutAll },
738         { "WAI",  0x0000001, 0xcb, 0, PutAll },
739         { "XBA",  0x0000001, 0xeb, 0, PutAll },
740         { "XCE",  0x0000001, 0xfb, 0, PutAll }
741     }
742 };
743
744 /* Instruction table for the SWEET16 pseudo CPU */
745 static const struct {
746     unsigned Count;
747     InsDesc  Ins[26];
748 } InsTabSweet16 = {
749     sizeof (InsTabSweet16.Ins) / sizeof (InsTabSweet16.Ins[0]),
750     {
751         { "ADD",  AMSW16_REG,              0xA0, 0, PutSweet16 },
752         { "BC",   AMSW16_BRA,              0x03, 0, PutSweet16Branch },
753         { "BK",   AMSW16_IMP,              0x0A, 0, PutSweet16 },
754         { "BM",   AMSW16_BRA,              0x05, 0, PutSweet16Branch },
755         { "BM1",  AMSW16_BRA,              0x08, 0, PutSweet16Branch },
756         { "BNC",  AMSW16_BRA,              0x02, 0, PutSweet16Branch },
757         { "BNM1", AMSW16_BRA,              0x09, 0, PutSweet16Branch },
758         { "BNZ",  AMSW16_BRA,              0x07, 0, PutSweet16Branch },
759         { "BP",   AMSW16_BRA,              0x04, 0, PutSweet16Branch },
760         { "BR",   AMSW16_BRA,              0x01, 0, PutSweet16Branch },
761         { "BS",   AMSW16_BRA,              0x0B, 0, PutSweet16Branch },
762         { "BZ",   AMSW16_BRA,              0x06, 0, PutSweet16Branch },
763         { "CPR",  AMSW16_REG,              0xD0, 0, PutSweet16 },
764         { "DCR",  AMSW16_REG,              0xF0, 0, PutSweet16 },
765         { "INR",  AMSW16_REG,              0xE0, 0, PutSweet16 },
766         { "LD",   AMSW16_REG | AMSW16_IND, 0x00, 1, PutSweet16 },
767         { "LDD",  AMSW16_IND,              0x60, 0, PutSweet16 },
768         { "POP",  AMSW16_IND,              0x80, 0, PutSweet16 },
769         { "POPD", AMSW16_IND,              0xC0, 0, PutSweet16 },
770         { "RS",   AMSW16_IMP,              0x0B, 0, PutSweet16 },
771         { "RTN",  AMSW16_IMP,              0x00, 0, PutSweet16 },
772         { "SET",  AMSW16_IMM,              0x10, 0, PutSweet16 },
773         { "ST",   AMSW16_REG | AMSW16_IND, 0x10, 1, PutSweet16 },
774         { "STD",  AMSW16_IND,              0x70, 0, PutSweet16 },
775         { "STP",  AMSW16_IND,              0x90, 0, PutSweet16 },
776         { "SUB",  AMSW16_REG,              0xB0, 0, PutSweet16 },
777     }
778 };
779
780 /* Instruction table for the HuC6280 (the CPU used in the PC engine) */
781 static const struct {
782     unsigned Count;
783     InsDesc  Ins[135];
784 } InsTabHuC6280 = {
785     sizeof (InsTabHuC6280.Ins) / sizeof (InsTabHuC6280.Ins[0]),
786     {
787         { "ADC",  0x080A66C, 0x60, 0, PutAll },
788         { "AND",  0x080A66C, 0x20, 0, PutAll },
789         { "ASL",  0x000006e, 0x02, 1, PutAll },
790         { "BBR0", 0x0000000, 0x0F, 0, PutBitBranch },
791         { "BBR1", 0x0000000, 0x1F, 0, PutBitBranch },
792         { "BBR2", 0x0000000, 0x2F, 0, PutBitBranch },
793         { "BBR3", 0x0000000, 0x3F, 0, PutBitBranch },
794         { "BBR4", 0x0000000, 0x4F, 0, PutBitBranch },
795         { "BBR5", 0x0000000, 0x5F, 0, PutBitBranch },
796         { "BBR6", 0x0000000, 0x6F, 0, PutBitBranch },
797         { "BBR7", 0x0000000, 0x7F, 0, PutBitBranch },
798         { "BBS0", 0x0000000, 0x8F, 0, PutBitBranch },
799         { "BBS1", 0x0000000, 0x9F, 0, PutBitBranch },
800         { "BBS2", 0x0000000, 0xAF, 0, PutBitBranch },
801         { "BBS3", 0x0000000, 0xBF, 0, PutBitBranch },
802         { "BBS4", 0x0000000, 0xCF, 0, PutBitBranch },
803         { "BBS5", 0x0000000, 0xDF, 0, PutBitBranch },
804         { "BBS6", 0x0000000, 0xEF, 0, PutBitBranch },
805         { "BBS7", 0x0000000, 0xFF, 0, PutBitBranch },
806         { "BCC",  0x0020000, 0x90, 0, PutPCRel8 },
807         { "BCS",  0x0020000, 0xb0, 0, PutPCRel8 },
808         { "BEQ",  0x0020000, 0xf0, 0, PutPCRel8 },
809         { "BIT",  0x0A0006C, 0x00, 2, PutAll },
810         { "BMI",  0x0020000, 0x30, 0, PutPCRel8 },
811         { "BNE",  0x0020000, 0xd0, 0, PutPCRel8 },
812         { "BPL",  0x0020000, 0x10, 0, PutPCRel8 },
813         { "BRA",  0x0020000, 0x80, 0, PutPCRel8 },
814         { "BRK",  0x0000001, 0x00, 0, PutAll },
815         { "BSR",  0x0020000, 0x44, 0, PutPCRel8 },
816         { "BVC",  0x0020000, 0x50, 0, PutPCRel8 },
817         { "BVS",  0x0020000, 0x70, 0, PutPCRel8 },
818         { "CLA",  0x0000001, 0x62, 0, PutAll },
819         { "CLC",  0x0000001, 0x18, 0, PutAll },
820         { "CLD",  0x0000001, 0xd8, 0, PutAll },
821         { "CLI",  0x0000001, 0x58, 0, PutAll },
822         { "CLV",  0x0000001, 0xb8, 0, PutAll },
823         { "CLX",  0x0000001, 0x82, 0, PutAll },
824         { "CLY",  0x0000001, 0xc2, 0, PutAll },
825         { "CMP",  0x080A66C, 0xc0, 0, PutAll },
826         { "CPX",  0x080000C, 0xe0, 1, PutAll },
827         { "CPY",  0x080000C, 0xc0, 1, PutAll },
828         { "CSH",  0x0000001, 0xd4, 0, PutAll },
829         { "CSL",  0x0000001, 0x54, 0, PutAll },
830         { "DEA",  0x0000001, 0x00, 3, PutAll },   /* == DEC */
831         { "DEC",  0x000006F, 0x00, 3, PutAll },
832         { "DEX",  0x0000001, 0xca, 0, PutAll },
833         { "DEY",  0x0000001, 0x88, 0, PutAll },
834         { "EOR",  0x080A66C, 0x40, 0, PutAll },
835         { "INA",  0x0000001, 0x00, 4, PutAll },   /* == INC */
836         { "INC",  0x000006f, 0x00, 4, PutAll },
837         { "INX",  0x0000001, 0xe8, 0, PutAll },
838         { "INY",  0x0000001, 0xc8, 0, PutAll },
839         { "JMP",  0x0010808, 0x4c, 6, PutAll },
840         { "JSR",  0x0000008, 0x20, 7, PutAll },
841         { "LDA",  0x080A66C, 0xa0, 0, PutAll },
842         { "LDX",  0x080030C, 0xa2, 1, PutAll },
843         { "LDY",  0x080006C, 0xa0, 1, PutAll },
844         { "LSR",  0x000006F, 0x42, 1, PutAll },
845         { "NOP",  0x0000001, 0xea, 0, PutAll },
846         { "ORA",  0x080A66C, 0x00, 0, PutAll },
847         { "PHA",  0x0000001, 0x48, 0, PutAll },
848         { "PHP",  0x0000001, 0x08, 0, PutAll },
849         { "PHX",  0x0000001, 0xda, 0, PutAll },
850         { "PHY",  0x0000001, 0x5a, 0, PutAll },
851         { "PLA",  0x0000001, 0x68, 0, PutAll },
852         { "PLP",  0x0000001, 0x28, 0, PutAll },
853         { "PLX",  0x0000001, 0xfa, 0, PutAll },
854         { "PLY",  0x0000001, 0x7a, 0, PutAll },
855         { "RMB0", 0x0000004, 0x07, 1, PutAll },
856         { "RMB1", 0x0000004, 0x17, 1, PutAll },
857         { "RMB2", 0x0000004, 0x27, 1, PutAll },
858         { "RMB3", 0x0000004, 0x37, 1, PutAll },
859         { "RMB4", 0x0000004, 0x47, 1, PutAll },
860         { "RMB5", 0x0000004, 0x57, 1, PutAll },
861         { "RMB6", 0x0000004, 0x67, 1, PutAll },
862         { "RMB7", 0x0000004, 0x77, 1, PutAll },
863         { "ROL",  0x000006F, 0x22, 1, PutAll },
864         { "ROR",  0x000006F, 0x62, 1, PutAll },
865         { "RTI",  0x0000001, 0x40, 0, PutAll },
866         { "RTS",  0x0000001, 0x60, 0, PutAll },
867         { "SAX",  0x0000001, 0x22, 0, PutAll },
868         { "SAY",  0x0000001, 0x42, 0, PutAll },
869         { "SBC",  0x080A66C, 0xe0, 0, PutAll },
870         { "SEC",  0x0000001, 0x38, 0, PutAll },
871         { "SED",  0x0000001, 0xf8, 0, PutAll },
872         { "SEI",  0x0000001, 0x78, 0, PutAll },
873         { "SET",  0x0000001, 0xf4, 0, PutAll },
874         { "SMB0", 0x0000004, 0x87, 1, PutAll },
875         { "SMB1", 0x0000004, 0x97, 1, PutAll },
876         { "SMB2", 0x0000004, 0xA7, 1, PutAll },
877         { "SMB3", 0x0000004, 0xB7, 1, PutAll },
878         { "SMB4", 0x0000004, 0xC7, 1, PutAll },
879         { "SMB5", 0x0000004, 0xD7, 1, PutAll },
880         { "SMB6", 0x0000004, 0xE7, 1, PutAll },
881         { "SMB7", 0x0000004, 0xF7, 1, PutAll },
882         { "ST0",  0x0800000, 0x03, 1, PutAll },
883         { "ST1",  0x0800000, 0x13, 1, PutAll },
884         { "ST2",  0x0800000, 0x23, 1, PutAll },
885         { "STA",  0x000A66C, 0x80, 0, PutAll },
886         { "STX",  0x000010c, 0x82, 1, PutAll },
887         { "STY",  0x000002c, 0x80, 1, PutAll },
888         { "STZ",  0x000006c, 0x04, 5, PutAll },
889         { "SXY",  0x0000001, 0x02, 0, PutAll },
890         { "TAI",  0x2000000, 0xf3, 0, PutBlockTransfer },
891         { "TAM",  0x0800000, 0x53, 1, PutAll },
892         { "TAM0", 0x0000001, 0x01, 0, PutTAMn},
893         { "TAM1", 0x0000001, 0x02, 0, PutTAMn},
894         { "TAM2", 0x0000001, 0x04, 0, PutTAMn},
895         { "TAM3", 0x0000001, 0x08, 0, PutTAMn},
896         { "TAM4", 0x0000001, 0x10, 0, PutTAMn},
897         { "TAM5", 0x0000001, 0x20, 0, PutTAMn},
898         { "TAM6", 0x0000001, 0x40, 0, PutTAMn},
899         { "TAM7", 0x0000001, 0x80, 0, PutTAMn},
900         { "TAX",  0x0000001, 0xaa, 0, PutAll },
901         { "TAY",  0x0000001, 0xa8, 0, PutAll },
902         { "TDD",  0x2000000, 0xc3, 0, PutBlockTransfer },
903         { "TIA",  0x2000000, 0xe3, 0, PutBlockTransfer },
904         { "TII",  0x2000000, 0x73, 0, PutBlockTransfer },
905         { "TIN",  0x2000000, 0xD3, 0, PutBlockTransfer },
906         { "TMA",  0x0800000, 0x43, 1, PutTMA },
907         { "TMA0", 0x0000001, 0x01, 0, PutTMAn},
908         { "TMA1", 0x0000001, 0x02, 0, PutTMAn},
909         { "TMA2", 0x0000001, 0x04, 0, PutTMAn},
910         { "TMA3", 0x0000001, 0x08, 0, PutTMAn},
911         { "TMA4", 0x0000001, 0x10, 0, PutTMAn},
912         { "TMA5", 0x0000001, 0x20, 0, PutTMAn},
913         { "TMA6", 0x0000001, 0x40, 0, PutTMAn},
914         { "TMA7", 0x0000001, 0x80, 0, PutTMAn},
915         { "TRB",  0x000000c, 0x10, 1, PutAll },
916         { "TSB",  0x000000c, 0x00, 1, PutAll },
917         { "TST",  0x000006c, 0x83, 9, PutTST },
918         { "TSX",  0x0000001, 0xba, 0, PutAll },
919         { "TXA",  0x0000001, 0x8a, 0, PutAll },
920         { "TXS",  0x0000001, 0x9a, 0, PutAll },
921         { "TYA",  0x0000001, 0x98, 0, PutAll }
922     }
923 };
924
925
926
927 /* An array with instruction tables */
928 static const InsTable* InsTabs[CPU_COUNT] = {
929     (const InsTable*) &InsTabNone,
930     (const InsTable*) &InsTab6502,
931     (const InsTable*) &InsTab6502X,
932     (const InsTable*) &InsTab65SC02,
933     (const InsTable*) &InsTab65C02,
934     (const InsTable*) &InsTab65816,
935     (const InsTable*) &InsTabSweet16,
936     (const InsTable*) &InsTabHuC6280,
937     0,                                  /* Mitsubishi 740 */
938     (const InsTable*) &InsTab4510,
939 };
940 const InsTable* InsTab = (const InsTable*) &InsTab6502;
941
942 /* Table to build the effective 65xx opcode from a base opcode and an
943 ** addressing mode. (The value in the table is ORed with the base opcode)
944 */
945 static unsigned char EATab[12][AM65I_COUNT] = {
946     {   /* Table 0 */
947         0x00, 0x00, 0x05, 0x0D, 0x0F, 0x15, 0x1D, 0x1F,
948         0x00, 0x19, 0x12, 0x00, 0x07, 0x11, 0x17, 0x01,
949         0x00, 0x00, 0x00, 0x03, 0x13, 0x09, 0x00, 0x09,
950         0x00, 0x00, 0x00, 0x00
951     },
952     {   /* Table 1 */
953         0x08, 0x08, 0x04, 0x0C, 0x00, 0x14, 0x1C, 0x00,
954         0x14, 0x1C, 0x00, 0x80, 0x00, 0x10, 0x00, 0x00,
955         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
956         0x00, 0x00, 0x80, 0x00
957     },
958     {   /* Table 2 */
959         0x00, 0x00, 0x24, 0x2C, 0x0F, 0x34, 0x3C, 0x00,
960         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
961         0x00, 0x00, 0x00, 0x00, 0x00, 0x89, 0x00, 0x00,
962         0x00, 0x00, 0x00, 0x00
963     },
964     {   /* Table 3 */
965         0x3A, 0x3A, 0xC6, 0xCE, 0x00, 0xD6, 0xDE, 0x00,
966         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
967         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
968         0x00, 0x00, 0x00, 0x00
969     },
970     {   /* Table 4 */
971         0x1A, 0x1A, 0xE6, 0xEE, 0x00, 0xF6, 0xFE, 0x00,
972         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
973         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
974         0x00, 0x00, 0x00, 0x00
975     },
976     {   /* Table 5 */
977         0x00, 0x00, 0x60, 0x98, 0x00, 0x70, 0x9E, 0x00,
978         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
979         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
980         0x00, 0x00, 0x00, 0x00
981     },
982     {   /* Table 6 */
983         0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
984         0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00,
985         0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
986         0x00, 0x00, 0x90, 0x00
987     },
988     {   /* Table 7 (Subroutine opcodes) */
989         0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
990         0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00,
991         0xDC, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
992         0x00, 0x00, 0x00, 0x00
993     },
994     {   /* Table 8 */
995         0x00, 0x40, 0x01, 0x41, 0x00, 0x09, 0x49, 0x00,
996         0x00, 0x00, 0x00, 0x51, 0x00, 0x00, 0x00, 0x00,
997         0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00,
998         0x00, 0x00, 0x00, 0x00
999     },
1000     {   /* Table 9 */
1001         0x00, 0x00, 0x00, 0x10, 0x00, 0x20, 0x30, 0x00,
1002         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1003         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1004         0x00, 0x00, 0x00, 0x00
1005     },
1006     {   /* Table 10 (NOPs) */
1007         0xea, 0x00, 0x04, 0x0c, 0x00, 0x14, 0x1c, 0x00,
1008         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1009         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80,
1010         0x00, 0x00, 0x00, 0x00
1011     },
1012     {   /* Table 11 (LAX) */
1013         0x08, 0x08, 0x04, 0x0C, 0x00, 0x14, 0x1C, 0x00,
1014         0x14, 0x1C, 0x00, 0x80, 0x00, 0x10, 0x00, 0x00,
1015         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08,
1016         0x00, 0x00, 0x80, 0x00
1017     },
1018 };
1019
1020 /* Table to build the effective SWEET16 opcode from a base opcode and an
1021 ** addressing mode.
1022 */
1023 static unsigned char Sweet16EATab[2][AMSW16I_COUNT] = {
1024     {   /* Table 0 */
1025         0x00, 0x00, 0x00, 0x00, 0x00,
1026     },
1027     {   /* Table 1 */
1028         0x00, 0x00, 0x00, 0x40, 0x20,
1029     },
1030 };
1031
1032 /* Table that encodes the additional bytes for each 65xx instruction */
1033 unsigned char ExtBytes[AM65I_COUNT] = {
1034     0,          /* Implicit */
1035     0,          /* Accu */
1036     1,          /* Direct */
1037     2,          /* Absolute */
1038     3,          /* Absolute long */
1039     1,          /* Direct,X */
1040     2,          /* Absolute,X */
1041     3,          /* Absolute long,X */
1042     1,          /* Direct,Y */
1043     2,          /* Absolute,Y */
1044     1,          /* (Direct) */
1045     2,          /* (Absolute) */
1046     1,          /* [Direct] */
1047     1,          /* (Direct),Y */
1048     1,          /* [Direct],Y */
1049     1,          /* (Direct,X) */
1050     2,          /* (Absolute,X) */
1051     1,          /* Relative short */
1052     2,          /* Relative long */
1053     1,          /* r,s */
1054     1,          /* (r,s),y */
1055     1,          /* Immidiate accu */
1056     1,          /* Immidiate index */
1057     1,          /* Immidiate byte */
1058     2,          /* Blockmove (65816) */
1059     7,          /* Block transfer (HuC6280) */
1060     2,          /* Absolute Indirect long */
1061     2,          /* Immidiate word */
1062 };
1063
1064 /* Table that encodes the additional bytes for each SWEET16 instruction */
1065 static unsigned char Sweet16ExtBytes[AMSW16I_COUNT] = {
1066     0,          /* AMSW16_IMP */
1067     1,          /* AMSW16_BRA */
1068     2,          /* AMSW16_IMM */
1069     0,          /* AMSW16_IND */
1070     0,          /* AMSW16_REG */
1071 };
1072
1073
1074
1075 /*****************************************************************************/
1076 /*                   Handler functions for 6502 derivates                    */
1077 /*****************************************************************************/
1078
1079
1080
1081 static int EvalEA (const InsDesc* Ins, EffAddr* A)
1082 /* Evaluate the effective address. All fields in A will be valid after calling
1083 ** this function. The function returns true on success and false on errors.
1084 */
1085 {
1086     /* Get the set of possible addressing modes */
1087     GetEA (A);
1088
1089     /* From the possible addressing modes, remove the ones that are invalid
1090     ** for this instruction or CPU.
1091     */
1092     A->AddrModeSet &= Ins->AddrMode;
1093
1094     /* If we have an expression, check it and remove any addressing modes that
1095     ** are too small for the expression size. Since we have to study the
1096     ** expression anyway, do also replace it by a simpler one if possible.
1097     */
1098     if (A->Expr) {
1099         ExprDesc ED;
1100         ED_Init (&ED);
1101
1102         /* Study the expression */
1103         StudyExpr (A->Expr, &ED);
1104
1105         /* Simplify it if possible */
1106         A->Expr = SimplifyExpr (A->Expr, &ED);
1107
1108         if (ED.AddrSize == ADDR_SIZE_DEFAULT) {
1109             /* We don't know how big the expression is. If the instruction
1110             ** allows just one addressing mode, assume this as address size
1111             ** for the expression. Otherwise assume the default address size
1112             ** for data.
1113             */
1114             if ((A->AddrModeSet & ~AM65_ALL_ZP) == 0) {
1115                 ED.AddrSize = ADDR_SIZE_ZP;
1116             } else if ((A->AddrModeSet & ~AM65_ALL_ABS) == 0) {
1117                 ED.AddrSize = ADDR_SIZE_ABS;
1118             } else if ((A->AddrModeSet & ~AM65_ALL_FAR) == 0) {
1119                 ED.AddrSize = ADDR_SIZE_FAR;
1120             } else {
1121                 ED.AddrSize = DataAddrSize;
1122                 /* If the default address size of the data segment is unequal
1123                 ** to zero page addressing, but zero page addressing is 
1124                 ** allowed by the instruction, mark all symbols in the 
1125                 ** expression tree. This mark will be checked at end of 
1126                 ** assembly, and a warning is issued, if a zero page symbol
1127                 ** was guessed wrong here.
1128                 */
1129                 if (ED.AddrSize > ADDR_SIZE_ZP && (A->AddrModeSet & AM65_SET_ZP)) {
1130                     ExprGuessedAddrSize (A->Expr, ADDR_SIZE_ZP);
1131                 }
1132             }
1133         }
1134
1135         /* Check the size */
1136         switch (ED.AddrSize) {
1137
1138             case ADDR_SIZE_ABS:
1139                 A->AddrModeSet &= ~AM65_SET_ZP;
1140                 break;
1141
1142             case ADDR_SIZE_FAR:
1143                 A->AddrModeSet &= ~(AM65_SET_ZP | AM65_SET_ABS);
1144                 break;
1145         }
1146
1147         /* Free any resource associated with the expression desc */
1148         ED_Done (&ED);
1149     }
1150
1151     /* Check if we have any adressing modes left */
1152     if (A->AddrModeSet == 0) {
1153         Error ("Illegal addressing mode");
1154         return 0;
1155     }
1156     A->AddrMode    = BitFind (A->AddrModeSet);
1157     A->AddrModeBit = (0x01UL << A->AddrMode);
1158
1159     /* If the instruction has a one byte operand and immediate addressing is
1160     ** allowed but not used, check for an operand expression in the form
1161     ** <label or >label, where label is a far or absolute label. If found,
1162     ** emit a warning. This warning protects against a typo, where the '#'
1163     ** for the immediate operand is omitted.
1164     */
1165     if (A->Expr && (Ins->AddrMode & AM65_ALL_IMM)                &&
1166         (A->AddrModeSet & (AM65_DIR | AM65_ABS | AM65_ABS_LONG)) &&
1167         ExtBytes[A->AddrMode] == 1) {
1168
1169         /* Found, check the expression */
1170         ExprNode* Left = A->Expr->Left;
1171         if ((A->Expr->Op == EXPR_BYTE0 || A->Expr->Op == EXPR_BYTE1) &&
1172             Left->Op == EXPR_SYMBOL                                  &&
1173             GetSymAddrSize (Left->V.Sym) != ADDR_SIZE_ZP) {
1174
1175             /* Output a warning */
1176             Warning (1, "Suspicious address expression");
1177         }
1178     }
1179
1180     /* Build the opcode */
1181     A->Opcode = Ins->BaseCode | EATab[Ins->ExtCode][A->AddrMode];
1182
1183     /* If feature force_range is active, and we have immediate addressing mode,
1184     ** limit the expression to the maximum possible value.
1185     */
1186     if (A->AddrMode == AM65I_IMM_ACCU || A->AddrMode == AM65I_IMM_INDEX ||
1187         A->AddrMode == AM65I_IMM_IMPLICIT || A->AddrMode == AM65I_IMM_IMPLICIT_WORD) {
1188         if (ForceRange && A->Expr) {
1189             A->Expr = MakeBoundedExpr (A->Expr, ExtBytes[A->AddrMode]);
1190         }
1191     }
1192
1193     /* Success */
1194     return 1;
1195 }
1196
1197
1198
1199 static void EmitCode (EffAddr* A)
1200 /* Output code for the data in A */
1201 {
1202     /* Check how many extension bytes are needed and output the instruction */
1203     switch (ExtBytes[A->AddrMode]) {
1204
1205         case 0:
1206             Emit0 (A->Opcode);
1207             break;
1208
1209         case 1:
1210             Emit1 (A->Opcode, A->Expr);
1211             break;
1212
1213         case 2:
1214             if (CPU == CPU_65816 && (A->AddrModeBit & (AM65_ABS | AM65_ABS_X | AM65_ABS_Y))) {
1215                 /* This is a 16 bit mode that uses an address. If in 65816,
1216                 ** mode, force this address into 16 bit range to allow
1217                 ** addressing inside a 64K segment.
1218                 */
1219                 Emit2 (A->Opcode, GenWordExpr (A->Expr));
1220             } else {
1221                 Emit2 (A->Opcode, A->Expr);
1222             }
1223             break;
1224
1225         case 3:
1226             /* Far argument */
1227             Emit3 (A->Opcode, A->Expr);
1228             break;
1229
1230         default:
1231             Internal ("Invalid operand byte count: %u", ExtBytes[A->AddrMode]);
1232
1233     }
1234 }
1235
1236
1237
1238 static long PutImmed8 (const InsDesc* Ins)
1239 /* Parse and emit an immediate 8 bit instruction. Return the value of the
1240 ** operand if it's available and const.
1241 */
1242 {
1243     EffAddr A;
1244     long Val = -1;
1245
1246     /* Evaluate the addressing mode */
1247     if (EvalEA (Ins, &A) == 0) {
1248         /* An error occurred */
1249         return -1L;
1250     }
1251
1252     /* If we have an expression and it's const, get it's value */
1253     if (A.Expr) {
1254         (void) IsConstExpr (A.Expr, &Val);
1255     }
1256
1257     /* Check how many extension bytes are needed and output the instruction */
1258     switch (ExtBytes[A.AddrMode]) {
1259
1260         case 1:
1261             Emit1 (A.Opcode, A.Expr);
1262             break;
1263
1264         default:
1265             Internal ("Invalid operand byte count: %u", ExtBytes[A.AddrMode]);
1266     }
1267
1268     /* Return the expression value */
1269     return Val;
1270 }
1271
1272
1273
1274 static void PutPCRel8 (const InsDesc* Ins)
1275 /* Handle branches with a 8 bit distance */
1276 {
1277     EmitPCRel (Ins->BaseCode, GenBranchExpr (2), 1);
1278 }
1279
1280
1281
1282 static void PutPCRel16 (const InsDesc* Ins)
1283 /* Handle branches with an 16 bit distance and PER */
1284 {
1285     EmitPCRel (Ins->BaseCode, GenBranchExpr (3), 2);
1286 }
1287
1288
1289
1290 static void PutPCRel4510 (const InsDesc* Ins)
1291 /* Handle branches with a 16 bit distance */
1292 {
1293     /* 16 bit branch opcode is 8 bit branch opcode or'ed with 0x03 */
1294     EmitPCRel (Ins->BaseCode, GenBranchExpr (2), 2);
1295 }
1296
1297
1298 static void PutBlockMove (const InsDesc* Ins)
1299 /* Handle the blockmove instructions (65816) */
1300 {
1301     Emit0 (Ins->BaseCode);
1302     EmitByte (Expression ());
1303     ConsumeComma ();
1304     EmitByte (Expression ());
1305 }
1306
1307
1308
1309 static void PutBlockTransfer (const InsDesc* Ins)
1310 /* Handle the block transfer instructions (HuC6280) */
1311 {
1312     Emit0 (Ins->BaseCode);
1313     EmitWord (Expression ());
1314     ConsumeComma ();
1315     EmitWord (Expression ());
1316     ConsumeComma ();
1317     EmitWord (Expression ());
1318 }
1319
1320
1321
1322 static void PutBitBranch (const InsDesc* Ins)
1323 /* Handle 65C02 branch on bit condition */
1324 {
1325     Emit0 (Ins->BaseCode);
1326     EmitByte (Expression ());
1327     ConsumeComma ();
1328     EmitSigned (GenBranchExpr (1), 1);
1329 }
1330
1331
1332
1333 static void PutREP (const InsDesc* Ins)
1334 /* Emit a REP instruction, track register sizes */
1335 {
1336     /* Use the generic handler */
1337     long Val = PutImmed8 (Ins);
1338
1339     /* We track the status only for the 816 CPU and in smart mode */
1340     if (CPU == CPU_65816 && SmartMode) {
1341
1342         /* Check the range for Val. */
1343         if (Val < 0) {
1344             /* We had an error */
1345             Warning (1, "Cannot track processor status byte");
1346         } else {
1347             if (Val & 0x10) {
1348                 /* Index registers to 16 bit */
1349                 ExtBytes[AM65I_IMM_INDEX] = 2;
1350             }
1351             if (Val & 0x20) {
1352                 /* Accu to 16 bit */
1353                 ExtBytes[AM65I_IMM_ACCU] = 2;
1354             }
1355         }
1356     }
1357 }
1358
1359
1360
1361 static void PutSEP (const InsDesc* Ins)
1362 /* Emit a SEP instruction (65816), track register sizes */
1363 {
1364     /* Use the generic handler */
1365     long Val = PutImmed8 (Ins);
1366
1367     /* We track the status only for the 816 CPU and in smart mode */
1368     if (CPU == CPU_65816 && SmartMode) {
1369
1370         /* Check the range for Val. */
1371         if (Val < 0) {
1372             /* We had an error */
1373             Warning (1, "Cannot track processor status byte");
1374         } else {
1375             if (Val & 0x10) {
1376                 /* Index registers to 8 bit */
1377                 ExtBytes[AM65I_IMM_INDEX] = 1;
1378             }
1379             if (Val & 0x20) {
1380                 /* Accu to 8 bit */
1381                 ExtBytes[AM65I_IMM_ACCU] = 1;
1382             }
1383         }
1384     }
1385 }
1386
1387
1388
1389 static void PutTAMn (const InsDesc* Ins)
1390 /* Emit a TAMn instruction (HuC6280). Since this is a two byte instruction with
1391 ** implicit addressing mode, the opcode byte in the table is actually the
1392 ** second operand byte. The TAM instruction is the more generic form, it takes
1393 ** an immediate argument.
1394 */
1395 {
1396     /* Emit the TAM opcode itself */
1397     Emit0 (0x53);
1398
1399     /* Emit the argument, which is the opcode from the table */
1400     Emit0 (Ins->BaseCode);
1401 }
1402
1403
1404
1405 static void PutTMA (const InsDesc* Ins)
1406 /* Emit a TMA instruction (HuC6280) with an immediate argument. Only one bit
1407 ** in the argument byte may be set.
1408 */
1409 {
1410     /* Use the generic handler */
1411     long Val = PutImmed8 (Ins);
1412
1413     /* Check the range for Val. */
1414     if (Val < 0) {
1415         /* We had an error */
1416         Warning (1, "Cannot check argument of TMA instruction");
1417     } else {
1418         /* Make sure just one bit is set */
1419         if ((Val & (Val - 1)) != 0) {
1420             Error ("Argument to TAM must be a power of two");
1421         }
1422     }
1423 }
1424
1425
1426
1427 static void PutTMAn (const InsDesc* Ins)
1428 /* Emit a TMAn instruction (HuC6280). Since this is a two byte instruction with
1429 ** implicit addressing mode, the opcode byte in the table is actually the
1430 ** second operand byte. The TAM instruction is the more generic form, it takes
1431 ** an immediate argument.
1432 */
1433 {
1434     /* Emit the TMA opcode itself */
1435     Emit0 (0x43);
1436
1437     /* Emit the argument, which is the opcode from the table */
1438     Emit0 (Ins->BaseCode);
1439 }
1440
1441
1442
1443 static void PutTST (const InsDesc* Ins)
1444 /* Emit a TST instruction (HuC6280). */
1445 {
1446     ExprNode* Arg1;
1447     EffAddr   A;
1448
1449     /* The first argument is always an immediate byte */
1450     if (CurTok.Tok != TOK_HASH) {
1451         ErrorSkip ("Invalid addressing mode");
1452         return;
1453     }
1454     NextTok ();
1455     Arg1 = Expression ();
1456
1457     /* Second argument follows */
1458     ConsumeComma ();
1459
1460     /* For the second argument, we use the standard function */
1461     if (EvalEA (Ins, &A)) {
1462
1463         /* No error, output code */
1464         Emit1 (A.Opcode, Arg1);
1465
1466         /* Check how many extension bytes are needed and output the instruction */
1467         switch (ExtBytes[A.AddrMode]) {
1468
1469             case 1:
1470                 EmitByte (A.Expr);
1471                 break;
1472
1473             case 2:
1474                 EmitWord (A.Expr);
1475                 break;
1476         }
1477     }
1478 }
1479
1480
1481
1482 static void PutJMP (const InsDesc* Ins)
1483 /* Handle the jump instruction for the 6502. Problem is that these chips have
1484 ** a bug: If the address crosses a page, the upper byte gets not corrected and
1485 ** the instruction will fail. The PutJmp function will add a linker assertion
1486 ** to check for this case and is otherwise identical to PutAll.
1487 */
1488 {
1489     EffAddr A;
1490
1491     /* Evaluate the addressing mode used */
1492     if (EvalEA (Ins, &A)) {
1493
1494         /* Check for indirect addressing */
1495         if (A.AddrModeBit & AM65_ABS_IND) {
1496
1497             /* Compare the low byte of the expression to 0xFF to check for
1498             ** a page cross. Be sure to use a copy of the expression otherwise
1499             ** things will go weird later.
1500             */
1501             ExprNode* E = GenNE (GenByteExpr (CloneExpr (A.Expr)), 0xFF);
1502
1503             /* Generate the message */
1504             unsigned Msg = GetStringId ("\"jmp (abs)\" across page border");
1505
1506             /* Generate the assertion */
1507             AddAssertion (E, ASSERT_ACT_WARN, Msg);
1508         }
1509
1510         /* No error, output code */
1511         EmitCode (&A);
1512     }
1513 }
1514
1515
1516
1517 static void PutRTS (const InsDesc* Ins attribute ((unused)))
1518 /* Handle the RTS instruction for the 816. In smart mode emit a RTL opcode if
1519 ** the enclosing scope is FAR.
1520 */
1521 {
1522     if (SmartMode && CurrentScope->AddrSize == ADDR_SIZE_FAR) {
1523         Emit0 (0x6B);       /* RTL */
1524     } else {
1525         Emit0 (0x60);       /* RTS */
1526     }
1527 }
1528
1529
1530
1531 static void PutAll (const InsDesc* Ins)
1532 /* Handle all other instructions */
1533 {
1534     EffAddr A;
1535
1536     /* Evaluate the addressing mode used */
1537     if (EvalEA (Ins, &A)) {
1538         /* No error, output code */
1539         EmitCode (&A);
1540     }
1541 }
1542
1543
1544
1545 static void Put4510 (const InsDesc* Ins)
1546 /* Handle all other instructions, with modifications for 4510 */
1547 {
1548     /* The 4510 uses all 256 possible opcodes, so the last ones were crammed
1549     ** in where an opcode was still undefined. As a result, some of those
1550     ** don't follow any rules for encoding the addressmodes. So the EATab
1551     ** approach does not work always. In this function, the wrongly calculated
1552     ** opcode is replaced by the correct one "on the fly". Suggestions for a
1553     ** better approach are welcome.
1554     **
1555     ** These are:
1556     ** $47 -> $44 : ASR $12
1557     ** $57 -> $54 : ASR $12,X
1558     ** $93 -> $82 : STA ($12,SP),Y
1559     ** $9c -> $8b : STY $1234,X
1560     ** $9e -> $9b : STX $1234,Y
1561     ** $af -> $ab : LDZ $1234
1562     ** $bf -> $bb : LDZ $1234,X
1563     ** $b3 -> $e2 : LDA ($12,SP),Y
1564     ** $d0 -> $c2 : CPZ #$00
1565     ** $fc -> $23 : JSR ($1234,X)
1566     */
1567     EffAddr A;
1568
1569     /* Evaluate the addressing mode used */
1570     if (EvalEA (Ins, &A)) {
1571         switch (A.Opcode) {
1572             case 0x47: A.Opcode = 0x44; break;
1573             case 0x57: A.Opcode = 0x54; break;
1574             case 0x93: A.Opcode = 0x82; break;
1575             case 0x9C: A.Opcode = 0x8B; break;
1576             case 0x9E: A.Opcode = 0x9B; break;
1577             case 0xAF: A.Opcode = 0xAB; break;
1578             case 0xBF: A.Opcode = 0xBB; break;
1579             case 0xB3: A.Opcode = 0xE2; break;
1580             case 0xD0: A.Opcode = 0xC2; break;
1581             case 0xFC: A.Opcode = 0x23; break;
1582             default: /* Keep opcode as it is */ break;
1583         }
1584
1585         /* No error, output code */
1586         EmitCode (&A);
1587     }
1588 }
1589
1590
1591
1592 /*****************************************************************************/
1593 /*                       Handler functions for SWEET16                       */
1594 /*****************************************************************************/
1595
1596
1597
1598 static void PutSweet16 (const InsDesc* Ins)
1599 /* Handle a generic sweet16 instruction */
1600 {
1601     EffAddr A;
1602
1603     /* Evaluate the addressing mode used */
1604     GetSweet16EA (&A);
1605
1606     /* From the possible addressing modes, remove the ones that are invalid
1607     ** for this instruction or CPU.
1608     */
1609     A.AddrModeSet &= Ins->AddrMode;
1610
1611     /* Check if we have any adressing modes left */
1612     if (A.AddrModeSet == 0) {
1613         Error ("Illegal addressing mode");
1614         return;
1615     }
1616     A.AddrMode    = BitFind (A.AddrModeSet);
1617     A.AddrModeBit = (0x01UL << A.AddrMode);
1618
1619     /* Build the opcode */
1620     A.Opcode = Ins->BaseCode | Sweet16EATab[Ins->ExtCode][A.AddrMode] | A.Reg;
1621
1622     /* Check how many extension bytes are needed and output the instruction */
1623     switch (Sweet16ExtBytes[A.AddrMode]) {
1624
1625         case 0:
1626             Emit0 (A.Opcode);
1627             break;
1628
1629         case 1:
1630             Emit1 (A.Opcode, A.Expr);
1631             break;
1632
1633         case 2:
1634             Emit2 (A.Opcode, A.Expr);
1635             break;
1636
1637         default:
1638             Internal ("Invalid operand byte count: %u", Sweet16ExtBytes[A.AddrMode]);
1639
1640     }
1641 }
1642
1643
1644
1645 static void PutSweet16Branch (const InsDesc* Ins)
1646 /* Handle a sweet16 branch instruction */
1647 {
1648     EmitPCRel (Ins->BaseCode, GenBranchExpr (2), 1);
1649 }
1650
1651
1652
1653 /*****************************************************************************/
1654 /*                                   Code                                    */
1655 /*****************************************************************************/
1656
1657
1658
1659 static int CmpName (const void* Key, const void* Instr)
1660 /* Compare function for bsearch */
1661 {
1662     return strcmp ((const char*)Key, ((const InsDesc*) Instr)->Mnemonic);
1663 }
1664
1665
1666
1667 void SetCPU (cpu_t NewCPU)
1668 /* Set a new CPU */
1669 {
1670     /* Make sure the parameter is correct */
1671     CHECK (NewCPU < CPU_COUNT);
1672
1673     /* Check if we have support for the new CPU, if so, use it */
1674     if (NewCPU != CPU_UNKNOWN && InsTabs[NewCPU]) {
1675         CPU = NewCPU;
1676         InsTab = InsTabs[CPU];
1677     } else {
1678         Error ("CPU not supported");
1679     }
1680 }
1681
1682
1683
1684 cpu_t GetCPU (void)
1685 /* Return the current CPU */
1686 {
1687     return CPU;
1688 }
1689
1690
1691
1692 int FindInstruction (const StrBuf* Ident)
1693 /* Check if Ident is a valid mnemonic. If so, return the index in the
1694 ** instruction table. If not, return -1.
1695 */
1696 {
1697     unsigned I;
1698     const InsDesc* ID;
1699     char Key[sizeof (ID->Mnemonic)];
1700
1701     /* Shortcut for the "none" CPU: If there are no instructions to search
1702     ** for, bail out early.
1703     */
1704     if (InsTab->Count == 0) {
1705         /* Not found */
1706         return -1;
1707     }
1708
1709     /* Make a copy, and uppercase that copy */
1710     I = 0;
1711     while (I < SB_GetLen (Ident)) {
1712         /* If the identifier is longer than the longest mnemonic, it cannot
1713         ** be one.
1714         */
1715         if (I >= sizeof (Key) - 1) {
1716             /* Not found, no need for further action */
1717             return -1;
1718         }
1719         Key[I] = toupper ((unsigned char)SB_AtUnchecked (Ident, I));
1720         ++I;
1721     }
1722     Key[I] = '\0';
1723
1724     /* Search for the key */
1725     ID = bsearch (Key, InsTab->Ins, InsTab->Count, sizeof (InsDesc), CmpName);
1726     if (ID == 0) {
1727         /* Not found */
1728         return -1;
1729     } else {
1730         /* Found, return the entry */
1731         return ID - InsTab->Ins;
1732     }
1733 }
1734
1735
1736
1737 void HandleInstruction (unsigned Index)
1738 /* Handle the mnemonic with the given index */
1739 {
1740     /* Safety check */
1741     PRECONDITION (Index < InsTab->Count);
1742
1743     /* Skip the mnemonic token */
1744     NextTok ();
1745
1746     /* Call the handler */
1747     InsTab->Ins[Index].Emit (&InsTab->Ins[Index]);
1748 }