]> git.sur5r.net Git - cc65/blob - src/ca65/instr.c
912e458670994a2d108c5e9c6fc5935a39369ba6
[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, 6, 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,              0x0C, 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
1299 static void PutBlockMove (const InsDesc* Ins)
1300 /* Handle the blockmove instructions (65816) */
1301 {
1302     ExprNode* Arg1;
1303     ExprNode* Arg2;
1304
1305     Emit0 (Ins->BaseCode);
1306
1307     if (CurTok.Tok == TOK_HASH) {
1308         /* The operand is a bank-byte expression. */
1309         NextTok ();
1310         Arg1 = Expression ();
1311     } else {
1312         /* The operand is a far-address expression.
1313         ** Use only its bank part.
1314         */
1315         Arg1 = FuncBankByte ();
1316     }
1317     ConsumeComma ();
1318
1319     if (CurTok.Tok == TOK_HASH) {
1320         NextTok ();
1321         Arg2 = Expression ();
1322     } else {
1323         Arg2 = FuncBankByte ();
1324     }
1325
1326     /* The operands are written in Assembly code as source, destination;
1327     ** but, they're assembled as <destination> <source>.
1328     */
1329     EmitByte (Arg2);
1330     EmitByte (Arg1);
1331 }
1332
1333
1334
1335 static void PutBlockTransfer (const InsDesc* Ins)
1336 /* Handle the block transfer instructions (HuC6280) */
1337 {
1338     Emit0 (Ins->BaseCode);
1339     EmitWord (Expression ());
1340     ConsumeComma ();
1341     EmitWord (Expression ());
1342     ConsumeComma ();
1343     EmitWord (Expression ());
1344 }
1345
1346
1347
1348 static void PutBitBranch (const InsDesc* Ins)
1349 /* Handle 65C02 branch on bit condition */
1350 {
1351     Emit0 (Ins->BaseCode);
1352     EmitByte (Expression ());
1353     ConsumeComma ();
1354     EmitSigned (GenBranchExpr (1), 1);
1355 }
1356
1357
1358
1359 static void PutREP (const InsDesc* Ins)
1360 /* Emit a REP instruction, track register sizes */
1361 {
1362     /* Use the generic handler */
1363     long Val = PutImmed8 (Ins);
1364
1365     /* We track the status only for the 816 CPU and in smart mode */
1366     if (CPU == CPU_65816 && SmartMode) {
1367
1368         /* Check the range for Val. */
1369         if (Val < 0) {
1370             /* We had an error */
1371             Warning (1, "Cannot track processor status byte");
1372         } else {
1373             if (Val & 0x10) {
1374                 /* Index registers to 16 bit */
1375                 ExtBytes[AM65I_IMM_INDEX] = 2;
1376             }
1377             if (Val & 0x20) {
1378                 /* Accu to 16 bit */
1379                 ExtBytes[AM65I_IMM_ACCU] = 2;
1380             }
1381         }
1382     }
1383 }
1384
1385
1386
1387 static void PutSEP (const InsDesc* Ins)
1388 /* Emit a SEP instruction (65816), track register sizes */
1389 {
1390     /* Use the generic handler */
1391     long Val = PutImmed8 (Ins);
1392
1393     /* We track the status only for the 816 CPU and in smart mode */
1394     if (CPU == CPU_65816 && SmartMode) {
1395
1396         /* Check the range for Val. */
1397         if (Val < 0) {
1398             /* We had an error */
1399             Warning (1, "Cannot track processor status byte");
1400         } else {
1401             if (Val & 0x10) {
1402                 /* Index registers to 8 bit */
1403                 ExtBytes[AM65I_IMM_INDEX] = 1;
1404             }
1405             if (Val & 0x20) {
1406                 /* Accu to 8 bit */
1407                 ExtBytes[AM65I_IMM_ACCU] = 1;
1408             }
1409         }
1410     }
1411 }
1412
1413
1414
1415 static void PutTAMn (const InsDesc* Ins)
1416 /* Emit a TAMn instruction (HuC6280). Since this is a two byte instruction with
1417 ** implicit addressing mode, the opcode byte in the table is actually the
1418 ** second operand byte. The TAM instruction is the more generic form, it takes
1419 ** an immediate argument.
1420 */
1421 {
1422     /* Emit the TAM opcode itself */
1423     Emit0 (0x53);
1424
1425     /* Emit the argument, which is the opcode from the table */
1426     Emit0 (Ins->BaseCode);
1427 }
1428
1429
1430
1431 static void PutTMA (const InsDesc* Ins)
1432 /* Emit a TMA instruction (HuC6280) with an immediate argument. Only one bit
1433 ** in the argument byte may be set.
1434 */
1435 {
1436     /* Use the generic handler */
1437     long Val = PutImmed8 (Ins);
1438
1439     /* Check the range for Val. */
1440     if (Val < 0) {
1441         /* We had an error */
1442         Warning (1, "Cannot check argument of TMA instruction");
1443     } else {
1444         /* Make sure just one bit is set */
1445         if ((Val & (Val - 1)) != 0) {
1446             Error ("Argument to TAM must be a power of two");
1447         }
1448     }
1449 }
1450
1451
1452
1453 static void PutTMAn (const InsDesc* Ins)
1454 /* Emit a TMAn instruction (HuC6280). Since this is a two byte instruction with
1455 ** implicit addressing mode, the opcode byte in the table is actually the
1456 ** second operand byte. The TAM instruction is the more generic form, it takes
1457 ** an immediate argument.
1458 */
1459 {
1460     /* Emit the TMA opcode itself */
1461     Emit0 (0x43);
1462
1463     /* Emit the argument, which is the opcode from the table */
1464     Emit0 (Ins->BaseCode);
1465 }
1466
1467
1468
1469 static void PutTST (const InsDesc* Ins)
1470 /* Emit a TST instruction (HuC6280). */
1471 {
1472     ExprNode* Arg1;
1473     EffAddr   A;
1474
1475     /* The first argument is always an immediate byte */
1476     if (CurTok.Tok != TOK_HASH) {
1477         ErrorSkip ("Invalid addressing mode");
1478         return;
1479     }
1480     NextTok ();
1481     Arg1 = Expression ();
1482
1483     /* Second argument follows */
1484     ConsumeComma ();
1485
1486     /* For the second argument, we use the standard function */
1487     if (EvalEA (Ins, &A)) {
1488
1489         /* No error, output code */
1490         Emit1 (A.Opcode, Arg1);
1491
1492         /* Check how many extension bytes are needed and output the instruction */
1493         switch (ExtBytes[A.AddrMode]) {
1494
1495             case 1:
1496                 EmitByte (A.Expr);
1497                 break;
1498
1499             case 2:
1500                 EmitWord (A.Expr);
1501                 break;
1502         }
1503     }
1504 }
1505
1506
1507
1508 static void PutJMP (const InsDesc* Ins)
1509 /* Handle the jump instruction for the 6502. Problem is that these chips have
1510 ** a bug: If the address crosses a page, the upper byte gets not corrected and
1511 ** the instruction will fail. The PutJmp function will add a linker assertion
1512 ** to check for this case and is otherwise identical to PutAll.
1513 */
1514 {
1515     EffAddr A;
1516
1517     /* Evaluate the addressing mode used */
1518     if (EvalEA (Ins, &A)) {
1519
1520         /* Check for indirect addressing */
1521         if (A.AddrModeBit & AM65_ABS_IND) {
1522
1523             /* Compare the low byte of the expression to 0xFF to check for
1524             ** a page cross. Be sure to use a copy of the expression otherwise
1525             ** things will go weird later.
1526             */
1527             ExprNode* E = GenNE (GenByteExpr (CloneExpr (A.Expr)), 0xFF);
1528
1529             /* Generate the message */
1530             unsigned Msg = GetStringId ("\"jmp (abs)\" across page border");
1531
1532             /* Generate the assertion */
1533             AddAssertion (E, ASSERT_ACT_WARN, Msg);
1534         }
1535
1536         /* No error, output code */
1537         EmitCode (&A);
1538     }
1539 }
1540
1541
1542
1543 static void PutRTS (const InsDesc* Ins attribute ((unused)))
1544 /* Handle the RTS instruction for the 816. In smart mode emit a RTL opcode if
1545 ** the enclosing scope is FAR.
1546 */
1547 {
1548     if (SmartMode && CurrentScope->AddrSize == ADDR_SIZE_FAR) {
1549         Emit0 (0x6B);       /* RTL */
1550     } else {
1551         Emit0 (0x60);       /* RTS */
1552     }
1553 }
1554
1555
1556
1557 static void PutAll (const InsDesc* Ins)
1558 /* Handle all other instructions */
1559 {
1560     EffAddr A;
1561
1562     /* Evaluate the addressing mode used */
1563     if (EvalEA (Ins, &A)) {
1564         /* No error, output code */
1565         EmitCode (&A);
1566     }
1567 }
1568
1569
1570
1571 static void Put4510 (const InsDesc* Ins)
1572 /* Handle all other instructions, with modifications for 4510 */
1573 {
1574     /* The 4510 uses all 256 possible opcodes, so the last ones were crammed
1575     ** in where an opcode was still undefined. As a result, some of those
1576     ** don't follow any rules for encoding the addressmodes. So the EATab
1577     ** approach does not work always. In this function, the wrongly calculated
1578     ** opcode is replaced by the correct one "on the fly". Suggestions for a
1579     ** better approach are welcome.
1580     **
1581     ** These are:
1582     ** $47 -> $44 : ASR $12
1583     ** $57 -> $54 : ASR $12,X
1584     ** $93 -> $82 : STA ($12,SP),Y
1585     ** $9c -> $8b : STY $1234,X
1586     ** $9e -> $9b : STX $1234,Y
1587     ** $af -> $ab : LDZ $1234
1588     ** $bf -> $bb : LDZ $1234,X
1589     ** $b3 -> $e2 : LDA ($12,SP),Y
1590     ** $d0 -> $c2 : CPZ #$00
1591     ** $fc -> $23 : JSR ($1234,X)
1592     */
1593     EffAddr A;
1594
1595     /* Evaluate the addressing mode used */
1596     if (EvalEA (Ins, &A)) {
1597         switch (A.Opcode) {
1598             case 0x47: A.Opcode = 0x44; break;
1599             case 0x57: A.Opcode = 0x54; break;
1600             case 0x93: A.Opcode = 0x82; break;
1601             case 0x9C: A.Opcode = 0x8B; break;
1602             case 0x9E: A.Opcode = 0x9B; break;
1603             case 0xAF: A.Opcode = 0xAB; break;
1604             case 0xBF: A.Opcode = 0xBB; break;
1605             case 0xB3: A.Opcode = 0xE2; break;
1606             case 0xD0: A.Opcode = 0xC2; break;
1607             case 0xFC: A.Opcode = 0x23; break;
1608             default: /* Keep opcode as it is */ break;
1609         }
1610
1611         /* No error, output code */
1612         EmitCode (&A);
1613     }
1614 }
1615
1616
1617
1618 /*****************************************************************************/
1619 /*                       Handler functions for SWEET16                       */
1620 /*****************************************************************************/
1621
1622
1623
1624 static void PutSweet16 (const InsDesc* Ins)
1625 /* Handle a generic sweet16 instruction */
1626 {
1627     EffAddr A;
1628
1629     /* Evaluate the addressing mode used */
1630     GetSweet16EA (&A);
1631
1632     /* From the possible addressing modes, remove the ones that are invalid
1633     ** for this instruction or CPU.
1634     */
1635     A.AddrModeSet &= Ins->AddrMode;
1636
1637     /* Check if we have any adressing modes left */
1638     if (A.AddrModeSet == 0) {
1639         Error ("Illegal addressing mode");
1640         return;
1641     }
1642     A.AddrMode    = BitFind (A.AddrModeSet);
1643     A.AddrModeBit = (0x01UL << A.AddrMode);
1644
1645     /* Build the opcode */
1646     A.Opcode = Ins->BaseCode | Sweet16EATab[Ins->ExtCode][A.AddrMode] | A.Reg;
1647
1648     /* Check how many extension bytes are needed and output the instruction */
1649     switch (Sweet16ExtBytes[A.AddrMode]) {
1650
1651         case 0:
1652             Emit0 (A.Opcode);
1653             break;
1654
1655         case 1:
1656             Emit1 (A.Opcode, A.Expr);
1657             break;
1658
1659         case 2:
1660             Emit2 (A.Opcode, A.Expr);
1661             break;
1662
1663         default:
1664             Internal ("Invalid operand byte count: %u", Sweet16ExtBytes[A.AddrMode]);
1665
1666     }
1667 }
1668
1669
1670
1671 static void PutSweet16Branch (const InsDesc* Ins)
1672 /* Handle a sweet16 branch instruction */
1673 {
1674     EmitPCRel (Ins->BaseCode, GenBranchExpr (2), 1);
1675 }
1676
1677
1678
1679 /*****************************************************************************/
1680 /*                                   Code                                    */
1681 /*****************************************************************************/
1682
1683
1684
1685 static int CmpName (const void* Key, const void* Instr)
1686 /* Compare function for bsearch */
1687 {
1688     return strcmp ((const char*)Key, ((const InsDesc*) Instr)->Mnemonic);
1689 }
1690
1691
1692
1693 void SetCPU (cpu_t NewCPU)
1694 /* Set a new CPU */
1695 {
1696     /* Make sure the parameter is correct */
1697     CHECK (NewCPU < CPU_COUNT);
1698
1699     /* Check if we have support for the new CPU, if so, use it */
1700     if (NewCPU != CPU_UNKNOWN && InsTabs[NewCPU]) {
1701         CPU = NewCPU;
1702         InsTab = InsTabs[CPU];
1703     } else {
1704         Error ("CPU not supported");
1705     }
1706 }
1707
1708
1709
1710 cpu_t GetCPU (void)
1711 /* Return the current CPU */
1712 {
1713     return CPU;
1714 }
1715
1716
1717
1718 int FindInstruction (const StrBuf* Ident)
1719 /* Check if Ident is a valid mnemonic. If so, return the index in the
1720 ** instruction table. If not, return -1.
1721 */
1722 {
1723     unsigned I;
1724     const InsDesc* ID;
1725     char Key[sizeof (ID->Mnemonic)];
1726
1727     /* Shortcut for the "none" CPU: If there are no instructions to search
1728     ** for, bail out early.
1729     */
1730     if (InsTab->Count == 0) {
1731         /* Not found */
1732         return -1;
1733     }
1734
1735     /* Make a copy, and uppercase that copy */
1736     I = 0;
1737     while (I < SB_GetLen (Ident)) {
1738         /* If the identifier is longer than the longest mnemonic, it cannot
1739         ** be one.
1740         */
1741         if (I >= sizeof (Key) - 1) {
1742             /* Not found, no need for further action */
1743             return -1;
1744         }
1745         Key[I] = toupper ((unsigned char)SB_AtUnchecked (Ident, I));
1746         ++I;
1747     }
1748     Key[I] = '\0';
1749
1750     /* Search for the key */
1751     ID = bsearch (Key, InsTab->Ins, InsTab->Count, sizeof (InsDesc), CmpName);
1752     if (ID == 0) {
1753         /* Not found */
1754         return -1;
1755     } else {
1756         /* Found, return the entry */
1757         return ID - InsTab->Ins;
1758     }
1759 }
1760
1761
1762
1763 void HandleInstruction (unsigned Index)
1764 /* Handle the mnemonic with the given index */
1765 {
1766     /* Safety check */
1767     PRECONDITION (Index < InsTab->Count);
1768
1769     /* Skip the mnemonic token */
1770     NextTok ();
1771
1772     /* Call the handler */
1773     InsTab->Ins[Index].Emit (&InsTab->Ins[Index]);
1774 }