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