]> git.sur5r.net Git - cc65/blob - src/ca65/instr.c
Merge pull request #863 from Compyx/master
[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[100];
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         { "WDM",  0x0000004, 0x42, 6, PutAll },
740         { "XBA",  0x0000001, 0xeb, 0, PutAll },
741         { "XCE",  0x0000001, 0xfb, 0, PutAll }
742     }
743 };
744
745 /* Instruction table for the SWEET16 pseudo CPU */
746 static const struct {
747     unsigned Count;
748     InsDesc  Ins[26];
749 } InsTabSweet16 = {
750     sizeof (InsTabSweet16.Ins) / sizeof (InsTabSweet16.Ins[0]),
751     {
752         { "ADD",  AMSW16_REG,              0xA0, 0, PutSweet16 },
753         { "BC",   AMSW16_BRA,              0x03, 0, PutSweet16Branch },
754         { "BK",   AMSW16_IMP,              0x0A, 0, PutSweet16 },
755         { "BM",   AMSW16_BRA,              0x05, 0, PutSweet16Branch },
756         { "BM1",  AMSW16_BRA,              0x08, 0, PutSweet16Branch },
757         { "BNC",  AMSW16_BRA,              0x02, 0, PutSweet16Branch },
758         { "BNM1", AMSW16_BRA,              0x09, 0, PutSweet16Branch },
759         { "BNZ",  AMSW16_BRA,              0x07, 0, PutSweet16Branch },
760         { "BP",   AMSW16_BRA,              0x04, 0, PutSweet16Branch },
761         { "BR",   AMSW16_BRA,              0x01, 0, PutSweet16Branch },
762         { "BS",   AMSW16_BRA,              0x0C, 0, PutSweet16Branch },
763         { "BZ",   AMSW16_BRA,              0x06, 0, PutSweet16Branch },
764         { "CPR",  AMSW16_REG,              0xD0, 0, PutSweet16 },
765         { "DCR",  AMSW16_REG,              0xF0, 0, PutSweet16 },
766         { "INR",  AMSW16_REG,              0xE0, 0, PutSweet16 },
767         { "LD",   AMSW16_REG | AMSW16_IND, 0x00, 1, PutSweet16 },
768         { "LDD",  AMSW16_IND,              0x60, 0, PutSweet16 },
769         { "POP",  AMSW16_IND,              0x80, 0, PutSweet16 },
770         { "POPD", AMSW16_IND,              0xC0, 0, PutSweet16 },
771         { "RS",   AMSW16_IMP,              0x0B, 0, PutSweet16 },
772         { "RTN",  AMSW16_IMP,              0x00, 0, PutSweet16 },
773         { "SET",  AMSW16_IMM,              0x10, 0, PutSweet16 },
774         { "ST",   AMSW16_REG | AMSW16_IND, 0x10, 1, PutSweet16 },
775         { "STD",  AMSW16_IND,              0x70, 0, PutSweet16 },
776         { "STP",  AMSW16_IND,              0x90, 0, PutSweet16 },
777         { "SUB",  AMSW16_REG,              0xB0, 0, PutSweet16 },
778     }
779 };
780
781 /* Instruction table for the HuC6280 (the CPU used in the PC engine) */
782 static const struct {
783     unsigned Count;
784     InsDesc  Ins[135];
785 } InsTabHuC6280 = {
786     sizeof (InsTabHuC6280.Ins) / sizeof (InsTabHuC6280.Ins[0]),
787     {
788         { "ADC",  0x080A66C, 0x60, 0, PutAll },
789         { "AND",  0x080A66C, 0x20, 0, PutAll },
790         { "ASL",  0x000006e, 0x02, 1, PutAll },
791         { "BBR0", 0x0000000, 0x0F, 0, PutBitBranch },
792         { "BBR1", 0x0000000, 0x1F, 0, PutBitBranch },
793         { "BBR2", 0x0000000, 0x2F, 0, PutBitBranch },
794         { "BBR3", 0x0000000, 0x3F, 0, PutBitBranch },
795         { "BBR4", 0x0000000, 0x4F, 0, PutBitBranch },
796         { "BBR5", 0x0000000, 0x5F, 0, PutBitBranch },
797         { "BBR6", 0x0000000, 0x6F, 0, PutBitBranch },
798         { "BBR7", 0x0000000, 0x7F, 0, PutBitBranch },
799         { "BBS0", 0x0000000, 0x8F, 0, PutBitBranch },
800         { "BBS1", 0x0000000, 0x9F, 0, PutBitBranch },
801         { "BBS2", 0x0000000, 0xAF, 0, PutBitBranch },
802         { "BBS3", 0x0000000, 0xBF, 0, PutBitBranch },
803         { "BBS4", 0x0000000, 0xCF, 0, PutBitBranch },
804         { "BBS5", 0x0000000, 0xDF, 0, PutBitBranch },
805         { "BBS6", 0x0000000, 0xEF, 0, PutBitBranch },
806         { "BBS7", 0x0000000, 0xFF, 0, PutBitBranch },
807         { "BCC",  0x0020000, 0x90, 0, PutPCRel8 },
808         { "BCS",  0x0020000, 0xb0, 0, PutPCRel8 },
809         { "BEQ",  0x0020000, 0xf0, 0, PutPCRel8 },
810         { "BIT",  0x0A0006C, 0x00, 2, PutAll },
811         { "BMI",  0x0020000, 0x30, 0, PutPCRel8 },
812         { "BNE",  0x0020000, 0xd0, 0, PutPCRel8 },
813         { "BPL",  0x0020000, 0x10, 0, PutPCRel8 },
814         { "BRA",  0x0020000, 0x80, 0, PutPCRel8 },
815         { "BRK",  0x0000001, 0x00, 0, PutAll },
816         { "BSR",  0x0020000, 0x44, 0, PutPCRel8 },
817         { "BVC",  0x0020000, 0x50, 0, PutPCRel8 },
818         { "BVS",  0x0020000, 0x70, 0, PutPCRel8 },
819         { "CLA",  0x0000001, 0x62, 0, PutAll },
820         { "CLC",  0x0000001, 0x18, 0, PutAll },
821         { "CLD",  0x0000001, 0xd8, 0, PutAll },
822         { "CLI",  0x0000001, 0x58, 0, PutAll },
823         { "CLV",  0x0000001, 0xb8, 0, PutAll },
824         { "CLX",  0x0000001, 0x82, 0, PutAll },
825         { "CLY",  0x0000001, 0xc2, 0, PutAll },
826         { "CMP",  0x080A66C, 0xc0, 0, PutAll },
827         { "CPX",  0x080000C, 0xe0, 1, PutAll },
828         { "CPY",  0x080000C, 0xc0, 1, PutAll },
829         { "CSH",  0x0000001, 0xd4, 0, PutAll },
830         { "CSL",  0x0000001, 0x54, 0, PutAll },
831         { "DEA",  0x0000001, 0x00, 3, PutAll },   /* == DEC */
832         { "DEC",  0x000006F, 0x00, 3, PutAll },
833         { "DEX",  0x0000001, 0xca, 0, PutAll },
834         { "DEY",  0x0000001, 0x88, 0, PutAll },
835         { "EOR",  0x080A66C, 0x40, 0, PutAll },
836         { "INA",  0x0000001, 0x00, 4, PutAll },   /* == INC */
837         { "INC",  0x000006f, 0x00, 4, PutAll },
838         { "INX",  0x0000001, 0xe8, 0, PutAll },
839         { "INY",  0x0000001, 0xc8, 0, PutAll },
840         { "JMP",  0x0010808, 0x4c, 6, PutAll },
841         { "JSR",  0x0000008, 0x20, 7, PutAll },
842         { "LDA",  0x080A66C, 0xa0, 0, PutAll },
843         { "LDX",  0x080030C, 0xa2, 1, PutAll },
844         { "LDY",  0x080006C, 0xa0, 1, PutAll },
845         { "LSR",  0x000006F, 0x42, 1, PutAll },
846         { "NOP",  0x0000001, 0xea, 0, PutAll },
847         { "ORA",  0x080A66C, 0x00, 0, PutAll },
848         { "PHA",  0x0000001, 0x48, 0, PutAll },
849         { "PHP",  0x0000001, 0x08, 0, PutAll },
850         { "PHX",  0x0000001, 0xda, 0, PutAll },
851         { "PHY",  0x0000001, 0x5a, 0, PutAll },
852         { "PLA",  0x0000001, 0x68, 0, PutAll },
853         { "PLP",  0x0000001, 0x28, 0, PutAll },
854         { "PLX",  0x0000001, 0xfa, 0, PutAll },
855         { "PLY",  0x0000001, 0x7a, 0, PutAll },
856         { "RMB0", 0x0000004, 0x07, 1, PutAll },
857         { "RMB1", 0x0000004, 0x17, 1, PutAll },
858         { "RMB2", 0x0000004, 0x27, 1, PutAll },
859         { "RMB3", 0x0000004, 0x37, 1, PutAll },
860         { "RMB4", 0x0000004, 0x47, 1, PutAll },
861         { "RMB5", 0x0000004, 0x57, 1, PutAll },
862         { "RMB6", 0x0000004, 0x67, 1, PutAll },
863         { "RMB7", 0x0000004, 0x77, 1, PutAll },
864         { "ROL",  0x000006F, 0x22, 1, PutAll },
865         { "ROR",  0x000006F, 0x62, 1, PutAll },
866         { "RTI",  0x0000001, 0x40, 0, PutAll },
867         { "RTS",  0x0000001, 0x60, 0, PutAll },
868         { "SAX",  0x0000001, 0x22, 0, PutAll },
869         { "SAY",  0x0000001, 0x42, 0, PutAll },
870         { "SBC",  0x080A66C, 0xe0, 0, PutAll },
871         { "SEC",  0x0000001, 0x38, 0, PutAll },
872         { "SED",  0x0000001, 0xf8, 0, PutAll },
873         { "SEI",  0x0000001, 0x78, 0, PutAll },
874         { "SET",  0x0000001, 0xf4, 0, PutAll },
875         { "SMB0", 0x0000004, 0x87, 1, PutAll },
876         { "SMB1", 0x0000004, 0x97, 1, PutAll },
877         { "SMB2", 0x0000004, 0xA7, 1, PutAll },
878         { "SMB3", 0x0000004, 0xB7, 1, PutAll },
879         { "SMB4", 0x0000004, 0xC7, 1, PutAll },
880         { "SMB5", 0x0000004, 0xD7, 1, PutAll },
881         { "SMB6", 0x0000004, 0xE7, 1, PutAll },
882         { "SMB7", 0x0000004, 0xF7, 1, PutAll },
883         { "ST0",  0x0800000, 0x03, 1, PutAll },
884         { "ST1",  0x0800000, 0x13, 1, PutAll },
885         { "ST2",  0x0800000, 0x23, 1, PutAll },
886         { "STA",  0x000A66C, 0x80, 0, PutAll },
887         { "STX",  0x000010c, 0x82, 1, PutAll },
888         { "STY",  0x000002c, 0x80, 1, PutAll },
889         { "STZ",  0x000006c, 0x04, 5, PutAll },
890         { "SXY",  0x0000001, 0x02, 0, PutAll },
891         { "TAI",  0x2000000, 0xf3, 0, PutBlockTransfer },
892         { "TAM",  0x0800000, 0x53, 1, PutAll },
893         { "TAM0", 0x0000001, 0x01, 0, PutTAMn},
894         { "TAM1", 0x0000001, 0x02, 0, PutTAMn},
895         { "TAM2", 0x0000001, 0x04, 0, PutTAMn},
896         { "TAM3", 0x0000001, 0x08, 0, PutTAMn},
897         { "TAM4", 0x0000001, 0x10, 0, PutTAMn},
898         { "TAM5", 0x0000001, 0x20, 0, PutTAMn},
899         { "TAM6", 0x0000001, 0x40, 0, PutTAMn},
900         { "TAM7", 0x0000001, 0x80, 0, PutTAMn},
901         { "TAX",  0x0000001, 0xaa, 0, PutAll },
902         { "TAY",  0x0000001, 0xa8, 0, PutAll },
903         { "TDD",  0x2000000, 0xc3, 0, PutBlockTransfer },
904         { "TIA",  0x2000000, 0xe3, 0, PutBlockTransfer },
905         { "TII",  0x2000000, 0x73, 0, PutBlockTransfer },
906         { "TIN",  0x2000000, 0xD3, 0, PutBlockTransfer },
907         { "TMA",  0x0800000, 0x43, 1, PutTMA },
908         { "TMA0", 0x0000001, 0x01, 0, PutTMAn},
909         { "TMA1", 0x0000001, 0x02, 0, PutTMAn},
910         { "TMA2", 0x0000001, 0x04, 0, PutTMAn},
911         { "TMA3", 0x0000001, 0x08, 0, PutTMAn},
912         { "TMA4", 0x0000001, 0x10, 0, PutTMAn},
913         { "TMA5", 0x0000001, 0x20, 0, PutTMAn},
914         { "TMA6", 0x0000001, 0x40, 0, PutTMAn},
915         { "TMA7", 0x0000001, 0x80, 0, PutTMAn},
916         { "TRB",  0x000000c, 0x10, 1, PutAll },
917         { "TSB",  0x000000c, 0x00, 1, PutAll },
918         { "TST",  0x000006c, 0x83, 9, PutTST },
919         { "TSX",  0x0000001, 0xba, 0, PutAll },
920         { "TXA",  0x0000001, 0x8a, 0, PutAll },
921         { "TXS",  0x0000001, 0x9a, 0, PutAll },
922         { "TYA",  0x0000001, 0x98, 0, PutAll }
923     }
924 };
925
926
927
928 /* An array with instruction tables */
929 static const InsTable* InsTabs[CPU_COUNT] = {
930     (const InsTable*) &InsTabNone,
931     (const InsTable*) &InsTab6502,
932     (const InsTable*) &InsTab6502X,
933     (const InsTable*) &InsTab65SC02,
934     (const InsTable*) &InsTab65C02,
935     (const InsTable*) &InsTab65816,
936     (const InsTable*) &InsTabSweet16,
937     (const InsTable*) &InsTabHuC6280,
938     0,                                  /* Mitsubishi 740 */
939     (const InsTable*) &InsTab4510,
940 };
941 const InsTable* InsTab = (const InsTable*) &InsTab6502;
942
943 /* Table to build the effective 65xx opcode from a base opcode and an
944 ** addressing mode. (The value in the table is ORed with the base opcode)
945 */
946 static unsigned char EATab[12][AM65I_COUNT] = {
947     {   /* Table 0 */
948         0x00, 0x00, 0x05, 0x0D, 0x0F, 0x15, 0x1D, 0x1F,
949         0x00, 0x19, 0x12, 0x00, 0x07, 0x11, 0x17, 0x01,
950         0x00, 0x00, 0x00, 0x03, 0x13, 0x09, 0x00, 0x09,
951         0x00, 0x00, 0x00, 0x00
952     },
953     {   /* Table 1 */
954         0x08, 0x08, 0x04, 0x0C, 0x00, 0x14, 0x1C, 0x00,
955         0x14, 0x1C, 0x00, 0x80, 0x00, 0x10, 0x00, 0x00,
956         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
957         0x00, 0x00, 0x80, 0x00
958     },
959     {   /* Table 2 */
960         0x00, 0x00, 0x24, 0x2C, 0x0F, 0x34, 0x3C, 0x00,
961         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
962         0x00, 0x00, 0x00, 0x00, 0x00, 0x89, 0x00, 0x00,
963         0x00, 0x00, 0x00, 0x00
964     },
965     {   /* Table 3 */
966         0x3A, 0x3A, 0xC6, 0xCE, 0x00, 0xD6, 0xDE, 0x00,
967         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
968         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
969         0x00, 0x00, 0x00, 0x00
970     },
971     {   /* Table 4 */
972         0x1A, 0x1A, 0xE6, 0xEE, 0x00, 0xF6, 0xFE, 0x00,
973         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
974         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
975         0x00, 0x00, 0x00, 0x00
976     },
977     {   /* Table 5 */
978         0x00, 0x00, 0x60, 0x98, 0x00, 0x70, 0x9E, 0x00,
979         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
980         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
981         0x00, 0x00, 0x00, 0x00
982     },
983     {   /* Table 6 */
984         0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
985         0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00,
986         0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
987         0x00, 0x00, 0x90, 0x00
988     },
989     {   /* Table 7 (Subroutine opcodes) */
990         0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
991         0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00,
992         0xDC, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
993         0x00, 0x00, 0x00, 0x00
994     },
995     {   /* Table 8 */
996         0x00, 0x40, 0x01, 0x41, 0x00, 0x09, 0x49, 0x00,
997         0x00, 0x00, 0x00, 0x51, 0x00, 0x00, 0x00, 0x00,
998         0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00,
999         0x00, 0x00, 0x00, 0x00
1000     },
1001     {   /* Table 9 */
1002         0x00, 0x00, 0x00, 0x10, 0x00, 0x20, 0x30, 0x00,
1003         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1004         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1005         0x00, 0x00, 0x00, 0x00
1006     },
1007     {   /* Table 10 (NOPs) */
1008         0xea, 0x00, 0x04, 0x0c, 0x00, 0x14, 0x1c, 0x00,
1009         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1010         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80,
1011         0x00, 0x00, 0x00, 0x00
1012     },
1013     {   /* Table 11 (LAX) */
1014         0x08, 0x08, 0x04, 0x0C, 0x00, 0x14, 0x1C, 0x00,
1015         0x14, 0x1C, 0x00, 0x80, 0x00, 0x10, 0x00, 0x00,
1016         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08,
1017         0x00, 0x00, 0x80, 0x00
1018     },
1019 };
1020
1021 /* Table to build the effective SWEET16 opcode from a base opcode and an
1022 ** addressing mode.
1023 */
1024 static unsigned char Sweet16EATab[2][AMSW16I_COUNT] = {
1025     {   /* Table 0 */
1026         0x00, 0x00, 0x00, 0x00, 0x00,
1027     },
1028     {   /* Table 1 */
1029         0x00, 0x00, 0x00, 0x40, 0x20,
1030     },
1031 };
1032
1033 /* Table that encodes the additional bytes for each 65xx instruction */
1034 unsigned char ExtBytes[AM65I_COUNT] = {
1035     0,          /* Implicit */
1036     0,          /* Accu */
1037     1,          /* Direct */
1038     2,          /* Absolute */
1039     3,          /* Absolute long */
1040     1,          /* Direct,X */
1041     2,          /* Absolute,X */
1042     3,          /* Absolute long,X */
1043     1,          /* Direct,Y */
1044     2,          /* Absolute,Y */
1045     1,          /* (Direct) */
1046     2,          /* (Absolute) */
1047     1,          /* [Direct] */
1048     1,          /* (Direct),Y */
1049     1,          /* [Direct],Y */
1050     1,          /* (Direct,X) */
1051     2,          /* (Absolute,X) */
1052     1,          /* Relative short */
1053     2,          /* Relative long */
1054     1,          /* r,s */
1055     1,          /* (r,s),y */
1056     1,          /* Immidiate accu */
1057     1,          /* Immidiate index */
1058     1,          /* Immidiate byte */
1059     2,          /* Blockmove (65816) */
1060     7,          /* Block transfer (HuC6280) */
1061     2,          /* Absolute Indirect long */
1062     2,          /* Immidiate word */
1063 };
1064
1065 /* Table that encodes the additional bytes for each SWEET16 instruction */
1066 static unsigned char Sweet16ExtBytes[AMSW16I_COUNT] = {
1067     0,          /* AMSW16_IMP */
1068     1,          /* AMSW16_BRA */
1069     2,          /* AMSW16_IMM */
1070     0,          /* AMSW16_IND */
1071     0,          /* AMSW16_REG */
1072 };
1073
1074
1075
1076 /*****************************************************************************/
1077 /*                   Handler functions for 6502 derivates                    */
1078 /*****************************************************************************/
1079
1080
1081
1082 static int EvalEA (const InsDesc* Ins, EffAddr* A)
1083 /* Evaluate the effective address. All fields in A will be valid after calling
1084 ** this function. The function returns true on success and false on errors.
1085 */
1086 {
1087     /* Get the set of possible addressing modes */
1088     GetEA (A);
1089
1090     /* From the possible addressing modes, remove the ones that are invalid
1091     ** for this instruction or CPU.
1092     */
1093     A->AddrModeSet &= Ins->AddrMode;
1094
1095     /* If we have an expression, check it and remove any addressing modes that
1096     ** are too small for the expression size. Since we have to study the
1097     ** expression anyway, do also replace it by a simpler one if possible.
1098     */
1099     if (A->Expr) {
1100         ExprDesc ED;
1101         ED_Init (&ED);
1102
1103         /* Study the expression */
1104         StudyExpr (A->Expr, &ED);
1105
1106         /* Simplify it if possible */
1107         A->Expr = SimplifyExpr (A->Expr, &ED);
1108
1109         if (ED.AddrSize == ADDR_SIZE_DEFAULT) {
1110             /* We don't know how big the expression is. If the instruction
1111             ** allows just one addressing mode, assume this as address size
1112             ** for the expression. Otherwise assume the default address size
1113             ** for data.
1114             */
1115             if ((A->AddrModeSet & ~AM65_ALL_ZP) == 0) {
1116                 ED.AddrSize = ADDR_SIZE_ZP;
1117             } else if ((A->AddrModeSet & ~AM65_ALL_ABS) == 0) {
1118                 ED.AddrSize = ADDR_SIZE_ABS;
1119             } else if ((A->AddrModeSet & ~AM65_ALL_FAR) == 0) {
1120                 ED.AddrSize = ADDR_SIZE_FAR;
1121             } else {
1122                 ED.AddrSize = DataAddrSize;
1123                 /* If the default address size of the data segment is unequal
1124                 ** to zero page addressing, but zero page addressing is 
1125                 ** allowed by the instruction, mark all symbols in the 
1126                 ** expression tree. This mark will be checked at end of 
1127                 ** assembly, and a warning is issued, if a zero page symbol
1128                 ** was guessed wrong here.
1129                 */
1130                 if (ED.AddrSize > ADDR_SIZE_ZP && (A->AddrModeSet & AM65_SET_ZP)) {
1131                     ExprGuessedAddrSize (A->Expr, ADDR_SIZE_ZP);
1132                 }
1133             }
1134         }
1135
1136         /* Check the size */
1137         switch (ED.AddrSize) {
1138
1139             case ADDR_SIZE_ABS:
1140                 A->AddrModeSet &= ~AM65_SET_ZP;
1141                 break;
1142
1143             case ADDR_SIZE_FAR:
1144                 A->AddrModeSet &= ~(AM65_SET_ZP | AM65_SET_ABS);
1145                 break;
1146         }
1147
1148         /* Free any resource associated with the expression desc */
1149         ED_Done (&ED);
1150     }
1151
1152     /* Check if we have any adressing modes left */
1153     if (A->AddrModeSet == 0) {
1154         Error ("Illegal addressing mode");
1155         return 0;
1156     }
1157     A->AddrMode    = BitFind (A->AddrModeSet);
1158     A->AddrModeBit = (0x01UL << A->AddrMode);
1159
1160     /* If the instruction has a one byte operand and immediate addressing is
1161     ** allowed but not used, check for an operand expression in the form
1162     ** <label or >label, where label is a far or absolute label. If found,
1163     ** emit a warning. This warning protects against a typo, where the '#'
1164     ** for the immediate operand is omitted.
1165     */
1166     if (A->Expr && (Ins->AddrMode & AM65_ALL_IMM)                &&
1167         (A->AddrModeSet & (AM65_DIR | AM65_ABS | AM65_ABS_LONG)) &&
1168         ExtBytes[A->AddrMode] == 1) {
1169
1170         /* Found, check the expression */
1171         ExprNode* Left = A->Expr->Left;
1172         if ((A->Expr->Op == EXPR_BYTE0 || A->Expr->Op == EXPR_BYTE1) &&
1173             Left->Op == EXPR_SYMBOL                                  &&
1174             GetSymAddrSize (Left->V.Sym) != ADDR_SIZE_ZP) {
1175
1176             /* Output a warning */
1177             Warning (1, "Suspicious address expression");
1178         }
1179     }
1180
1181     /* Build the opcode */
1182     A->Opcode = Ins->BaseCode | EATab[Ins->ExtCode][A->AddrMode];
1183
1184     /* If feature force_range is active, and we have immediate addressing mode,
1185     ** limit the expression to the maximum possible value.
1186     */
1187     if (A->AddrMode == AM65I_IMM_ACCU || A->AddrMode == AM65I_IMM_INDEX ||
1188         A->AddrMode == AM65I_IMM_IMPLICIT || A->AddrMode == AM65I_IMM_IMPLICIT_WORD) {
1189         if (ForceRange && A->Expr) {
1190             A->Expr = MakeBoundedExpr (A->Expr, ExtBytes[A->AddrMode]);
1191         }
1192     }
1193
1194     /* Success */
1195     return 1;
1196 }
1197
1198
1199
1200 static void EmitCode (EffAddr* A)
1201 /* Output code for the data in A */
1202 {
1203     /* Check how many extension bytes are needed and output the instruction */
1204     switch (ExtBytes[A->AddrMode]) {
1205
1206         case 0:
1207             Emit0 (A->Opcode);
1208             break;
1209
1210         case 1:
1211             Emit1 (A->Opcode, A->Expr);
1212             break;
1213
1214         case 2:
1215             if (CPU == CPU_65816 && (A->AddrModeBit & (AM65_ABS | AM65_ABS_X | AM65_ABS_Y))) {
1216                 /* This is a 16 bit mode that uses an address. If in 65816,
1217                 ** mode, force this address into 16 bit range to allow
1218                 ** addressing inside a 64K segment.
1219                 */
1220                 Emit2 (A->Opcode, GenWordExpr (A->Expr));
1221             } else {
1222                 Emit2 (A->Opcode, A->Expr);
1223             }
1224             break;
1225
1226         case 3:
1227             /* Far argument */
1228             Emit3 (A->Opcode, A->Expr);
1229             break;
1230
1231         default:
1232             Internal ("Invalid operand byte count: %u", ExtBytes[A->AddrMode]);
1233
1234     }
1235 }
1236
1237
1238
1239 static long PutImmed8 (const InsDesc* Ins)
1240 /* Parse and emit an immediate 8 bit instruction. Return the value of the
1241 ** operand if it's available and const.
1242 */
1243 {
1244     EffAddr A;
1245     long Val = -1;
1246
1247     /* Evaluate the addressing mode */
1248     if (EvalEA (Ins, &A) == 0) {
1249         /* An error occurred */
1250         return -1L;
1251     }
1252
1253     /* If we have an expression and it's const, get it's value */
1254     if (A.Expr) {
1255         (void) IsConstExpr (A.Expr, &Val);
1256     }
1257
1258     /* Check how many extension bytes are needed and output the instruction */
1259     switch (ExtBytes[A.AddrMode]) {
1260
1261         case 1:
1262             Emit1 (A.Opcode, A.Expr);
1263             break;
1264
1265         default:
1266             Internal ("Invalid operand byte count: %u", ExtBytes[A.AddrMode]);
1267     }
1268
1269     /* Return the expression value */
1270     return Val;
1271 }
1272
1273
1274
1275 static void PutPCRel8 (const InsDesc* Ins)
1276 /* Handle branches with a 8 bit distance */
1277 {
1278     EmitPCRel (Ins->BaseCode, GenBranchExpr (2), 1);
1279 }
1280
1281
1282
1283 static void PutPCRel16 (const InsDesc* Ins)
1284 /* Handle branches with an 16 bit distance and PER */
1285 {
1286     EmitPCRel (Ins->BaseCode, GenBranchExpr (3), 2);
1287 }
1288
1289
1290
1291 static void PutPCRel4510 (const InsDesc* Ins)
1292 /* Handle branches with a 16 bit distance */
1293 {
1294     /* 16 bit branch opcode is 8 bit branch opcode or'ed with 0x03 */
1295     EmitPCRel (Ins->BaseCode, GenBranchExpr (2), 2);
1296 }
1297
1298
1299
1300 static void PutBlockMove (const InsDesc* Ins)
1301 /* Handle the blockmove instructions (65816) */
1302 {
1303     ExprNode* Arg1;
1304     ExprNode* Arg2;
1305
1306     Emit0 (Ins->BaseCode);
1307
1308     if (CurTok.Tok == TOK_HASH) {
1309         /* The operand is a bank-byte expression. */
1310         NextTok ();
1311         Arg1 = Expression ();
1312     } else {
1313         /* The operand is a far-address expression.
1314         ** Use only its bank part.
1315         */
1316         Arg1 = FuncBankByte ();
1317     }
1318     ConsumeComma ();
1319
1320     if (CurTok.Tok == TOK_HASH) {
1321         NextTok ();
1322         Arg2 = Expression ();
1323     } else {
1324         Arg2 = FuncBankByte ();
1325     }
1326
1327     /* The operands are written in Assembly code as source, destination;
1328     ** but, they're assembled as <destination> <source>.
1329     */
1330     EmitByte (Arg2);
1331     EmitByte (Arg1);
1332 }
1333
1334
1335
1336 static void PutBlockTransfer (const InsDesc* Ins)
1337 /* Handle the block transfer instructions (HuC6280) */
1338 {
1339     Emit0 (Ins->BaseCode);
1340     EmitWord (Expression ());
1341     ConsumeComma ();
1342     EmitWord (Expression ());
1343     ConsumeComma ();
1344     EmitWord (Expression ());
1345 }
1346
1347
1348
1349 static void PutBitBranch (const InsDesc* Ins)
1350 /* Handle 65C02 branch on bit condition */
1351 {
1352     Emit0 (Ins->BaseCode);
1353     EmitByte (Expression ());
1354     ConsumeComma ();
1355     EmitSigned (GenBranchExpr (1), 1);
1356 }
1357
1358
1359
1360 static void PutREP (const InsDesc* Ins)
1361 /* Emit a REP instruction, track register sizes */
1362 {
1363     /* Use the generic handler */
1364     long Val = PutImmed8 (Ins);
1365
1366     /* We track the status only for the 816 CPU and in smart mode */
1367     if (CPU == CPU_65816 && SmartMode) {
1368
1369         /* Check the range for Val. */
1370         if (Val < 0) {
1371             /* We had an error */
1372             Warning (1, "Cannot track processor status byte");
1373         } else {
1374             if (Val & 0x10) {
1375                 /* Index registers to 16 bit */
1376                 ExtBytes[AM65I_IMM_INDEX] = 2;
1377             }
1378             if (Val & 0x20) {
1379                 /* Accu to 16 bit */
1380                 ExtBytes[AM65I_IMM_ACCU] = 2;
1381             }
1382         }
1383     }
1384 }
1385
1386
1387
1388 static void PutSEP (const InsDesc* Ins)
1389 /* Emit a SEP instruction (65816), track register sizes */
1390 {
1391     /* Use the generic handler */
1392     long Val = PutImmed8 (Ins);
1393
1394     /* We track the status only for the 816 CPU and in smart mode */
1395     if (CPU == CPU_65816 && SmartMode) {
1396
1397         /* Check the range for Val. */
1398         if (Val < 0) {
1399             /* We had an error */
1400             Warning (1, "Cannot track processor status byte");
1401         } else {
1402             if (Val & 0x10) {
1403                 /* Index registers to 8 bit */
1404                 ExtBytes[AM65I_IMM_INDEX] = 1;
1405             }
1406             if (Val & 0x20) {
1407                 /* Accu to 8 bit */
1408                 ExtBytes[AM65I_IMM_ACCU] = 1;
1409             }
1410         }
1411     }
1412 }
1413
1414
1415
1416 static void PutTAMn (const InsDesc* Ins)
1417 /* Emit a TAMn instruction (HuC6280). Since this is a two byte instruction with
1418 ** implicit addressing mode, the opcode byte in the table is actually the
1419 ** second operand byte. The TAM instruction is the more generic form, it takes
1420 ** an immediate argument.
1421 */
1422 {
1423     /* Emit the TAM opcode itself */
1424     Emit0 (0x53);
1425
1426     /* Emit the argument, which is the opcode from the table */
1427     Emit0 (Ins->BaseCode);
1428 }
1429
1430
1431
1432 static void PutTMA (const InsDesc* Ins)
1433 /* Emit a TMA instruction (HuC6280) with an immediate argument. Only one bit
1434 ** in the argument byte may be set.
1435 */
1436 {
1437     /* Use the generic handler */
1438     long Val = PutImmed8 (Ins);
1439
1440     /* Check the range for Val. */
1441     if (Val < 0) {
1442         /* We had an error */
1443         Warning (1, "Cannot check argument of TMA instruction");
1444     } else {
1445         /* Make sure just one bit is set */
1446         if ((Val & (Val - 1)) != 0) {
1447             Error ("Argument to TAM must be a power of two");
1448         }
1449     }
1450 }
1451
1452
1453
1454 static void PutTMAn (const InsDesc* Ins)
1455 /* Emit a TMAn instruction (HuC6280). Since this is a two byte instruction with
1456 ** implicit addressing mode, the opcode byte in the table is actually the
1457 ** second operand byte. The TAM instruction is the more generic form, it takes
1458 ** an immediate argument.
1459 */
1460 {
1461     /* Emit the TMA opcode itself */
1462     Emit0 (0x43);
1463
1464     /* Emit the argument, which is the opcode from the table */
1465     Emit0 (Ins->BaseCode);
1466 }
1467
1468
1469
1470 static void PutTST (const InsDesc* Ins)
1471 /* Emit a TST instruction (HuC6280). */
1472 {
1473     ExprNode* Arg1;
1474     EffAddr   A;
1475
1476     /* The first argument is always an immediate byte */
1477     if (CurTok.Tok != TOK_HASH) {
1478         ErrorSkip ("Invalid addressing mode");
1479         return;
1480     }
1481     NextTok ();
1482     Arg1 = Expression ();
1483
1484     /* Second argument follows */
1485     ConsumeComma ();
1486
1487     /* For the second argument, we use the standard function */
1488     if (EvalEA (Ins, &A)) {
1489
1490         /* No error, output code */
1491         Emit1 (A.Opcode, Arg1);
1492
1493         /* Check how many extension bytes are needed and output the instruction */
1494         switch (ExtBytes[A.AddrMode]) {
1495
1496             case 1:
1497                 EmitByte (A.Expr);
1498                 break;
1499
1500             case 2:
1501                 EmitWord (A.Expr);
1502                 break;
1503         }
1504     }
1505 }
1506
1507
1508
1509 static void PutJMP (const InsDesc* Ins)
1510 /* Handle the jump instruction for the 6502. Problem is that these chips have
1511 ** a bug: If the address crosses a page, the upper byte gets not corrected and
1512 ** the instruction will fail. The PutJmp function will add a linker assertion
1513 ** to check for this case and is otherwise identical to PutAll.
1514 */
1515 {
1516     EffAddr A;
1517
1518     /* Evaluate the addressing mode used */
1519     if (EvalEA (Ins, &A)) {
1520
1521         /* Check for indirect addressing */
1522         if (A.AddrModeBit & AM65_ABS_IND) {
1523
1524             /* Compare the low byte of the expression to 0xFF to check for
1525             ** a page cross. Be sure to use a copy of the expression otherwise
1526             ** things will go weird later.
1527             */
1528             ExprNode* E = GenNE (GenByteExpr (CloneExpr (A.Expr)), 0xFF);
1529
1530             /* Generate the message */
1531             unsigned Msg = GetStringId ("\"jmp (abs)\" across page border");
1532
1533             /* Generate the assertion */
1534             AddAssertion (E, ASSERT_ACT_WARN, Msg);
1535         }
1536
1537         /* No error, output code */
1538         EmitCode (&A);
1539     }
1540 }
1541
1542
1543
1544 static void PutRTS (const InsDesc* Ins attribute ((unused)))
1545 /* Handle the RTS instruction for the 816. In smart mode emit a RTL opcode if
1546 ** the enclosing scope is FAR.
1547 */
1548 {
1549     if (SmartMode && CurrentScope->AddrSize == ADDR_SIZE_FAR) {
1550         Emit0 (0x6B);       /* RTL */
1551     } else {
1552         Emit0 (0x60);       /* RTS */
1553     }
1554 }
1555
1556
1557
1558 static void PutAll (const InsDesc* Ins)
1559 /* Handle all other instructions */
1560 {
1561     EffAddr A;
1562
1563     /* Evaluate the addressing mode used */
1564     if (EvalEA (Ins, &A)) {
1565         /* No error, output code */
1566         EmitCode (&A);
1567     }
1568 }
1569
1570
1571
1572 static void Put4510 (const InsDesc* Ins)
1573 /* Handle all other instructions, with modifications for 4510 */
1574 {
1575     /* The 4510 uses all 256 possible opcodes, so the last ones were crammed
1576     ** in where an opcode was still undefined. As a result, some of those
1577     ** don't follow any rules for encoding the addressmodes. So the EATab
1578     ** approach does not work always. In this function, the wrongly calculated
1579     ** opcode is replaced by the correct one "on the fly". Suggestions for a
1580     ** better approach are welcome.
1581     **
1582     ** These are:
1583     ** $47 -> $44 : ASR $12
1584     ** $57 -> $54 : ASR $12,X
1585     ** $93 -> $82 : STA ($12,SP),Y
1586     ** $9c -> $8b : STY $1234,X
1587     ** $9e -> $9b : STX $1234,Y
1588     ** $af -> $ab : LDZ $1234
1589     ** $bf -> $bb : LDZ $1234,X
1590     ** $b3 -> $e2 : LDA ($12,SP),Y
1591     ** $d0 -> $c2 : CPZ #$00
1592     ** $fc -> $23 : JSR ($1234,X)
1593     */
1594     EffAddr A;
1595
1596     /* Evaluate the addressing mode used */
1597     if (EvalEA (Ins, &A)) {
1598         switch (A.Opcode) {
1599             case 0x47: A.Opcode = 0x44; break;
1600             case 0x57: A.Opcode = 0x54; break;
1601             case 0x93: A.Opcode = 0x82; break;
1602             case 0x9C: A.Opcode = 0x8B; break;
1603             case 0x9E: A.Opcode = 0x9B; break;
1604             case 0xAF: A.Opcode = 0xAB; break;
1605             case 0xBF: A.Opcode = 0xBB; break;
1606             case 0xB3: A.Opcode = 0xE2; break;
1607             case 0xD0: A.Opcode = 0xC2; break;
1608             case 0xFC: A.Opcode = 0x23; break;
1609             default: /* Keep opcode as it is */ break;
1610         }
1611
1612         /* No error, output code */
1613         EmitCode (&A);
1614     }
1615 }
1616
1617
1618
1619 /*****************************************************************************/
1620 /*                       Handler functions for SWEET16                       */
1621 /*****************************************************************************/
1622
1623
1624
1625 static void PutSweet16 (const InsDesc* Ins)
1626 /* Handle a generic sweet16 instruction */
1627 {
1628     EffAddr A;
1629
1630     /* Evaluate the addressing mode used */
1631     GetSweet16EA (&A);
1632
1633     /* From the possible addressing modes, remove the ones that are invalid
1634     ** for this instruction or CPU.
1635     */
1636     A.AddrModeSet &= Ins->AddrMode;
1637
1638     /* Check if we have any adressing modes left */
1639     if (A.AddrModeSet == 0) {
1640         Error ("Illegal addressing mode");
1641         return;
1642     }
1643     A.AddrMode    = BitFind (A.AddrModeSet);
1644     A.AddrModeBit = (0x01UL << A.AddrMode);
1645
1646     /* Build the opcode */
1647     A.Opcode = Ins->BaseCode | Sweet16EATab[Ins->ExtCode][A.AddrMode] | A.Reg;
1648
1649     /* Check how many extension bytes are needed and output the instruction */
1650     switch (Sweet16ExtBytes[A.AddrMode]) {
1651
1652         case 0:
1653             Emit0 (A.Opcode);
1654             break;
1655
1656         case 1:
1657             Emit1 (A.Opcode, A.Expr);
1658             break;
1659
1660         case 2:
1661             Emit2 (A.Opcode, A.Expr);
1662             break;
1663
1664         default:
1665             Internal ("Invalid operand byte count: %u", Sweet16ExtBytes[A.AddrMode]);
1666
1667     }
1668 }
1669
1670
1671
1672 static void PutSweet16Branch (const InsDesc* Ins)
1673 /* Handle a sweet16 branch instruction */
1674 {
1675     EmitPCRel (Ins->BaseCode, GenBranchExpr (2), 1);
1676 }
1677
1678
1679
1680 /*****************************************************************************/
1681 /*                                   Code                                    */
1682 /*****************************************************************************/
1683
1684
1685
1686 static int CmpName (const void* Key, const void* Instr)
1687 /* Compare function for bsearch */
1688 {
1689     return strcmp ((const char*)Key, ((const InsDesc*) Instr)->Mnemonic);
1690 }
1691
1692
1693
1694 void SetCPU (cpu_t NewCPU)
1695 /* Set a new CPU */
1696 {
1697     /* Make sure the parameter is correct */
1698     CHECK (NewCPU < CPU_COUNT);
1699
1700     /* Check if we have support for the new CPU, if so, use it */
1701     if (NewCPU != CPU_UNKNOWN && InsTabs[NewCPU]) {
1702         CPU = NewCPU;
1703         InsTab = InsTabs[CPU];
1704     } else {
1705         Error ("CPU not supported");
1706     }
1707 }
1708
1709
1710
1711 cpu_t GetCPU (void)
1712 /* Return the current CPU */
1713 {
1714     return CPU;
1715 }
1716
1717
1718
1719 int FindInstruction (const StrBuf* Ident)
1720 /* Check if Ident is a valid mnemonic. If so, return the index in the
1721 ** instruction table. If not, return -1.
1722 */
1723 {
1724     unsigned I;
1725     const InsDesc* ID;
1726     char Key[sizeof (ID->Mnemonic)];
1727
1728     /* Shortcut for the "none" CPU: If there are no instructions to search
1729     ** for, bail out early.
1730     */
1731     if (InsTab->Count == 0) {
1732         /* Not found */
1733         return -1;
1734     }
1735
1736     /* Make a copy, and uppercase that copy */
1737     I = 0;
1738     while (I < SB_GetLen (Ident)) {
1739         /* If the identifier is longer than the longest mnemonic, it cannot
1740         ** be one.
1741         */
1742         if (I >= sizeof (Key) - 1) {
1743             /* Not found, no need for further action */
1744             return -1;
1745         }
1746         Key[I] = toupper ((unsigned char)SB_AtUnchecked (Ident, I));
1747         ++I;
1748     }
1749     Key[I] = '\0';
1750
1751     /* Search for the key */
1752     ID = bsearch (Key, InsTab->Ins, InsTab->Count, sizeof (InsDesc), CmpName);
1753     if (ID == 0) {
1754         /* Not found */
1755         return -1;
1756     } else {
1757         /* Found, return the entry */
1758         return ID - InsTab->Ins;
1759     }
1760 }
1761
1762
1763
1764 void HandleInstruction (unsigned Index)
1765 /* Handle the mnemonic with the given index */
1766 {
1767     /* Safety check */
1768     PRECONDITION (Index < InsTab->Count);
1769
1770     /* Skip the mnemonic token */
1771     NextTok ();
1772
1773     /* Call the handler */
1774     InsTab->Ins[Index].Emit (&InsTab->Ins[Index]);
1775 }