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