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", 0x0000001, 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, 0x0B, 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);
1298 static void PutBlockMove (const InsDesc* Ins)
1299 /* Handle the blockmove instructions (65816) */
1301 Emit0 (Ins->BaseCode);
1302 EmitByte (Expression ());
1304 EmitByte (Expression ());
1309 static void PutBlockTransfer (const InsDesc* Ins)
1310 /* Handle the block transfer instructions (HuC6280) */
1312 Emit0 (Ins->BaseCode);
1313 EmitWord (Expression ());
1315 EmitWord (Expression ());
1317 EmitWord (Expression ());
1322 static void PutBitBranch (const InsDesc* Ins)
1323 /* Handle 65C02 branch on bit condition */
1325 Emit0 (Ins->BaseCode);
1326 EmitByte (Expression ());
1328 EmitSigned (GenBranchExpr (1), 1);
1333 static void PutREP (const InsDesc* Ins)
1334 /* Emit a REP instruction, track register sizes */
1336 /* Use the generic handler */
1337 long Val = PutImmed8 (Ins);
1339 /* We track the status only for the 816 CPU and in smart mode */
1340 if (CPU == CPU_65816 && SmartMode) {
1342 /* Check the range for Val. */
1344 /* We had an error */
1345 Warning (1, "Cannot track processor status byte");
1348 /* Index registers to 16 bit */
1349 ExtBytes[AM65I_IMM_INDEX] = 2;
1352 /* Accu to 16 bit */
1353 ExtBytes[AM65I_IMM_ACCU] = 2;
1361 static void PutSEP (const InsDesc* Ins)
1362 /* Emit a SEP instruction (65816), track register sizes */
1364 /* Use the generic handler */
1365 long Val = PutImmed8 (Ins);
1367 /* We track the status only for the 816 CPU and in smart mode */
1368 if (CPU == CPU_65816 && SmartMode) {
1370 /* Check the range for Val. */
1372 /* We had an error */
1373 Warning (1, "Cannot track processor status byte");
1376 /* Index registers to 8 bit */
1377 ExtBytes[AM65I_IMM_INDEX] = 1;
1381 ExtBytes[AM65I_IMM_ACCU] = 1;
1389 static void PutTAMn (const InsDesc* Ins)
1390 /* Emit a TAMn instruction (HuC6280). Since this is a two byte instruction with
1391 ** implicit addressing mode, the opcode byte in the table is actually the
1392 ** second operand byte. The TAM instruction is the more generic form, it takes
1393 ** an immediate argument.
1396 /* Emit the TAM opcode itself */
1399 /* Emit the argument, which is the opcode from the table */
1400 Emit0 (Ins->BaseCode);
1405 static void PutTMA (const InsDesc* Ins)
1406 /* Emit a TMA instruction (HuC6280) with an immediate argument. Only one bit
1407 ** in the argument byte may be set.
1410 /* Use the generic handler */
1411 long Val = PutImmed8 (Ins);
1413 /* Check the range for Val. */
1415 /* We had an error */
1416 Warning (1, "Cannot check argument of TMA instruction");
1418 /* Make sure just one bit is set */
1419 if ((Val & (Val - 1)) != 0) {
1420 Error ("Argument to TAM must be a power of two");
1427 static void PutTMAn (const InsDesc* Ins)
1428 /* Emit a TMAn instruction (HuC6280). Since this is a two byte instruction with
1429 ** implicit addressing mode, the opcode byte in the table is actually the
1430 ** second operand byte. The TAM instruction is the more generic form, it takes
1431 ** an immediate argument.
1434 /* Emit the TMA opcode itself */
1437 /* Emit the argument, which is the opcode from the table */
1438 Emit0 (Ins->BaseCode);
1443 static void PutTST (const InsDesc* Ins)
1444 /* Emit a TST instruction (HuC6280). */
1449 /* The first argument is always an immediate byte */
1450 if (CurTok.Tok != TOK_HASH) {
1451 ErrorSkip ("Invalid addressing mode");
1455 Arg1 = Expression ();
1457 /* Second argument follows */
1460 /* For the second argument, we use the standard function */
1461 if (EvalEA (Ins, &A)) {
1463 /* No error, output code */
1464 Emit1 (A.Opcode, Arg1);
1466 /* Check how many extension bytes are needed and output the instruction */
1467 switch (ExtBytes[A.AddrMode]) {
1482 static void PutJMP (const InsDesc* Ins)
1483 /* Handle the jump instruction for the 6502. Problem is that these chips have
1484 ** a bug: If the address crosses a page, the upper byte gets not corrected and
1485 ** the instruction will fail. The PutJmp function will add a linker assertion
1486 ** to check for this case and is otherwise identical to PutAll.
1491 /* Evaluate the addressing mode used */
1492 if (EvalEA (Ins, &A)) {
1494 /* Check for indirect addressing */
1495 if (A.AddrModeBit & AM65_ABS_IND) {
1497 /* Compare the low byte of the expression to 0xFF to check for
1498 ** a page cross. Be sure to use a copy of the expression otherwise
1499 ** things will go weird later.
1501 ExprNode* E = GenNE (GenByteExpr (CloneExpr (A.Expr)), 0xFF);
1503 /* Generate the message */
1504 unsigned Msg = GetStringId ("\"jmp (abs)\" across page border");
1506 /* Generate the assertion */
1507 AddAssertion (E, ASSERT_ACT_WARN, Msg);
1510 /* No error, output code */
1517 static void PutRTS (const InsDesc* Ins attribute ((unused)))
1518 /* Handle the RTS instruction for the 816. In smart mode emit a RTL opcode if
1519 ** the enclosing scope is FAR.
1522 if (SmartMode && CurrentScope->AddrSize == ADDR_SIZE_FAR) {
1523 Emit0 (0x6B); /* RTL */
1525 Emit0 (0x60); /* RTS */
1531 static void PutAll (const InsDesc* Ins)
1532 /* Handle all other instructions */
1536 /* Evaluate the addressing mode used */
1537 if (EvalEA (Ins, &A)) {
1538 /* No error, output code */
1545 static void Put4510 (const InsDesc* Ins)
1546 /* Handle all other instructions, with modifications for 4510 */
1548 /* The 4510 uses all 256 possible opcodes, so the last ones were crammed
1549 ** in where an opcode was still undefined. As a result, some of those
1550 ** don't follow any rules for encoding the addressmodes. So the EATab
1551 ** approach does not work always. In this function, the wrongly calculated
1552 ** opcode is replaced by the correct one "on the fly". Suggestions for a
1553 ** better approach are welcome.
1556 ** $47 -> $44 : ASR $12
1557 ** $57 -> $54 : ASR $12,X
1558 ** $93 -> $82 : STA ($12,SP),Y
1559 ** $9c -> $8b : STY $1234,X
1560 ** $9e -> $9b : STX $1234,Y
1561 ** $af -> $ab : LDZ $1234
1562 ** $bf -> $bb : LDZ $1234,X
1563 ** $b3 -> $e2 : LDA ($12,SP),Y
1564 ** $d0 -> $c2 : CPZ #$00
1565 ** $fc -> $23 : JSR ($1234,X)
1569 /* Evaluate the addressing mode used */
1570 if (EvalEA (Ins, &A)) {
1572 case 0x47: A.Opcode = 0x44; break;
1573 case 0x57: A.Opcode = 0x54; break;
1574 case 0x93: A.Opcode = 0x82; break;
1575 case 0x9C: A.Opcode = 0x8B; break;
1576 case 0x9E: A.Opcode = 0x9B; break;
1577 case 0xAF: A.Opcode = 0xAB; break;
1578 case 0xBF: A.Opcode = 0xBB; break;
1579 case 0xB3: A.Opcode = 0xE2; break;
1580 case 0xD0: A.Opcode = 0xC2; break;
1581 case 0xFC: A.Opcode = 0x23; break;
1582 default: /* Keep opcode as it is */ break;
1585 /* No error, output code */
1592 /*****************************************************************************/
1593 /* Handler functions for SWEET16 */
1594 /*****************************************************************************/
1598 static void PutSweet16 (const InsDesc* Ins)
1599 /* Handle a generic sweet16 instruction */
1603 /* Evaluate the addressing mode used */
1606 /* From the possible addressing modes, remove the ones that are invalid
1607 ** for this instruction or CPU.
1609 A.AddrModeSet &= Ins->AddrMode;
1611 /* Check if we have any adressing modes left */
1612 if (A.AddrModeSet == 0) {
1613 Error ("Illegal addressing mode");
1616 A.AddrMode = BitFind (A.AddrModeSet);
1617 A.AddrModeBit = (0x01UL << A.AddrMode);
1619 /* Build the opcode */
1620 A.Opcode = Ins->BaseCode | Sweet16EATab[Ins->ExtCode][A.AddrMode] | A.Reg;
1622 /* Check how many extension bytes are needed and output the instruction */
1623 switch (Sweet16ExtBytes[A.AddrMode]) {
1630 Emit1 (A.Opcode, A.Expr);
1634 Emit2 (A.Opcode, A.Expr);
1638 Internal ("Invalid operand byte count: %u", Sweet16ExtBytes[A.AddrMode]);
1645 static void PutSweet16Branch (const InsDesc* Ins)
1646 /* Handle a sweet16 branch instruction */
1648 EmitPCRel (Ins->BaseCode, GenBranchExpr (2), 1);
1653 /*****************************************************************************/
1655 /*****************************************************************************/
1659 static int CmpName (const void* Key, const void* Instr)
1660 /* Compare function for bsearch */
1662 return strcmp ((const char*)Key, ((const InsDesc*) Instr)->Mnemonic);
1667 void SetCPU (cpu_t NewCPU)
1670 /* Make sure the parameter is correct */
1671 CHECK (NewCPU < CPU_COUNT);
1673 /* Check if we have support for the new CPU, if so, use it */
1674 if (NewCPU != CPU_UNKNOWN && InsTabs[NewCPU]) {
1676 InsTab = InsTabs[CPU];
1678 Error ("CPU not supported");
1685 /* Return the current CPU */
1692 int FindInstruction (const StrBuf* Ident)
1693 /* Check if Ident is a valid mnemonic. If so, return the index in the
1694 ** instruction table. If not, return -1.
1699 char Key[sizeof (ID->Mnemonic)];
1701 /* Shortcut for the "none" CPU: If there are no instructions to search
1702 ** for, bail out early.
1704 if (InsTab->Count == 0) {
1709 /* Make a copy, and uppercase that copy */
1711 while (I < SB_GetLen (Ident)) {
1712 /* If the identifier is longer than the longest mnemonic, it cannot
1715 if (I >= sizeof (Key) - 1) {
1716 /* Not found, no need for further action */
1719 Key[I] = toupper ((unsigned char)SB_AtUnchecked (Ident, I));
1724 /* Search for the key */
1725 ID = bsearch (Key, InsTab->Ins, InsTab->Count, sizeof (InsDesc), CmpName);
1730 /* Found, return the entry */
1731 return ID - InsTab->Ins;
1737 void HandleInstruction (unsigned Index)
1738 /* Handle the mnemonic with the given index */
1741 PRECONDITION (Index < InsTab->Count);
1743 /* Skip the mnemonic token */
1746 /* Call the handler */
1747 InsTab->Ins[Index].Emit (&InsTab->Ins[Index]);