]> git.sur5r.net Git - cc65/blob - src/ca65/instr.c
Add 6502X cpu
[cc65] / src / ca65 / instr.c
1 /*****************************************************************************/
2 /*                                                                           */
3 /*                                  instr.c                                  */
4 /*                                                                           */
5 /*             Instruction encoding for the ca65 macroassembler              */
6 /*                                                                           */
7 /*                                                                           */
8 /*                                                                           */
9 /* (C) 1998-2003 Ullrich von Bassewitz                                       */
10 /*               Römerstraße 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 "error.h"
52 #include "expr.h"
53 #include "global.h"
54 #include "instr.h"
55 #include "nexttok.h"
56 #include "objcode.h"
57 #include "spool.h"
58 #include "studyexpr.h"
59 #include "symtab.h"
60
61
62
63 /*****************************************************************************/
64 /*                                   Data                                    */
65 /*****************************************************************************/
66
67
68
69 /* Forwards for handler functions */
70 static void PutPCRel8 (const InsDesc* Ins);
71 static void PutPCRel16 (const InsDesc* Ins);
72 static void PutBlockMove (const InsDesc* Ins);
73 static void PutBitBranch (const InsDesc* Ins);
74 static void PutREP (const InsDesc* Ins);
75 static void PutSEP (const InsDesc* Ins);
76 static void PutJMP (const InsDesc* Ins);
77 static void PutRTS (const InsDesc* Ins);
78 static void PutAll (const InsDesc* Ins);
79
80
81
82 /* Instruction table for the 6502 */
83 #define INS_COUNT_6502          56
84 static const struct {
85     unsigned Count;
86     InsDesc  Ins[INS_COUNT_6502];
87 } InsTab6502 = {
88     INS_COUNT_6502,
89     {
90         { "ADC",  0x080A26C, 0x60, 0, PutAll },
91         { "AND",  0x080A26C, 0x20, 0, PutAll },
92         { "ASL",  0x000006e, 0x02, 1, PutAll },
93         { "BCC",  0x0020000, 0x90, 0, PutPCRel8 },
94         { "BCS",  0x0020000, 0xb0, 0, PutPCRel8 },
95         { "BEQ",  0x0020000, 0xf0, 0, PutPCRel8 },
96         { "BIT",  0x000000C, 0x00, 2, PutAll },
97         { "BMI",  0x0020000, 0x30, 0, PutPCRel8 },
98         { "BNE",  0x0020000, 0xd0, 0, PutPCRel8 },
99         { "BPL",  0x0020000, 0x10, 0, PutPCRel8 },
100         { "BRK",  0x0000001, 0x00, 0, PutAll },
101         { "BVC",  0x0020000, 0x50, 0, PutPCRel8 },
102         { "BVS",  0x0020000, 0x70, 0, PutPCRel8 },
103         { "CLC",  0x0000001, 0x18, 0, PutAll },
104         { "CLD",  0x0000001, 0xd8, 0, PutAll },
105         { "CLI",  0x0000001, 0x58, 0, PutAll },
106         { "CLV",  0x0000001, 0xb8, 0, PutAll },
107         { "CMP",  0x080A26C, 0xc0, 0, PutAll },
108         { "CPX",  0x080000C, 0xe0, 1, PutAll },
109         { "CPY",  0x080000C, 0xc0, 1, PutAll },
110         { "DEC",  0x000006C, 0x00, 3, PutAll },
111         { "DEX",  0x0000001, 0xca, 0, PutAll },
112         { "DEY",  0x0000001, 0x88, 0, PutAll },
113         { "EOR",  0x080A26C, 0x40, 0, PutAll },
114         { "INC",  0x000006c, 0x00, 4, PutAll },
115         { "INX",  0x0000001, 0xe8, 0, PutAll },
116         { "INY",  0x0000001, 0xc8, 0, PutAll },
117         { "JMP",  0x0000808, 0x4c, 6, PutJMP },
118         { "JSR",  0x0000008, 0x20, 7, PutAll },
119         { "LDA",  0x080A26C, 0xa0, 0, PutAll },
120         { "LDX",  0x080030C, 0xa2, 1, PutAll },
121         { "LDY",  0x080006C, 0xa0, 1, PutAll },
122         { "LSR",  0x000006F, 0x42, 1, PutAll },
123         { "NOP",  0x0000001, 0xea, 0, PutAll },
124         { "ORA",  0x080A26C, 0x00, 0, PutAll },
125         { "PHA",  0x0000001, 0x48, 0, PutAll },
126         { "PHP",  0x0000001, 0x08, 0, PutAll },
127         { "PLA",  0x0000001, 0x68, 0, PutAll },
128         { "PLP",  0x0000001, 0x28, 0, PutAll },
129         { "ROL",  0x000006F, 0x22, 1, PutAll },
130         { "ROR",  0x000006F, 0x62, 1, PutAll },
131         { "RTI",  0x0000001, 0x40, 0, PutAll },
132         { "RTS",  0x0000001, 0x60, 0, PutAll },
133         { "SBC",  0x080A26C, 0xe0, 0, PutAll },
134         { "SEC",  0x0000001, 0x38, 0, PutAll },
135         { "SED",  0x0000001, 0xf8, 0, PutAll },
136         { "SEI",  0x0000001, 0x78, 0, PutAll },
137         { "STA",  0x000A26C, 0x80, 0, PutAll },
138         { "STX",  0x000010c, 0x82, 1, PutAll },
139         { "STY",  0x000002c, 0x80, 1, PutAll },
140         { "TAX",  0x0000001, 0xaa, 0, PutAll },
141         { "TAY",  0x0000001, 0xa8, 0, PutAll },
142         { "TSX",  0x0000001, 0xba, 0, PutAll },
143         { "TXA",  0x0000001, 0x8a, 0, PutAll },
144         { "TXS",  0x0000001, 0x9a, 0, PutAll },
145         { "TYA",  0x0000001, 0x98, 0, PutAll }
146     }
147 };
148
149 /* Instruction table for the 6502 with illegal instructions */
150 #define INS_COUNT_6502X         57
151 static const struct {
152     unsigned Count;
153     InsDesc  Ins[INS_COUNT_6502X];
154 } InsTab6502X = {
155     INS_COUNT_6502X,
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         { "JAM",  0x0000001, 0x02, 0, PutAll },         /* X */
185         { "JMP",  0x0000808, 0x4c, 6, PutJMP },
186         { "JSR",  0x0000008, 0x20, 7, PutAll },
187         { "LDA",  0x080A26C, 0xa0, 0, PutAll },
188         { "LDX",  0x080030C, 0xa2, 1, PutAll },
189         { "LDY",  0x080006C, 0xa0, 1, PutAll },
190         { "LSR",  0x000006F, 0x42, 1, PutAll },
191         { "NOP",  0x0000001, 0xea, 0, PutAll },
192         { "ORA",  0x080A26C, 0x00, 0, PutAll },
193         { "PHA",  0x0000001, 0x48, 0, PutAll },
194         { "PHP",  0x0000001, 0x08, 0, PutAll },
195         { "PLA",  0x0000001, 0x68, 0, PutAll },
196         { "PLP",  0x0000001, 0x28, 0, PutAll },
197         { "ROL",  0x000006F, 0x22, 1, PutAll },
198         { "ROR",  0x000006F, 0x62, 1, PutAll },
199         { "RTI",  0x0000001, 0x40, 0, PutAll },
200         { "RTS",  0x0000001, 0x60, 0, PutAll },
201         { "SBC",  0x080A26C, 0xe0, 0, PutAll },
202         { "SEC",  0x0000001, 0x38, 0, PutAll },
203         { "SED",  0x0000001, 0xf8, 0, PutAll },
204         { "SEI",  0x0000001, 0x78, 0, PutAll },
205         { "STA",  0x000A26C, 0x80, 0, PutAll },
206         { "STX",  0x000010c, 0x82, 1, PutAll },
207         { "STY",  0x000002c, 0x80, 1, PutAll },
208         { "TAX",  0x0000001, 0xaa, 0, PutAll },
209         { "TAY",  0x0000001, 0xa8, 0, PutAll },
210         { "TSX",  0x0000001, 0xba, 0, PutAll },
211         { "TXA",  0x0000001, 0x8a, 0, PutAll },
212         { "TXS",  0x0000001, 0x9a, 0, PutAll },
213         { "TYA",  0x0000001, 0x98, 0, PutAll }
214     }
215 };
216
217 /* Instruction table for the 65SC02 */
218 #define INS_COUNT_65SC02        66
219 static const struct {
220     unsigned Count;
221     InsDesc  Ins[INS_COUNT_65SC02];
222 } InsTab65SC02 = {
223     INS_COUNT_65SC02,
224     {
225         { "ADC",  0x080A66C, 0x60, 0, PutAll },
226         { "AND",  0x080A66C, 0x20, 0, PutAll },
227         { "ASL",  0x000006e, 0x02, 1, PutAll },
228         { "BCC",  0x0020000, 0x90, 0, PutPCRel8 },
229         { "BCS",  0x0020000, 0xb0, 0, PutPCRel8 },
230         { "BEQ",  0x0020000, 0xf0, 0, PutPCRel8 },
231         { "BIT",  0x0A0006C, 0x00, 2, PutAll },
232         { "BMI",  0x0020000, 0x30, 0, PutPCRel8 },
233         { "BNE",  0x0020000, 0xd0, 0, PutPCRel8 },
234         { "BPL",  0x0020000, 0x10, 0, PutPCRel8 },
235         { "BRA",  0x0020000, 0x80, 0, PutPCRel8 },
236         { "BRK",  0x0000001, 0x00, 0, PutAll },
237         { "BVC",  0x0020000, 0x50, 0, PutPCRel8 },
238         { "BVS",  0x0020000, 0x70, 0, PutPCRel8 },
239         { "CLC",  0x0000001, 0x18, 0, PutAll },
240         { "CLD",  0x0000001, 0xd8, 0, PutAll },
241         { "CLI",  0x0000001, 0x58, 0, PutAll },
242         { "CLV",  0x0000001, 0xb8, 0, PutAll },
243         { "CMP",  0x080A66C, 0xc0, 0, PutAll },
244         { "CPX",  0x080000C, 0xe0, 1, PutAll },
245         { "CPY",  0x080000C, 0xc0, 1, PutAll },
246         { "DEA",  0x0000001, 0x00, 3, PutAll },   /* == DEC */
247         { "DEC",  0x000006F, 0x00, 3, PutAll },
248         { "DEX",  0x0000001, 0xca, 0, PutAll },
249         { "DEY",  0x0000001, 0x88, 0, PutAll },
250         { "EOR",  0x080A66C, 0x40, 0, PutAll },
251         { "INA",  0x0000001, 0x00, 4, PutAll },   /* == INC */
252         { "INC",  0x000006f, 0x00, 4, PutAll },
253         { "INX",  0x0000001, 0xe8, 0, PutAll },
254         { "INY",  0x0000001, 0xc8, 0, PutAll },
255         { "JMP",  0x0010808, 0x4c, 6, PutAll },
256         { "JSR",  0x0000008, 0x20, 7, PutAll },
257         { "LDA",  0x080A66C, 0xa0, 0, PutAll },
258         { "LDX",  0x080030C, 0xa2, 1, PutAll },
259         { "LDY",  0x080006C, 0xa0, 1, PutAll },
260         { "LSR",  0x000006F, 0x42, 1, PutAll },
261         { "NOP",  0x0000001, 0xea, 0, PutAll },
262         { "ORA",  0x080A66C, 0x00, 0, PutAll },
263         { "PHA",  0x0000001, 0x48, 0, PutAll },
264         { "PHP",  0x0000001, 0x08, 0, PutAll },
265         { "PHX",  0x0000001, 0xda, 0, PutAll },
266         { "PHY",  0x0000001, 0x5a, 0, PutAll },
267         { "PLA",  0x0000001, 0x68, 0, PutAll },
268         { "PLP",  0x0000001, 0x28, 0, PutAll },
269         { "PLX",  0x0000001, 0xfa, 0, PutAll },
270         { "PLY",  0x0000001, 0x7a, 0, PutAll },
271         { "ROL",  0x000006F, 0x22, 1, PutAll },
272         { "ROR",  0x000006F, 0x62, 1, PutAll },
273         { "RTI",  0x0000001, 0x40, 0, PutAll },
274         { "RTS",  0x0000001, 0x60, 0, PutAll },
275         { "SBC",  0x080A66C, 0xe0, 0, PutAll },
276         { "SEC",  0x0000001, 0x38, 0, PutAll },
277         { "SED",  0x0000001, 0xf8, 0, PutAll },
278         { "SEI",  0x0000001, 0x78, 0, PutAll },
279         { "STA",  0x000A66C, 0x80, 0, PutAll },
280         { "STX",  0x000010c, 0x82, 1, PutAll },
281         { "STY",  0x000002c, 0x80, 1, PutAll },
282         { "STZ",  0x000006c, 0x04, 5, PutAll },
283         { "TAX",  0x0000001, 0xaa, 0, PutAll },
284         { "TAY",  0x0000001, 0xa8, 0, PutAll },
285         { "TRB",  0x000000c, 0x10, 1, PutAll },
286         { "TSB",  0x000000c, 0x00, 1, PutAll },
287         { "TSX",  0x0000001, 0xba, 0, PutAll },
288         { "TXA",  0x0000001, 0x8a, 0, PutAll },
289         { "TXS",  0x0000001, 0x9a, 0, PutAll },
290         { "TYA",  0x0000001, 0x98, 0, PutAll }
291     }
292 };
293
294 /* Instruction table for the 65C02 */
295 #define INS_COUNT_65C02         98
296 static const struct {
297     unsigned Count;
298     InsDesc  Ins[INS_COUNT_65C02];
299 } InsTab65C02 = {
300     INS_COUNT_65C02,
301     {
302         { "ADC",  0x080A66C, 0x60, 0, PutAll },
303         { "AND",  0x080A66C, 0x20, 0, PutAll },
304         { "ASL",  0x000006e, 0x02, 1, PutAll },
305         { "BBR0", 0x0000000, 0x0F, 0, PutBitBranch },
306         { "BBR1", 0x0000000, 0x1F, 0, PutBitBranch },
307         { "BBR2", 0x0000000, 0x2F, 0, PutBitBranch },
308         { "BBR3", 0x0000000, 0x3F, 0, PutBitBranch },
309         { "BBR4", 0x0000000, 0x4F, 0, PutBitBranch },
310         { "BBR5", 0x0000000, 0x5F, 0, PutBitBranch },
311         { "BBR6", 0x0000000, 0x6F, 0, PutBitBranch },
312         { "BBR7", 0x0000000, 0x7F, 0, PutBitBranch },
313         { "BBS0", 0x0000000, 0x8F, 0, PutBitBranch },
314         { "BBS1", 0x0000000, 0x9F, 0, PutBitBranch },
315         { "BBS2", 0x0000000, 0xAF, 0, PutBitBranch },
316         { "BBS3", 0x0000000, 0xBF, 0, PutBitBranch },
317         { "BBS4", 0x0000000, 0xCF, 0, PutBitBranch },
318         { "BBS5", 0x0000000, 0xDF, 0, PutBitBranch },
319         { "BBS6", 0x0000000, 0xEF, 0, PutBitBranch },
320         { "BBS7", 0x0000000, 0xFF, 0, PutBitBranch },
321         { "BCC",  0x0020000, 0x90, 0, PutPCRel8 },
322         { "BCS",  0x0020000, 0xb0, 0, PutPCRel8 },
323         { "BEQ",  0x0020000, 0xf0, 0, PutPCRel8 },
324         { "BIT",  0x0A0006C, 0x00, 2, PutAll },
325         { "BMI",  0x0020000, 0x30, 0, PutPCRel8 },
326         { "BNE",  0x0020000, 0xd0, 0, PutPCRel8 },
327         { "BPL",  0x0020000, 0x10, 0, PutPCRel8 },
328         { "BRA",  0x0020000, 0x80, 0, PutPCRel8 },
329         { "BRK",  0x0000001, 0x00, 0, PutAll },
330         { "BVC",  0x0020000, 0x50, 0, PutPCRel8 },
331         { "BVS",  0x0020000, 0x70, 0, PutPCRel8 },
332         { "CLC",  0x0000001, 0x18, 0, PutAll },
333         { "CLD",  0x0000001, 0xd8, 0, PutAll },
334         { "CLI",  0x0000001, 0x58, 0, PutAll },
335         { "CLV",  0x0000001, 0xb8, 0, PutAll },
336         { "CMP",  0x080A66C, 0xc0, 0, PutAll },
337         { "CPX",  0x080000C, 0xe0, 1, PutAll },
338         { "CPY",  0x080000C, 0xc0, 1, PutAll },
339         { "DEA",  0x0000001, 0x00, 3, PutAll },   /* == DEC */
340         { "DEC",  0x000006F, 0x00, 3, PutAll },
341         { "DEX",  0x0000001, 0xca, 0, PutAll },
342         { "DEY",  0x0000001, 0x88, 0, PutAll },
343         { "EOR",  0x080A66C, 0x40, 0, PutAll },
344         { "INA",  0x0000001, 0x00, 4, PutAll },   /* == INC */
345         { "INC",  0x000006f, 0x00, 4, PutAll },
346         { "INX",  0x0000001, 0xe8, 0, PutAll },
347         { "INY",  0x0000001, 0xc8, 0, PutAll },
348         { "JMP",  0x0010808, 0x4c, 6, PutAll },
349         { "JSR",  0x0000008, 0x20, 7, PutAll },
350         { "LDA",  0x080A66C, 0xa0, 0, PutAll },
351         { "LDX",  0x080030C, 0xa2, 1, PutAll },
352         { "LDY",  0x080006C, 0xa0, 1, PutAll },
353         { "LSR",  0x000006F, 0x42, 1, PutAll },
354         { "NOP",  0x0000001, 0xea, 0, PutAll },
355         { "ORA",  0x080A66C, 0x00, 0, PutAll },
356         { "PHA",  0x0000001, 0x48, 0, PutAll },
357         { "PHP",  0x0000001, 0x08, 0, PutAll },
358         { "PHX",  0x0000001, 0xda, 0, PutAll },
359         { "PHY",  0x0000001, 0x5a, 0, PutAll },
360         { "PLA",  0x0000001, 0x68, 0, PutAll },
361         { "PLP",  0x0000001, 0x28, 0, PutAll },
362         { "PLX",  0x0000001, 0xfa, 0, PutAll },
363         { "PLY",  0x0000001, 0x7a, 0, PutAll },
364         { "RMB0", 0x0000004, 0x07, 1, PutAll },
365         { "RMB1", 0x0000004, 0x17, 1, PutAll },
366         { "RMB2", 0x0000004, 0x27, 1, PutAll },
367         { "RMB3", 0x0000004, 0x37, 1, PutAll },
368         { "RMB4", 0x0000004, 0x47, 1, PutAll },
369         { "RMB5", 0x0000004, 0x57, 1, PutAll },
370         { "RMB6", 0x0000004, 0x67, 1, PutAll },
371         { "RMB7", 0x0000004, 0x77, 1, PutAll },
372         { "ROL",  0x000006F, 0x22, 1, PutAll },
373         { "ROR",  0x000006F, 0x62, 1, PutAll },
374         { "RTI",  0x0000001, 0x40, 0, PutAll },
375         { "RTS",  0x0000001, 0x60, 0, PutAll },
376         { "SBC",  0x080A66C, 0xe0, 0, PutAll },
377         { "SEC",  0x0000001, 0x38, 0, PutAll },
378         { "SED",  0x0000001, 0xf8, 0, PutAll },
379         { "SEI",  0x0000001, 0x78, 0, PutAll },
380         { "SMB0", 0x0000004, 0x87, 1, PutAll },
381         { "SMB1", 0x0000004, 0x97, 1, PutAll },
382         { "SMB2", 0x0000004, 0xA7, 1, PutAll },
383         { "SMB3", 0x0000004, 0xB7, 1, PutAll },
384         { "SMB4", 0x0000004, 0xC7, 1, PutAll },
385         { "SMB5", 0x0000004, 0xD7, 1, PutAll },
386         { "SMB6", 0x0000004, 0xE7, 1, PutAll },
387         { "SMB7", 0x0000004, 0xF7, 1, PutAll },
388         { "STA",  0x000A66C, 0x80, 0, PutAll },
389         { "STX",  0x000010c, 0x82, 1, PutAll },
390         { "STY",  0x000002c, 0x80, 1, PutAll },
391         { "STZ",  0x000006c, 0x04, 5, PutAll },
392         { "TAX",  0x0000001, 0xaa, 0, PutAll },
393         { "TAY",  0x0000001, 0xa8, 0, PutAll },
394         { "TRB",  0x000000c, 0x10, 1, PutAll },
395         { "TSB",  0x000000c, 0x00, 1, PutAll },
396         { "TSX",  0x0000001, 0xba, 0, PutAll },
397         { "TXA",  0x0000001, 0x8a, 0, PutAll },
398         { "TXS",  0x0000001, 0x9a, 0, PutAll },
399         { "TYA",  0x0000001, 0x98, 0, PutAll }
400     }
401 };
402
403 /* Instruction table for the 65816 */
404 #define INS_COUNT_65816 101
405 static const struct {
406     unsigned Count;
407     InsDesc  Ins[INS_COUNT_65816];
408 } InsTab65816 = {
409     INS_COUNT_65816,
410     {
411         { "ADC",  0x0b8f6fc, 0x60, 0, PutAll },
412         { "AND",  0x0b8f6fc, 0x20, 0, PutAll },
413         { "ASL",  0x000006e, 0x02, 1, PutAll },
414         { "BCC",  0x0020000, 0x90, 0, PutPCRel8 },
415         { "BCS",  0x0020000, 0xb0, 0, PutPCRel8 },
416         { "BEQ",  0x0020000, 0xf0, 0, PutPCRel8 },
417         { "BGE",  0x0020000, 0xb0, 0, PutPCRel8 },   /* == BCS */
418         { "BIT",  0x0a0006c, 0x00, 2, PutAll },
419         { "BLT",  0x0020000, 0x90, 0, PutPCRel8 },   /* == BCC */
420         { "BMI",  0x0020000, 0x30, 0, PutPCRel8 },
421         { "BNE",  0x0020000, 0xd0, 0, PutPCRel8 },
422         { "BPL",  0x0020000, 0x10, 0, PutPCRel8 },
423         { "BRA",  0x0020000, 0x80, 0, PutPCRel8 },
424         { "BRK",  0x0000001, 0x00, 0, PutAll },
425         { "BRL",  0x0040000, 0x82, 0, PutPCRel16 },
426         { "BVC",  0x0020000, 0x50, 0, PutPCRel8 },
427         { "BVS",  0x0020000, 0x70, 0, PutPCRel8 },
428         { "CLC",  0x0000001, 0x18, 0, PutAll },
429         { "CLD",  0x0000001, 0xd8, 0, PutAll },
430         { "CLI",  0x0000001, 0x58, 0, PutAll },
431         { "CLV",  0x0000001, 0xb8, 0, PutAll },
432         { "CMP",  0x0b8f6fc, 0xc0, 0, PutAll },
433         { "COP",  0x0000004, 0x02, 6, PutAll },
434         { "CPA",  0x0b8f6fc, 0xc0, 0, PutAll },   /* == CMP */
435         { "CPX",  0x0c0000c, 0xe0, 1, PutAll },
436         { "CPY",  0x0c0000c, 0xc0, 1, PutAll },
437         { "DEA",  0x0000001, 0x00, 3, PutAll },   /* == DEC */
438         { "DEC",  0x000006F, 0x00, 3, PutAll },
439         { "DEX",  0x0000001, 0xca, 0, PutAll },
440         { "DEY",  0x0000001, 0x88, 0, PutAll },
441         { "EOR",  0x0b8f6fc, 0x40, 0, PutAll },
442         { "INA",  0x0000001, 0x00, 4, PutAll },   /* == INC */
443         { "INC",  0x000006F, 0x00, 4, PutAll },
444         { "INX",  0x0000001, 0xe8, 0, PutAll },
445         { "INY",  0x0000001, 0xc8, 0, PutAll },
446         { "JML",  0x0000810, 0x5c, 1, PutAll },
447         { "JMP",  0x0010818, 0x4c, 6, PutAll },
448         { "JSL",  0x0000010, 0x20, 7, PutAll },
449         { "JSR",  0x0010018, 0x20, 7, PutAll },
450         { "LDA",  0x0b8f6fc, 0xa0, 0, PutAll },
451         { "LDX",  0x0c0030c, 0xa2, 1, PutAll },
452         { "LDY",  0x0c0006c, 0xa0, 1, PutAll },
453         { "LSR",  0x000006F, 0x42, 1, PutAll },
454         { "MVN",  0x1000000, 0x54, 0, PutBlockMove },
455         { "MVP",  0x1000000, 0x44, 0, PutBlockMove },
456         { "NOP",  0x0000001, 0xea, 0, PutAll },
457         { "ORA",  0x0b8f6fc, 0x00, 0, PutAll },
458         { "PEA",  0x0000008, 0xf4, 6, PutAll },
459         { "PEI",  0x0000400, 0xd4, 1, PutAll },
460         { "PER",  0x0040000, 0x62, 0, PutPCRel16 },
461         { "PHA",  0x0000001, 0x48, 0, PutAll },
462         { "PHB",  0x0000001, 0x8b, 0, PutAll },
463         { "PHD",  0x0000001, 0x0b, 0, PutAll },
464         { "PHK",  0x0000001, 0x4b, 0, PutAll },
465         { "PHP",  0x0000001, 0x08, 0, PutAll },
466         { "PHX",  0x0000001, 0xda, 0, PutAll },
467         { "PHY",  0x0000001, 0x5a, 0, PutAll },
468         { "PLA",  0x0000001, 0x68, 0, PutAll },
469         { "PLB",  0x0000001, 0xab, 0, PutAll },
470         { "PLD",  0x0000001, 0x2b, 0, PutAll },
471         { "PLP",  0x0000001, 0x28, 0, PutAll },
472         { "PLX",  0x0000001, 0xfa, 0, PutAll },
473         { "PLY",  0x0000001, 0x7a, 0, PutAll },
474         { "REP",  0x0800000, 0xc2, 1, PutREP },
475         { "ROL",  0x000006F, 0x22, 1, PutAll },
476         { "ROR",  0x000006F, 0x62, 1, PutAll },
477         { "RTI",  0x0000001, 0x40, 0, PutAll },
478         { "RTL",  0x0000001, 0x6b, 0, PutAll },
479         { "RTS",  0x0000001, 0x60, 0, PutRTS },
480         { "SBC",  0x0b8f6fc, 0xe0, 0, PutAll },
481         { "SEC",  0x0000001, 0x38, 0, PutAll },
482         { "SED",  0x0000001, 0xf8, 0, PutAll },
483         { "SEI",  0x0000001, 0x78, 0, PutAll },
484         { "SEP",  0x0800000, 0xe2, 1, PutSEP },
485         { "STA",  0x018f6fc, 0x80, 0, PutAll },
486         { "STP",  0x0000001, 0xdb, 0, PutAll },
487         { "STX",  0x000010c, 0x82, 1, PutAll },
488         { "STY",  0x000002c, 0x80, 1, PutAll },
489         { "STZ",  0x000006c, 0x04, 5, PutAll },
490         { "SWA",  0x0000001, 0xeb, 0, PutAll },   /* == XBA */
491         { "TAD",  0x0000001, 0x5b, 0, PutAll },   /* == TCD */
492         { "TAS",  0x0000001, 0x1b, 0, PutAll },   /* == TCS */
493         { "TAX",  0x0000001, 0xaa, 0, PutAll },
494         { "TAY",  0x0000001, 0xa8, 0, PutAll },
495         { "TCD",  0x0000001, 0x5b, 0, PutAll },
496         { "TCS",  0x0000001, 0x1b, 0, PutAll },
497         { "TDA",  0x0000001, 0x7b, 0, PutAll },   /* == TDC */
498         { "TDC",  0x0000001, 0x7b, 0, PutAll },
499         { "TRB",  0x000000c, 0x10, 1, PutAll },
500         { "TSA",  0x0000001, 0x3b, 0, PutAll },   /* == TSC */
501         { "TSB",  0x000000c, 0x00, 1, PutAll },
502         { "TSC",  0x0000001, 0x3b, 0, PutAll },
503         { "TSX",  0x0000001, 0xba, 0, PutAll },
504         { "TXA",  0x0000001, 0x8a, 0, PutAll },
505         { "TXS",  0x0000001, 0x9a, 0, PutAll },
506         { "TXY",  0x0000001, 0x9b, 0, PutAll },
507         { "TYA",  0x0000001, 0x98, 0, PutAll },
508         { "TYX",  0x0000001, 0xbb, 0, PutAll },
509         { "WAI",  0x0000001, 0xcb, 0, PutAll },
510         { "XBA",  0x0000001, 0xeb, 0, PutAll },
511         { "XCE",  0x0000001, 0xfb, 0, PutAll }
512     }
513 };
514
515 #ifdef SUNPLUS
516 /* Table for the SUNPLUS CPU */
517 #include "sunplus.inc"
518 #endif
519
520
521
522 /* An array with instruction tables */
523 static const InsTable* InsTabs[CPU_COUNT] = {
524     (const InsTable*) &InsTab6502,
525     (const InsTable*) &InsTab6502X,
526     (const InsTable*) &InsTab65SC02,
527     (const InsTable*) &InsTab65C02,
528     (const InsTable*) &InsTab65816,
529 #ifdef SUNPLUS
530     (const InsTable*) &InsTabSunPlus,
531 #endif
532 };
533 const InsTable* InsTab = (const InsTable*) &InsTab6502;
534
535 /* Table to build the effective opcode from a base opcode and an addressing
536  * mode.
537  */
538 unsigned char EATab [9][AMI_COUNT] = {
539     {   /* Table 0 */
540         0x00, 0x00, 0x05, 0x0D, 0x0F, 0x15, 0x1D, 0x1F,
541         0x00, 0x19, 0x12, 0x00, 0x07, 0x11, 0x17, 0x01,
542         0x00, 0x00, 0x00, 0x03, 0x13, 0x09, 0x00, 0x09,
543         0x00
544     },
545     {   /* Table 1 */
546         0x08, 0x08, 0x04, 0x0C, 0x00, 0x14, 0x1C, 0x00,
547         0x14, 0x1C, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00,
548         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
549         0x00
550     },
551     {   /* Table 2 */
552         0x00, 0x00, 0x24, 0x2C, 0x0F, 0x34, 0x3C, 0x00,
553         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
554         0x00, 0x00, 0x00, 0x00, 0x00, 0x89, 0x00, 0x00,
555         0x00                        
556     },
557     {   /* Table 3 */
558         0x3A, 0x3A, 0xC6, 0xCE, 0x00, 0xD6, 0xDE, 0x00,
559         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
560         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
561         0x00
562     },
563     {   /* Table 4 */
564         0x1A, 0x1A, 0xE6, 0xEE, 0x00, 0xF6, 0xFE, 0x00,
565         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
566         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
567         0x00
568     },
569     {   /* Table 5 */
570         0x00, 0x00, 0x60, 0x98, 0x00, 0x70, 0x9E, 0x00,
571         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
572         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
573         0x00
574     },
575     {   /* Table 6 */
576         0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
577         0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00,
578         0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
579         0x00
580     },
581     {   /* Table 7 */
582         0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
583         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
584         0xDC, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
585         0x00
586     },
587     {   /* Table 8 */
588         0x00, 0x40, 0x01, 0x41, 0x00, 0x09, 0x49, 0x00,
589         0x00, 0x00, 0x00, 0x51, 0x00, 0x00, 0x00, 0x00,
590         0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00,
591         0x00
592     },
593 };
594
595 /* Table that encodes the additional bytes for each instruction */
596 unsigned char ExtBytes [AMI_COUNT] = {
597     0,          /* Implicit */
598     0,          /* Accu */
599     1,          /* Direct */
600     2,          /* Absolute */
601     3,          /* Absolute long */
602     1,          /* Direct,X */
603     2,          /* Absolute,X */
604     3,          /* Absolute long,X */
605     1,          /* Direct,Y */
606     2,          /* Absolute,Y */
607     1,          /* (Direct) */
608     2,          /* (Absolute) */
609     1,          /* [Direct] */
610     1,          /* (Direct),Y */
611     1,          /* [Direct],Y */
612     1,          /* (Direct,X) */
613     2,          /* (Absolute,X) */
614     1,          /* Relative short */
615     2,          /* Relative long */
616     1,          /* r,s */
617     1,          /* (r,s),y */
618     1,          /* Immidiate accu */
619     1,          /* Immidiate index */
620     1,          /* Immidiate byte */
621     2           /* Blockmove */
622 };
623
624
625
626 /*****************************************************************************/
627 /*                             Handler functions                             */
628 /*****************************************************************************/
629
630
631
632 static int EvalEA (const InsDesc* Ins, EffAddr* A)
633 /* Evaluate the effective address. All fields in A will be valid after calling
634  * this function. The function returns true on success and false on errors.
635  */
636 {
637     /* Get the set of possible addressing modes */
638     GetEA (A);
639
640     /* From the possible addressing modes, remove the ones that are invalid
641      * for this instruction or CPU.
642      */
643     A->AddrModeSet &= Ins->AddrMode;
644
645     /* If we have an expression, check it and remove any addressing modes that
646      * are too small for the expression size. Since we have to study the
647      * expression anyway, do also replace it by a simpler one if possible.
648      */
649     if (A->Expr) {
650         ExprDesc ED;
651         ED_Init (&ED);
652
653         /* Study the expression */
654         StudyExpr (A->Expr, &ED);
655
656         /* Simplify it if possible */
657         A->Expr = SimplifyExpr (A->Expr, &ED);
658
659         /* If we don't know how big the expression is, assume the default
660          * address size for data.
661          */
662         if (ED.AddrSize == ADDR_SIZE_DEFAULT) {
663             ED.AddrSize = DataAddrSize;
664         }
665
666         /* Check the size */
667         switch (ED.AddrSize) {
668
669             case ADDR_SIZE_ABS:
670                 A->AddrModeSet &= ~AM_SET_ZP;
671                 break;
672
673             case ADDR_SIZE_FAR:
674                 A->AddrModeSet &= ~(AM_SET_ZP | AM_SET_ABS);
675                 break;
676         }
677
678         /* Free any resource associated with the expression desc */
679         ED_Done (&ED);
680     }
681
682     /* Check if we have any adressing modes left */
683     if (A->AddrModeSet == 0) {
684         Error ("Illegal addressing mode");
685         return 0;
686     }
687     A->AddrMode    = BitFind (A->AddrModeSet);
688     A->AddrModeBit = (0x01UL << A->AddrMode);
689
690     /* If the instruction has a one byte operand and immediate addressing is
691      * allowed but not used, check for an operand expression in the form
692      * <label or >label, where label is a far or absolute label. If found,
693      * emit a warning. This warning protects against a typo, where the '#'
694      * for the immediate operand is omitted.
695      */
696     if (A->Expr && (Ins->AddrMode & AM_IMM)                &&
697         (A->AddrModeSet & (AM_DIR | AM_ABS | AM_ABS_LONG)) &&
698         ExtBytes[A->AddrMode] == 1) {
699
700         /* Found, check the expression */
701         ExprNode* Left = A->Expr->Left;
702         if ((A->Expr->Op == EXPR_BYTE0 || A->Expr->Op == EXPR_BYTE1) &&
703             Left->Op == EXPR_SYMBOL                                  &&
704             GetSymAddrSize (Left->V.Sym) != ADDR_SIZE_ZP) {
705
706             /* Output a warning */
707             Warning (1, "Suspicious address expression");
708         }
709     }
710
711     /* Build the opcode */
712     A->Opcode = Ins->BaseCode | EATab[Ins->ExtCode][A->AddrMode];
713
714     /* Success */
715     return 1;
716 }
717
718
719
720 static void EmitCode (EffAddr* A)
721 /* Output code for the data in A */
722 {
723     /* Check how many extension bytes are needed and output the instruction */
724     switch (ExtBytes[A->AddrMode]) {
725
726         case 0:
727             Emit0 (A->Opcode);
728             break;
729
730         case 1:
731             Emit1 (A->Opcode, A->Expr);
732             break;
733
734         case 2:
735             if (CPU == CPU_65816 && (A->AddrModeBit & (AM_ABS | AM_ABS_X | AM_ABS_Y))) {
736                 /* This is a 16 bit mode that uses an address. If in 65816,
737                  * mode, force this address into 16 bit range to allow
738                  * addressing inside a 64K segment.
739                  */
740                 Emit2 (A->Opcode, GenWordExpr (A->Expr));
741             } else {
742                 Emit2 (A->Opcode, A->Expr);
743             }
744             break;
745
746         case 3:
747             /* Far argument */
748             Emit3 (A->Opcode, A->Expr);
749             break;
750
751         default:
752             Internal ("Invalid operand byte count: %u", ExtBytes[A->AddrMode]);
753
754     }
755 }
756
757
758
759 static long PutImmed8 (const InsDesc* Ins)
760 /* Parse and emit an immediate 8 bit instruction. Return the value of the
761  * operand if it's available and const.
762  */
763 {
764     EffAddr A;
765     long Val = -1;
766
767     /* Evaluate the addressing mode */
768     if (EvalEA (Ins, &A) == 0) {
769         /* An error occurred */
770         return -1L;
771     }
772
773     /* If we have an expression and it's const, get it's value */
774     if (A.Expr) {
775         (void) IsConstExpr (A.Expr, &Val);
776     }
777
778     /* Check how many extension bytes are needed and output the instruction */
779     switch (ExtBytes[A.AddrMode]) {
780
781         case 1:
782             Emit1 (A.Opcode, A.Expr);
783             break;
784
785         default:
786             Internal ("Invalid operand byte count: %u", ExtBytes[A.AddrMode]);
787     }
788
789     /* Return the expression value */
790     return Val;
791 }
792
793
794
795 static void PutPCRel8 (const InsDesc* Ins)
796 /* Handle branches with a 8 bit distance */
797 {
798     EmitPCRel (Ins->BaseCode, GenBranchExpr (2), 1);
799 }
800
801
802
803 static void PutPCRel16 (const InsDesc* Ins)
804 /* Handle branches with an 16 bit distance and PER */
805 {
806     EmitPCRel (Ins->BaseCode, GenBranchExpr (3), 2);
807 }
808
809
810
811 static void PutBlockMove (const InsDesc* Ins)
812 /* Handle the blockmove instructions */
813 {
814     Emit0 (Ins->BaseCode);
815     EmitByte (Expression ());
816     ConsumeComma ();
817     EmitByte (Expression ());
818 }
819
820
821
822 static void PutBitBranch (const InsDesc* Ins)
823 /* Handle 65C02 branch on bit condition */
824 {
825     Emit0 (Ins->BaseCode);
826     EmitByte (Expression ());
827     ConsumeComma ();
828     EmitSigned (GenBranchExpr (1), 1);
829 }
830
831
832
833 static void PutREP (const InsDesc* Ins)
834 /* Emit a REP instruction, track register sizes */
835 {
836     /* Use the generic handler */
837     long Val = PutImmed8 (Ins);
838
839     /* We track the status only for the 816 CPU and in smart mode */
840     if (CPU == CPU_65816 && SmartMode) {
841
842         /* Check the range for Val. */
843         if (Val < 0) {
844             /* We had an error */
845             Warning (1, "Cannot track processor status byte");
846         } else {
847             if (Val & 0x10) {
848                 /* Index registers to 16 bit */
849                 ExtBytes[AMI_IMM_INDEX] = 2;
850             }
851             if (Val & 0x20) {
852                 /* Accu to 16 bit */
853                 ExtBytes[AMI_IMM_ACCU] = 2;
854             }
855         }
856     }
857 }
858
859
860
861 static void PutSEP (const InsDesc* Ins)
862 /* Emit a SEP instruction, track register sizes */
863 {
864     /* Use the generic handler */
865     long Val = PutImmed8 (Ins);
866
867     /* We track the status only for the 816 CPU and in smart mode */
868     if (CPU == CPU_65816 && SmartMode) {
869
870         /* Check the range for Val. */
871         if (Val < 0) {
872             /* We had an error */
873             Warning (1, "Cannot track processor status byte");
874         } else {
875             if (Val & 0x10) {
876                 /* Index registers to 8 bit */
877                 ExtBytes [AMI_IMM_INDEX] = 1;
878             }
879             if (Val & 0x20) {
880                 /* Accu to 8 bit */
881                 ExtBytes [AMI_IMM_ACCU] = 1;
882             }
883         }
884     }
885 }
886
887
888
889 static void PutJMP (const InsDesc* Ins)
890 /* Handle the jump instruction for the 6502. Problem is that these chips have
891  * a bug: If the address crosses a page, the upper byte gets not corrected and
892  * the instruction will fail. The PutJmp function will add a linker assertion
893  * to check for this case and is otherwise identical to PutAll.
894  */
895 {
896     EffAddr A;
897
898     /* Evaluate the addressing mode used */
899     if (EvalEA (Ins, &A)) {
900
901         /* Check for indirect addressing */
902         if (A.AddrModeBit & AM_ABS_IND) {
903
904             /* Compare the low byte of the expression to 0xFF to check for
905              * a page cross. Be sure to use a copy of the expression otherwise
906              * things will go weird later.
907              */
908             ExprNode* E = GenNE (GenByteExpr (CloneExpr (A.Expr)), 0xFF);
909
910             /* Generate the message */
911             unsigned Msg = GetStringId ("\"jmp (abs)\" across page border");
912
913             /* Generate the assertion */
914             AddAssertion (E, ASSERT_ACT_WARN, Msg);
915         }
916
917         /* No error, output code */
918         EmitCode (&A);
919     }
920 }
921
922
923
924 static void PutRTS (const InsDesc* Ins attribute ((unused)))
925 /* Handle the RTS instruction for the 816. In smart mode emit a RTL opcode if
926  * the enclosing scope is FAR.
927  */
928 {
929     if (SmartMode && CurrentScope->AddrSize == ADDR_SIZE_FAR) {
930         Emit0 (0x6B);       /* RTL */
931     } else {
932         Emit0 (0x60);       /* RTS */
933     }
934 }
935
936
937
938 static void PutAll (const InsDesc* Ins)
939 /* Handle all other instructions */
940 {
941     EffAddr A;
942
943     /* Evaluate the addressing mode used */
944     if (EvalEA (Ins, &A)) {
945         /* No error, output code */
946         EmitCode (&A);
947     }
948 }
949
950
951
952 /*****************************************************************************/
953 /*                                   Code                                    */
954 /*****************************************************************************/
955
956
957
958 static int CmpName (const void* Key, const void* Instr)
959 /* Compare function for bsearch */
960 {
961     return strcmp ((const char*)Key, ((const InsDesc*) Instr)->Mnemonic);
962 }
963
964
965
966 void SetCPU (cpu_t NewCPU)
967 /* Set a new CPU */
968 {
969     /* Make sure the parameter is correct */
970     CHECK (NewCPU < CPU_COUNT);
971
972     /* Check if we have support for the new CPU, if so, use it */
973     if (InsTabs[NewCPU]) {
974         CPU = NewCPU;
975         InsTab = InsTabs[CPU];
976     } else {
977         Error ("CPU not supported");
978     }
979 }
980
981
982
983 cpu_t GetCPU (void)
984 /* Return the current CPU */
985 {
986     return CPU;
987 }
988
989
990
991 int FindInstruction (const char* Ident)
992 /* Check if Ident is a valid mnemonic. If so, return the index in the
993  * instruction table. If not, return -1.
994  */
995 {
996     unsigned I;
997     const InsDesc* ID;
998     char Key[sizeof (ID->Mnemonic)];
999
1000     /* Make a copy, and uppercase that copy */
1001     I = 0;
1002     while (Ident[I] != '\0') {
1003         /* If the identifier is longer than the longest mnemonic, it cannot
1004          * be one.
1005          */
1006         if (I >= sizeof (Key) - 1) {
1007             /* Not found, no need for further action */
1008             return -1;
1009         }
1010         Key[I] = toupper ((unsigned char)Ident[I]);
1011         ++I;
1012     }
1013     Key[I] = '\0';
1014
1015     /* Search for the key */
1016     ID = bsearch (Key, InsTab->Ins, InsTab->Count, sizeof (InsDesc), CmpName);
1017     if (ID == 0) {
1018         /* Not found */
1019         return -1;
1020     } else {
1021         /* Found, return the entry */
1022         return ID - InsTab->Ins;
1023     }
1024 }
1025
1026
1027
1028 void HandleInstruction (unsigned Index)
1029 /* Handle the mnemonic with the given index */
1030 {
1031     /* Safety check */
1032     PRECONDITION (Index < InsTab->Count);
1033
1034     /* Skip the mnemonic token */
1035     NextTok ();
1036
1037     /* Call the handler */
1038     InsTab->Ins[Index].Emit (&InsTab->Ins[Index]);
1039 }
1040
1041
1042