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, 6, 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 { "WDM", 0x0000004, 0x42, 6, PutAll },
740 { "XBA", 0x0000001, 0xeb, 0, PutAll },
741 { "XCE", 0x0000001, 0xfb, 0, PutAll }
745 /* Instruction table for the SWEET16 pseudo CPU */
746 static const struct {
750 sizeof (InsTabSweet16.Ins) / sizeof (InsTabSweet16.Ins[0]),
752 { "ADD", AMSW16_REG, 0xA0, 0, PutSweet16 },
753 { "BC", AMSW16_BRA, 0x03, 0, PutSweet16Branch },
754 { "BK", AMSW16_IMP, 0x0A, 0, PutSweet16 },
755 { "BM", AMSW16_BRA, 0x05, 0, PutSweet16Branch },
756 { "BM1", AMSW16_BRA, 0x08, 0, PutSweet16Branch },
757 { "BNC", AMSW16_BRA, 0x02, 0, PutSweet16Branch },
758 { "BNM1", AMSW16_BRA, 0x09, 0, PutSweet16Branch },
759 { "BNZ", AMSW16_BRA, 0x07, 0, PutSweet16Branch },
760 { "BP", AMSW16_BRA, 0x04, 0, PutSweet16Branch },
761 { "BR", AMSW16_BRA, 0x01, 0, PutSweet16Branch },
762 { "BS", AMSW16_BRA, 0x0C, 0, PutSweet16Branch },
763 { "BZ", AMSW16_BRA, 0x06, 0, PutSweet16Branch },
764 { "CPR", AMSW16_REG, 0xD0, 0, PutSweet16 },
765 { "DCR", AMSW16_REG, 0xF0, 0, PutSweet16 },
766 { "INR", AMSW16_REG, 0xE0, 0, PutSweet16 },
767 { "LD", AMSW16_REG | AMSW16_IND, 0x00, 1, PutSweet16 },
768 { "LDD", AMSW16_IND, 0x60, 0, PutSweet16 },
769 { "POP", AMSW16_IND, 0x80, 0, PutSweet16 },
770 { "POPD", AMSW16_IND, 0xC0, 0, PutSweet16 },
771 { "RS", AMSW16_IMP, 0x0B, 0, PutSweet16 },
772 { "RTN", AMSW16_IMP, 0x00, 0, PutSweet16 },
773 { "SET", AMSW16_IMM, 0x10, 0, PutSweet16 },
774 { "ST", AMSW16_REG | AMSW16_IND, 0x10, 1, PutSweet16 },
775 { "STD", AMSW16_IND, 0x70, 0, PutSweet16 },
776 { "STP", AMSW16_IND, 0x90, 0, PutSweet16 },
777 { "SUB", AMSW16_REG, 0xB0, 0, PutSweet16 },
781 /* Instruction table for the HuC6280 (the CPU used in the PC engine) */
782 static const struct {
786 sizeof (InsTabHuC6280.Ins) / sizeof (InsTabHuC6280.Ins[0]),
788 { "ADC", 0x080A66C, 0x60, 0, PutAll },
789 { "AND", 0x080A66C, 0x20, 0, PutAll },
790 { "ASL", 0x000006e, 0x02, 1, PutAll },
791 { "BBR0", 0x0000000, 0x0F, 0, PutBitBranch },
792 { "BBR1", 0x0000000, 0x1F, 0, PutBitBranch },
793 { "BBR2", 0x0000000, 0x2F, 0, PutBitBranch },
794 { "BBR3", 0x0000000, 0x3F, 0, PutBitBranch },
795 { "BBR4", 0x0000000, 0x4F, 0, PutBitBranch },
796 { "BBR5", 0x0000000, 0x5F, 0, PutBitBranch },
797 { "BBR6", 0x0000000, 0x6F, 0, PutBitBranch },
798 { "BBR7", 0x0000000, 0x7F, 0, PutBitBranch },
799 { "BBS0", 0x0000000, 0x8F, 0, PutBitBranch },
800 { "BBS1", 0x0000000, 0x9F, 0, PutBitBranch },
801 { "BBS2", 0x0000000, 0xAF, 0, PutBitBranch },
802 { "BBS3", 0x0000000, 0xBF, 0, PutBitBranch },
803 { "BBS4", 0x0000000, 0xCF, 0, PutBitBranch },
804 { "BBS5", 0x0000000, 0xDF, 0, PutBitBranch },
805 { "BBS6", 0x0000000, 0xEF, 0, PutBitBranch },
806 { "BBS7", 0x0000000, 0xFF, 0, PutBitBranch },
807 { "BCC", 0x0020000, 0x90, 0, PutPCRel8 },
808 { "BCS", 0x0020000, 0xb0, 0, PutPCRel8 },
809 { "BEQ", 0x0020000, 0xf0, 0, PutPCRel8 },
810 { "BIT", 0x0A0006C, 0x00, 2, PutAll },
811 { "BMI", 0x0020000, 0x30, 0, PutPCRel8 },
812 { "BNE", 0x0020000, 0xd0, 0, PutPCRel8 },
813 { "BPL", 0x0020000, 0x10, 0, PutPCRel8 },
814 { "BRA", 0x0020000, 0x80, 0, PutPCRel8 },
815 { "BRK", 0x0000001, 0x00, 0, PutAll },
816 { "BSR", 0x0020000, 0x44, 0, PutPCRel8 },
817 { "BVC", 0x0020000, 0x50, 0, PutPCRel8 },
818 { "BVS", 0x0020000, 0x70, 0, PutPCRel8 },
819 { "CLA", 0x0000001, 0x62, 0, PutAll },
820 { "CLC", 0x0000001, 0x18, 0, PutAll },
821 { "CLD", 0x0000001, 0xd8, 0, PutAll },
822 { "CLI", 0x0000001, 0x58, 0, PutAll },
823 { "CLV", 0x0000001, 0xb8, 0, PutAll },
824 { "CLX", 0x0000001, 0x82, 0, PutAll },
825 { "CLY", 0x0000001, 0xc2, 0, PutAll },
826 { "CMP", 0x080A66C, 0xc0, 0, PutAll },
827 { "CPX", 0x080000C, 0xe0, 1, PutAll },
828 { "CPY", 0x080000C, 0xc0, 1, PutAll },
829 { "CSH", 0x0000001, 0xd4, 0, PutAll },
830 { "CSL", 0x0000001, 0x54, 0, PutAll },
831 { "DEA", 0x0000001, 0x00, 3, PutAll }, /* == DEC */
832 { "DEC", 0x000006F, 0x00, 3, PutAll },
833 { "DEX", 0x0000001, 0xca, 0, PutAll },
834 { "DEY", 0x0000001, 0x88, 0, PutAll },
835 { "EOR", 0x080A66C, 0x40, 0, PutAll },
836 { "INA", 0x0000001, 0x00, 4, PutAll }, /* == INC */
837 { "INC", 0x000006f, 0x00, 4, PutAll },
838 { "INX", 0x0000001, 0xe8, 0, PutAll },
839 { "INY", 0x0000001, 0xc8, 0, PutAll },
840 { "JMP", 0x0010808, 0x4c, 6, PutAll },
841 { "JSR", 0x0000008, 0x20, 7, PutAll },
842 { "LDA", 0x080A66C, 0xa0, 0, PutAll },
843 { "LDX", 0x080030C, 0xa2, 1, PutAll },
844 { "LDY", 0x080006C, 0xa0, 1, PutAll },
845 { "LSR", 0x000006F, 0x42, 1, PutAll },
846 { "NOP", 0x0000001, 0xea, 0, PutAll },
847 { "ORA", 0x080A66C, 0x00, 0, PutAll },
848 { "PHA", 0x0000001, 0x48, 0, PutAll },
849 { "PHP", 0x0000001, 0x08, 0, PutAll },
850 { "PHX", 0x0000001, 0xda, 0, PutAll },
851 { "PHY", 0x0000001, 0x5a, 0, PutAll },
852 { "PLA", 0x0000001, 0x68, 0, PutAll },
853 { "PLP", 0x0000001, 0x28, 0, PutAll },
854 { "PLX", 0x0000001, 0xfa, 0, PutAll },
855 { "PLY", 0x0000001, 0x7a, 0, PutAll },
856 { "RMB0", 0x0000004, 0x07, 1, PutAll },
857 { "RMB1", 0x0000004, 0x17, 1, PutAll },
858 { "RMB2", 0x0000004, 0x27, 1, PutAll },
859 { "RMB3", 0x0000004, 0x37, 1, PutAll },
860 { "RMB4", 0x0000004, 0x47, 1, PutAll },
861 { "RMB5", 0x0000004, 0x57, 1, PutAll },
862 { "RMB6", 0x0000004, 0x67, 1, PutAll },
863 { "RMB7", 0x0000004, 0x77, 1, PutAll },
864 { "ROL", 0x000006F, 0x22, 1, PutAll },
865 { "ROR", 0x000006F, 0x62, 1, PutAll },
866 { "RTI", 0x0000001, 0x40, 0, PutAll },
867 { "RTS", 0x0000001, 0x60, 0, PutAll },
868 { "SAX", 0x0000001, 0x22, 0, PutAll },
869 { "SAY", 0x0000001, 0x42, 0, PutAll },
870 { "SBC", 0x080A66C, 0xe0, 0, PutAll },
871 { "SEC", 0x0000001, 0x38, 0, PutAll },
872 { "SED", 0x0000001, 0xf8, 0, PutAll },
873 { "SEI", 0x0000001, 0x78, 0, PutAll },
874 { "SET", 0x0000001, 0xf4, 0, PutAll },
875 { "SMB0", 0x0000004, 0x87, 1, PutAll },
876 { "SMB1", 0x0000004, 0x97, 1, PutAll },
877 { "SMB2", 0x0000004, 0xA7, 1, PutAll },
878 { "SMB3", 0x0000004, 0xB7, 1, PutAll },
879 { "SMB4", 0x0000004, 0xC7, 1, PutAll },
880 { "SMB5", 0x0000004, 0xD7, 1, PutAll },
881 { "SMB6", 0x0000004, 0xE7, 1, PutAll },
882 { "SMB7", 0x0000004, 0xF7, 1, PutAll },
883 { "ST0", 0x0800000, 0x03, 1, PutAll },
884 { "ST1", 0x0800000, 0x13, 1, PutAll },
885 { "ST2", 0x0800000, 0x23, 1, PutAll },
886 { "STA", 0x000A66C, 0x80, 0, PutAll },
887 { "STX", 0x000010c, 0x82, 1, PutAll },
888 { "STY", 0x000002c, 0x80, 1, PutAll },
889 { "STZ", 0x000006c, 0x04, 5, PutAll },
890 { "SXY", 0x0000001, 0x02, 0, PutAll },
891 { "TAI", 0x2000000, 0xf3, 0, PutBlockTransfer },
892 { "TAM", 0x0800000, 0x53, 1, PutAll },
893 { "TAM0", 0x0000001, 0x01, 0, PutTAMn},
894 { "TAM1", 0x0000001, 0x02, 0, PutTAMn},
895 { "TAM2", 0x0000001, 0x04, 0, PutTAMn},
896 { "TAM3", 0x0000001, 0x08, 0, PutTAMn},
897 { "TAM4", 0x0000001, 0x10, 0, PutTAMn},
898 { "TAM5", 0x0000001, 0x20, 0, PutTAMn},
899 { "TAM6", 0x0000001, 0x40, 0, PutTAMn},
900 { "TAM7", 0x0000001, 0x80, 0, PutTAMn},
901 { "TAX", 0x0000001, 0xaa, 0, PutAll },
902 { "TAY", 0x0000001, 0xa8, 0, PutAll },
903 { "TDD", 0x2000000, 0xc3, 0, PutBlockTransfer },
904 { "TIA", 0x2000000, 0xe3, 0, PutBlockTransfer },
905 { "TII", 0x2000000, 0x73, 0, PutBlockTransfer },
906 { "TIN", 0x2000000, 0xD3, 0, PutBlockTransfer },
907 { "TMA", 0x0800000, 0x43, 1, PutTMA },
908 { "TMA0", 0x0000001, 0x01, 0, PutTMAn},
909 { "TMA1", 0x0000001, 0x02, 0, PutTMAn},
910 { "TMA2", 0x0000001, 0x04, 0, PutTMAn},
911 { "TMA3", 0x0000001, 0x08, 0, PutTMAn},
912 { "TMA4", 0x0000001, 0x10, 0, PutTMAn},
913 { "TMA5", 0x0000001, 0x20, 0, PutTMAn},
914 { "TMA6", 0x0000001, 0x40, 0, PutTMAn},
915 { "TMA7", 0x0000001, 0x80, 0, PutTMAn},
916 { "TRB", 0x000000c, 0x10, 1, PutAll },
917 { "TSB", 0x000000c, 0x00, 1, PutAll },
918 { "TST", 0x000006c, 0x83, 9, PutTST },
919 { "TSX", 0x0000001, 0xba, 0, PutAll },
920 { "TXA", 0x0000001, 0x8a, 0, PutAll },
921 { "TXS", 0x0000001, 0x9a, 0, PutAll },
922 { "TYA", 0x0000001, 0x98, 0, PutAll }
928 /* An array with instruction tables */
929 static const InsTable* InsTabs[CPU_COUNT] = {
930 (const InsTable*) &InsTabNone,
931 (const InsTable*) &InsTab6502,
932 (const InsTable*) &InsTab6502X,
933 (const InsTable*) &InsTab65SC02,
934 (const InsTable*) &InsTab65C02,
935 (const InsTable*) &InsTab65816,
936 (const InsTable*) &InsTabSweet16,
937 (const InsTable*) &InsTabHuC6280,
938 0, /* Mitsubishi 740 */
939 (const InsTable*) &InsTab4510,
941 const InsTable* InsTab = (const InsTable*) &InsTab6502;
943 /* Table to build the effective 65xx opcode from a base opcode and an
944 ** addressing mode. (The value in the table is ORed with the base opcode)
946 static unsigned char EATab[12][AM65I_COUNT] = {
948 0x00, 0x00, 0x05, 0x0D, 0x0F, 0x15, 0x1D, 0x1F,
949 0x00, 0x19, 0x12, 0x00, 0x07, 0x11, 0x17, 0x01,
950 0x00, 0x00, 0x00, 0x03, 0x13, 0x09, 0x00, 0x09,
951 0x00, 0x00, 0x00, 0x00
954 0x08, 0x08, 0x04, 0x0C, 0x00, 0x14, 0x1C, 0x00,
955 0x14, 0x1C, 0x00, 0x80, 0x00, 0x10, 0x00, 0x00,
956 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
957 0x00, 0x00, 0x80, 0x00
960 0x00, 0x00, 0x24, 0x2C, 0x0F, 0x34, 0x3C, 0x00,
961 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
962 0x00, 0x00, 0x00, 0x00, 0x00, 0x89, 0x00, 0x00,
963 0x00, 0x00, 0x00, 0x00
966 0x3A, 0x3A, 0xC6, 0xCE, 0x00, 0xD6, 0xDE, 0x00,
967 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
968 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
969 0x00, 0x00, 0x00, 0x00
972 0x1A, 0x1A, 0xE6, 0xEE, 0x00, 0xF6, 0xFE, 0x00,
973 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
974 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
975 0x00, 0x00, 0x00, 0x00
978 0x00, 0x00, 0x60, 0x98, 0x00, 0x70, 0x9E, 0x00,
979 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
980 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
981 0x00, 0x00, 0x00, 0x00
984 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
985 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00,
986 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
987 0x00, 0x00, 0x90, 0x00
989 { /* Table 7 (Subroutine opcodes) */
990 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
991 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00,
992 0xDC, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
993 0x00, 0x00, 0x00, 0x00
996 0x00, 0x40, 0x01, 0x41, 0x00, 0x09, 0x49, 0x00,
997 0x00, 0x00, 0x00, 0x51, 0x00, 0x00, 0x00, 0x00,
998 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00,
999 0x00, 0x00, 0x00, 0x00
1002 0x00, 0x00, 0x00, 0x10, 0x00, 0x20, 0x30, 0x00,
1003 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1004 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1005 0x00, 0x00, 0x00, 0x00
1007 { /* Table 10 (NOPs) */
1008 0xea, 0x00, 0x04, 0x0c, 0x00, 0x14, 0x1c, 0x00,
1009 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1010 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80,
1011 0x00, 0x00, 0x00, 0x00
1013 { /* Table 11 (LAX) */
1014 0x08, 0x08, 0x04, 0x0C, 0x00, 0x14, 0x1C, 0x00,
1015 0x14, 0x1C, 0x00, 0x80, 0x00, 0x10, 0x00, 0x00,
1016 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08,
1017 0x00, 0x00, 0x80, 0x00
1021 /* Table to build the effective SWEET16 opcode from a base opcode and an
1024 static unsigned char Sweet16EATab[2][AMSW16I_COUNT] = {
1026 0x00, 0x00, 0x00, 0x00, 0x00,
1029 0x00, 0x00, 0x00, 0x40, 0x20,
1033 /* Table that encodes the additional bytes for each 65xx instruction */
1034 unsigned char ExtBytes[AM65I_COUNT] = {
1039 3, /* Absolute long */
1042 3, /* Absolute long,X */
1051 2, /* (Absolute,X) */
1052 1, /* Relative short */
1053 2, /* Relative long */
1056 1, /* Immidiate accu */
1057 1, /* Immidiate index */
1058 1, /* Immidiate byte */
1059 2, /* Blockmove (65816) */
1060 7, /* Block transfer (HuC6280) */
1061 2, /* Absolute Indirect long */
1062 2, /* Immidiate word */
1065 /* Table that encodes the additional bytes for each SWEET16 instruction */
1066 static unsigned char Sweet16ExtBytes[AMSW16I_COUNT] = {
1076 /*****************************************************************************/
1077 /* Handler functions for 6502 derivates */
1078 /*****************************************************************************/
1082 static int EvalEA (const InsDesc* Ins, EffAddr* A)
1083 /* Evaluate the effective address. All fields in A will be valid after calling
1084 ** this function. The function returns true on success and false on errors.
1087 /* Get the set of possible addressing modes */
1090 /* From the possible addressing modes, remove the ones that are invalid
1091 ** for this instruction or CPU.
1093 A->AddrModeSet &= Ins->AddrMode;
1095 /* If we have an expression, check it and remove any addressing modes that
1096 ** are too small for the expression size. Since we have to study the
1097 ** expression anyway, do also replace it by a simpler one if possible.
1103 /* Study the expression */
1104 StudyExpr (A->Expr, &ED);
1106 /* Simplify it if possible */
1107 A->Expr = SimplifyExpr (A->Expr, &ED);
1109 if (ED.AddrSize == ADDR_SIZE_DEFAULT) {
1110 /* We don't know how big the expression is. If the instruction
1111 ** allows just one addressing mode, assume this as address size
1112 ** for the expression. Otherwise assume the default address size
1115 if ((A->AddrModeSet & ~AM65_ALL_ZP) == 0) {
1116 ED.AddrSize = ADDR_SIZE_ZP;
1117 } else if ((A->AddrModeSet & ~AM65_ALL_ABS) == 0) {
1118 ED.AddrSize = ADDR_SIZE_ABS;
1119 } else if ((A->AddrModeSet & ~AM65_ALL_FAR) == 0) {
1120 ED.AddrSize = ADDR_SIZE_FAR;
1122 ED.AddrSize = DataAddrSize;
1123 /* If the default address size of the data segment is unequal
1124 ** to zero page addressing, but zero page addressing is
1125 ** allowed by the instruction, mark all symbols in the
1126 ** expression tree. This mark will be checked at end of
1127 ** assembly, and a warning is issued, if a zero page symbol
1128 ** was guessed wrong here.
1130 if (ED.AddrSize > ADDR_SIZE_ZP && (A->AddrModeSet & AM65_SET_ZP)) {
1131 ExprGuessedAddrSize (A->Expr, ADDR_SIZE_ZP);
1136 /* Check the size */
1137 switch (ED.AddrSize) {
1140 A->AddrModeSet &= ~AM65_SET_ZP;
1144 A->AddrModeSet &= ~(AM65_SET_ZP | AM65_SET_ABS);
1148 /* Free any resource associated with the expression desc */
1152 /* Check if we have any adressing modes left */
1153 if (A->AddrModeSet == 0) {
1154 Error ("Illegal addressing mode");
1157 A->AddrMode = BitFind (A->AddrModeSet);
1158 A->AddrModeBit = (0x01UL << A->AddrMode);
1160 /* If the instruction has a one byte operand and immediate addressing is
1161 ** allowed but not used, check for an operand expression in the form
1162 ** <label or >label, where label is a far or absolute label. If found,
1163 ** emit a warning. This warning protects against a typo, where the '#'
1164 ** for the immediate operand is omitted.
1166 if (A->Expr && (Ins->AddrMode & AM65_ALL_IMM) &&
1167 (A->AddrModeSet & (AM65_DIR | AM65_ABS | AM65_ABS_LONG)) &&
1168 ExtBytes[A->AddrMode] == 1) {
1170 /* Found, check the expression */
1171 ExprNode* Left = A->Expr->Left;
1172 if ((A->Expr->Op == EXPR_BYTE0 || A->Expr->Op == EXPR_BYTE1) &&
1173 Left->Op == EXPR_SYMBOL &&
1174 GetSymAddrSize (Left->V.Sym) != ADDR_SIZE_ZP) {
1176 /* Output a warning */
1177 Warning (1, "Suspicious address expression");
1181 /* Build the opcode */
1182 A->Opcode = Ins->BaseCode | EATab[Ins->ExtCode][A->AddrMode];
1184 /* If feature force_range is active, and we have immediate addressing mode,
1185 ** limit the expression to the maximum possible value.
1187 if (A->AddrMode == AM65I_IMM_ACCU || A->AddrMode == AM65I_IMM_INDEX ||
1188 A->AddrMode == AM65I_IMM_IMPLICIT || A->AddrMode == AM65I_IMM_IMPLICIT_WORD) {
1189 if (ForceRange && A->Expr) {
1190 A->Expr = MakeBoundedExpr (A->Expr, ExtBytes[A->AddrMode]);
1200 static void EmitCode (EffAddr* A)
1201 /* Output code for the data in A */
1203 /* Check how many extension bytes are needed and output the instruction */
1204 switch (ExtBytes[A->AddrMode]) {
1211 Emit1 (A->Opcode, A->Expr);
1215 if (CPU == CPU_65816 && (A->AddrModeBit & (AM65_ABS | AM65_ABS_X | AM65_ABS_Y))) {
1216 /* This is a 16 bit mode that uses an address. If in 65816,
1217 ** mode, force this address into 16 bit range to allow
1218 ** addressing inside a 64K segment.
1220 Emit2 (A->Opcode, GenWordExpr (A->Expr));
1222 Emit2 (A->Opcode, A->Expr);
1228 Emit3 (A->Opcode, A->Expr);
1232 Internal ("Invalid operand byte count: %u", ExtBytes[A->AddrMode]);
1239 static long PutImmed8 (const InsDesc* Ins)
1240 /* Parse and emit an immediate 8 bit instruction. Return the value of the
1241 ** operand if it's available and const.
1247 /* Evaluate the addressing mode */
1248 if (EvalEA (Ins, &A) == 0) {
1249 /* An error occurred */
1253 /* If we have an expression and it's const, get it's value */
1255 (void) IsConstExpr (A.Expr, &Val);
1258 /* Check how many extension bytes are needed and output the instruction */
1259 switch (ExtBytes[A.AddrMode]) {
1262 Emit1 (A.Opcode, A.Expr);
1266 Internal ("Invalid operand byte count: %u", ExtBytes[A.AddrMode]);
1269 /* Return the expression value */
1275 static void PutPCRel8 (const InsDesc* Ins)
1276 /* Handle branches with a 8 bit distance */
1278 EmitPCRel (Ins->BaseCode, GenBranchExpr (2), 1);
1283 static void PutPCRel16 (const InsDesc* Ins)
1284 /* Handle branches with an 16 bit distance and PER */
1286 EmitPCRel (Ins->BaseCode, GenBranchExpr (3), 2);
1291 static void PutPCRel4510 (const InsDesc* Ins)
1292 /* Handle branches with a 16 bit distance */
1294 /* 16 bit branch opcode is 8 bit branch opcode or'ed with 0x03 */
1295 EmitPCRel (Ins->BaseCode, GenBranchExpr (2), 2);
1300 static void PutBlockMove (const InsDesc* Ins)
1301 /* Handle the blockmove instructions (65816) */
1306 Emit0 (Ins->BaseCode);
1308 if (CurTok.Tok == TOK_HASH) {
1309 /* The operand is a bank-byte expression. */
1311 Arg1 = Expression ();
1313 /* The operand is a far-address expression.
1314 ** Use only its bank part.
1316 Arg1 = FuncBankByte ();
1320 if (CurTok.Tok == TOK_HASH) {
1322 Arg2 = Expression ();
1324 Arg2 = FuncBankByte ();
1327 /* The operands are written in Assembly code as source, destination;
1328 ** but, they're assembled as <destination> <source>.
1336 static void PutBlockTransfer (const InsDesc* Ins)
1337 /* Handle the block transfer instructions (HuC6280) */
1339 Emit0 (Ins->BaseCode);
1340 EmitWord (Expression ());
1342 EmitWord (Expression ());
1344 EmitWord (Expression ());
1349 static void PutBitBranch (const InsDesc* Ins)
1350 /* Handle 65C02 branch on bit condition */
1352 Emit0 (Ins->BaseCode);
1353 EmitByte (Expression ());
1355 EmitSigned (GenBranchExpr (1), 1);
1360 static void PutREP (const InsDesc* Ins)
1361 /* Emit a REP instruction, track register sizes */
1363 /* Use the generic handler */
1364 long Val = PutImmed8 (Ins);
1366 /* We track the status only for the 816 CPU and in smart mode */
1367 if (CPU == CPU_65816 && SmartMode) {
1369 /* Check the range for Val. */
1371 /* We had an error */
1372 Warning (1, "Cannot track processor status byte");
1375 /* Index registers to 16 bit */
1376 ExtBytes[AM65I_IMM_INDEX] = 2;
1379 /* Accu to 16 bit */
1380 ExtBytes[AM65I_IMM_ACCU] = 2;
1388 static void PutSEP (const InsDesc* Ins)
1389 /* Emit a SEP instruction (65816), track register sizes */
1391 /* Use the generic handler */
1392 long Val = PutImmed8 (Ins);
1394 /* We track the status only for the 816 CPU and in smart mode */
1395 if (CPU == CPU_65816 && SmartMode) {
1397 /* Check the range for Val. */
1399 /* We had an error */
1400 Warning (1, "Cannot track processor status byte");
1403 /* Index registers to 8 bit */
1404 ExtBytes[AM65I_IMM_INDEX] = 1;
1408 ExtBytes[AM65I_IMM_ACCU] = 1;
1416 static void PutTAMn (const InsDesc* Ins)
1417 /* Emit a TAMn instruction (HuC6280). Since this is a two byte instruction with
1418 ** implicit addressing mode, the opcode byte in the table is actually the
1419 ** second operand byte. The TAM instruction is the more generic form, it takes
1420 ** an immediate argument.
1423 /* Emit the TAM opcode itself */
1426 /* Emit the argument, which is the opcode from the table */
1427 Emit0 (Ins->BaseCode);
1432 static void PutTMA (const InsDesc* Ins)
1433 /* Emit a TMA instruction (HuC6280) with an immediate argument. Only one bit
1434 ** in the argument byte may be set.
1437 /* Use the generic handler */
1438 long Val = PutImmed8 (Ins);
1440 /* Check the range for Val. */
1442 /* We had an error */
1443 Warning (1, "Cannot check argument of TMA instruction");
1445 /* Make sure just one bit is set */
1446 if ((Val & (Val - 1)) != 0) {
1447 Error ("Argument to TAM must be a power of two");
1454 static void PutTMAn (const InsDesc* Ins)
1455 /* Emit a TMAn instruction (HuC6280). Since this is a two byte instruction with
1456 ** implicit addressing mode, the opcode byte in the table is actually the
1457 ** second operand byte. The TAM instruction is the more generic form, it takes
1458 ** an immediate argument.
1461 /* Emit the TMA opcode itself */
1464 /* Emit the argument, which is the opcode from the table */
1465 Emit0 (Ins->BaseCode);
1470 static void PutTST (const InsDesc* Ins)
1471 /* Emit a TST instruction (HuC6280). */
1476 /* The first argument is always an immediate byte */
1477 if (CurTok.Tok != TOK_HASH) {
1478 ErrorSkip ("Invalid addressing mode");
1482 Arg1 = Expression ();
1484 /* Second argument follows */
1487 /* For the second argument, we use the standard function */
1488 if (EvalEA (Ins, &A)) {
1490 /* No error, output code */
1491 Emit1 (A.Opcode, Arg1);
1493 /* Check how many extension bytes are needed and output the instruction */
1494 switch (ExtBytes[A.AddrMode]) {
1509 static void PutJMP (const InsDesc* Ins)
1510 /* Handle the jump instruction for the 6502. Problem is that these chips have
1511 ** a bug: If the address crosses a page, the upper byte gets not corrected and
1512 ** the instruction will fail. The PutJmp function will add a linker assertion
1513 ** to check for this case and is otherwise identical to PutAll.
1518 /* Evaluate the addressing mode used */
1519 if (EvalEA (Ins, &A)) {
1521 /* Check for indirect addressing */
1522 if (A.AddrModeBit & AM65_ABS_IND) {
1524 /* Compare the low byte of the expression to 0xFF to check for
1525 ** a page cross. Be sure to use a copy of the expression otherwise
1526 ** things will go weird later.
1528 ExprNode* E = GenNE (GenByteExpr (CloneExpr (A.Expr)), 0xFF);
1530 /* Generate the message */
1531 unsigned Msg = GetStringId ("\"jmp (abs)\" across page border");
1533 /* Generate the assertion */
1534 AddAssertion (E, ASSERT_ACT_WARN, Msg);
1537 /* No error, output code */
1544 static void PutRTS (const InsDesc* Ins attribute ((unused)))
1545 /* Handle the RTS instruction for the 816. In smart mode emit a RTL opcode if
1546 ** the enclosing scope is FAR.
1549 if (SmartMode && CurrentScope->AddrSize == ADDR_SIZE_FAR) {
1550 Emit0 (0x6B); /* RTL */
1552 Emit0 (0x60); /* RTS */
1558 static void PutAll (const InsDesc* Ins)
1559 /* Handle all other instructions */
1563 /* Evaluate the addressing mode used */
1564 if (EvalEA (Ins, &A)) {
1565 /* No error, output code */
1572 static void Put4510 (const InsDesc* Ins)
1573 /* Handle all other instructions, with modifications for 4510 */
1575 /* The 4510 uses all 256 possible opcodes, so the last ones were crammed
1576 ** in where an opcode was still undefined. As a result, some of those
1577 ** don't follow any rules for encoding the addressmodes. So the EATab
1578 ** approach does not work always. In this function, the wrongly calculated
1579 ** opcode is replaced by the correct one "on the fly". Suggestions for a
1580 ** better approach are welcome.
1583 ** $47 -> $44 : ASR $12
1584 ** $57 -> $54 : ASR $12,X
1585 ** $93 -> $82 : STA ($12,SP),Y
1586 ** $9c -> $8b : STY $1234,X
1587 ** $9e -> $9b : STX $1234,Y
1588 ** $af -> $ab : LDZ $1234
1589 ** $bf -> $bb : LDZ $1234,X
1590 ** $b3 -> $e2 : LDA ($12,SP),Y
1591 ** $d0 -> $c2 : CPZ #$00
1592 ** $fc -> $23 : JSR ($1234,X)
1596 /* Evaluate the addressing mode used */
1597 if (EvalEA (Ins, &A)) {
1599 case 0x47: A.Opcode = 0x44; break;
1600 case 0x57: A.Opcode = 0x54; break;
1601 case 0x93: A.Opcode = 0x82; break;
1602 case 0x9C: A.Opcode = 0x8B; break;
1603 case 0x9E: A.Opcode = 0x9B; break;
1604 case 0xAF: A.Opcode = 0xAB; break;
1605 case 0xBF: A.Opcode = 0xBB; break;
1606 case 0xB3: A.Opcode = 0xE2; break;
1607 case 0xD0: A.Opcode = 0xC2; break;
1608 case 0xFC: A.Opcode = 0x23; break;
1609 default: /* Keep opcode as it is */ break;
1612 /* No error, output code */
1619 /*****************************************************************************/
1620 /* Handler functions for SWEET16 */
1621 /*****************************************************************************/
1625 static void PutSweet16 (const InsDesc* Ins)
1626 /* Handle a generic sweet16 instruction */
1630 /* Evaluate the addressing mode used */
1633 /* From the possible addressing modes, remove the ones that are invalid
1634 ** for this instruction or CPU.
1636 A.AddrModeSet &= Ins->AddrMode;
1638 /* Check if we have any adressing modes left */
1639 if (A.AddrModeSet == 0) {
1640 Error ("Illegal addressing mode");
1643 A.AddrMode = BitFind (A.AddrModeSet);
1644 A.AddrModeBit = (0x01UL << A.AddrMode);
1646 /* Build the opcode */
1647 A.Opcode = Ins->BaseCode | Sweet16EATab[Ins->ExtCode][A.AddrMode] | A.Reg;
1649 /* Check how many extension bytes are needed and output the instruction */
1650 switch (Sweet16ExtBytes[A.AddrMode]) {
1657 Emit1 (A.Opcode, A.Expr);
1661 Emit2 (A.Opcode, A.Expr);
1665 Internal ("Invalid operand byte count: %u", Sweet16ExtBytes[A.AddrMode]);
1672 static void PutSweet16Branch (const InsDesc* Ins)
1673 /* Handle a sweet16 branch instruction */
1675 EmitPCRel (Ins->BaseCode, GenBranchExpr (2), 1);
1680 /*****************************************************************************/
1682 /*****************************************************************************/
1686 static int CmpName (const void* Key, const void* Instr)
1687 /* Compare function for bsearch */
1689 return strcmp ((const char*)Key, ((const InsDesc*) Instr)->Mnemonic);
1694 void SetCPU (cpu_t NewCPU)
1697 /* Make sure the parameter is correct */
1698 CHECK (NewCPU < CPU_COUNT);
1700 /* Check if we have support for the new CPU, if so, use it */
1701 if (NewCPU != CPU_UNKNOWN && InsTabs[NewCPU]) {
1703 InsTab = InsTabs[CPU];
1705 Error ("CPU not supported");
1712 /* Return the current CPU */
1719 int FindInstruction (const StrBuf* Ident)
1720 /* Check if Ident is a valid mnemonic. If so, return the index in the
1721 ** instruction table. If not, return -1.
1726 char Key[sizeof (ID->Mnemonic)];
1728 /* Shortcut for the "none" CPU: If there are no instructions to search
1729 ** for, bail out early.
1731 if (InsTab->Count == 0) {
1736 /* Make a copy, and uppercase that copy */
1738 while (I < SB_GetLen (Ident)) {
1739 /* If the identifier is longer than the longest mnemonic, it cannot
1742 if (I >= sizeof (Key) - 1) {
1743 /* Not found, no need for further action */
1746 Key[I] = toupper ((unsigned char)SB_AtUnchecked (Ident, I));
1751 /* Search for the key */
1752 ID = bsearch (Key, InsTab->Ins, InsTab->Count, sizeof (InsDesc), CmpName);
1757 /* Found, return the entry */
1758 return ID - InsTab->Ins;
1764 void HandleInstruction (unsigned Index)
1765 /* Handle the mnemonic with the given index */
1768 PRECONDITION (Index < InsTab->Count);
1770 /* Skip the mnemonic token */
1773 /* Call the handler */
1774 InsTab->Ins[Index].Emit (&InsTab->Ins[Index]);