]> git.sur5r.net Git - cc65/blob - src/ca65/instr.c
Removed redundant attempts to build uncompilable files.
[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",  0x080A30C, 0xA3, 11, 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         { "SHX",  0x0000200, 0x9e, 1, PutAll },         /* X */
284         { "SHY",  0x0000040, 0x9c, 1, PutAll },         /* X */
285         { "SLO",  0x000A26C, 0x03, 0, PutAll },         /* X */
286         { "SRE",  0x000A26C, 0x43, 0, PutAll },         /* X */
287         { "STA",  0x000A26C, 0x80, 0, PutAll },
288         { "STX",  0x000010c, 0x82, 1, PutAll },
289         { "STY",  0x000002c, 0x80, 1, PutAll },
290         { "TAS",  0x0000200, 0x9b, 0, PutAll },         /* X */
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         { "SAX",  0x0000001, 0x22, 0, PutAll },
717         { "SAY",  0x0000001, 0x42, 0, PutAll },
718         { "SBC",  0x080A66C, 0xe0, 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[12][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     {   /* Table 11 (LAX) */
861         0x08, 0x08, 0x04, 0x0C, 0x00, 0x14, 0x1C, 0x00,
862         0x14, 0x1C, 0x00, 0x80, 0x00, 0x10, 0x00, 0x00,
863         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08,
864         0x00, 0x00, 0x80
865     },
866 };
867
868 /* Table to build the effective SWEET16 opcode from a base opcode and an
869 ** addressing mode.
870 */
871 static unsigned char Sweet16EATab[2][AMSW16I_COUNT] = {
872     {   /* Table 0 */
873         0x00, 0x00, 0x00, 0x00, 0x00,
874     },
875     {   /* Table 1 */
876         0x00, 0x00, 0x00, 0x40, 0x20,
877     },
878 };
879
880 /* Table that encodes the additional bytes for each 65xx instruction */
881 unsigned char ExtBytes[AM65I_COUNT] = {
882     0,          /* Implicit */
883     0,          /* Accu */
884     1,          /* Direct */
885     2,          /* Absolute */
886     3,          /* Absolute long */
887     1,          /* Direct,X */
888     2,          /* Absolute,X */
889     3,          /* Absolute long,X */
890     1,          /* Direct,Y */
891     2,          /* Absolute,Y */
892     1,          /* (Direct) */
893     2,          /* (Absolute) */
894     1,          /* [Direct] */
895     1,          /* (Direct),Y */
896     1,          /* [Direct],Y */
897     1,          /* (Direct,X) */
898     2,          /* (Absolute,X) */
899     1,          /* Relative short */
900     2,          /* Relative long */
901     1,          /* r,s */
902     1,          /* (r,s),y */
903     1,          /* Immidiate accu */
904     1,          /* Immidiate index */
905     1,          /* Immidiate byte */
906     2,          /* Blockmove (65816) */
907     7,          /* Block transfer (HuC6280) */
908     2,          /* Absolute Indirect long */
909 };
910
911 /* Table that encodes the additional bytes for each SWEET16 instruction */
912 static unsigned char Sweet16ExtBytes[AMSW16I_COUNT] = {
913     0,          /* AMSW16_IMP */
914     1,          /* AMSW16_BRA */
915     2,          /* AMSW16_IMM */
916     0,          /* AMSW16_IND */
917     0,          /* AMSW16_REG */
918 };
919
920
921
922 /*****************************************************************************/
923 /*                   Handler functions for 6502 derivates                    */
924 /*****************************************************************************/
925
926
927
928 static int EvalEA (const InsDesc* Ins, EffAddr* A)
929 /* Evaluate the effective address. All fields in A will be valid after calling
930 ** this function. The function returns true on success and false on errors.
931 */
932 {
933     /* Get the set of possible addressing modes */
934     GetEA (A);
935
936     /* From the possible addressing modes, remove the ones that are invalid
937     ** for this instruction or CPU.
938     */
939     A->AddrModeSet &= Ins->AddrMode;
940
941     /* If we have an expression, check it and remove any addressing modes that
942     ** are too small for the expression size. Since we have to study the
943     ** expression anyway, do also replace it by a simpler one if possible.
944     */
945     if (A->Expr) {
946         ExprDesc ED;
947         ED_Init (&ED);
948
949         /* Study the expression */
950         StudyExpr (A->Expr, &ED);
951
952         /* Simplify it if possible */
953         A->Expr = SimplifyExpr (A->Expr, &ED);
954
955         if (ED.AddrSize == ADDR_SIZE_DEFAULT) {
956             /* We don't know how big the expression is. If the instruction
957             ** allows just one addressing mode, assume this as address size
958             ** for the expression. Otherwise assume the default address size
959             ** for data.
960             */
961             if ((A->AddrModeSet & ~AM65_ALL_ZP) == 0) {
962                 ED.AddrSize = ADDR_SIZE_ZP;
963             } else if ((A->AddrModeSet & ~AM65_ALL_ABS) == 0) {
964                 ED.AddrSize = ADDR_SIZE_ABS;
965             } else if ((A->AddrModeSet & ~AM65_ALL_FAR) == 0) {
966                 ED.AddrSize = ADDR_SIZE_FAR;
967             } else {
968                 ED.AddrSize = DataAddrSize;
969                 /* If the default address size of the data segment is unequal
970                 ** to zero page addressing, but zero page addressing is 
971                 ** allowed by the instruction, mark all symbols in the 
972                 ** expression tree. This mark will be checked at end of 
973                 ** assembly, and a warning is issued, if a zero page symbol
974                 ** was guessed wrong here.
975                 */
976                 if (ED.AddrSize > ADDR_SIZE_ZP && (A->AddrModeSet & AM65_SET_ZP)) {
977                     ExprGuessedAddrSize (A->Expr, ADDR_SIZE_ZP);
978                 }
979             }
980         }
981
982         /* Check the size */
983         switch (ED.AddrSize) {
984
985             case ADDR_SIZE_ABS:
986                 A->AddrModeSet &= ~AM65_SET_ZP;
987                 break;
988
989             case ADDR_SIZE_FAR:
990                 A->AddrModeSet &= ~(AM65_SET_ZP | AM65_SET_ABS);
991                 break;
992         }
993
994         /* Free any resource associated with the expression desc */
995         ED_Done (&ED);
996     }
997
998     /* Check if we have any adressing modes left */
999     if (A->AddrModeSet == 0) {
1000         Error ("Illegal addressing mode");
1001         return 0;
1002     }
1003     A->AddrMode    = BitFind (A->AddrModeSet);
1004     A->AddrModeBit = (0x01UL << A->AddrMode);
1005
1006     /* If the instruction has a one byte operand and immediate addressing is
1007     ** allowed but not used, check for an operand expression in the form
1008     ** <label or >label, where label is a far or absolute label. If found,
1009     ** emit a warning. This warning protects against a typo, where the '#'
1010     ** for the immediate operand is omitted.
1011     */
1012     if (A->Expr && (Ins->AddrMode & AM65_ALL_IMM)                &&
1013         (A->AddrModeSet & (AM65_DIR | AM65_ABS | AM65_ABS_LONG)) &&
1014         ExtBytes[A->AddrMode] == 1) {
1015
1016         /* Found, check the expression */
1017         ExprNode* Left = A->Expr->Left;
1018         if ((A->Expr->Op == EXPR_BYTE0 || A->Expr->Op == EXPR_BYTE1) &&
1019             Left->Op == EXPR_SYMBOL                                  &&
1020             GetSymAddrSize (Left->V.Sym) != ADDR_SIZE_ZP) {
1021
1022             /* Output a warning */
1023             Warning (1, "Suspicious address expression");
1024         }
1025     }
1026
1027     /* Build the opcode */
1028     A->Opcode = Ins->BaseCode | EATab[Ins->ExtCode][A->AddrMode];
1029
1030     /* If feature force_range is active, and we have immediate addressing mode,
1031     ** limit the expression to the maximum possible value.
1032     */
1033     if (A->AddrMode == AM65I_IMM_ACCU || A->AddrMode == AM65I_IMM_INDEX ||
1034         A->AddrMode == AM65I_IMM_IMPLICIT) {
1035         if (ForceRange && A->Expr) {
1036             A->Expr = MakeBoundedExpr (A->Expr, ExtBytes[A->AddrMode]);
1037         }
1038     }
1039
1040     /* Success */
1041     return 1;
1042 }
1043
1044
1045
1046 static void EmitCode (EffAddr* A)
1047 /* Output code for the data in A */
1048 {
1049     /* Check how many extension bytes are needed and output the instruction */
1050     switch (ExtBytes[A->AddrMode]) {
1051
1052         case 0:
1053             Emit0 (A->Opcode);
1054             break;
1055
1056         case 1:
1057             Emit1 (A->Opcode, A->Expr);
1058             break;
1059
1060         case 2:
1061             if (CPU == CPU_65816 && (A->AddrModeBit & (AM65_ABS | AM65_ABS_X | AM65_ABS_Y))) {
1062                 /* This is a 16 bit mode that uses an address. If in 65816,
1063                 ** mode, force this address into 16 bit range to allow
1064                 ** addressing inside a 64K segment.
1065                 */
1066                 Emit2 (A->Opcode, GenWordExpr (A->Expr));
1067             } else {
1068                 Emit2 (A->Opcode, A->Expr);
1069             }
1070             break;
1071
1072         case 3:
1073             /* Far argument */
1074             Emit3 (A->Opcode, A->Expr);
1075             break;
1076
1077         default:
1078             Internal ("Invalid operand byte count: %u", ExtBytes[A->AddrMode]);
1079
1080     }
1081 }
1082
1083
1084
1085 static long PutImmed8 (const InsDesc* Ins)
1086 /* Parse and emit an immediate 8 bit instruction. Return the value of the
1087 ** operand if it's available and const.
1088 */
1089 {
1090     EffAddr A;
1091     long Val = -1;
1092
1093     /* Evaluate the addressing mode */
1094     if (EvalEA (Ins, &A) == 0) {
1095         /* An error occurred */
1096         return -1L;
1097     }
1098
1099     /* If we have an expression and it's const, get it's value */
1100     if (A.Expr) {
1101         (void) IsConstExpr (A.Expr, &Val);
1102     }
1103
1104     /* Check how many extension bytes are needed and output the instruction */
1105     switch (ExtBytes[A.AddrMode]) {
1106
1107         case 1:
1108             Emit1 (A.Opcode, A.Expr);
1109             break;
1110
1111         default:
1112             Internal ("Invalid operand byte count: %u", ExtBytes[A.AddrMode]);
1113     }
1114
1115     /* Return the expression value */
1116     return Val;
1117 }
1118
1119
1120
1121 static void PutPCRel8 (const InsDesc* Ins)
1122 /* Handle branches with a 8 bit distance */
1123 {
1124     EmitPCRel (Ins->BaseCode, GenBranchExpr (2), 1);
1125 }
1126
1127
1128
1129 static void PutPCRel16 (const InsDesc* Ins)
1130 /* Handle branches with an 16 bit distance and PER */
1131 {
1132     EmitPCRel (Ins->BaseCode, GenBranchExpr (3), 2);
1133 }
1134
1135
1136
1137 static void PutBlockMove (const InsDesc* Ins)
1138 /* Handle the blockmove instructions (65816) */
1139 {
1140     Emit0 (Ins->BaseCode);
1141     EmitByte (Expression ());
1142     ConsumeComma ();
1143     EmitByte (Expression ());
1144 }
1145
1146
1147
1148 static void PutBlockTransfer (const InsDesc* Ins)
1149 /* Handle the block transfer instructions (HuC6280) */
1150 {
1151     Emit0 (Ins->BaseCode);
1152     EmitWord (Expression ());
1153     ConsumeComma ();
1154     EmitWord (Expression ());
1155     ConsumeComma ();
1156     EmitWord (Expression ());
1157 }
1158
1159
1160
1161 static void PutBitBranch (const InsDesc* Ins)
1162 /* Handle 65C02 branch on bit condition */
1163 {
1164     Emit0 (Ins->BaseCode);
1165     EmitByte (Expression ());
1166     ConsumeComma ();
1167     EmitSigned (GenBranchExpr (1), 1);
1168 }
1169
1170
1171
1172 static void PutREP (const InsDesc* Ins)
1173 /* Emit a REP instruction, track register sizes */
1174 {
1175     /* Use the generic handler */
1176     long Val = PutImmed8 (Ins);
1177
1178     /* We track the status only for the 816 CPU and in smart mode */
1179     if (CPU == CPU_65816 && SmartMode) {
1180
1181         /* Check the range for Val. */
1182         if (Val < 0) {
1183             /* We had an error */
1184             Warning (1, "Cannot track processor status byte");
1185         } else {
1186             if (Val & 0x10) {
1187                 /* Index registers to 16 bit */
1188                 ExtBytes[AM65I_IMM_INDEX] = 2;
1189             }
1190             if (Val & 0x20) {
1191                 /* Accu to 16 bit */
1192                 ExtBytes[AM65I_IMM_ACCU] = 2;
1193             }
1194         }
1195     }
1196 }
1197
1198
1199
1200 static void PutSEP (const InsDesc* Ins)
1201 /* Emit a SEP instruction (65816), track register sizes */
1202 {
1203     /* Use the generic handler */
1204     long Val = PutImmed8 (Ins);
1205
1206     /* We track the status only for the 816 CPU and in smart mode */
1207     if (CPU == CPU_65816 && SmartMode) {
1208
1209         /* Check the range for Val. */
1210         if (Val < 0) {
1211             /* We had an error */
1212             Warning (1, "Cannot track processor status byte");
1213         } else {
1214             if (Val & 0x10) {
1215                 /* Index registers to 8 bit */
1216                 ExtBytes[AM65I_IMM_INDEX] = 1;
1217             }
1218             if (Val & 0x20) {
1219                 /* Accu to 8 bit */
1220                 ExtBytes[AM65I_IMM_ACCU] = 1;
1221             }
1222         }
1223     }
1224 }
1225
1226
1227
1228 static void PutTAMn (const InsDesc* Ins)
1229 /* Emit a TAMn instruction (HuC6280). Since this is a two byte instruction with
1230 ** implicit addressing mode, the opcode byte in the table is actually the
1231 ** second operand byte. The TAM instruction is the more generic form, it takes
1232 ** an immediate argument.
1233 */
1234 {
1235     /* Emit the TAM opcode itself */
1236     Emit0 (0x53);
1237
1238     /* Emit the argument, which is the opcode from the table */
1239     Emit0 (Ins->BaseCode);
1240 }
1241
1242
1243
1244 static void PutTMA (const InsDesc* Ins)
1245 /* Emit a TMA instruction (HuC6280) with an immediate argument. Only one bit
1246 ** in the argument byte may be set.
1247 */
1248 {
1249     /* Use the generic handler */
1250     long Val = PutImmed8 (Ins);
1251
1252     /* Check the range for Val. */
1253     if (Val < 0) {
1254         /* We had an error */
1255         Warning (1, "Cannot check argument of TMA instruction");
1256     } else {
1257         /* Make sure just one bit is set */
1258         if ((Val & (Val - 1)) != 0) {
1259             Error ("Argument to TAM must be a power of two");
1260         }
1261     }
1262 }
1263
1264
1265
1266 static void PutTMAn (const InsDesc* Ins)
1267 /* Emit a TMAn instruction (HuC6280). Since this is a two byte instruction with
1268 ** implicit addressing mode, the opcode byte in the table is actually the
1269 ** second operand byte. The TAM instruction is the more generic form, it takes
1270 ** an immediate argument.
1271 */
1272 {
1273     /* Emit the TMA opcode itself */
1274     Emit0 (0x43);
1275
1276     /* Emit the argument, which is the opcode from the table */
1277     Emit0 (Ins->BaseCode);
1278 }
1279
1280
1281
1282 static void PutTST (const InsDesc* Ins)
1283 /* Emit a TST instruction (HuC6280). */
1284 {
1285     ExprNode* Arg1;
1286     EffAddr   A;
1287
1288     /* The first argument is always an immediate byte */
1289     if (CurTok.Tok != TOK_HASH) {
1290         ErrorSkip ("Invalid addressing mode");
1291         return;
1292     }
1293     NextTok ();
1294     Arg1 = Expression ();
1295
1296     /* Second argument follows */
1297     ConsumeComma ();
1298
1299     /* For the second argument, we use the standard function */
1300     if (EvalEA (Ins, &A)) {
1301
1302         /* No error, output code */
1303         Emit1 (A.Opcode, Arg1);
1304
1305         /* Check how many extension bytes are needed and output the instruction */
1306         switch (ExtBytes[A.AddrMode]) {
1307
1308             case 1:
1309                 EmitByte (A.Expr);
1310                 break;
1311
1312             case 2:
1313                 EmitWord (A.Expr);
1314                 break;
1315         }
1316     }
1317 }
1318
1319
1320
1321 static void PutJMP (const InsDesc* Ins)
1322 /* Handle the jump instruction for the 6502. Problem is that these chips have
1323 ** a bug: If the address crosses a page, the upper byte gets not corrected and
1324 ** the instruction will fail. The PutJmp function will add a linker assertion
1325 ** to check for this case and is otherwise identical to PutAll.
1326 */
1327 {
1328     EffAddr A;
1329
1330     /* Evaluate the addressing mode used */
1331     if (EvalEA (Ins, &A)) {
1332
1333         /* Check for indirect addressing */
1334         if (A.AddrModeBit & AM65_ABS_IND) {
1335
1336             /* Compare the low byte of the expression to 0xFF to check for
1337             ** a page cross. Be sure to use a copy of the expression otherwise
1338             ** things will go weird later.
1339             */
1340             ExprNode* E = GenNE (GenByteExpr (CloneExpr (A.Expr)), 0xFF);
1341
1342             /* Generate the message */
1343             unsigned Msg = GetStringId ("\"jmp (abs)\" across page border");
1344
1345             /* Generate the assertion */
1346             AddAssertion (E, ASSERT_ACT_WARN, Msg);
1347         }
1348
1349         /* No error, output code */
1350         EmitCode (&A);
1351     }
1352 }
1353
1354
1355
1356 static void PutRTS (const InsDesc* Ins attribute ((unused)))
1357 /* Handle the RTS instruction for the 816. In smart mode emit a RTL opcode if
1358 ** the enclosing scope is FAR.
1359 */
1360 {
1361     if (SmartMode && CurrentScope->AddrSize == ADDR_SIZE_FAR) {
1362         Emit0 (0x6B);       /* RTL */
1363     } else {
1364         Emit0 (0x60);       /* RTS */
1365     }
1366 }
1367
1368
1369
1370 static void PutAll (const InsDesc* Ins)
1371 /* Handle all other instructions */
1372 {
1373     EffAddr A;
1374
1375     /* Evaluate the addressing mode used */
1376     if (EvalEA (Ins, &A)) {
1377         /* No error, output code */
1378         EmitCode (&A);
1379     }
1380 }
1381
1382
1383
1384 /*****************************************************************************/
1385 /*                       Handler functions for SWEET16                       */
1386 /*****************************************************************************/
1387
1388
1389
1390 static void PutSweet16 (const InsDesc* Ins)
1391 /* Handle a generic sweet16 instruction */
1392 {
1393     EffAddr A;
1394
1395     /* Evaluate the addressing mode used */
1396     GetSweet16EA (&A);
1397
1398     /* From the possible addressing modes, remove the ones that are invalid
1399     ** for this instruction or CPU.
1400     */
1401     A.AddrModeSet &= Ins->AddrMode;
1402
1403     /* Check if we have any adressing modes left */
1404     if (A.AddrModeSet == 0) {
1405         Error ("Illegal addressing mode");
1406         return;
1407     }
1408     A.AddrMode    = BitFind (A.AddrModeSet);
1409     A.AddrModeBit = (0x01UL << A.AddrMode);
1410
1411     /* Build the opcode */
1412     A.Opcode = Ins->BaseCode | Sweet16EATab[Ins->ExtCode][A.AddrMode] | A.Reg;
1413
1414     /* Check how many extension bytes are needed and output the instruction */
1415     switch (Sweet16ExtBytes[A.AddrMode]) {
1416
1417         case 0:
1418             Emit0 (A.Opcode);
1419             break;
1420
1421         case 1:
1422             Emit1 (A.Opcode, A.Expr);
1423             break;
1424
1425         case 2:
1426             Emit2 (A.Opcode, A.Expr);
1427             break;
1428
1429         default:
1430             Internal ("Invalid operand byte count: %u", Sweet16ExtBytes[A.AddrMode]);
1431
1432     }
1433 }
1434
1435
1436
1437 static void PutSweet16Branch (const InsDesc* Ins)
1438 /* Handle a sweet16 branch instruction */
1439 {
1440     EmitPCRel (Ins->BaseCode, GenBranchExpr (2), 1);
1441 }
1442
1443
1444
1445 /*****************************************************************************/
1446 /*                                   Code                                    */
1447 /*****************************************************************************/
1448
1449
1450
1451 static int CmpName (const void* Key, const void* Instr)
1452 /* Compare function for bsearch */
1453 {
1454     return strcmp ((const char*)Key, ((const InsDesc*) Instr)->Mnemonic);
1455 }
1456
1457
1458
1459 void SetCPU (cpu_t NewCPU)
1460 /* Set a new CPU */
1461 {
1462     /* Make sure the parameter is correct */
1463     CHECK (NewCPU < CPU_COUNT);
1464
1465     /* Check if we have support for the new CPU, if so, use it */
1466     if (NewCPU != CPU_UNKNOWN && InsTabs[NewCPU]) {
1467         CPU = NewCPU;
1468         InsTab = InsTabs[CPU];
1469     } else {
1470         Error ("CPU not supported");
1471     }
1472 }
1473
1474
1475
1476 cpu_t GetCPU (void)
1477 /* Return the current CPU */
1478 {
1479     return CPU;
1480 }
1481
1482
1483
1484 int FindInstruction (const StrBuf* Ident)
1485 /* Check if Ident is a valid mnemonic. If so, return the index in the
1486 ** instruction table. If not, return -1.
1487 */
1488 {
1489     unsigned I;
1490     const InsDesc* ID;
1491     char Key[sizeof (ID->Mnemonic)];
1492
1493     /* Shortcut for the "none" CPU: If there are no instructions to search
1494     ** for, bail out early.
1495     */
1496     if (InsTab->Count == 0) {
1497         /* Not found */
1498         return -1;
1499     }
1500
1501     /* Make a copy, and uppercase that copy */
1502     I = 0;
1503     while (I < SB_GetLen (Ident)) {
1504         /* If the identifier is longer than the longest mnemonic, it cannot
1505         ** be one.
1506         */
1507         if (I >= sizeof (Key) - 1) {
1508             /* Not found, no need for further action */
1509             return -1;
1510         }
1511         Key[I] = toupper ((unsigned char)SB_AtUnchecked (Ident, I));
1512         ++I;
1513     }
1514     Key[I] = '\0';
1515
1516     /* Search for the key */
1517     ID = bsearch (Key, InsTab->Ins, InsTab->Count, sizeof (InsDesc), CmpName);
1518     if (ID == 0) {
1519         /* Not found */
1520         return -1;
1521     } else {
1522         /* Found, return the entry */
1523         return ID - InsTab->Ins;
1524     }
1525 }
1526
1527
1528
1529 void HandleInstruction (unsigned Index)
1530 /* Handle the mnemonic with the given index */
1531 {
1532     /* Safety check */
1533     PRECONDITION (Index < InsTab->Count);
1534
1535     /* Skip the mnemonic token */
1536     NextTok ();
1537
1538     /* Call the handler */
1539     InsTab->Ins[Index].Emit (&InsTab->Ins[Index]);
1540 }