1 /*****************************************************************************/
5 /* Instruction encoding for the ca65 macroassembler */
9 /* (C) 1998-2012, Ullrich von Bassewitz */
10 /* Roemerstrasse 52 */
11 /* D-70794 Filderstadt */
12 /* EMail: uz@cc65.org */
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. */
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: */
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 */
32 /*****************************************************************************/
59 #include "studyexpr.h"
64 /*****************************************************************************/
66 /*****************************************************************************/
70 static void PutPCRel8 (const InsDesc* Ins);
71 /* Handle branches with a 8 bit distance */
73 static void PutPCRel16 (const InsDesc* Ins);
74 /* Handle branches with an 16 bit distance and PER */
76 static void PutPCRel4510 (const InsDesc* Ins);
77 /* Handle branches with a 16 bit distance for 4510 */
79 static void PutBlockMove (const InsDesc* Ins);
80 /* Handle the blockmove instructions (65816) */
82 static void PutBlockTransfer (const InsDesc* Ins);
83 /* Handle the block transfer instructions (HuC6280) */
85 static void PutBitBranch (const InsDesc* Ins);
86 /* Handle 65C02 branch on bit condition */
88 static void PutREP (const InsDesc* Ins);
89 /* Emit a REP instruction, track register sizes */
91 static void PutSEP (const InsDesc* Ins);
92 /* Emit a SEP instruction (65816), track register sizes */
94 static void PutTAMn (const InsDesc* Ins);
95 /* Emit a TAMn instruction (HuC6280). Since this is a two byte instruction with
96 ** implicit addressing mode, the opcode byte in the table is actually the
97 ** second operand byte. The TAM instruction is the more generic form, it takes
98 ** an immediate argument.
101 static void PutTMA (const InsDesc* Ins);
102 /* Emit a TMA instruction (HuC6280) with an immediate argument. Only one bit
103 ** in the argument byte may be set.
106 static void PutTMAn (const InsDesc* Ins);
107 /* Emit a TMAn instruction (HuC6280). Since this is a two byte instruction with
108 ** implicit addressing mode, the opcode byte in the table is actually the
109 ** second operand byte. The TAM instruction is the more generic form, it takes
110 ** an immediate argument.
113 static void PutTST (const InsDesc* Ins);
114 /* Emit a TST instruction (HuC6280). */
116 static void PutJMP (const InsDesc* Ins);
117 /* Handle the jump instruction for the 6502. Problem is that these chips have
118 ** a bug: If the address crosses a page, the upper byte gets not corrected and
119 ** the instruction will fail. The PutJmp function will add a linker assertion
120 ** to check for this case and is otherwise identical to PutAll.
123 static void PutRTS (const InsDesc* Ins attribute ((unused)));
124 /* Handle the RTS instruction for the 816. In smart mode emit a RTL opcode if
125 ** the enclosing scope is FAR.
128 static void PutAll (const InsDesc* Ins);
129 /* Handle all other instructions */
131 static void Put4510 (const InsDesc* Ins);
132 /* Handle instructions of 4510 not matching any EATab */
134 static void PutSweet16 (const InsDesc* Ins);
135 /* Handle a generic sweet16 instruction */
137 static void PutSweet16Branch (const InsDesc* Ins);
138 /* Handle a sweet16 branch instruction */
142 /*****************************************************************************/
144 /*****************************************************************************/
148 /* Empty instruction table */
149 static const struct {
155 /* Instruction table for the 6502 */
156 static const struct {
160 sizeof (InsTab6502.Ins) / sizeof (InsTab6502.Ins[0]),
162 { "ADC", 0x080A26C, 0x60, 0, PutAll },
163 { "AND", 0x080A26C, 0x20, 0, PutAll },
164 { "ASL", 0x000006e, 0x02, 1, PutAll },
165 { "BCC", 0x0020000, 0x90, 0, PutPCRel8 },
166 { "BCS", 0x0020000, 0xb0, 0, PutPCRel8 },
167 { "BEQ", 0x0020000, 0xf0, 0, PutPCRel8 },
168 { "BIT", 0x000000C, 0x00, 2, PutAll },
169 { "BMI", 0x0020000, 0x30, 0, PutPCRel8 },
170 { "BNE", 0x0020000, 0xd0, 0, PutPCRel8 },
171 { "BPL", 0x0020000, 0x10, 0, PutPCRel8 },
172 { "BRK", 0x0000001, 0x00, 0, PutAll },
173 { "BVC", 0x0020000, 0x50, 0, PutPCRel8 },
174 { "BVS", 0x0020000, 0x70, 0, PutPCRel8 },
175 { "CLC", 0x0000001, 0x18, 0, PutAll },
176 { "CLD", 0x0000001, 0xd8, 0, PutAll },
177 { "CLI", 0x0000001, 0x58, 0, PutAll },
178 { "CLV", 0x0000001, 0xb8, 0, PutAll },
179 { "CMP", 0x080A26C, 0xc0, 0, PutAll },
180 { "CPX", 0x080000C, 0xe0, 1, PutAll },
181 { "CPY", 0x080000C, 0xc0, 1, PutAll },
182 { "DEC", 0x000006C, 0x00, 3, PutAll },
183 { "DEX", 0x0000001, 0xca, 0, PutAll },
184 { "DEY", 0x0000001, 0x88, 0, PutAll },
185 { "EOR", 0x080A26C, 0x40, 0, PutAll },
186 { "INC", 0x000006c, 0x00, 4, PutAll },
187 { "INX", 0x0000001, 0xe8, 0, PutAll },
188 { "INY", 0x0000001, 0xc8, 0, PutAll },
189 { "JMP", 0x0000808, 0x4c, 6, PutJMP },
190 { "JSR", 0x0000008, 0x20, 7, PutAll },
191 { "LDA", 0x080A26C, 0xa0, 0, PutAll },
192 { "LDX", 0x080030C, 0xa2, 1, PutAll },
193 { "LDY", 0x080006C, 0xa0, 1, PutAll },
194 { "LSR", 0x000006F, 0x42, 1, PutAll },
195 { "NOP", 0x0000001, 0xea, 0, PutAll },
196 { "ORA", 0x080A26C, 0x00, 0, PutAll },
197 { "PHA", 0x0000001, 0x48, 0, PutAll },
198 { "PHP", 0x0000001, 0x08, 0, PutAll },
199 { "PLA", 0x0000001, 0x68, 0, PutAll },
200 { "PLP", 0x0000001, 0x28, 0, PutAll },
201 { "ROL", 0x000006F, 0x22, 1, PutAll },
202 { "ROR", 0x000006F, 0x62, 1, PutAll },
203 { "RTI", 0x0000001, 0x40, 0, PutAll },
204 { "RTS", 0x0000001, 0x60, 0, PutAll },
205 { "SBC", 0x080A26C, 0xe0, 0, PutAll },
206 { "SEC", 0x0000001, 0x38, 0, PutAll },
207 { "SED", 0x0000001, 0xf8, 0, PutAll },
208 { "SEI", 0x0000001, 0x78, 0, PutAll },
209 { "STA", 0x000A26C, 0x80, 0, PutAll },
210 { "STX", 0x000010c, 0x82, 1, PutAll },
211 { "STY", 0x000002c, 0x80, 1, PutAll },
212 { "TAX", 0x0000001, 0xaa, 0, PutAll },
213 { "TAY", 0x0000001, 0xa8, 0, PutAll },
214 { "TSX", 0x0000001, 0xba, 0, PutAll },
215 { "TXA", 0x0000001, 0x8a, 0, PutAll },
216 { "TXS", 0x0000001, 0x9a, 0, PutAll },
217 { "TYA", 0x0000001, 0x98, 0, PutAll }
221 /* Instruction table for the 6502 with illegal instructions */
222 static const struct {
226 sizeof (InsTab6502X.Ins) / sizeof (InsTab6502X.Ins[0]),
228 { "ADC", 0x080A26C, 0x60, 0, PutAll },
229 { "ALR", 0x0800000, 0x4B, 0, PutAll }, /* X */
230 { "ANC", 0x0800000, 0x0B, 0, PutAll }, /* X */
231 { "AND", 0x080A26C, 0x20, 0, PutAll },
232 { "ANE", 0x0800000, 0x8B, 0, PutAll }, /* X */
233 { "ARR", 0x0800000, 0x6B, 0, PutAll }, /* X */
234 { "ASL", 0x000006e, 0x02, 1, PutAll },
235 { "AXS", 0x0800000, 0xCB, 0, PutAll }, /* X */
236 { "BCC", 0x0020000, 0x90, 0, PutPCRel8 },
237 { "BCS", 0x0020000, 0xb0, 0, PutPCRel8 },
238 { "BEQ", 0x0020000, 0xf0, 0, PutPCRel8 },
239 { "BIT", 0x000000C, 0x00, 2, PutAll },
240 { "BMI", 0x0020000, 0x30, 0, PutPCRel8 },
241 { "BNE", 0x0020000, 0xd0, 0, PutPCRel8 },
242 { "BPL", 0x0020000, 0x10, 0, PutPCRel8 },
243 { "BRK", 0x0000001, 0x00, 0, PutAll },
244 { "BVC", 0x0020000, 0x50, 0, PutPCRel8 },
245 { "BVS", 0x0020000, 0x70, 0, PutPCRel8 },
246 { "CLC", 0x0000001, 0x18, 0, PutAll },
247 { "CLD", 0x0000001, 0xd8, 0, PutAll },
248 { "CLI", 0x0000001, 0x58, 0, PutAll },
249 { "CLV", 0x0000001, 0xb8, 0, PutAll },
250 { "CMP", 0x080A26C, 0xc0, 0, PutAll },
251 { "CPX", 0x080000C, 0xe0, 1, PutAll },
252 { "CPY", 0x080000C, 0xc0, 1, PutAll },
253 { "DCP", 0x000A26C, 0xC3, 0, PutAll }, /* X */
254 { "DEC", 0x000006C, 0x00, 3, PutAll },
255 { "DEX", 0x0000001, 0xca, 0, PutAll },
256 { "DEY", 0x0000001, 0x88, 0, PutAll },
257 { "EOR", 0x080A26C, 0x40, 0, PutAll },
258 { "INC", 0x000006c, 0x00, 4, PutAll },
259 { "INX", 0x0000001, 0xe8, 0, PutAll },
260 { "INY", 0x0000001, 0xc8, 0, PutAll },
261 { "ISC", 0x000A26C, 0xE3, 0, PutAll }, /* X */
262 { "JAM", 0x0000001, 0x02, 0, PutAll }, /* X */
263 { "JMP", 0x0000808, 0x4c, 6, PutJMP },
264 { "JSR", 0x0000008, 0x20, 7, PutAll },
265 { "LAS", 0x0000200, 0xBB, 0, PutAll }, /* X */
266 { "LAX", 0x080A30C, 0xA3, 11, PutAll }, /* X */
267 { "LDA", 0x080A26C, 0xa0, 0, PutAll },
268 { "LDX", 0x080030C, 0xa2, 1, PutAll },
269 { "LDY", 0x080006C, 0xa0, 1, PutAll },
270 { "LSR", 0x000006F, 0x42, 1, PutAll },
271 { "NOP", 0x080006D, 0x00, 10, PutAll }, /* X */
272 { "ORA", 0x080A26C, 0x00, 0, PutAll },
273 { "PHA", 0x0000001, 0x48, 0, PutAll },
274 { "PHP", 0x0000001, 0x08, 0, PutAll },
275 { "PLA", 0x0000001, 0x68, 0, PutAll },
276 { "PLP", 0x0000001, 0x28, 0, PutAll },
277 { "RLA", 0x000A26C, 0x23, 0, PutAll }, /* X */
278 { "ROL", 0x000006F, 0x22, 1, PutAll },
279 { "ROR", 0x000006F, 0x62, 1, PutAll },
280 { "RRA", 0x000A26C, 0x63, 0, PutAll }, /* X */
281 { "RTI", 0x0000001, 0x40, 0, PutAll },
282 { "RTS", 0x0000001, 0x60, 0, PutAll },
283 { "SAX", 0x000810C, 0x83, 1, PutAll }, /* X */
284 { "SBC", 0x080A26C, 0xe0, 0, PutAll },
285 { "SEC", 0x0000001, 0x38, 0, PutAll },
286 { "SED", 0x0000001, 0xf8, 0, PutAll },
287 { "SEI", 0x0000001, 0x78, 0, PutAll },
288 { "SHA", 0x0002200, 0x93, 1, PutAll }, /* X */
289 { "SHX", 0x0000200, 0x9e, 1, PutAll }, /* X */
290 { "SHY", 0x0000040, 0x9c, 1, PutAll }, /* X */
291 { "SLO", 0x000A26C, 0x03, 0, PutAll }, /* X */
292 { "SRE", 0x000A26C, 0x43, 0, PutAll }, /* X */
293 { "STA", 0x000A26C, 0x80, 0, PutAll },
294 { "STX", 0x000010c, 0x82, 1, PutAll },
295 { "STY", 0x000002c, 0x80, 1, PutAll },
296 { "TAS", 0x0000200, 0x9b, 0, PutAll }, /* X */
297 { "TAX", 0x0000001, 0xaa, 0, PutAll },
298 { "TAY", 0x0000001, 0xa8, 0, PutAll },
299 { "TSX", 0x0000001, 0xba, 0, PutAll },
300 { "TXA", 0x0000001, 0x8a, 0, PutAll },
301 { "TXS", 0x0000001, 0x9a, 0, PutAll },
302 { "TYA", 0x0000001, 0x98, 0, PutAll }
306 /* Instruction table for the 65SC02 */
307 static const struct {
311 sizeof (InsTab65SC02.Ins) / sizeof (InsTab65SC02.Ins[0]),
313 { "ADC", 0x080A66C, 0x60, 0, PutAll },
314 { "AND", 0x080A66C, 0x20, 0, PutAll },
315 { "ASL", 0x000006e, 0x02, 1, PutAll },
316 { "BCC", 0x0020000, 0x90, 0, PutPCRel8 },
317 { "BCS", 0x0020000, 0xb0, 0, PutPCRel8 },
318 { "BEQ", 0x0020000, 0xf0, 0, PutPCRel8 },
319 { "BIT", 0x0A0006C, 0x00, 2, PutAll },
320 { "BMI", 0x0020000, 0x30, 0, PutPCRel8 },
321 { "BNE", 0x0020000, 0xd0, 0, PutPCRel8 },
322 { "BPL", 0x0020000, 0x10, 0, PutPCRel8 },
323 { "BRA", 0x0020000, 0x80, 0, PutPCRel8 },
324 { "BRK", 0x0000001, 0x00, 0, PutAll },
325 { "BVC", 0x0020000, 0x50, 0, PutPCRel8 },
326 { "BVS", 0x0020000, 0x70, 0, PutPCRel8 },
327 { "CLC", 0x0000001, 0x18, 0, PutAll },
328 { "CLD", 0x0000001, 0xd8, 0, PutAll },
329 { "CLI", 0x0000001, 0x58, 0, PutAll },
330 { "CLV", 0x0000001, 0xb8, 0, PutAll },
331 { "CMP", 0x080A66C, 0xc0, 0, PutAll },
332 { "CPX", 0x080000C, 0xe0, 1, PutAll },
333 { "CPY", 0x080000C, 0xc0, 1, PutAll },
334 { "DEA", 0x0000001, 0x00, 3, PutAll }, /* == DEC */
335 { "DEC", 0x000006F, 0x00, 3, PutAll },
336 { "DEX", 0x0000001, 0xca, 0, PutAll },
337 { "DEY", 0x0000001, 0x88, 0, PutAll },
338 { "EOR", 0x080A66C, 0x40, 0, PutAll },
339 { "INA", 0x0000001, 0x00, 4, PutAll }, /* == INC */
340 { "INC", 0x000006f, 0x00, 4, PutAll },
341 { "INX", 0x0000001, 0xe8, 0, PutAll },
342 { "INY", 0x0000001, 0xc8, 0, PutAll },
343 { "JMP", 0x0010808, 0x4c, 6, PutAll },
344 { "JSR", 0x0000008, 0x20, 7, PutAll },
345 { "LDA", 0x080A66C, 0xa0, 0, PutAll },
346 { "LDX", 0x080030C, 0xa2, 1, PutAll },
347 { "LDY", 0x080006C, 0xa0, 1, PutAll },
348 { "LSR", 0x000006F, 0x42, 1, PutAll },
349 { "NOP", 0x0000001, 0xea, 0, PutAll },
350 { "ORA", 0x080A66C, 0x00, 0, PutAll },
351 { "PHA", 0x0000001, 0x48, 0, PutAll },
352 { "PHP", 0x0000001, 0x08, 0, PutAll },
353 { "PHX", 0x0000001, 0xda, 0, PutAll },
354 { "PHY", 0x0000001, 0x5a, 0, PutAll },
355 { "PLA", 0x0000001, 0x68, 0, PutAll },
356 { "PLP", 0x0000001, 0x28, 0, PutAll },
357 { "PLX", 0x0000001, 0xfa, 0, PutAll },
358 { "PLY", 0x0000001, 0x7a, 0, PutAll },
359 { "ROL", 0x000006F, 0x22, 1, PutAll },
360 { "ROR", 0x000006F, 0x62, 1, PutAll },
361 { "RTI", 0x0000001, 0x40, 0, PutAll },
362 { "RTS", 0x0000001, 0x60, 0, PutAll },
363 { "SBC", 0x080A66C, 0xe0, 0, PutAll },
364 { "SEC", 0x0000001, 0x38, 0, PutAll },
365 { "SED", 0x0000001, 0xf8, 0, PutAll },
366 { "SEI", 0x0000001, 0x78, 0, PutAll },
367 { "STA", 0x000A66C, 0x80, 0, PutAll },
368 { "STX", 0x000010c, 0x82, 1, PutAll },
369 { "STY", 0x000002c, 0x80, 1, PutAll },
370 { "STZ", 0x000006c, 0x04, 5, PutAll },
371 { "TAX", 0x0000001, 0xaa, 0, PutAll },
372 { "TAY", 0x0000001, 0xa8, 0, PutAll },
373 { "TRB", 0x000000c, 0x10, 1, PutAll },
374 { "TSB", 0x000000c, 0x00, 1, PutAll },
375 { "TSX", 0x0000001, 0xba, 0, PutAll },
376 { "TXA", 0x0000001, 0x8a, 0, PutAll },
377 { "TXS", 0x0000001, 0x9a, 0, PutAll },
378 { "TYA", 0x0000001, 0x98, 0, PutAll }
382 /* Instruction table for the 65C02 */
383 static const struct {
387 sizeof (InsTab65C02.Ins) / sizeof (InsTab65C02.Ins[0]),
389 { "ADC", 0x080A66C, 0x60, 0, PutAll },
390 { "AND", 0x080A66C, 0x20, 0, PutAll },
391 { "ASL", 0x000006e, 0x02, 1, PutAll },
392 { "BBR0", 0x0000000, 0x0F, 0, PutBitBranch },
393 { "BBR1", 0x0000000, 0x1F, 0, PutBitBranch },
394 { "BBR2", 0x0000000, 0x2F, 0, PutBitBranch },
395 { "BBR3", 0x0000000, 0x3F, 0, PutBitBranch },
396 { "BBR4", 0x0000000, 0x4F, 0, PutBitBranch },
397 { "BBR5", 0x0000000, 0x5F, 0, PutBitBranch },
398 { "BBR6", 0x0000000, 0x6F, 0, PutBitBranch },
399 { "BBR7", 0x0000000, 0x7F, 0, PutBitBranch },
400 { "BBS0", 0x0000000, 0x8F, 0, PutBitBranch },
401 { "BBS1", 0x0000000, 0x9F, 0, PutBitBranch },
402 { "BBS2", 0x0000000, 0xAF, 0, PutBitBranch },
403 { "BBS3", 0x0000000, 0xBF, 0, PutBitBranch },
404 { "BBS4", 0x0000000, 0xCF, 0, PutBitBranch },
405 { "BBS5", 0x0000000, 0xDF, 0, PutBitBranch },
406 { "BBS6", 0x0000000, 0xEF, 0, PutBitBranch },
407 { "BBS7", 0x0000000, 0xFF, 0, PutBitBranch },
408 { "BCC", 0x0020000, 0x90, 0, PutPCRel8 },
409 { "BCS", 0x0020000, 0xb0, 0, PutPCRel8 },
410 { "BEQ", 0x0020000, 0xf0, 0, PutPCRel8 },
411 { "BIT", 0x0A0006C, 0x00, 2, PutAll },
412 { "BMI", 0x0020000, 0x30, 0, PutPCRel8 },
413 { "BNE", 0x0020000, 0xd0, 0, PutPCRel8 },
414 { "BPL", 0x0020000, 0x10, 0, PutPCRel8 },
415 { "BRA", 0x0020000, 0x80, 0, PutPCRel8 },
416 { "BRK", 0x0000001, 0x00, 0, PutAll },
417 { "BVC", 0x0020000, 0x50, 0, PutPCRel8 },
418 { "BVS", 0x0020000, 0x70, 0, PutPCRel8 },
419 { "CLC", 0x0000001, 0x18, 0, PutAll },
420 { "CLD", 0x0000001, 0xd8, 0, PutAll },
421 { "CLI", 0x0000001, 0x58, 0, PutAll },
422 { "CLV", 0x0000001, 0xb8, 0, PutAll },
423 { "CMP", 0x080A66C, 0xc0, 0, PutAll },
424 { "CPX", 0x080000C, 0xe0, 1, PutAll },
425 { "CPY", 0x080000C, 0xc0, 1, PutAll },
426 { "DEA", 0x0000001, 0x00, 3, PutAll }, /* == DEC */
427 { "DEC", 0x000006F, 0x00, 3, PutAll },
428 { "DEX", 0x0000001, 0xca, 0, PutAll },
429 { "DEY", 0x0000001, 0x88, 0, PutAll },
430 { "EOR", 0x080A66C, 0x40, 0, PutAll },
431 { "INA", 0x0000001, 0x00, 4, PutAll }, /* == INC */
432 { "INC", 0x000006f, 0x00, 4, PutAll },
433 { "INX", 0x0000001, 0xe8, 0, PutAll },
434 { "INY", 0x0000001, 0xc8, 0, PutAll },
435 { "JMP", 0x0010808, 0x4c, 6, PutAll },
436 { "JSR", 0x0000008, 0x20, 7, PutAll },
437 { "LDA", 0x080A66C, 0xa0, 0, PutAll },
438 { "LDX", 0x080030C, 0xa2, 1, PutAll },
439 { "LDY", 0x080006C, 0xa0, 1, PutAll },
440 { "LSR", 0x000006F, 0x42, 1, PutAll },
441 { "NOP", 0x0000001, 0xea, 0, PutAll },
442 { "ORA", 0x080A66C, 0x00, 0, PutAll },
443 { "PHA", 0x0000001, 0x48, 0, PutAll },
444 { "PHP", 0x0000001, 0x08, 0, PutAll },
445 { "PHX", 0x0000001, 0xda, 0, PutAll },
446 { "PHY", 0x0000001, 0x5a, 0, PutAll },
447 { "PLA", 0x0000001, 0x68, 0, PutAll },
448 { "PLP", 0x0000001, 0x28, 0, PutAll },
449 { "PLX", 0x0000001, 0xfa, 0, PutAll },
450 { "PLY", 0x0000001, 0x7a, 0, PutAll },
451 { "RMB0", 0x0000004, 0x07, 1, PutAll },
452 { "RMB1", 0x0000004, 0x17, 1, PutAll },
453 { "RMB2", 0x0000004, 0x27, 1, PutAll },
454 { "RMB3", 0x0000004, 0x37, 1, PutAll },
455 { "RMB4", 0x0000004, 0x47, 1, PutAll },
456 { "RMB5", 0x0000004, 0x57, 1, PutAll },
457 { "RMB6", 0x0000004, 0x67, 1, PutAll },
458 { "RMB7", 0x0000004, 0x77, 1, PutAll },
459 { "ROL", 0x000006F, 0x22, 1, PutAll },
460 { "ROR", 0x000006F, 0x62, 1, PutAll },
461 { "RTI", 0x0000001, 0x40, 0, PutAll },
462 { "RTS", 0x0000001, 0x60, 0, PutAll },
463 { "SBC", 0x080A66C, 0xe0, 0, PutAll },
464 { "SEC", 0x0000001, 0x38, 0, PutAll },
465 { "SED", 0x0000001, 0xf8, 0, PutAll },
466 { "SEI", 0x0000001, 0x78, 0, PutAll },
467 { "SMB0", 0x0000004, 0x87, 1, PutAll },
468 { "SMB1", 0x0000004, 0x97, 1, PutAll },
469 { "SMB2", 0x0000004, 0xA7, 1, PutAll },
470 { "SMB3", 0x0000004, 0xB7, 1, PutAll },
471 { "SMB4", 0x0000004, 0xC7, 1, PutAll },
472 { "SMB5", 0x0000004, 0xD7, 1, PutAll },
473 { "SMB6", 0x0000004, 0xE7, 1, PutAll },
474 { "SMB7", 0x0000004, 0xF7, 1, PutAll },
475 { "STA", 0x000A66C, 0x80, 0, PutAll },
476 { "STP", 0x0000001, 0xdb, 0, PutAll },
477 { "STX", 0x000010c, 0x82, 1, PutAll },
478 { "STY", 0x000002c, 0x80, 1, PutAll },
479 { "STZ", 0x000006c, 0x04, 5, PutAll },
480 { "TAX", 0x0000001, 0xaa, 0, PutAll },
481 { "TAY", 0x0000001, 0xa8, 0, PutAll },
482 { "TRB", 0x000000c, 0x10, 1, PutAll },
483 { "TSB", 0x000000c, 0x00, 1, PutAll },
484 { "TSX", 0x0000001, 0xba, 0, PutAll },
485 { "TXA", 0x0000001, 0x8a, 0, PutAll },
486 { "TXS", 0x0000001, 0x9a, 0, PutAll },
487 { "TYA", 0x0000001, 0x98, 0, PutAll },
488 { "WAI", 0x0000001, 0xcb, 0, PutAll }
492 /* Instruction table for the 4510 */
493 static const struct {
497 sizeof (InsTab4510.Ins) / sizeof (InsTab4510.Ins[0]),
499 { "ADC", 0x080A66C, 0x60, 0, PutAll },
500 { "AND", 0x080A66C, 0x20, 0, PutAll },
501 { "ASL", 0x000006e, 0x02, 1, PutAll },
502 { "ASR", 0x0000026, 0x43, 0, Put4510 },
503 { "ASW", 0x0000008, 0xcb, 6, PutAll },
504 { "BBR0", 0x0000000, 0x0F, 0, PutBitBranch },
505 { "BBR1", 0x0000000, 0x1F, 0, PutBitBranch },
506 { "BBR2", 0x0000000, 0x2F, 0, PutBitBranch },
507 { "BBR3", 0x0000000, 0x3F, 0, PutBitBranch },
508 { "BBR4", 0x0000000, 0x4F, 0, PutBitBranch },
509 { "BBR5", 0x0000000, 0x5F, 0, PutBitBranch },
510 { "BBR6", 0x0000000, 0x6F, 0, PutBitBranch },
511 { "BBR7", 0x0000000, 0x7F, 0, PutBitBranch },
512 { "BBS0", 0x0000000, 0x8F, 0, PutBitBranch },
513 { "BBS1", 0x0000000, 0x9F, 0, PutBitBranch },
514 { "BBS2", 0x0000000, 0xAF, 0, PutBitBranch },
515 { "BBS3", 0x0000000, 0xBF, 0, PutBitBranch },
516 { "BBS4", 0x0000000, 0xCF, 0, PutBitBranch },
517 { "BBS5", 0x0000000, 0xDF, 0, PutBitBranch },
518 { "BBS6", 0x0000000, 0xEF, 0, PutBitBranch },
519 { "BBS7", 0x0000000, 0xFF, 0, PutBitBranch },
520 { "BCC", 0x0020000, 0x90, 0, PutPCRel8 },
521 { "BCS", 0x0020000, 0xb0, 0, PutPCRel8 },
522 { "BEQ", 0x0020000, 0xf0, 0, PutPCRel8 },
523 { "BIT", 0x0A0006C, 0x00, 2, PutAll },
524 { "BMI", 0x0020000, 0x30, 0, PutPCRel8 },
525 { "BNE", 0x0020000, 0xd0, 0, PutPCRel8 },
526 { "BPL", 0x0020000, 0x10, 0, PutPCRel8 },
527 { "BRA", 0x0020000, 0x80, 0, PutPCRel8 },
528 { "BRK", 0x0000001, 0x00, 0, PutAll },
529 { "BSR", 0x0040000, 0x63, 0, PutPCRel4510 },
530 { "BVC", 0x0020000, 0x50, 0, PutPCRel8 },
531 { "BVS", 0x0020000, 0x70, 0, PutPCRel8 },
532 { "CLC", 0x0000001, 0x18, 0, PutAll },
533 { "CLD", 0x0000001, 0xd8, 0, PutAll },
534 { "CLE", 0x0000001, 0x02, 0, PutAll },
535 { "CLI", 0x0000001, 0x58, 0, PutAll },
536 { "CLV", 0x0000001, 0xb8, 0, PutAll },
537 { "CMP", 0x080A66C, 0xc0, 0, PutAll },
538 { "CPX", 0x080000C, 0xe0, 1, PutAll },
539 { "CPY", 0x080000C, 0xc0, 1, PutAll },
540 { "CPZ", 0x080000C, 0xd0, 1, Put4510 },
541 { "DEA", 0x0000001, 0x00, 3, PutAll }, /* == DEC */
542 { "DEC", 0x000006F, 0x00, 3, PutAll },
543 { "DEW", 0x0000004, 0xc3, 9, PutAll },
544 { "DEX", 0x0000001, 0xca, 0, PutAll },
545 { "DEY", 0x0000001, 0x88, 0, PutAll },
546 { "DEZ", 0x0000001, 0x3B, 0, PutAll },
547 { "EOM", 0x0000001, 0xea, 0, PutAll },
548 { "EOR", 0x080A66C, 0x40, 0, PutAll },
549 { "INA", 0x0000001, 0x00, 4, PutAll }, /* == INC */
550 { "INC", 0x000006f, 0x00, 4, PutAll },
551 { "INW", 0x0000004, 0xe3, 9, PutAll },
552 { "INX", 0x0000001, 0xe8, 0, PutAll },
553 { "INY", 0x0000001, 0xc8, 0, PutAll },
554 { "INZ", 0x0000001, 0x1B, 0, PutAll },
555 { "JMP", 0x0010808, 0x4c, 6, PutAll },
556 { "JSR", 0x0010808, 0x20, 7, Put4510 },
557 { "LBCC", 0x0040000, 0x93, 0, PutPCRel4510 },
558 { "LBCS", 0x0040000, 0xb3, 0, PutPCRel4510 },
559 { "LBEQ", 0x0040000, 0xf3, 0, PutPCRel4510 },
560 { "LBMI", 0x0040000, 0x33, 0, PutPCRel4510 },
561 { "LBNE", 0x0040000, 0xd3, 0, PutPCRel4510 },
562 { "LBPL", 0x0040000, 0x13, 0, PutPCRel4510 },
563 { "LBRA", 0x0040000, 0x83, 0, PutPCRel4510 },
564 { "LBVC", 0x0040000, 0x53, 0, PutPCRel4510 },
565 { "LBVS", 0x0040000, 0x73, 0, PutPCRel4510 },
566 { "LDA", 0x090A66C, 0xa0, 0, Put4510 },
567 { "LDX", 0x080030C, 0xa2, 1, PutAll },
568 { "LDY", 0x080006C, 0xa0, 1, PutAll },
569 { "LDZ", 0x0800048, 0xa3, 1, Put4510 },
570 { "LSR", 0x000006F, 0x42, 1, PutAll },
571 { "MAP", 0x0000001, 0x5C, 0, PutAll },
572 { "NEG", 0x0000001, 0x42, 0, PutAll },
573 { "NOP", 0x0000001, 0xea, 0, PutAll }, /* == EOM */
574 { "ORA", 0x080A66C, 0x00, 0, PutAll },
575 { "PHA", 0x0000001, 0x48, 0, PutAll },
576 { "PHD", 0x8000008, 0xf4, 1, PutAll }, /* == PHW */
577 { "PHP", 0x0000001, 0x08, 0, PutAll },
578 { "PHW", 0x8000008, 0xf4, 1, PutAll },
579 { "PHX", 0x0000001, 0xda, 0, PutAll },
580 { "PHY", 0x0000001, 0x5a, 0, PutAll },
581 { "PHZ", 0x0000001, 0xdb, 0, PutAll },
582 { "PLA", 0x0000001, 0x68, 0, PutAll },
583 { "PLP", 0x0000001, 0x28, 0, PutAll },
584 { "PLX", 0x0000001, 0xfa, 0, PutAll },
585 { "PLY", 0x0000001, 0x7a, 0, PutAll },
586 { "PLZ", 0x0000001, 0xfb, 0, PutAll },
587 { "RMB0", 0x0000004, 0x07, 1, PutAll },
588 { "RMB1", 0x0000004, 0x17, 1, PutAll },
589 { "RMB2", 0x0000004, 0x27, 1, PutAll },
590 { "RMB3", 0x0000004, 0x37, 1, PutAll },
591 { "RMB4", 0x0000004, 0x47, 1, PutAll },
592 { "RMB5", 0x0000004, 0x57, 1, PutAll },
593 { "RMB6", 0x0000004, 0x67, 1, PutAll },
594 { "RMB7", 0x0000004, 0x77, 1, PutAll },
595 { "ROL", 0x000006F, 0x22, 1, PutAll },
596 { "ROR", 0x000006F, 0x62, 1, PutAll },
597 { "ROW", 0x0000008, 0xeb, 6, PutAll },
598 { "RTI", 0x0000001, 0x40, 0, PutAll },
599 { "RTN", 0x0800000, 0x62, 1, PutAll },
600 { "RTS", 0x0000001, 0x60, 0, PutAll },
601 { "SBC", 0x080A66C, 0xe0, 0, PutAll },
602 { "SEC", 0x0000001, 0x38, 0, PutAll },
603 { "SED", 0x0000001, 0xf8, 0, PutAll },
604 { "SEE", 0x0000001, 0x03, 0, PutAll },
605 { "SEI", 0x0000001, 0x78, 0, PutAll },
606 { "SMB0", 0x0000004, 0x87, 1, PutAll },
607 { "SMB1", 0x0000004, 0x97, 1, PutAll },
608 { "SMB2", 0x0000004, 0xA7, 1, PutAll },
609 { "SMB3", 0x0000004, 0xB7, 1, PutAll },
610 { "SMB4", 0x0000004, 0xC7, 1, PutAll },
611 { "SMB5", 0x0000004, 0xD7, 1, PutAll },
612 { "SMB6", 0x0000004, 0xE7, 1, PutAll },
613 { "SMB7", 0x0000004, 0xF7, 1, PutAll },
614 { "STA", 0x010A66C, 0x80, 0, Put4510 },
615 { "STX", 0x000030c, 0x82, 1, Put4510 },
616 { "STY", 0x000006c, 0x80, 1, Put4510 },
617 { "STZ", 0x000006c, 0x04, 5, PutAll },
618 { "TAB", 0x0000001, 0x5b, 0, PutAll },
619 { "TAX", 0x0000001, 0xaa, 0, PutAll },
620 { "TAY", 0x0000001, 0xa8, 0, PutAll },
621 { "TAZ", 0x0000001, 0x4b, 0, PutAll },
622 { "TBA", 0x0000001, 0x7b, 0, PutAll },
623 { "TRB", 0x000000c, 0x10, 1, PutAll },
624 { "TSB", 0x000000c, 0x00, 1, PutAll },
625 { "TSX", 0x0000001, 0xba, 0, PutAll },
626 { "TSY", 0x0000001, 0x0b, 0, PutAll },
627 { "TXA", 0x0000001, 0x8a, 0, PutAll },
628 { "TXS", 0x0000001, 0x9a, 0, PutAll },
629 { "TYA", 0x0000001, 0x98, 0, PutAll },
630 { "TYS", 0x0000001, 0x2b, 0, PutAll },
631 { "TZA", 0x0000001, 0x6b, 0, PutAll },
635 /* Instruction table for the 65816 */
636 static const struct {
640 sizeof (InsTab65816.Ins) / sizeof (InsTab65816.Ins[0]),
642 { "ADC", 0x0b8f6fc, 0x60, 0, PutAll },
643 { "AND", 0x0b8f6fc, 0x20, 0, PutAll },
644 { "ASL", 0x000006e, 0x02, 1, PutAll },
645 { "BCC", 0x0020000, 0x90, 0, PutPCRel8 },
646 { "BCS", 0x0020000, 0xb0, 0, PutPCRel8 },
647 { "BEQ", 0x0020000, 0xf0, 0, PutPCRel8 },
648 { "BIT", 0x0a0006c, 0x00, 2, PutAll },
649 { "BMI", 0x0020000, 0x30, 0, PutPCRel8 },
650 { "BNE", 0x0020000, 0xd0, 0, PutPCRel8 },
651 { "BPL", 0x0020000, 0x10, 0, PutPCRel8 },
652 { "BRA", 0x0020000, 0x80, 0, PutPCRel8 },
653 { "BRK", 0x0000005, 0x00, 0, PutAll },
654 { "BRL", 0x0040000, 0x82, 0, PutPCRel16 },
655 { "BVC", 0x0020000, 0x50, 0, PutPCRel8 },
656 { "BVS", 0x0020000, 0x70, 0, PutPCRel8 },
657 { "CLC", 0x0000001, 0x18, 0, PutAll },
658 { "CLD", 0x0000001, 0xd8, 0, PutAll },
659 { "CLI", 0x0000001, 0x58, 0, PutAll },
660 { "CLV", 0x0000001, 0xb8, 0, PutAll },
661 { "CMP", 0x0b8f6fc, 0xc0, 0, PutAll },
662 { "COP", 0x0000004, 0x02, 6, PutAll },
663 { "CPA", 0x0b8f6fc, 0xc0, 0, PutAll }, /* == CMP */
664 { "CPX", 0x0c0000c, 0xe0, 1, PutAll },
665 { "CPY", 0x0c0000c, 0xc0, 1, PutAll },
666 { "DEA", 0x0000001, 0x00, 3, PutAll }, /* == DEC */
667 { "DEC", 0x000006F, 0x00, 3, PutAll },
668 { "DEX", 0x0000001, 0xca, 0, PutAll },
669 { "DEY", 0x0000001, 0x88, 0, PutAll },
670 { "EOR", 0x0b8f6fc, 0x40, 0, PutAll },
671 { "INA", 0x0000001, 0x00, 4, PutAll }, /* == INC */
672 { "INC", 0x000006F, 0x00, 4, PutAll },
673 { "INX", 0x0000001, 0xe8, 0, PutAll },
674 { "INY", 0x0000001, 0xc8, 0, PutAll },
675 { "JML", 0x4000010, 0x5c, 1, PutAll },
676 { "JMP", 0x4010818, 0x4c, 6, PutAll },
677 { "JSL", 0x0000010, 0x20, 7, PutAll },
678 { "JSR", 0x0010018, 0x20, 7, PutAll },
679 { "LDA", 0x0b8f6fc, 0xa0, 0, PutAll },
680 { "LDX", 0x0c0030c, 0xa2, 1, PutAll },
681 { "LDY", 0x0c0006c, 0xa0, 1, PutAll },
682 { "LSR", 0x000006F, 0x42, 1, PutAll },
683 { "MVN", 0x1000000, 0x54, 0, PutBlockMove },
684 { "MVP", 0x1000000, 0x44, 0, PutBlockMove },
685 { "NOP", 0x0000001, 0xea, 0, PutAll },
686 { "ORA", 0x0b8f6fc, 0x00, 0, PutAll },
687 { "PEA", 0x0000008, 0xf4, 6, PutAll },
688 { "PEI", 0x0000400, 0xd4, 1, PutAll },
689 { "PER", 0x0040000, 0x62, 0, PutPCRel16 },
690 { "PHA", 0x0000001, 0x48, 0, PutAll },
691 { "PHB", 0x0000001, 0x8b, 0, PutAll },
692 { "PHD", 0x0000001, 0x0b, 0, PutAll },
693 { "PHK", 0x0000001, 0x4b, 0, PutAll },
694 { "PHP", 0x0000001, 0x08, 0, PutAll },
695 { "PHX", 0x0000001, 0xda, 0, PutAll },
696 { "PHY", 0x0000001, 0x5a, 0, PutAll },
697 { "PLA", 0x0000001, 0x68, 0, PutAll },
698 { "PLB", 0x0000001, 0xab, 0, PutAll },
699 { "PLD", 0x0000001, 0x2b, 0, PutAll },
700 { "PLP", 0x0000001, 0x28, 0, PutAll },
701 { "PLX", 0x0000001, 0xfa, 0, PutAll },
702 { "PLY", 0x0000001, 0x7a, 0, PutAll },
703 { "REP", 0x0800000, 0xc2, 1, PutREP },
704 { "ROL", 0x000006F, 0x22, 1, PutAll },
705 { "ROR", 0x000006F, 0x62, 1, PutAll },
706 { "RTI", 0x0000001, 0x40, 0, PutAll },
707 { "RTL", 0x0000001, 0x6b, 0, PutAll },
708 { "RTS", 0x0000001, 0x60, 0, PutRTS },
709 { "SBC", 0x0b8f6fc, 0xe0, 0, PutAll },
710 { "SEC", 0x0000001, 0x38, 0, PutAll },
711 { "SED", 0x0000001, 0xf8, 0, PutAll },
712 { "SEI", 0x0000001, 0x78, 0, PutAll },
713 { "SEP", 0x0800000, 0xe2, 1, PutSEP },
714 { "STA", 0x018f6fc, 0x80, 0, PutAll },
715 { "STP", 0x0000001, 0xdb, 0, PutAll },
716 { "STX", 0x000010c, 0x82, 1, PutAll },
717 { "STY", 0x000002c, 0x80, 1, PutAll },
718 { "STZ", 0x000006c, 0x04, 5, PutAll },
719 { "SWA", 0x0000001, 0xeb, 0, PutAll }, /* == XBA */
720 { "TAD", 0x0000001, 0x5b, 0, PutAll }, /* == TCD */
721 { "TAS", 0x0000001, 0x1b, 0, PutAll }, /* == TCS */
722 { "TAX", 0x0000001, 0xaa, 0, PutAll },
723 { "TAY", 0x0000001, 0xa8, 0, PutAll },
724 { "TCD", 0x0000001, 0x5b, 0, PutAll },
725 { "TCS", 0x0000001, 0x1b, 0, PutAll },
726 { "TDA", 0x0000001, 0x7b, 0, PutAll }, /* == TDC */
727 { "TDC", 0x0000001, 0x7b, 0, PutAll },
728 { "TRB", 0x000000c, 0x10, 1, PutAll },
729 { "TSA", 0x0000001, 0x3b, 0, PutAll }, /* == TSC */
730 { "TSB", 0x000000c, 0x00, 1, PutAll },
731 { "TSC", 0x0000001, 0x3b, 0, PutAll },
732 { "TSX", 0x0000001, 0xba, 0, PutAll },
733 { "TXA", 0x0000001, 0x8a, 0, PutAll },
734 { "TXS", 0x0000001, 0x9a, 0, PutAll },
735 { "TXY", 0x0000001, 0x9b, 0, PutAll },
736 { "TYA", 0x0000001, 0x98, 0, PutAll },
737 { "TYX", 0x0000001, 0xbb, 0, PutAll },
738 { "WAI", 0x0000001, 0xcb, 0, PutAll },
739 { "XBA", 0x0000001, 0xeb, 0, PutAll },
740 { "XCE", 0x0000001, 0xfb, 0, PutAll }
744 /* Instruction table for the SWEET16 pseudo CPU */
745 static const struct {
749 sizeof (InsTabSweet16.Ins) / sizeof (InsTabSweet16.Ins[0]),
751 { "ADD", AMSW16_REG, 0xA0, 0, PutSweet16 },
752 { "BC", AMSW16_BRA, 0x03, 0, PutSweet16Branch },
753 { "BK", AMSW16_IMP, 0x0A, 0, PutSweet16 },
754 { "BM", AMSW16_BRA, 0x05, 0, PutSweet16Branch },
755 { "BM1", AMSW16_BRA, 0x08, 0, PutSweet16Branch },
756 { "BNC", AMSW16_BRA, 0x02, 0, PutSweet16Branch },
757 { "BNM1", AMSW16_BRA, 0x09, 0, PutSweet16Branch },
758 { "BNZ", AMSW16_BRA, 0x07, 0, PutSweet16Branch },
759 { "BP", AMSW16_BRA, 0x04, 0, PutSweet16Branch },
760 { "BR", AMSW16_BRA, 0x01, 0, PutSweet16Branch },
761 { "BS", AMSW16_BRA, 0x0C, 0, PutSweet16Branch },
762 { "BZ", AMSW16_BRA, 0x06, 0, PutSweet16Branch },
763 { "CPR", AMSW16_REG, 0xD0, 0, PutSweet16 },
764 { "DCR", AMSW16_REG, 0xF0, 0, PutSweet16 },
765 { "INR", AMSW16_REG, 0xE0, 0, PutSweet16 },
766 { "LD", AMSW16_REG | AMSW16_IND, 0x00, 1, PutSweet16 },
767 { "LDD", AMSW16_IND, 0x60, 0, PutSweet16 },
768 { "POP", AMSW16_IND, 0x80, 0, PutSweet16 },
769 { "POPD", AMSW16_IND, 0xC0, 0, PutSweet16 },
770 { "RS", AMSW16_IMP, 0x0B, 0, PutSweet16 },
771 { "RTN", AMSW16_IMP, 0x00, 0, PutSweet16 },
772 { "SET", AMSW16_IMM, 0x10, 0, PutSweet16 },
773 { "ST", AMSW16_REG | AMSW16_IND, 0x10, 1, PutSweet16 },
774 { "STD", AMSW16_IND, 0x70, 0, PutSweet16 },
775 { "STP", AMSW16_IND, 0x90, 0, PutSweet16 },
776 { "SUB", AMSW16_REG, 0xB0, 0, PutSweet16 },
780 /* Instruction table for the HuC6280 (the CPU used in the PC engine) */
781 static const struct {
785 sizeof (InsTabHuC6280.Ins) / sizeof (InsTabHuC6280.Ins[0]),
787 { "ADC", 0x080A66C, 0x60, 0, PutAll },
788 { "AND", 0x080A66C, 0x20, 0, PutAll },
789 { "ASL", 0x000006e, 0x02, 1, PutAll },
790 { "BBR0", 0x0000000, 0x0F, 0, PutBitBranch },
791 { "BBR1", 0x0000000, 0x1F, 0, PutBitBranch },
792 { "BBR2", 0x0000000, 0x2F, 0, PutBitBranch },
793 { "BBR3", 0x0000000, 0x3F, 0, PutBitBranch },
794 { "BBR4", 0x0000000, 0x4F, 0, PutBitBranch },
795 { "BBR5", 0x0000000, 0x5F, 0, PutBitBranch },
796 { "BBR6", 0x0000000, 0x6F, 0, PutBitBranch },
797 { "BBR7", 0x0000000, 0x7F, 0, PutBitBranch },
798 { "BBS0", 0x0000000, 0x8F, 0, PutBitBranch },
799 { "BBS1", 0x0000000, 0x9F, 0, PutBitBranch },
800 { "BBS2", 0x0000000, 0xAF, 0, PutBitBranch },
801 { "BBS3", 0x0000000, 0xBF, 0, PutBitBranch },
802 { "BBS4", 0x0000000, 0xCF, 0, PutBitBranch },
803 { "BBS5", 0x0000000, 0xDF, 0, PutBitBranch },
804 { "BBS6", 0x0000000, 0xEF, 0, PutBitBranch },
805 { "BBS7", 0x0000000, 0xFF, 0, PutBitBranch },
806 { "BCC", 0x0020000, 0x90, 0, PutPCRel8 },
807 { "BCS", 0x0020000, 0xb0, 0, PutPCRel8 },
808 { "BEQ", 0x0020000, 0xf0, 0, PutPCRel8 },
809 { "BIT", 0x0A0006C, 0x00, 2, PutAll },
810 { "BMI", 0x0020000, 0x30, 0, PutPCRel8 },
811 { "BNE", 0x0020000, 0xd0, 0, PutPCRel8 },
812 { "BPL", 0x0020000, 0x10, 0, PutPCRel8 },
813 { "BRA", 0x0020000, 0x80, 0, PutPCRel8 },
814 { "BRK", 0x0000001, 0x00, 0, PutAll },
815 { "BSR", 0x0020000, 0x44, 0, PutPCRel8 },
816 { "BVC", 0x0020000, 0x50, 0, PutPCRel8 },
817 { "BVS", 0x0020000, 0x70, 0, PutPCRel8 },
818 { "CLA", 0x0000001, 0x62, 0, PutAll },
819 { "CLC", 0x0000001, 0x18, 0, PutAll },
820 { "CLD", 0x0000001, 0xd8, 0, PutAll },
821 { "CLI", 0x0000001, 0x58, 0, PutAll },
822 { "CLV", 0x0000001, 0xb8, 0, PutAll },
823 { "CLX", 0x0000001, 0x82, 0, PutAll },
824 { "CLY", 0x0000001, 0xc2, 0, PutAll },
825 { "CMP", 0x080A66C, 0xc0, 0, PutAll },
826 { "CPX", 0x080000C, 0xe0, 1, PutAll },
827 { "CPY", 0x080000C, 0xc0, 1, PutAll },
828 { "CSH", 0x0000001, 0xd4, 0, PutAll },
829 { "CSL", 0x0000001, 0x54, 0, PutAll },
830 { "DEA", 0x0000001, 0x00, 3, PutAll }, /* == DEC */
831 { "DEC", 0x000006F, 0x00, 3, PutAll },
832 { "DEX", 0x0000001, 0xca, 0, PutAll },
833 { "DEY", 0x0000001, 0x88, 0, PutAll },
834 { "EOR", 0x080A66C, 0x40, 0, PutAll },
835 { "INA", 0x0000001, 0x00, 4, PutAll }, /* == INC */
836 { "INC", 0x000006f, 0x00, 4, PutAll },
837 { "INX", 0x0000001, 0xe8, 0, PutAll },
838 { "INY", 0x0000001, 0xc8, 0, PutAll },
839 { "JMP", 0x0010808, 0x4c, 6, PutAll },
840 { "JSR", 0x0000008, 0x20, 7, PutAll },
841 { "LDA", 0x080A66C, 0xa0, 0, PutAll },
842 { "LDX", 0x080030C, 0xa2, 1, PutAll },
843 { "LDY", 0x080006C, 0xa0, 1, PutAll },
844 { "LSR", 0x000006F, 0x42, 1, PutAll },
845 { "NOP", 0x0000001, 0xea, 0, PutAll },
846 { "ORA", 0x080A66C, 0x00, 0, PutAll },
847 { "PHA", 0x0000001, 0x48, 0, PutAll },
848 { "PHP", 0x0000001, 0x08, 0, PutAll },
849 { "PHX", 0x0000001, 0xda, 0, PutAll },
850 { "PHY", 0x0000001, 0x5a, 0, PutAll },
851 { "PLA", 0x0000001, 0x68, 0, PutAll },
852 { "PLP", 0x0000001, 0x28, 0, PutAll },
853 { "PLX", 0x0000001, 0xfa, 0, PutAll },
854 { "PLY", 0x0000001, 0x7a, 0, PutAll },
855 { "RMB0", 0x0000004, 0x07, 1, PutAll },
856 { "RMB1", 0x0000004, 0x17, 1, PutAll },
857 { "RMB2", 0x0000004, 0x27, 1, PutAll },
858 { "RMB3", 0x0000004, 0x37, 1, PutAll },
859 { "RMB4", 0x0000004, 0x47, 1, PutAll },
860 { "RMB5", 0x0000004, 0x57, 1, PutAll },
861 { "RMB6", 0x0000004, 0x67, 1, PutAll },
862 { "RMB7", 0x0000004, 0x77, 1, PutAll },
863 { "ROL", 0x000006F, 0x22, 1, PutAll },
864 { "ROR", 0x000006F, 0x62, 1, PutAll },
865 { "RTI", 0x0000001, 0x40, 0, PutAll },
866 { "RTS", 0x0000001, 0x60, 0, PutAll },
867 { "SAX", 0x0000001, 0x22, 0, PutAll },
868 { "SAY", 0x0000001, 0x42, 0, PutAll },
869 { "SBC", 0x080A66C, 0xe0, 0, PutAll },
870 { "SEC", 0x0000001, 0x38, 0, PutAll },
871 { "SED", 0x0000001, 0xf8, 0, PutAll },
872 { "SEI", 0x0000001, 0x78, 0, PutAll },
873 { "SET", 0x0000001, 0xf4, 0, PutAll },
874 { "SMB0", 0x0000004, 0x87, 1, PutAll },
875 { "SMB1", 0x0000004, 0x97, 1, PutAll },
876 { "SMB2", 0x0000004, 0xA7, 1, PutAll },
877 { "SMB3", 0x0000004, 0xB7, 1, PutAll },
878 { "SMB4", 0x0000004, 0xC7, 1, PutAll },
879 { "SMB5", 0x0000004, 0xD7, 1, PutAll },
880 { "SMB6", 0x0000004, 0xE7, 1, PutAll },
881 { "SMB7", 0x0000004, 0xF7, 1, PutAll },
882 { "ST0", 0x0800000, 0x03, 1, PutAll },
883 { "ST1", 0x0800000, 0x13, 1, PutAll },
884 { "ST2", 0x0800000, 0x23, 1, PutAll },
885 { "STA", 0x000A66C, 0x80, 0, PutAll },
886 { "STX", 0x000010c, 0x82, 1, PutAll },
887 { "STY", 0x000002c, 0x80, 1, PutAll },
888 { "STZ", 0x000006c, 0x04, 5, PutAll },
889 { "SXY", 0x0000001, 0x02, 0, PutAll },
890 { "TAI", 0x2000000, 0xf3, 0, PutBlockTransfer },
891 { "TAM", 0x0800000, 0x53, 1, PutAll },
892 { "TAM0", 0x0000001, 0x01, 0, PutTAMn},
893 { "TAM1", 0x0000001, 0x02, 0, PutTAMn},
894 { "TAM2", 0x0000001, 0x04, 0, PutTAMn},
895 { "TAM3", 0x0000001, 0x08, 0, PutTAMn},
896 { "TAM4", 0x0000001, 0x10, 0, PutTAMn},
897 { "TAM5", 0x0000001, 0x20, 0, PutTAMn},
898 { "TAM6", 0x0000001, 0x40, 0, PutTAMn},
899 { "TAM7", 0x0000001, 0x80, 0, PutTAMn},
900 { "TAX", 0x0000001, 0xaa, 0, PutAll },
901 { "TAY", 0x0000001, 0xa8, 0, PutAll },
902 { "TDD", 0x2000000, 0xc3, 0, PutBlockTransfer },
903 { "TIA", 0x2000000, 0xe3, 0, PutBlockTransfer },
904 { "TII", 0x2000000, 0x73, 0, PutBlockTransfer },
905 { "TIN", 0x2000000, 0xD3, 0, PutBlockTransfer },
906 { "TMA", 0x0800000, 0x43, 1, PutTMA },
907 { "TMA0", 0x0000001, 0x01, 0, PutTMAn},
908 { "TMA1", 0x0000001, 0x02, 0, PutTMAn},
909 { "TMA2", 0x0000001, 0x04, 0, PutTMAn},
910 { "TMA3", 0x0000001, 0x08, 0, PutTMAn},
911 { "TMA4", 0x0000001, 0x10, 0, PutTMAn},
912 { "TMA5", 0x0000001, 0x20, 0, PutTMAn},
913 { "TMA6", 0x0000001, 0x40, 0, PutTMAn},
914 { "TMA7", 0x0000001, 0x80, 0, PutTMAn},
915 { "TRB", 0x000000c, 0x10, 1, PutAll },
916 { "TSB", 0x000000c, 0x00, 1, PutAll },
917 { "TST", 0x000006c, 0x83, 9, PutTST },
918 { "TSX", 0x0000001, 0xba, 0, PutAll },
919 { "TXA", 0x0000001, 0x8a, 0, PutAll },
920 { "TXS", 0x0000001, 0x9a, 0, PutAll },
921 { "TYA", 0x0000001, 0x98, 0, PutAll }
927 /* An array with instruction tables */
928 static const InsTable* InsTabs[CPU_COUNT] = {
929 (const InsTable*) &InsTabNone,
930 (const InsTable*) &InsTab6502,
931 (const InsTable*) &InsTab6502X,
932 (const InsTable*) &InsTab65SC02,
933 (const InsTable*) &InsTab65C02,
934 (const InsTable*) &InsTab65816,
935 (const InsTable*) &InsTabSweet16,
936 (const InsTable*) &InsTabHuC6280,
937 0, /* Mitsubishi 740 */
938 (const InsTable*) &InsTab4510,
940 const InsTable* InsTab = (const InsTable*) &InsTab6502;
942 /* Table to build the effective 65xx opcode from a base opcode and an
943 ** addressing mode. (The value in the table is ORed with the base opcode)
945 static unsigned char EATab[12][AM65I_COUNT] = {
947 0x00, 0x00, 0x05, 0x0D, 0x0F, 0x15, 0x1D, 0x1F,
948 0x00, 0x19, 0x12, 0x00, 0x07, 0x11, 0x17, 0x01,
949 0x00, 0x00, 0x00, 0x03, 0x13, 0x09, 0x00, 0x09,
950 0x00, 0x00, 0x00, 0x00
953 0x08, 0x08, 0x04, 0x0C, 0x00, 0x14, 0x1C, 0x00,
954 0x14, 0x1C, 0x00, 0x80, 0x00, 0x10, 0x00, 0x00,
955 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
956 0x00, 0x00, 0x80, 0x00
959 0x00, 0x00, 0x24, 0x2C, 0x0F, 0x34, 0x3C, 0x00,
960 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
961 0x00, 0x00, 0x00, 0x00, 0x00, 0x89, 0x00, 0x00,
962 0x00, 0x00, 0x00, 0x00
965 0x3A, 0x3A, 0xC6, 0xCE, 0x00, 0xD6, 0xDE, 0x00,
966 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
967 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
968 0x00, 0x00, 0x00, 0x00
971 0x1A, 0x1A, 0xE6, 0xEE, 0x00, 0xF6, 0xFE, 0x00,
972 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
973 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
974 0x00, 0x00, 0x00, 0x00
977 0x00, 0x00, 0x60, 0x98, 0x00, 0x70, 0x9E, 0x00,
978 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
979 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
980 0x00, 0x00, 0x00, 0x00
983 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
984 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00,
985 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
986 0x00, 0x00, 0x90, 0x00
988 { /* Table 7 (Subroutine opcodes) */
989 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
990 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00,
991 0xDC, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
992 0x00, 0x00, 0x00, 0x00
995 0x00, 0x40, 0x01, 0x41, 0x00, 0x09, 0x49, 0x00,
996 0x00, 0x00, 0x00, 0x51, 0x00, 0x00, 0x00, 0x00,
997 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00,
998 0x00, 0x00, 0x00, 0x00
1001 0x00, 0x00, 0x00, 0x10, 0x00, 0x20, 0x30, 0x00,
1002 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1003 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1004 0x00, 0x00, 0x00, 0x00
1006 { /* Table 10 (NOPs) */
1007 0xea, 0x00, 0x04, 0x0c, 0x00, 0x14, 0x1c, 0x00,
1008 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1009 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80,
1010 0x00, 0x00, 0x00, 0x00
1012 { /* Table 11 (LAX) */
1013 0x08, 0x08, 0x04, 0x0C, 0x00, 0x14, 0x1C, 0x00,
1014 0x14, 0x1C, 0x00, 0x80, 0x00, 0x10, 0x00, 0x00,
1015 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08,
1016 0x00, 0x00, 0x80, 0x00
1020 /* Table to build the effective SWEET16 opcode from a base opcode and an
1023 static unsigned char Sweet16EATab[2][AMSW16I_COUNT] = {
1025 0x00, 0x00, 0x00, 0x00, 0x00,
1028 0x00, 0x00, 0x00, 0x40, 0x20,
1032 /* Table that encodes the additional bytes for each 65xx instruction */
1033 unsigned char ExtBytes[AM65I_COUNT] = {
1038 3, /* Absolute long */
1041 3, /* Absolute long,X */
1050 2, /* (Absolute,X) */
1051 1, /* Relative short */
1052 2, /* Relative long */
1055 1, /* Immidiate accu */
1056 1, /* Immidiate index */
1057 1, /* Immidiate byte */
1058 2, /* Blockmove (65816) */
1059 7, /* Block transfer (HuC6280) */
1060 2, /* Absolute Indirect long */
1061 2, /* Immidiate word */
1064 /* Table that encodes the additional bytes for each SWEET16 instruction */
1065 static unsigned char Sweet16ExtBytes[AMSW16I_COUNT] = {
1075 /*****************************************************************************/
1076 /* Handler functions for 6502 derivates */
1077 /*****************************************************************************/
1081 static int EvalEA (const InsDesc* Ins, EffAddr* A)
1082 /* Evaluate the effective address. All fields in A will be valid after calling
1083 ** this function. The function returns true on success and false on errors.
1086 /* Get the set of possible addressing modes */
1089 /* From the possible addressing modes, remove the ones that are invalid
1090 ** for this instruction or CPU.
1092 A->AddrModeSet &= Ins->AddrMode;
1094 /* If we have an expression, check it and remove any addressing modes that
1095 ** are too small for the expression size. Since we have to study the
1096 ** expression anyway, do also replace it by a simpler one if possible.
1102 /* Study the expression */
1103 StudyExpr (A->Expr, &ED);
1105 /* Simplify it if possible */
1106 A->Expr = SimplifyExpr (A->Expr, &ED);
1108 if (ED.AddrSize == ADDR_SIZE_DEFAULT) {
1109 /* We don't know how big the expression is. If the instruction
1110 ** allows just one addressing mode, assume this as address size
1111 ** for the expression. Otherwise assume the default address size
1114 if ((A->AddrModeSet & ~AM65_ALL_ZP) == 0) {
1115 ED.AddrSize = ADDR_SIZE_ZP;
1116 } else if ((A->AddrModeSet & ~AM65_ALL_ABS) == 0) {
1117 ED.AddrSize = ADDR_SIZE_ABS;
1118 } else if ((A->AddrModeSet & ~AM65_ALL_FAR) == 0) {
1119 ED.AddrSize = ADDR_SIZE_FAR;
1121 ED.AddrSize = DataAddrSize;
1122 /* If the default address size of the data segment is unequal
1123 ** to zero page addressing, but zero page addressing is
1124 ** allowed by the instruction, mark all symbols in the
1125 ** expression tree. This mark will be checked at end of
1126 ** assembly, and a warning is issued, if a zero page symbol
1127 ** was guessed wrong here.
1129 if (ED.AddrSize > ADDR_SIZE_ZP && (A->AddrModeSet & AM65_SET_ZP)) {
1130 ExprGuessedAddrSize (A->Expr, ADDR_SIZE_ZP);
1135 /* Check the size */
1136 switch (ED.AddrSize) {
1139 A->AddrModeSet &= ~AM65_SET_ZP;
1143 A->AddrModeSet &= ~(AM65_SET_ZP | AM65_SET_ABS);
1147 /* Free any resource associated with the expression desc */
1151 /* Check if we have any adressing modes left */
1152 if (A->AddrModeSet == 0) {
1153 Error ("Illegal addressing mode");
1156 A->AddrMode = BitFind (A->AddrModeSet);
1157 A->AddrModeBit = (0x01UL << A->AddrMode);
1159 /* If the instruction has a one byte operand and immediate addressing is
1160 ** allowed but not used, check for an operand expression in the form
1161 ** <label or >label, where label is a far or absolute label. If found,
1162 ** emit a warning. This warning protects against a typo, where the '#'
1163 ** for the immediate operand is omitted.
1165 if (A->Expr && (Ins->AddrMode & AM65_ALL_IMM) &&
1166 (A->AddrModeSet & (AM65_DIR | AM65_ABS | AM65_ABS_LONG)) &&
1167 ExtBytes[A->AddrMode] == 1) {
1169 /* Found, check the expression */
1170 ExprNode* Left = A->Expr->Left;
1171 if ((A->Expr->Op == EXPR_BYTE0 || A->Expr->Op == EXPR_BYTE1) &&
1172 Left->Op == EXPR_SYMBOL &&
1173 GetSymAddrSize (Left->V.Sym) != ADDR_SIZE_ZP) {
1175 /* Output a warning */
1176 Warning (1, "Suspicious address expression");
1180 /* Build the opcode */
1181 A->Opcode = Ins->BaseCode | EATab[Ins->ExtCode][A->AddrMode];
1183 /* If feature force_range is active, and we have immediate addressing mode,
1184 ** limit the expression to the maximum possible value.
1186 if (A->AddrMode == AM65I_IMM_ACCU || A->AddrMode == AM65I_IMM_INDEX ||
1187 A->AddrMode == AM65I_IMM_IMPLICIT || A->AddrMode == AM65I_IMM_IMPLICIT_WORD) {
1188 if (ForceRange && A->Expr) {
1189 A->Expr = MakeBoundedExpr (A->Expr, ExtBytes[A->AddrMode]);
1199 static void EmitCode (EffAddr* A)
1200 /* Output code for the data in A */
1202 /* Check how many extension bytes are needed and output the instruction */
1203 switch (ExtBytes[A->AddrMode]) {
1210 Emit1 (A->Opcode, A->Expr);
1214 if (CPU == CPU_65816 && (A->AddrModeBit & (AM65_ABS | AM65_ABS_X | AM65_ABS_Y))) {
1215 /* This is a 16 bit mode that uses an address. If in 65816,
1216 ** mode, force this address into 16 bit range to allow
1217 ** addressing inside a 64K segment.
1219 Emit2 (A->Opcode, GenWordExpr (A->Expr));
1221 Emit2 (A->Opcode, A->Expr);
1227 Emit3 (A->Opcode, A->Expr);
1231 Internal ("Invalid operand byte count: %u", ExtBytes[A->AddrMode]);
1238 static long PutImmed8 (const InsDesc* Ins)
1239 /* Parse and emit an immediate 8 bit instruction. Return the value of the
1240 ** operand if it's available and const.
1246 /* Evaluate the addressing mode */
1247 if (EvalEA (Ins, &A) == 0) {
1248 /* An error occurred */
1252 /* If we have an expression and it's const, get it's value */
1254 (void) IsConstExpr (A.Expr, &Val);
1257 /* Check how many extension bytes are needed and output the instruction */
1258 switch (ExtBytes[A.AddrMode]) {
1261 Emit1 (A.Opcode, A.Expr);
1265 Internal ("Invalid operand byte count: %u", ExtBytes[A.AddrMode]);
1268 /* Return the expression value */
1274 static void PutPCRel8 (const InsDesc* Ins)
1275 /* Handle branches with a 8 bit distance */
1277 EmitPCRel (Ins->BaseCode, GenBranchExpr (2), 1);
1282 static void PutPCRel16 (const InsDesc* Ins)
1283 /* Handle branches with an 16 bit distance and PER */
1285 EmitPCRel (Ins->BaseCode, GenBranchExpr (3), 2);
1290 static void PutPCRel4510 (const InsDesc* Ins)
1291 /* Handle branches with a 16 bit distance */
1293 /* 16 bit branch opcode is 8 bit branch opcode or'ed with 0x03 */
1294 EmitPCRel (Ins->BaseCode, GenBranchExpr (2), 2);
1299 static void PutBlockMove (const InsDesc* Ins)
1300 /* Handle the blockmove instructions (65816) */
1305 Emit0 (Ins->BaseCode);
1307 if (CurTok.Tok == TOK_HASH) {
1308 /* The operand is a bank-byte expression. */
1310 Arg1 = Expression ();
1312 /* The operand is a far-address expression.
1313 ** Use only its bank part.
1315 Arg1 = FuncBankByte ();
1319 if (CurTok.Tok == TOK_HASH) {
1321 Arg2 = Expression ();
1323 Arg2 = FuncBankByte ();
1326 /* The operands are written in Assembly code as source, destination;
1327 ** but, they're assembled as <destination> <source>.
1335 static void PutBlockTransfer (const InsDesc* Ins)
1336 /* Handle the block transfer instructions (HuC6280) */
1338 Emit0 (Ins->BaseCode);
1339 EmitWord (Expression ());
1341 EmitWord (Expression ());
1343 EmitWord (Expression ());
1348 static void PutBitBranch (const InsDesc* Ins)
1349 /* Handle 65C02 branch on bit condition */
1351 Emit0 (Ins->BaseCode);
1352 EmitByte (Expression ());
1354 EmitSigned (GenBranchExpr (1), 1);
1359 static void PutREP (const InsDesc* Ins)
1360 /* Emit a REP instruction, track register sizes */
1362 /* Use the generic handler */
1363 long Val = PutImmed8 (Ins);
1365 /* We track the status only for the 816 CPU and in smart mode */
1366 if (CPU == CPU_65816 && SmartMode) {
1368 /* Check the range for Val. */
1370 /* We had an error */
1371 Warning (1, "Cannot track processor status byte");
1374 /* Index registers to 16 bit */
1375 ExtBytes[AM65I_IMM_INDEX] = 2;
1378 /* Accu to 16 bit */
1379 ExtBytes[AM65I_IMM_ACCU] = 2;
1387 static void PutSEP (const InsDesc* Ins)
1388 /* Emit a SEP instruction (65816), track register sizes */
1390 /* Use the generic handler */
1391 long Val = PutImmed8 (Ins);
1393 /* We track the status only for the 816 CPU and in smart mode */
1394 if (CPU == CPU_65816 && SmartMode) {
1396 /* Check the range for Val. */
1398 /* We had an error */
1399 Warning (1, "Cannot track processor status byte");
1402 /* Index registers to 8 bit */
1403 ExtBytes[AM65I_IMM_INDEX] = 1;
1407 ExtBytes[AM65I_IMM_ACCU] = 1;
1415 static void PutTAMn (const InsDesc* Ins)
1416 /* Emit a TAMn instruction (HuC6280). Since this is a two byte instruction with
1417 ** implicit addressing mode, the opcode byte in the table is actually the
1418 ** second operand byte. The TAM instruction is the more generic form, it takes
1419 ** an immediate argument.
1422 /* Emit the TAM opcode itself */
1425 /* Emit the argument, which is the opcode from the table */
1426 Emit0 (Ins->BaseCode);
1431 static void PutTMA (const InsDesc* Ins)
1432 /* Emit a TMA instruction (HuC6280) with an immediate argument. Only one bit
1433 ** in the argument byte may be set.
1436 /* Use the generic handler */
1437 long Val = PutImmed8 (Ins);
1439 /* Check the range for Val. */
1441 /* We had an error */
1442 Warning (1, "Cannot check argument of TMA instruction");
1444 /* Make sure just one bit is set */
1445 if ((Val & (Val - 1)) != 0) {
1446 Error ("Argument to TAM must be a power of two");
1453 static void PutTMAn (const InsDesc* Ins)
1454 /* Emit a TMAn instruction (HuC6280). Since this is a two byte instruction with
1455 ** implicit addressing mode, the opcode byte in the table is actually the
1456 ** second operand byte. The TAM instruction is the more generic form, it takes
1457 ** an immediate argument.
1460 /* Emit the TMA opcode itself */
1463 /* Emit the argument, which is the opcode from the table */
1464 Emit0 (Ins->BaseCode);
1469 static void PutTST (const InsDesc* Ins)
1470 /* Emit a TST instruction (HuC6280). */
1475 /* The first argument is always an immediate byte */
1476 if (CurTok.Tok != TOK_HASH) {
1477 ErrorSkip ("Invalid addressing mode");
1481 Arg1 = Expression ();
1483 /* Second argument follows */
1486 /* For the second argument, we use the standard function */
1487 if (EvalEA (Ins, &A)) {
1489 /* No error, output code */
1490 Emit1 (A.Opcode, Arg1);
1492 /* Check how many extension bytes are needed and output the instruction */
1493 switch (ExtBytes[A.AddrMode]) {
1508 static void PutJMP (const InsDesc* Ins)
1509 /* Handle the jump instruction for the 6502. Problem is that these chips have
1510 ** a bug: If the address crosses a page, the upper byte gets not corrected and
1511 ** the instruction will fail. The PutJmp function will add a linker assertion
1512 ** to check for this case and is otherwise identical to PutAll.
1517 /* Evaluate the addressing mode used */
1518 if (EvalEA (Ins, &A)) {
1520 /* Check for indirect addressing */
1521 if (A.AddrModeBit & AM65_ABS_IND) {
1523 /* Compare the low byte of the expression to 0xFF to check for
1524 ** a page cross. Be sure to use a copy of the expression otherwise
1525 ** things will go weird later.
1527 ExprNode* E = GenNE (GenByteExpr (CloneExpr (A.Expr)), 0xFF);
1529 /* Generate the message */
1530 unsigned Msg = GetStringId ("\"jmp (abs)\" across page border");
1532 /* Generate the assertion */
1533 AddAssertion (E, ASSERT_ACT_WARN, Msg);
1536 /* No error, output code */
1543 static void PutRTS (const InsDesc* Ins attribute ((unused)))
1544 /* Handle the RTS instruction for the 816. In smart mode emit a RTL opcode if
1545 ** the enclosing scope is FAR.
1548 if (SmartMode && CurrentScope->AddrSize == ADDR_SIZE_FAR) {
1549 Emit0 (0x6B); /* RTL */
1551 Emit0 (0x60); /* RTS */
1557 static void PutAll (const InsDesc* Ins)
1558 /* Handle all other instructions */
1562 /* Evaluate the addressing mode used */
1563 if (EvalEA (Ins, &A)) {
1564 /* No error, output code */
1571 static void Put4510 (const InsDesc* Ins)
1572 /* Handle all other instructions, with modifications for 4510 */
1574 /* The 4510 uses all 256 possible opcodes, so the last ones were crammed
1575 ** in where an opcode was still undefined. As a result, some of those
1576 ** don't follow any rules for encoding the addressmodes. So the EATab
1577 ** approach does not work always. In this function, the wrongly calculated
1578 ** opcode is replaced by the correct one "on the fly". Suggestions for a
1579 ** better approach are welcome.
1582 ** $47 -> $44 : ASR $12
1583 ** $57 -> $54 : ASR $12,X
1584 ** $93 -> $82 : STA ($12,SP),Y
1585 ** $9c -> $8b : STY $1234,X
1586 ** $9e -> $9b : STX $1234,Y
1587 ** $af -> $ab : LDZ $1234
1588 ** $bf -> $bb : LDZ $1234,X
1589 ** $b3 -> $e2 : LDA ($12,SP),Y
1590 ** $d0 -> $c2 : CPZ #$00
1591 ** $fc -> $23 : JSR ($1234,X)
1595 /* Evaluate the addressing mode used */
1596 if (EvalEA (Ins, &A)) {
1598 case 0x47: A.Opcode = 0x44; break;
1599 case 0x57: A.Opcode = 0x54; break;
1600 case 0x93: A.Opcode = 0x82; break;
1601 case 0x9C: A.Opcode = 0x8B; break;
1602 case 0x9E: A.Opcode = 0x9B; break;
1603 case 0xAF: A.Opcode = 0xAB; break;
1604 case 0xBF: A.Opcode = 0xBB; break;
1605 case 0xB3: A.Opcode = 0xE2; break;
1606 case 0xD0: A.Opcode = 0xC2; break;
1607 case 0xFC: A.Opcode = 0x23; break;
1608 default: /* Keep opcode as it is */ break;
1611 /* No error, output code */
1618 /*****************************************************************************/
1619 /* Handler functions for SWEET16 */
1620 /*****************************************************************************/
1624 static void PutSweet16 (const InsDesc* Ins)
1625 /* Handle a generic sweet16 instruction */
1629 /* Evaluate the addressing mode used */
1632 /* From the possible addressing modes, remove the ones that are invalid
1633 ** for this instruction or CPU.
1635 A.AddrModeSet &= Ins->AddrMode;
1637 /* Check if we have any adressing modes left */
1638 if (A.AddrModeSet == 0) {
1639 Error ("Illegal addressing mode");
1642 A.AddrMode = BitFind (A.AddrModeSet);
1643 A.AddrModeBit = (0x01UL << A.AddrMode);
1645 /* Build the opcode */
1646 A.Opcode = Ins->BaseCode | Sweet16EATab[Ins->ExtCode][A.AddrMode] | A.Reg;
1648 /* Check how many extension bytes are needed and output the instruction */
1649 switch (Sweet16ExtBytes[A.AddrMode]) {
1656 Emit1 (A.Opcode, A.Expr);
1660 Emit2 (A.Opcode, A.Expr);
1664 Internal ("Invalid operand byte count: %u", Sweet16ExtBytes[A.AddrMode]);
1671 static void PutSweet16Branch (const InsDesc* Ins)
1672 /* Handle a sweet16 branch instruction */
1674 EmitPCRel (Ins->BaseCode, GenBranchExpr (2), 1);
1679 /*****************************************************************************/
1681 /*****************************************************************************/
1685 static int CmpName (const void* Key, const void* Instr)
1686 /* Compare function for bsearch */
1688 return strcmp ((const char*)Key, ((const InsDesc*) Instr)->Mnemonic);
1693 void SetCPU (cpu_t NewCPU)
1696 /* Make sure the parameter is correct */
1697 CHECK (NewCPU < CPU_COUNT);
1699 /* Check if we have support for the new CPU, if so, use it */
1700 if (NewCPU != CPU_UNKNOWN && InsTabs[NewCPU]) {
1702 InsTab = InsTabs[CPU];
1704 Error ("CPU not supported");
1711 /* Return the current CPU */
1718 int FindInstruction (const StrBuf* Ident)
1719 /* Check if Ident is a valid mnemonic. If so, return the index in the
1720 ** instruction table. If not, return -1.
1725 char Key[sizeof (ID->Mnemonic)];
1727 /* Shortcut for the "none" CPU: If there are no instructions to search
1728 ** for, bail out early.
1730 if (InsTab->Count == 0) {
1735 /* Make a copy, and uppercase that copy */
1737 while (I < SB_GetLen (Ident)) {
1738 /* If the identifier is longer than the longest mnemonic, it cannot
1741 if (I >= sizeof (Key) - 1) {
1742 /* Not found, no need for further action */
1745 Key[I] = toupper ((unsigned char)SB_AtUnchecked (Ident, I));
1750 /* Search for the key */
1751 ID = bsearch (Key, InsTab->Ins, InsTab->Count, sizeof (InsDesc), CmpName);
1756 /* Found, return the entry */
1757 return ID - InsTab->Ins;
1763 void HandleInstruction (unsigned Index)
1764 /* Handle the mnemonic with the given index */
1767 PRECONDITION (Index < InsTab->Count);
1769 /* Skip the mnemonic token */
1772 /* Call the handler */
1773 InsTab->Ins[Index].Emit (&InsTab->Ins[Index]);