1 /*****************************************************************************/
5 /* Instruction encoding for the ca65 macroassembler */
9 /* (C) 1998-2008, 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 /*****************************************************************************/
42 #include "assertdefs.h"
60 #include "studyexpr.h"
65 /*****************************************************************************/
67 /*****************************************************************************/
71 static void PutPCRel8 (const InsDesc* Ins);
72 /* Handle branches with a 8 bit distance */
74 static void PutPCRel16 (const InsDesc* Ins);
75 /* Handle branches with an 16 bit distance and PER */
77 static void PutBlockMove (const InsDesc* Ins);
78 /* Handle the blockmove instructions (65816) */
80 static void PutBlockTransfer (const InsDesc* Ins);
81 /* Handle the block transfer instructions (HuC6280) */
83 static void PutBitBranch (const InsDesc* Ins);
84 /* Handle 65C02 branch on bit condition */
86 static void PutREP (const InsDesc* Ins);
87 /* Emit a REP instruction, track register sizes */
89 static void PutSEP (const InsDesc* Ins);
90 /* Emit a SEP instruction (65816), track register sizes */
92 static void PutTAMn (const InsDesc* Ins);
93 /* Emit a TAMn instruction (HuC6280). Since this is a two byte instruction with
94 * implicit addressing mode, the opcode byte in the table is actually the
95 * second operand byte. The TAM instruction is the more generic form, it takes
96 * an immediate argument.
99 static void PutTMA (const InsDesc* Ins);
100 /* Emit a TMA instruction (HuC6280) with an immediate argument. Only one bit
101 * in the argument byte may be set.
104 static void PutTMAn (const InsDesc* Ins);
105 /* Emit a TMAn instruction (HuC6280). Since this is a two byte instruction with
106 * implicit addressing mode, the opcode byte in the table is actually the
107 * second operand byte. The TAM instruction is the more generic form, it takes
108 * an immediate argument.
111 static void PutTST (const InsDesc* Ins);
112 /* Emit a TST instruction (HuC6280). */
114 static void PutJMP (const InsDesc* Ins);
115 /* Handle the jump instruction for the 6502. Problem is that these chips have
116 * a bug: If the address crosses a page, the upper byte gets not corrected and
117 * the instruction will fail. The PutJmp function will add a linker assertion
118 * to check for this case and is otherwise identical to PutAll.
121 static void PutRTS (const InsDesc* Ins attribute ((unused)));
122 /* Handle the RTS instruction for the 816. In smart mode emit a RTL opcode if
123 * the enclosing scope is FAR.
126 static void PutAll (const InsDesc* Ins);
127 /* Handle all other instructions */
129 static void PutSweet16 (const InsDesc* Ins);
130 /* Handle a generic sweet16 instruction */
132 static void PutSweet16Branch (const InsDesc* Ins);
133 /* Handle a sweet16 branch instruction */
137 /*****************************************************************************/
139 /*****************************************************************************/
143 /* Empty instruction table */
144 static const struct {
150 /* Instruction table for the 6502 */
151 static const struct {
155 sizeof (InsTab6502.Ins) / sizeof (InsTab6502.Ins[0]),
157 { "ADC", 0x080A26C, 0x60, 0, PutAll },
158 { "AND", 0x080A26C, 0x20, 0, PutAll },
159 { "ASL", 0x000006e, 0x02, 1, PutAll },
160 { "BCC", 0x0020000, 0x90, 0, PutPCRel8 },
161 { "BCS", 0x0020000, 0xb0, 0, PutPCRel8 },
162 { "BEQ", 0x0020000, 0xf0, 0, PutPCRel8 },
163 { "BIT", 0x000000C, 0x00, 2, PutAll },
164 { "BMI", 0x0020000, 0x30, 0, PutPCRel8 },
165 { "BNE", 0x0020000, 0xd0, 0, PutPCRel8 },
166 { "BPL", 0x0020000, 0x10, 0, PutPCRel8 },
167 { "BRK", 0x0000001, 0x00, 0, PutAll },
168 { "BVC", 0x0020000, 0x50, 0, PutPCRel8 },
169 { "BVS", 0x0020000, 0x70, 0, PutPCRel8 },
170 { "CLC", 0x0000001, 0x18, 0, PutAll },
171 { "CLD", 0x0000001, 0xd8, 0, PutAll },
172 { "CLI", 0x0000001, 0x58, 0, PutAll },
173 { "CLV", 0x0000001, 0xb8, 0, PutAll },
174 { "CMP", 0x080A26C, 0xc0, 0, PutAll },
175 { "CPX", 0x080000C, 0xe0, 1, PutAll },
176 { "CPY", 0x080000C, 0xc0, 1, PutAll },
177 { "DEC", 0x000006C, 0x00, 3, PutAll },
178 { "DEX", 0x0000001, 0xca, 0, PutAll },
179 { "DEY", 0x0000001, 0x88, 0, PutAll },
180 { "EOR", 0x080A26C, 0x40, 0, PutAll },
181 { "INC", 0x000006c, 0x00, 4, PutAll },
182 { "INX", 0x0000001, 0xe8, 0, PutAll },
183 { "INY", 0x0000001, 0xc8, 0, PutAll },
184 { "JMP", 0x0000808, 0x4c, 6, PutJMP },
185 { "JSR", 0x0000008, 0x20, 7, PutAll },
186 { "LDA", 0x080A26C, 0xa0, 0, PutAll },
187 { "LDX", 0x080030C, 0xa2, 1, PutAll },
188 { "LDY", 0x080006C, 0xa0, 1, PutAll },
189 { "LSR", 0x000006F, 0x42, 1, PutAll },
190 { "NOP", 0x0000001, 0xea, 0, PutAll },
191 { "ORA", 0x080A26C, 0x00, 0, PutAll },
192 { "PHA", 0x0000001, 0x48, 0, PutAll },
193 { "PHP", 0x0000001, 0x08, 0, PutAll },
194 { "PLA", 0x0000001, 0x68, 0, PutAll },
195 { "PLP", 0x0000001, 0x28, 0, PutAll },
196 { "ROL", 0x000006F, 0x22, 1, PutAll },
197 { "ROR", 0x000006F, 0x62, 1, PutAll },
198 { "RTI", 0x0000001, 0x40, 0, PutAll },
199 { "RTS", 0x0000001, 0x60, 0, PutAll },
200 { "SBC", 0x080A26C, 0xe0, 0, PutAll },
201 { "SEC", 0x0000001, 0x38, 0, PutAll },
202 { "SED", 0x0000001, 0xf8, 0, PutAll },
203 { "SEI", 0x0000001, 0x78, 0, PutAll },
204 { "STA", 0x000A26C, 0x80, 0, PutAll },
205 { "STX", 0x000010c, 0x82, 1, PutAll },
206 { "STY", 0x000002c, 0x80, 1, PutAll },
207 { "TAX", 0x0000001, 0xaa, 0, PutAll },
208 { "TAY", 0x0000001, 0xa8, 0, PutAll },
209 { "TSX", 0x0000001, 0xba, 0, PutAll },
210 { "TXA", 0x0000001, 0x8a, 0, PutAll },
211 { "TXS", 0x0000001, 0x9a, 0, PutAll },
212 { "TYA", 0x0000001, 0x98, 0, PutAll }
216 /* Instruction table for the 6502 with illegal instructions */
217 static const struct {
221 sizeof (InsTab6502X.Ins) / sizeof (InsTab6502X.Ins[0]),
223 { "ADC", 0x080A26C, 0x60, 0, PutAll },
224 { "ALR", 0x0800000, 0x4B, 0, PutAll }, /* X */
225 { "ANC", 0x0800000, 0x0B, 0, PutAll }, /* X */
226 { "AND", 0x080A26C, 0x20, 0, PutAll },
227 { "ARR", 0x0800000, 0x6B, 0, PutAll }, /* X */
228 { "ASL", 0x000006e, 0x02, 1, PutAll },
229 { "AXS", 0x0800000, 0xCB, 0, PutAll }, /* X */
230 { "BCC", 0x0020000, 0x90, 0, PutPCRel8 },
231 { "BCS", 0x0020000, 0xb0, 0, PutPCRel8 },
232 { "BEQ", 0x0020000, 0xf0, 0, PutPCRel8 },
233 { "BIT", 0x000000C, 0x00, 2, PutAll },
234 { "BMI", 0x0020000, 0x30, 0, PutPCRel8 },
235 { "BNE", 0x0020000, 0xd0, 0, PutPCRel8 },
236 { "BPL", 0x0020000, 0x10, 0, PutPCRel8 },
237 { "BRK", 0x0000001, 0x00, 0, PutAll },
238 { "BVC", 0x0020000, 0x50, 0, PutPCRel8 },
239 { "BVS", 0x0020000, 0x70, 0, PutPCRel8 },
240 { "CLC", 0x0000001, 0x18, 0, PutAll },
241 { "CLD", 0x0000001, 0xd8, 0, PutAll },
242 { "CLI", 0x0000001, 0x58, 0, PutAll },
243 { "CLV", 0x0000001, 0xb8, 0, PutAll },
244 { "CMP", 0x080A26C, 0xc0, 0, PutAll },
245 { "CPX", 0x080000C, 0xe0, 1, PutAll },
246 { "CPY", 0x080000C, 0xc0, 1, PutAll },
247 { "DCP", 0x000A26C, 0xC3, 0, PutAll }, /* X */
248 { "DEC", 0x000006C, 0x00, 3, PutAll },
249 { "DEX", 0x0000001, 0xca, 0, PutAll },
250 { "DEY", 0x0000001, 0x88, 0, PutAll },
251 { "EOR", 0x080A26C, 0x40, 0, PutAll },
252 { "INC", 0x000006c, 0x00, 4, PutAll },
253 { "INX", 0x0000001, 0xe8, 0, PutAll },
254 { "INY", 0x0000001, 0xc8, 0, PutAll },
255 { "ISC", 0x000A26C, 0xE3, 0, PutAll }, /* X */
256 { "JAM", 0x0000001, 0x02, 0, PutAll }, /* X */
257 { "JMP", 0x0000808, 0x4c, 6, PutJMP },
258 { "JSR", 0x0000008, 0x20, 7, PutAll },
259 { "LAS", 0x0000200, 0xBB, 0, PutAll }, /* X */
260 { "LAX", 0x000A30C, 0xA3, 1, PutAll }, /* X */
261 { "LDA", 0x080A26C, 0xa0, 0, PutAll },
262 { "LDX", 0x080030C, 0xa2, 1, PutAll },
263 { "LDY", 0x080006C, 0xa0, 1, PutAll },
264 { "LSR", 0x000006F, 0x42, 1, PutAll },
265 { "NOP", 0x0000001, 0xea, 0, PutAll },
266 { "ORA", 0x080A26C, 0x00, 0, PutAll },
267 { "PHA", 0x0000001, 0x48, 0, PutAll },
268 { "PHP", 0x0000001, 0x08, 0, PutAll },
269 { "PLA", 0x0000001, 0x68, 0, PutAll },
270 { "PLP", 0x0000001, 0x28, 0, PutAll },
271 { "RLA", 0x000A26C, 0x23, 0, PutAll }, /* X */
272 { "ROL", 0x000006F, 0x22, 1, PutAll },
273 { "ROR", 0x000006F, 0x62, 1, PutAll },
274 { "RRA", 0x000A26C, 0x63, 0, PutAll }, /* X */
275 { "RTI", 0x0000001, 0x40, 0, PutAll },
276 { "RTS", 0x0000001, 0x60, 0, PutAll },
277 { "SAX", 0x000810C, 0x83, 1, PutAll }, /* X */
278 { "SBC", 0x080A26C, 0xe0, 0, PutAll },
279 { "SEC", 0x0000001, 0x38, 0, PutAll },
280 { "SED", 0x0000001, 0xf8, 0, PutAll },
281 { "SEI", 0x0000001, 0x78, 0, PutAll },
282 { "SLO", 0x000A26C, 0x03, 0, PutAll }, /* X */
283 { "SRE", 0x000A26C, 0x43, 0, PutAll }, /* X */
284 { "STA", 0x000A26C, 0x80, 0, PutAll },
285 { "STX", 0x000010c, 0x82, 1, PutAll },
286 { "STY", 0x000002c, 0x80, 1, PutAll },
287 { "TAX", 0x0000001, 0xaa, 0, PutAll },
288 { "TAY", 0x0000001, 0xa8, 0, PutAll },
289 { "TSX", 0x0000001, 0xba, 0, PutAll },
290 { "TXA", 0x0000001, 0x8a, 0, PutAll },
291 { "TXS", 0x0000001, 0x9a, 0, PutAll },
292 { "TYA", 0x0000001, 0x98, 0, PutAll }
296 /* Instruction table for the 65SC02 */
297 static const struct {
301 sizeof (InsTab65SC02.Ins) / sizeof (InsTab65SC02.Ins[0]),
303 { "ADC", 0x080A66C, 0x60, 0, PutAll },
304 { "AND", 0x080A66C, 0x20, 0, PutAll },
305 { "ASL", 0x000006e, 0x02, 1, PutAll },
306 { "BCC", 0x0020000, 0x90, 0, PutPCRel8 },
307 { "BCS", 0x0020000, 0xb0, 0, PutPCRel8 },
308 { "BEQ", 0x0020000, 0xf0, 0, PutPCRel8 },
309 { "BIT", 0x0A0006C, 0x00, 2, PutAll },
310 { "BMI", 0x0020000, 0x30, 0, PutPCRel8 },
311 { "BNE", 0x0020000, 0xd0, 0, PutPCRel8 },
312 { "BPL", 0x0020000, 0x10, 0, PutPCRel8 },
313 { "BRA", 0x0020000, 0x80, 0, PutPCRel8 },
314 { "BRK", 0x0000001, 0x00, 0, PutAll },
315 { "BVC", 0x0020000, 0x50, 0, PutPCRel8 },
316 { "BVS", 0x0020000, 0x70, 0, PutPCRel8 },
317 { "CLC", 0x0000001, 0x18, 0, PutAll },
318 { "CLD", 0x0000001, 0xd8, 0, PutAll },
319 { "CLI", 0x0000001, 0x58, 0, PutAll },
320 { "CLV", 0x0000001, 0xb8, 0, PutAll },
321 { "CMP", 0x080A66C, 0xc0, 0, PutAll },
322 { "CPX", 0x080000C, 0xe0, 1, PutAll },
323 { "CPY", 0x080000C, 0xc0, 1, PutAll },
324 { "DEA", 0x0000001, 0x00, 3, PutAll }, /* == DEC */
325 { "DEC", 0x000006F, 0x00, 3, PutAll },
326 { "DEX", 0x0000001, 0xca, 0, PutAll },
327 { "DEY", 0x0000001, 0x88, 0, PutAll },
328 { "EOR", 0x080A66C, 0x40, 0, PutAll },
329 { "INA", 0x0000001, 0x00, 4, PutAll }, /* == INC */
330 { "INC", 0x000006f, 0x00, 4, PutAll },
331 { "INX", 0x0000001, 0xe8, 0, PutAll },
332 { "INY", 0x0000001, 0xc8, 0, PutAll },
333 { "JMP", 0x0010808, 0x4c, 6, PutAll },
334 { "JSR", 0x0000008, 0x20, 7, PutAll },
335 { "LDA", 0x080A66C, 0xa0, 0, PutAll },
336 { "LDX", 0x080030C, 0xa2, 1, PutAll },
337 { "LDY", 0x080006C, 0xa0, 1, PutAll },
338 { "LSR", 0x000006F, 0x42, 1, PutAll },
339 { "NOP", 0x0000001, 0xea, 0, PutAll },
340 { "ORA", 0x080A66C, 0x00, 0, PutAll },
341 { "PHA", 0x0000001, 0x48, 0, PutAll },
342 { "PHP", 0x0000001, 0x08, 0, PutAll },
343 { "PHX", 0x0000001, 0xda, 0, PutAll },
344 { "PHY", 0x0000001, 0x5a, 0, PutAll },
345 { "PLA", 0x0000001, 0x68, 0, PutAll },
346 { "PLP", 0x0000001, 0x28, 0, PutAll },
347 { "PLX", 0x0000001, 0xfa, 0, PutAll },
348 { "PLY", 0x0000001, 0x7a, 0, PutAll },
349 { "ROL", 0x000006F, 0x22, 1, PutAll },
350 { "ROR", 0x000006F, 0x62, 1, PutAll },
351 { "RTI", 0x0000001, 0x40, 0, PutAll },
352 { "RTS", 0x0000001, 0x60, 0, PutAll },
353 { "SBC", 0x080A66C, 0xe0, 0, PutAll },
354 { "SEC", 0x0000001, 0x38, 0, PutAll },
355 { "SED", 0x0000001, 0xf8, 0, PutAll },
356 { "SEI", 0x0000001, 0x78, 0, PutAll },
357 { "STA", 0x000A66C, 0x80, 0, PutAll },
358 { "STX", 0x000010c, 0x82, 1, PutAll },
359 { "STY", 0x000002c, 0x80, 1, PutAll },
360 { "STZ", 0x000006c, 0x04, 5, PutAll },
361 { "TAX", 0x0000001, 0xaa, 0, PutAll },
362 { "TAY", 0x0000001, 0xa8, 0, PutAll },
363 { "TRB", 0x000000c, 0x10, 1, PutAll },
364 { "TSB", 0x000000c, 0x00, 1, PutAll },
365 { "TSX", 0x0000001, 0xba, 0, PutAll },
366 { "TXA", 0x0000001, 0x8a, 0, PutAll },
367 { "TXS", 0x0000001, 0x9a, 0, PutAll },
368 { "TYA", 0x0000001, 0x98, 0, PutAll }
372 /* Instruction table for the 65C02 */
373 static const struct {
377 sizeof (InsTab65C02.Ins) / sizeof (InsTab65C02.Ins[0]),
379 { "ADC", 0x080A66C, 0x60, 0, PutAll },
380 { "AND", 0x080A66C, 0x20, 0, PutAll },
381 { "ASL", 0x000006e, 0x02, 1, PutAll },
382 { "BBR0", 0x0000000, 0x0F, 0, PutBitBranch },
383 { "BBR1", 0x0000000, 0x1F, 0, PutBitBranch },
384 { "BBR2", 0x0000000, 0x2F, 0, PutBitBranch },
385 { "BBR3", 0x0000000, 0x3F, 0, PutBitBranch },
386 { "BBR4", 0x0000000, 0x4F, 0, PutBitBranch },
387 { "BBR5", 0x0000000, 0x5F, 0, PutBitBranch },
388 { "BBR6", 0x0000000, 0x6F, 0, PutBitBranch },
389 { "BBR7", 0x0000000, 0x7F, 0, PutBitBranch },
390 { "BBS0", 0x0000000, 0x8F, 0, PutBitBranch },
391 { "BBS1", 0x0000000, 0x9F, 0, PutBitBranch },
392 { "BBS2", 0x0000000, 0xAF, 0, PutBitBranch },
393 { "BBS3", 0x0000000, 0xBF, 0, PutBitBranch },
394 { "BBS4", 0x0000000, 0xCF, 0, PutBitBranch },
395 { "BBS5", 0x0000000, 0xDF, 0, PutBitBranch },
396 { "BBS6", 0x0000000, 0xEF, 0, PutBitBranch },
397 { "BBS7", 0x0000000, 0xFF, 0, PutBitBranch },
398 { "BCC", 0x0020000, 0x90, 0, PutPCRel8 },
399 { "BCS", 0x0020000, 0xb0, 0, PutPCRel8 },
400 { "BEQ", 0x0020000, 0xf0, 0, PutPCRel8 },
401 { "BIT", 0x0A0006C, 0x00, 2, PutAll },
402 { "BMI", 0x0020000, 0x30, 0, PutPCRel8 },
403 { "BNE", 0x0020000, 0xd0, 0, PutPCRel8 },
404 { "BPL", 0x0020000, 0x10, 0, PutPCRel8 },
405 { "BRA", 0x0020000, 0x80, 0, PutPCRel8 },
406 { "BRK", 0x0000001, 0x00, 0, PutAll },
407 { "BVC", 0x0020000, 0x50, 0, PutPCRel8 },
408 { "BVS", 0x0020000, 0x70, 0, PutPCRel8 },
409 { "CLC", 0x0000001, 0x18, 0, PutAll },
410 { "CLD", 0x0000001, 0xd8, 0, PutAll },
411 { "CLI", 0x0000001, 0x58, 0, PutAll },
412 { "CLV", 0x0000001, 0xb8, 0, PutAll },
413 { "CMP", 0x080A66C, 0xc0, 0, PutAll },
414 { "CPX", 0x080000C, 0xe0, 1, PutAll },
415 { "CPY", 0x080000C, 0xc0, 1, PutAll },
416 { "DEA", 0x0000001, 0x00, 3, PutAll }, /* == DEC */
417 { "DEC", 0x000006F, 0x00, 3, PutAll },
418 { "DEX", 0x0000001, 0xca, 0, PutAll },
419 { "DEY", 0x0000001, 0x88, 0, PutAll },
420 { "EOR", 0x080A66C, 0x40, 0, PutAll },
421 { "INA", 0x0000001, 0x00, 4, PutAll }, /* == INC */
422 { "INC", 0x000006f, 0x00, 4, PutAll },
423 { "INX", 0x0000001, 0xe8, 0, PutAll },
424 { "INY", 0x0000001, 0xc8, 0, PutAll },
425 { "JMP", 0x0010808, 0x4c, 6, PutAll },
426 { "JSR", 0x0000008, 0x20, 7, PutAll },
427 { "LDA", 0x080A66C, 0xa0, 0, PutAll },
428 { "LDX", 0x080030C, 0xa2, 1, PutAll },
429 { "LDY", 0x080006C, 0xa0, 1, PutAll },
430 { "LSR", 0x000006F, 0x42, 1, PutAll },
431 { "NOP", 0x0000001, 0xea, 0, PutAll },
432 { "ORA", 0x080A66C, 0x00, 0, PutAll },
433 { "PHA", 0x0000001, 0x48, 0, PutAll },
434 { "PHP", 0x0000001, 0x08, 0, PutAll },
435 { "PHX", 0x0000001, 0xda, 0, PutAll },
436 { "PHY", 0x0000001, 0x5a, 0, PutAll },
437 { "PLA", 0x0000001, 0x68, 0, PutAll },
438 { "PLP", 0x0000001, 0x28, 0, PutAll },
439 { "PLX", 0x0000001, 0xfa, 0, PutAll },
440 { "PLY", 0x0000001, 0x7a, 0, PutAll },
441 { "RMB0", 0x0000004, 0x07, 1, PutAll },
442 { "RMB1", 0x0000004, 0x17, 1, PutAll },
443 { "RMB2", 0x0000004, 0x27, 1, PutAll },
444 { "RMB3", 0x0000004, 0x37, 1, PutAll },
445 { "RMB4", 0x0000004, 0x47, 1, PutAll },
446 { "RMB5", 0x0000004, 0x57, 1, PutAll },
447 { "RMB6", 0x0000004, 0x67, 1, PutAll },
448 { "RMB7", 0x0000004, 0x77, 1, PutAll },
449 { "ROL", 0x000006F, 0x22, 1, PutAll },
450 { "ROR", 0x000006F, 0x62, 1, PutAll },
451 { "RTI", 0x0000001, 0x40, 0, PutAll },
452 { "RTS", 0x0000001, 0x60, 0, PutAll },
453 { "SBC", 0x080A66C, 0xe0, 0, PutAll },
454 { "SEC", 0x0000001, 0x38, 0, PutAll },
455 { "SED", 0x0000001, 0xf8, 0, PutAll },
456 { "SEI", 0x0000001, 0x78, 0, PutAll },
457 { "SMB0", 0x0000004, 0x87, 1, PutAll },
458 { "SMB1", 0x0000004, 0x97, 1, PutAll },
459 { "SMB2", 0x0000004, 0xA7, 1, PutAll },
460 { "SMB3", 0x0000004, 0xB7, 1, PutAll },
461 { "SMB4", 0x0000004, 0xC7, 1, PutAll },
462 { "SMB5", 0x0000004, 0xD7, 1, PutAll },
463 { "SMB6", 0x0000004, 0xE7, 1, PutAll },
464 { "SMB7", 0x0000004, 0xF7, 1, PutAll },
465 { "STA", 0x000A66C, 0x80, 0, PutAll },
466 { "STX", 0x000010c, 0x82, 1, PutAll },
467 { "STY", 0x000002c, 0x80, 1, PutAll },
468 { "STZ", 0x000006c, 0x04, 5, PutAll },
469 { "TAX", 0x0000001, 0xaa, 0, PutAll },
470 { "TAY", 0x0000001, 0xa8, 0, PutAll },
471 { "TRB", 0x000000c, 0x10, 1, PutAll },
472 { "TSB", 0x000000c, 0x00, 1, PutAll },
473 { "TSX", 0x0000001, 0xba, 0, PutAll },
474 { "TXA", 0x0000001, 0x8a, 0, PutAll },
475 { "TXS", 0x0000001, 0x9a, 0, PutAll },
476 { "TYA", 0x0000001, 0x98, 0, PutAll }
480 /* Instruction table for the 65816 */
481 static const struct {
485 sizeof (InsTab65816.Ins) / sizeof (InsTab65816.Ins[0]),
487 { "ADC", 0x0b8f6fc, 0x60, 0, PutAll },
488 { "AND", 0x0b8f6fc, 0x20, 0, PutAll },
489 { "ASL", 0x000006e, 0x02, 1, PutAll },
490 { "BCC", 0x0020000, 0x90, 0, PutPCRel8 },
491 { "BCS", 0x0020000, 0xb0, 0, PutPCRel8 },
492 { "BEQ", 0x0020000, 0xf0, 0, PutPCRel8 },
493 { "BGE", 0x0020000, 0xb0, 0, PutPCRel8 }, /* == BCS */
494 { "BIT", 0x0a0006c, 0x00, 2, PutAll },
495 { "BLT", 0x0020000, 0x90, 0, PutPCRel8 }, /* == BCC */
496 { "BMI", 0x0020000, 0x30, 0, PutPCRel8 },
497 { "BNE", 0x0020000, 0xd0, 0, PutPCRel8 },
498 { "BPL", 0x0020000, 0x10, 0, PutPCRel8 },
499 { "BRA", 0x0020000, 0x80, 0, PutPCRel8 },
500 { "BRK", 0x0000001, 0x00, 0, PutAll },
501 { "BRL", 0x0040000, 0x82, 0, PutPCRel16 },
502 { "BVC", 0x0020000, 0x50, 0, PutPCRel8 },
503 { "BVS", 0x0020000, 0x70, 0, PutPCRel8 },
504 { "CLC", 0x0000001, 0x18, 0, PutAll },
505 { "CLD", 0x0000001, 0xd8, 0, PutAll },
506 { "CLI", 0x0000001, 0x58, 0, PutAll },
507 { "CLV", 0x0000001, 0xb8, 0, PutAll },
508 { "CMP", 0x0b8f6fc, 0xc0, 0, PutAll },
509 { "COP", 0x0000004, 0x02, 6, PutAll },
510 { "CPA", 0x0b8f6fc, 0xc0, 0, PutAll }, /* == CMP */
511 { "CPX", 0x0c0000c, 0xe0, 1, PutAll },
512 { "CPY", 0x0c0000c, 0xc0, 1, PutAll },
513 { "DEA", 0x0000001, 0x00, 3, PutAll }, /* == DEC */
514 { "DEC", 0x000006F, 0x00, 3, PutAll },
515 { "DEX", 0x0000001, 0xca, 0, PutAll },
516 { "DEY", 0x0000001, 0x88, 0, PutAll },
517 { "EOR", 0x0b8f6fc, 0x40, 0, PutAll },
518 { "INA", 0x0000001, 0x00, 4, PutAll }, /* == INC */
519 { "INC", 0x000006F, 0x00, 4, PutAll },
520 { "INX", 0x0000001, 0xe8, 0, PutAll },
521 { "INY", 0x0000001, 0xc8, 0, PutAll },
522 { "JML", 0x0000810, 0x5c, 1, PutAll },
523 { "JMP", 0x0010818, 0x4c, 6, PutAll },
524 { "JSL", 0x0000010, 0x20, 7, PutAll },
525 { "JSR", 0x0010018, 0x20, 7, PutAll },
526 { "LDA", 0x0b8f6fc, 0xa0, 0, PutAll },
527 { "LDX", 0x0c0030c, 0xa2, 1, PutAll },
528 { "LDY", 0x0c0006c, 0xa0, 1, PutAll },
529 { "LSR", 0x000006F, 0x42, 1, PutAll },
530 { "MVN", 0x1000000, 0x54, 0, PutBlockMove },
531 { "MVP", 0x1000000, 0x44, 0, PutBlockMove },
532 { "NOP", 0x0000001, 0xea, 0, PutAll },
533 { "ORA", 0x0b8f6fc, 0x00, 0, PutAll },
534 { "PEA", 0x0000008, 0xf4, 6, PutAll },
535 { "PEI", 0x0000400, 0xd4, 1, PutAll },
536 { "PER", 0x0040000, 0x62, 0, PutPCRel16 },
537 { "PHA", 0x0000001, 0x48, 0, PutAll },
538 { "PHB", 0x0000001, 0x8b, 0, PutAll },
539 { "PHD", 0x0000001, 0x0b, 0, PutAll },
540 { "PHK", 0x0000001, 0x4b, 0, PutAll },
541 { "PHP", 0x0000001, 0x08, 0, PutAll },
542 { "PHX", 0x0000001, 0xda, 0, PutAll },
543 { "PHY", 0x0000001, 0x5a, 0, PutAll },
544 { "PLA", 0x0000001, 0x68, 0, PutAll },
545 { "PLB", 0x0000001, 0xab, 0, PutAll },
546 { "PLD", 0x0000001, 0x2b, 0, PutAll },
547 { "PLP", 0x0000001, 0x28, 0, PutAll },
548 { "PLX", 0x0000001, 0xfa, 0, PutAll },
549 { "PLY", 0x0000001, 0x7a, 0, PutAll },
550 { "REP", 0x0800000, 0xc2, 1, PutREP },
551 { "ROL", 0x000006F, 0x22, 1, PutAll },
552 { "ROR", 0x000006F, 0x62, 1, PutAll },
553 { "RTI", 0x0000001, 0x40, 0, PutAll },
554 { "RTL", 0x0000001, 0x6b, 0, PutAll },
555 { "RTS", 0x0000001, 0x60, 0, PutRTS },
556 { "SBC", 0x0b8f6fc, 0xe0, 0, PutAll },
557 { "SEC", 0x0000001, 0x38, 0, PutAll },
558 { "SED", 0x0000001, 0xf8, 0, PutAll },
559 { "SEI", 0x0000001, 0x78, 0, PutAll },
560 { "SEP", 0x0800000, 0xe2, 1, PutSEP },
561 { "STA", 0x018f6fc, 0x80, 0, PutAll },
562 { "STP", 0x0000001, 0xdb, 0, PutAll },
563 { "STX", 0x000010c, 0x82, 1, PutAll },
564 { "STY", 0x000002c, 0x80, 1, PutAll },
565 { "STZ", 0x000006c, 0x04, 5, PutAll },
566 { "SWA", 0x0000001, 0xeb, 0, PutAll }, /* == XBA */
567 { "TAD", 0x0000001, 0x5b, 0, PutAll }, /* == TCD */
568 { "TAS", 0x0000001, 0x1b, 0, PutAll }, /* == TCS */
569 { "TAX", 0x0000001, 0xaa, 0, PutAll },
570 { "TAY", 0x0000001, 0xa8, 0, PutAll },
571 { "TCD", 0x0000001, 0x5b, 0, PutAll },
572 { "TCS", 0x0000001, 0x1b, 0, PutAll },
573 { "TDA", 0x0000001, 0x7b, 0, PutAll }, /* == TDC */
574 { "TDC", 0x0000001, 0x7b, 0, PutAll },
575 { "TRB", 0x000000c, 0x10, 1, PutAll },
576 { "TSA", 0x0000001, 0x3b, 0, PutAll }, /* == TSC */
577 { "TSB", 0x000000c, 0x00, 1, PutAll },
578 { "TSC", 0x0000001, 0x3b, 0, PutAll },
579 { "TSX", 0x0000001, 0xba, 0, PutAll },
580 { "TXA", 0x0000001, 0x8a, 0, PutAll },
581 { "TXS", 0x0000001, 0x9a, 0, PutAll },
582 { "TXY", 0x0000001, 0x9b, 0, PutAll },
583 { "TYA", 0x0000001, 0x98, 0, PutAll },
584 { "TYX", 0x0000001, 0xbb, 0, PutAll },
585 { "WAI", 0x0000001, 0xcb, 0, PutAll },
586 { "XBA", 0x0000001, 0xeb, 0, PutAll },
587 { "XCE", 0x0000001, 0xfb, 0, PutAll }
592 /* Table for the SUNPLUS CPU */
593 #include "sunplus.inc"
596 /* Instruction table for the SWEET16 pseudo CPU */
597 static const struct {
601 sizeof (InsTabSweet16.Ins) / sizeof (InsTabSweet16.Ins[0]),
603 { "ADD", AMSW16_REG, 0xA0, 0, PutSweet16 },
604 { "BC", AMSW16_BRA, 0x03, 0, PutSweet16Branch },
605 { "BK", AMSW16_IMP, 0x0A, 0, PutSweet16 },
606 { "BM", AMSW16_BRA, 0x05, 0, PutSweet16Branch },
607 { "BM1", AMSW16_BRA, 0x08, 0, PutSweet16Branch },
608 { "BNC", AMSW16_BRA, 0x02, 0, PutSweet16Branch },
609 { "BNM1", AMSW16_BRA, 0x09, 0, PutSweet16Branch },
610 { "BNZ", AMSW16_BRA, 0x07, 0, PutSweet16Branch },
611 { "BP", AMSW16_BRA, 0x04, 0, PutSweet16Branch },
612 { "BR", AMSW16_BRA, 0x01, 0, PutSweet16Branch },
613 { "BS", AMSW16_BRA, 0x0B, 0, PutSweet16Branch },
614 { "BZ", AMSW16_BRA, 0x06, 0, PutSweet16Branch },
615 { "CPR", AMSW16_REG, 0xD0, 0, PutSweet16 },
616 { "DCR", AMSW16_REG, 0xF0, 0, PutSweet16 },
617 { "INR", AMSW16_REG, 0xE0, 0, PutSweet16 },
618 { "LD", AMSW16_REG | AMSW16_IND, 0x00, 1, PutSweet16 },
619 { "LDD", AMSW16_IND, 0x60, 0, PutSweet16 },
620 { "POP", AMSW16_IND, 0x80, 0, PutSweet16 },
621 { "POPD", AMSW16_IND, 0xC0, 0, PutSweet16 },
622 { "RS", AMSW16_IMP, 0x0B, 0, PutSweet16 },
623 { "RTN", AMSW16_IMP, 0x00, 0, PutSweet16 },
624 { "SET", AMSW16_IMM, 0x10, 0, PutSweet16 },
625 { "ST", AMSW16_REG | AMSW16_IND, 0x10, 1, PutSweet16 },
626 { "STD", AMSW16_IND, 0x70, 0, PutSweet16 },
627 { "STP", AMSW16_IND, 0x90, 0, PutSweet16 },
628 { "SUB", AMSW16_IMM, 0xB0, 0, PutSweet16 },
632 /* Instruction table for the HuC6280 (the CPU used in the PC engine) */
633 static const struct {
637 sizeof (InsTabHuC6280.Ins) / sizeof (InsTabHuC6280.Ins[0]),
639 { "ADC", 0x080A66C, 0x60, 0, PutAll },
640 { "AND", 0x080A66C, 0x20, 0, PutAll },
641 { "ASL", 0x000006e, 0x02, 1, PutAll },
642 { "BBR0", 0x0000000, 0x0F, 0, PutBitBranch },
643 { "BBR1", 0x0000000, 0x1F, 0, PutBitBranch },
644 { "BBR2", 0x0000000, 0x2F, 0, PutBitBranch },
645 { "BBR3", 0x0000000, 0x3F, 0, PutBitBranch },
646 { "BBR4", 0x0000000, 0x4F, 0, PutBitBranch },
647 { "BBR5", 0x0000000, 0x5F, 0, PutBitBranch },
648 { "BBR6", 0x0000000, 0x6F, 0, PutBitBranch },
649 { "BBR7", 0x0000000, 0x7F, 0, PutBitBranch },
650 { "BBS0", 0x0000000, 0x8F, 0, PutBitBranch },
651 { "BBS1", 0x0000000, 0x9F, 0, PutBitBranch },
652 { "BBS2", 0x0000000, 0xAF, 0, PutBitBranch },
653 { "BBS3", 0x0000000, 0xBF, 0, PutBitBranch },
654 { "BBS4", 0x0000000, 0xCF, 0, PutBitBranch },
655 { "BBS5", 0x0000000, 0xDF, 0, PutBitBranch },
656 { "BBS6", 0x0000000, 0xEF, 0, PutBitBranch },
657 { "BBS7", 0x0000000, 0xFF, 0, PutBitBranch },
658 { "BCC", 0x0020000, 0x90, 0, PutPCRel8 },
659 { "BCS", 0x0020000, 0xb0, 0, PutPCRel8 },
660 { "BEQ", 0x0020000, 0xf0, 0, PutPCRel8 },
661 { "BIT", 0x0A0006C, 0x00, 2, PutAll },
662 { "BMI", 0x0020000, 0x30, 0, PutPCRel8 },
663 { "BNE", 0x0020000, 0xd0, 0, PutPCRel8 },
664 { "BPL", 0x0020000, 0x10, 0, PutPCRel8 },
665 { "BRA", 0x0020000, 0x80, 0, PutPCRel8 },
666 { "BRK", 0x0000001, 0x00, 0, PutAll },
667 { "BSR", 0x0020000, 0x44, 0, PutPCRel8 },
668 { "BVC", 0x0020000, 0x50, 0, PutPCRel8 },
669 { "BVS", 0x0020000, 0x70, 0, PutPCRel8 },
670 { "CLA", 0x0000001, 0x62, 0, PutAll },
671 { "CLC", 0x0000001, 0x18, 0, PutAll },
672 { "CLD", 0x0000001, 0xd8, 0, PutAll },
673 { "CLI", 0x0000001, 0x58, 0, PutAll },
674 { "CLV", 0x0000001, 0xb8, 0, PutAll },
675 { "CLX", 0x0000001, 0x82, 0, PutAll },
676 { "CLY", 0x0000001, 0xc2, 0, PutAll },
677 { "CMP", 0x080A66C, 0xc0, 0, PutAll },
678 { "CPX", 0x080000C, 0xe0, 1, PutAll },
679 { "CPY", 0x080000C, 0xc0, 1, PutAll },
680 { "CSH", 0x0000001, 0xd4, 0, PutAll },
681 { "CSL", 0x0000001, 0x54, 0, PutAll },
682 { "DEA", 0x0000001, 0x00, 3, PutAll }, /* == DEC */
683 { "DEC", 0x000006F, 0x00, 3, PutAll },
684 { "DEX", 0x0000001, 0xca, 0, PutAll },
685 { "DEY", 0x0000001, 0x88, 0, PutAll },
686 { "EOR", 0x080A66C, 0x40, 0, PutAll },
687 { "INA", 0x0000001, 0x00, 4, PutAll }, /* == INC */
688 { "INC", 0x000006f, 0x00, 4, PutAll },
689 { "INX", 0x0000001, 0xe8, 0, PutAll },
690 { "INY", 0x0000001, 0xc8, 0, PutAll },
691 { "JMP", 0x0010808, 0x4c, 6, PutAll },
692 { "JSR", 0x0000008, 0x20, 7, PutAll },
693 { "LDA", 0x080A66C, 0xa0, 0, PutAll },
694 { "LDX", 0x080030C, 0xa2, 1, PutAll },
695 { "LDY", 0x080006C, 0xa0, 1, PutAll },
696 { "LSR", 0x000006F, 0x42, 1, PutAll },
697 { "NOP", 0x0000001, 0xea, 0, PutAll },
698 { "ORA", 0x080A66C, 0x00, 0, PutAll },
699 { "PHA", 0x0000001, 0x48, 0, PutAll },
700 { "PHP", 0x0000001, 0x08, 0, PutAll },
701 { "PHX", 0x0000001, 0xda, 0, PutAll },
702 { "PHY", 0x0000001, 0x5a, 0, PutAll },
703 { "PLA", 0x0000001, 0x68, 0, PutAll },
704 { "PLP", 0x0000001, 0x28, 0, PutAll },
705 { "PLX", 0x0000001, 0xfa, 0, PutAll },
706 { "PLY", 0x0000001, 0x7a, 0, PutAll },
707 { "RMB0", 0x0000004, 0x07, 1, PutAll },
708 { "RMB1", 0x0000004, 0x17, 1, PutAll },
709 { "RMB2", 0x0000004, 0x27, 1, PutAll },
710 { "RMB3", 0x0000004, 0x37, 1, PutAll },
711 { "RMB4", 0x0000004, 0x47, 1, PutAll },
712 { "RMB5", 0x0000004, 0x57, 1, PutAll },
713 { "RMB6", 0x0000004, 0x67, 1, PutAll },
714 { "RMB7", 0x0000004, 0x77, 1, PutAll },
715 { "ROL", 0x000006F, 0x22, 1, PutAll },
716 { "ROR", 0x000006F, 0x62, 1, PutAll },
717 { "RTI", 0x0000001, 0x40, 0, PutAll },
718 { "RTS", 0x0000001, 0x60, 0, PutAll },
719 { "SBC", 0x080A66C, 0xe0, 0, PutAll },
720 { "SAX", 0x0000001, 0x22, 0, PutAll },
721 { "SAY", 0x0000001, 0x42, 0, PutAll },
722 { "SEC", 0x0000001, 0x38, 0, PutAll },
723 { "SED", 0x0000001, 0xf8, 0, PutAll },
724 { "SEI", 0x0000001, 0x78, 0, PutAll },
725 { "SET", 0x0000001, 0xf4, 0, PutAll },
726 { "SMB0", 0x0000004, 0x87, 1, PutAll },
727 { "SMB1", 0x0000004, 0x97, 1, PutAll },
728 { "SMB2", 0x0000004, 0xA7, 1, PutAll },
729 { "SMB3", 0x0000004, 0xB7, 1, PutAll },
730 { "SMB4", 0x0000004, 0xC7, 1, PutAll },
731 { "SMB5", 0x0000004, 0xD7, 1, PutAll },
732 { "SMB6", 0x0000004, 0xE7, 1, PutAll },
733 { "SMB7", 0x0000004, 0xF7, 1, PutAll },
734 { "ST0", 0x0800000, 0x03, 1, PutAll },
735 { "ST1", 0x0800000, 0x13, 1, PutAll },
736 { "ST2", 0x0800000, 0x23, 1, PutAll },
737 { "STA", 0x000A66C, 0x80, 0, PutAll },
738 { "STX", 0x000010c, 0x82, 1, PutAll },
739 { "STY", 0x000002c, 0x80, 1, PutAll },
740 { "STZ", 0x000006c, 0x04, 5, PutAll },
741 { "SXY", 0x0000001, 0x02, 0, PutAll },
742 { "TAI", 0x2000000, 0xf3, 0, PutBlockTransfer },
743 { "TAM", 0x0800000, 0x53, 1, PutAll },
744 { "TAM0", 0x0000001, 0x01, 0, PutTAMn},
745 { "TAM1", 0x0000001, 0x02, 0, PutTAMn},
746 { "TAM2", 0x0000001, 0x04, 0, PutTAMn},
747 { "TAM3", 0x0000001, 0x08, 0, PutTAMn},
748 { "TAM4", 0x0000001, 0x10, 0, PutTAMn},
749 { "TAM5", 0x0000001, 0x20, 0, PutTAMn},
750 { "TAM6", 0x0000001, 0x40, 0, PutTAMn},
751 { "TAM7", 0x0000001, 0x80, 0, PutTAMn},
752 { "TAX", 0x0000001, 0xaa, 0, PutAll },
753 { "TAY", 0x0000001, 0xa8, 0, PutAll },
754 { "TDD", 0x2000000, 0xc3, 0, PutBlockTransfer },
755 { "TIA", 0x2000000, 0xe3, 0, PutBlockTransfer },
756 { "TII", 0x2000000, 0x73, 0, PutBlockTransfer },
757 { "TIN", 0x2000000, 0xD3, 0, PutBlockTransfer },
758 { "TMA", 0x0800000, 0x43, 1, PutTMA },
759 { "TMA0", 0x0000001, 0x01, 0, PutTMAn},
760 { "TMA1", 0x0000001, 0x02, 0, PutTMAn},
761 { "TMA2", 0x0000001, 0x04, 0, PutTMAn},
762 { "TMA3", 0x0000001, 0x08, 0, PutTMAn},
763 { "TMA4", 0x0000001, 0x10, 0, PutTMAn},
764 { "TMA5", 0x0000001, 0x20, 0, PutTMAn},
765 { "TMA6", 0x0000001, 0x40, 0, PutTMAn},
766 { "TMA7", 0x0000001, 0x80, 0, PutTMAn},
767 { "TRB", 0x000000c, 0x10, 1, PutAll },
768 { "TSB", 0x000000c, 0x00, 1, PutAll },
769 { "TST", 0x000006c, 0x83, 9, PutTST },
770 { "TSX", 0x0000001, 0xba, 0, PutAll },
771 { "TXA", 0x0000001, 0x8a, 0, PutAll },
772 { "TXS", 0x0000001, 0x9a, 0, PutAll },
773 { "TYA", 0x0000001, 0x98, 0, PutAll }
779 /* An array with instruction tables */
780 static const InsTable* InsTabs[CPU_COUNT] = {
781 (const InsTable*) &InsTabNone,
782 (const InsTable*) &InsTab6502,
783 (const InsTable*) &InsTab6502X,
784 (const InsTable*) &InsTab65SC02,
785 (const InsTable*) &InsTab65C02,
786 (const InsTable*) &InsTab65816,
788 (const InsTable*) &InsTabSunPlus,
792 (const InsTable*) &InsTabSweet16,
793 (const InsTable*) &InsTabHuC6280,
795 const InsTable* InsTab = (const InsTable*) &InsTab6502;
797 /* Table to build the effective 65xx opcode from a base opcode and an
800 static unsigned char EATab[10][AM65I_COUNT] = {
802 0x00, 0x00, 0x05, 0x0D, 0x0F, 0x15, 0x1D, 0x1F,
803 0x00, 0x19, 0x12, 0x00, 0x07, 0x11, 0x17, 0x01,
804 0x00, 0x00, 0x00, 0x03, 0x13, 0x09, 0x00, 0x09,
808 0x08, 0x08, 0x04, 0x0C, 0x00, 0x14, 0x1C, 0x00,
809 0x14, 0x1C, 0x00, 0x80, 0x00, 0x10, 0x00, 0x00,
810 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
814 0x00, 0x00, 0x24, 0x2C, 0x0F, 0x34, 0x3C, 0x00,
815 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
816 0x00, 0x00, 0x00, 0x00, 0x00, 0x89, 0x00, 0x00,
820 0x3A, 0x3A, 0xC6, 0xCE, 0x00, 0xD6, 0xDE, 0x00,
821 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
822 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
826 0x1A, 0x1A, 0xE6, 0xEE, 0x00, 0xF6, 0xFE, 0x00,
827 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
828 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
832 0x00, 0x00, 0x60, 0x98, 0x00, 0x70, 0x9E, 0x00,
833 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
834 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
838 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
839 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00,
840 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
844 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
845 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
846 0xDC, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
850 0x00, 0x40, 0x01, 0x41, 0x00, 0x09, 0x49, 0x00,
851 0x00, 0x00, 0x00, 0x51, 0x00, 0x00, 0x00, 0x00,
852 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00,
856 0x00, 0x00, 0x00, 0x10, 0x00, 0x20, 0x30, 0x00,
857 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
858 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
863 /* Table to build the effective SWEET16 opcode from a base opcode and an
866 static unsigned char Sweet16EATab[2][AMSW16I_COUNT] = {
868 0x00, 0x00, 0x00, 0x00, 0x00,
871 0x00, 0x00, 0x00, 0x40, 0x20,
875 /* Table that encodes the additional bytes for each 65xx instruction */
876 unsigned char ExtBytes[AM65I_COUNT] = {
881 3, /* Absolute long */
884 3, /* Absolute long,X */
893 2, /* (Absolute,X) */
894 1, /* Relative short */
895 2, /* Relative long */
898 1, /* Immidiate accu */
899 1, /* Immidiate index */
900 1, /* Immidiate byte */
901 2, /* Blockmove (65816) */
902 7, /* Block transfer (HuC6280) */
905 /* Table that encodes the additional bytes for each SWEET16 instruction */
906 static unsigned char Sweet16ExtBytes[AMSW16I_COUNT] = {
916 /*****************************************************************************/
917 /* Handler functions for 6502 derivates */
918 /*****************************************************************************/
922 static int EvalEA (const InsDesc* Ins, EffAddr* A)
923 /* Evaluate the effective address. All fields in A will be valid after calling
924 * this function. The function returns true on success and false on errors.
927 /* Get the set of possible addressing modes */
930 /* From the possible addressing modes, remove the ones that are invalid
931 * for this instruction or CPU.
933 A->AddrModeSet &= Ins->AddrMode;
935 /* If we have an expression, check it and remove any addressing modes that
936 * are too small for the expression size. Since we have to study the
937 * expression anyway, do also replace it by a simpler one if possible.
943 /* Study the expression */
944 StudyExpr (A->Expr, &ED);
946 /* Simplify it if possible */
947 A->Expr = SimplifyExpr (A->Expr, &ED);
949 if (ED.AddrSize == ADDR_SIZE_DEFAULT) {
950 /* If we don't know how big the expression is, assume the
951 * default address size for data. If this default address
952 * size is unequal to zero page addressing, but zero page
953 * addressing is allowed by the instruction, mark all symbols
954 * in the expression tree. This mark will be checked at end
955 * of assembly, and a warning is issued, if a zero page symbol
956 * was guessed wrong here.
958 ED.AddrSize = DataAddrSize;
959 if (ED.AddrSize > ADDR_SIZE_ZP && (A->AddrModeSet & AM65_SET_ZP)) {
960 ExprGuessedAddrSize (A->Expr, ADDR_SIZE_ZP);
965 switch (ED.AddrSize) {
968 A->AddrModeSet &= ~AM65_SET_ZP;
972 A->AddrModeSet &= ~(AM65_SET_ZP | AM65_SET_ABS);
976 /* Free any resource associated with the expression desc */
980 /* Check if we have any adressing modes left */
981 if (A->AddrModeSet == 0) {
982 Error ("Illegal addressing mode");
985 A->AddrMode = BitFind (A->AddrModeSet);
986 A->AddrModeBit = (0x01UL << A->AddrMode);
988 /* If the instruction has a one byte operand and immediate addressing is
989 * allowed but not used, check for an operand expression in the form
990 * <label or >label, where label is a far or absolute label. If found,
991 * emit a warning. This warning protects against a typo, where the '#'
992 * for the immediate operand is omitted.
994 if (A->Expr && (Ins->AddrMode & AM65_IMM) &&
995 (A->AddrModeSet & (AM65_DIR | AM65_ABS | AM65_ABS_LONG)) &&
996 ExtBytes[A->AddrMode] == 1) {
998 /* Found, check the expression */
999 ExprNode* Left = A->Expr->Left;
1000 if ((A->Expr->Op == EXPR_BYTE0 || A->Expr->Op == EXPR_BYTE1) &&
1001 Left->Op == EXPR_SYMBOL &&
1002 GetSymAddrSize (Left->V.Sym) != ADDR_SIZE_ZP) {
1004 /* Output a warning */
1005 Warning (1, "Suspicious address expression");
1009 /* Build the opcode */
1010 A->Opcode = Ins->BaseCode | EATab[Ins->ExtCode][A->AddrMode];
1018 static void EmitCode (EffAddr* A)
1019 /* Output code for the data in A */
1021 /* Check how many extension bytes are needed and output the instruction */
1022 switch (ExtBytes[A->AddrMode]) {
1029 Emit1 (A->Opcode, A->Expr);
1033 if (CPU == CPU_65816 && (A->AddrModeBit & (AM65_ABS | AM65_ABS_X | AM65_ABS_Y))) {
1034 /* This is a 16 bit mode that uses an address. If in 65816,
1035 * mode, force this address into 16 bit range to allow
1036 * addressing inside a 64K segment.
1038 Emit2 (A->Opcode, GenWordExpr (A->Expr));
1040 Emit2 (A->Opcode, A->Expr);
1046 Emit3 (A->Opcode, A->Expr);
1050 Internal ("Invalid operand byte count: %u", ExtBytes[A->AddrMode]);
1057 static long PutImmed8 (const InsDesc* Ins)
1058 /* Parse and emit an immediate 8 bit instruction. Return the value of the
1059 * operand if it's available and const.
1065 /* Evaluate the addressing mode */
1066 if (EvalEA (Ins, &A) == 0) {
1067 /* An error occurred */
1071 /* If we have an expression and it's const, get it's value */
1073 (void) IsConstExpr (A.Expr, &Val);
1076 /* Check how many extension bytes are needed and output the instruction */
1077 switch (ExtBytes[A.AddrMode]) {
1080 Emit1 (A.Opcode, A.Expr);
1084 Internal ("Invalid operand byte count: %u", ExtBytes[A.AddrMode]);
1087 /* Return the expression value */
1093 static void PutPCRel8 (const InsDesc* Ins)
1094 /* Handle branches with a 8 bit distance */
1096 EmitPCRel (Ins->BaseCode, GenBranchExpr (2), 1);
1101 static void PutPCRel16 (const InsDesc* Ins)
1102 /* Handle branches with an 16 bit distance and PER */
1104 EmitPCRel (Ins->BaseCode, GenBranchExpr (3), 2);
1109 static void PutBlockMove (const InsDesc* Ins)
1110 /* Handle the blockmove instructions (65816) */
1112 Emit0 (Ins->BaseCode);
1113 EmitByte (Expression ());
1115 EmitByte (Expression ());
1120 static void PutBlockTransfer (const InsDesc* Ins)
1121 /* Handle the block transfer instructions (HuC6280) */
1123 Emit0 (Ins->BaseCode);
1124 EmitWord (Expression ());
1126 EmitWord (Expression ());
1128 EmitWord (Expression ());
1133 static void PutBitBranch (const InsDesc* Ins)
1134 /* Handle 65C02 branch on bit condition */
1136 Emit0 (Ins->BaseCode);
1137 EmitByte (Expression ());
1139 EmitSigned (GenBranchExpr (1), 1);
1144 static void PutREP (const InsDesc* Ins)
1145 /* Emit a REP instruction, track register sizes */
1147 /* Use the generic handler */
1148 long Val = PutImmed8 (Ins);
1150 /* We track the status only for the 816 CPU and in smart mode */
1151 if (CPU == CPU_65816 && SmartMode) {
1153 /* Check the range for Val. */
1155 /* We had an error */
1156 Warning (1, "Cannot track processor status byte");
1159 /* Index registers to 16 bit */
1160 ExtBytes[AM65I_IMM_INDEX] = 2;
1163 /* Accu to 16 bit */
1164 ExtBytes[AM65I_IMM_ACCU] = 2;
1172 static void PutSEP (const InsDesc* Ins)
1173 /* Emit a SEP instruction (65816), track register sizes */
1175 /* Use the generic handler */
1176 long Val = PutImmed8 (Ins);
1178 /* We track the status only for the 816 CPU and in smart mode */
1179 if (CPU == CPU_65816 && SmartMode) {
1181 /* Check the range for Val. */
1183 /* We had an error */
1184 Warning (1, "Cannot track processor status byte");
1187 /* Index registers to 8 bit */
1188 ExtBytes[AM65I_IMM_INDEX] = 1;
1192 ExtBytes[AM65I_IMM_ACCU] = 1;
1200 static void PutTAMn (const InsDesc* Ins)
1201 /* Emit a TAMn instruction (HuC6280). Since this is a two byte instruction with
1202 * implicit addressing mode, the opcode byte in the table is actually the
1203 * second operand byte. The TAM instruction is the more generic form, it takes
1204 * an immediate argument.
1207 /* Emit the TAM opcode itself */
1210 /* Emit the argument, which is the opcode from the table */
1211 Emit0 (Ins->BaseCode);
1216 static void PutTMA (const InsDesc* Ins)
1217 /* Emit a TMA instruction (HuC6280) with an immediate argument. Only one bit
1218 * in the argument byte may be set.
1221 /* Use the generic handler */
1222 long Val = PutImmed8 (Ins);
1224 /* Check the range for Val. */
1226 /* We had an error */
1227 Warning (1, "Cannot check argument of TMA instruction");
1229 /* Make sure just one bit is set */
1230 if ((Val & (Val - 1)) != 0) {
1231 Error ("Argument to TAM must be a power of two");
1238 static void PutTMAn (const InsDesc* Ins)
1239 /* Emit a TMAn instruction (HuC6280). Since this is a two byte instruction with
1240 * implicit addressing mode, the opcode byte in the table is actually the
1241 * second operand byte. The TAM instruction is the more generic form, it takes
1242 * an immediate argument.
1245 /* Emit the TMA opcode itself */
1248 /* Emit the argument, which is the opcode from the table */
1249 Emit0 (Ins->BaseCode);
1254 static void PutTST (const InsDesc* Ins)
1255 /* Emit a TST instruction (HuC6280). */
1260 /* The first argument is always an immediate byte */
1261 if (Tok != TOK_HASH) {
1262 ErrorSkip ("Invalid addressing mode");
1266 Arg1 = Expression ();
1268 /* Second argument follows */
1271 /* For the second argument, we use the standard function */
1272 if (EvalEA (Ins, &A)) {
1274 /* No error, output code */
1275 Emit1 (A.Opcode, Arg1);
1277 /* Check how many extension bytes are needed and output the instruction */
1278 switch (ExtBytes[A.AddrMode]) {
1293 static void PutJMP (const InsDesc* Ins)
1294 /* Handle the jump instruction for the 6502. Problem is that these chips have
1295 * a bug: If the address crosses a page, the upper byte gets not corrected and
1296 * the instruction will fail. The PutJmp function will add a linker assertion
1297 * to check for this case and is otherwise identical to PutAll.
1302 /* Evaluate the addressing mode used */
1303 if (EvalEA (Ins, &A)) {
1305 /* Check for indirect addressing */
1306 if (A.AddrModeBit & AM65_ABS_IND) {
1308 /* Compare the low byte of the expression to 0xFF to check for
1309 * a page cross. Be sure to use a copy of the expression otherwise
1310 * things will go weird later.
1312 ExprNode* E = GenNE (GenByteExpr (CloneExpr (A.Expr)), 0xFF);
1314 /* Generate the message */
1315 unsigned Msg = GetStringId ("\"jmp (abs)\" across page border");
1317 /* Generate the assertion */
1318 AddAssertion (E, ASSERT_ACT_WARN, Msg);
1321 /* No error, output code */
1328 static void PutRTS (const InsDesc* Ins attribute ((unused)))
1329 /* Handle the RTS instruction for the 816. In smart mode emit a RTL opcode if
1330 * the enclosing scope is FAR.
1333 if (SmartMode && CurrentScope->AddrSize == ADDR_SIZE_FAR) {
1334 Emit0 (0x6B); /* RTL */
1336 Emit0 (0x60); /* RTS */
1342 static void PutAll (const InsDesc* Ins)
1343 /* Handle all other instructions */
1347 /* Evaluate the addressing mode used */
1348 if (EvalEA (Ins, &A)) {
1349 /* No error, output code */
1356 /*****************************************************************************/
1357 /* Handler functions for SWEET16 */
1358 /*****************************************************************************/
1362 static void PutSweet16 (const InsDesc* Ins)
1363 /* Handle a generic sweet16 instruction */
1367 /* Evaluate the addressing mode used */
1370 /* From the possible addressing modes, remove the ones that are invalid
1371 * for this instruction or CPU.
1373 A.AddrModeSet &= Ins->AddrMode;
1375 /* Check if we have any adressing modes left */
1376 if (A.AddrModeSet == 0) {
1377 Error ("Illegal addressing mode");
1380 A.AddrMode = BitFind (A.AddrModeSet);
1381 A.AddrModeBit = (0x01UL << A.AddrMode);
1383 /* Build the opcode */
1384 A.Opcode = Ins->BaseCode | Sweet16EATab[Ins->ExtCode][A.AddrMode] | A.Reg;
1386 /* Check how many extension bytes are needed and output the instruction */
1387 switch (Sweet16ExtBytes[A.AddrMode]) {
1394 Emit1 (A.Opcode, A.Expr);
1398 Emit2 (A.Opcode, A.Expr);
1402 Internal ("Invalid operand byte count: %u", Sweet16ExtBytes[A.AddrMode]);
1409 static void PutSweet16Branch (const InsDesc* Ins)
1410 /* Handle a sweet16 branch instruction */
1412 EmitPCRel (Ins->BaseCode, GenBranchExpr (2), 1);
1417 /*****************************************************************************/
1419 /*****************************************************************************/
1423 static int CmpName (const void* Key, const void* Instr)
1424 /* Compare function for bsearch */
1426 return strcmp ((const char*)Key, ((const InsDesc*) Instr)->Mnemonic);
1431 void SetCPU (cpu_t NewCPU)
1434 /* Make sure the parameter is correct */
1435 CHECK (NewCPU < CPU_COUNT);
1437 /* Check if we have support for the new CPU, if so, use it */
1438 if (NewCPU != CPU_UNKNOWN && InsTabs[NewCPU]) {
1440 InsTab = InsTabs[CPU];
1442 Error ("CPU not supported");
1449 /* Return the current CPU */
1456 int FindInstruction (const StrBuf* Ident)
1457 /* Check if Ident is a valid mnemonic. If so, return the index in the
1458 * instruction table. If not, return -1.
1463 char Key[sizeof (ID->Mnemonic)];
1465 /* Shortcut for the "none" CPU: If there are no instructions to search
1466 * for, bail out early.
1468 if (InsTab->Count == 0) {
1473 /* Make a copy, and uppercase that copy */
1475 while (I < SB_GetLen (Ident)) {
1476 /* If the identifier is longer than the longest mnemonic, it cannot
1479 if (I >= sizeof (Key) - 1) {
1480 /* Not found, no need for further action */
1483 Key[I] = toupper ((unsigned char)SB_AtUnchecked (Ident, I));
1488 /* Search for the key */
1489 ID = bsearch (Key, InsTab->Ins, InsTab->Count, sizeof (InsDesc), CmpName);
1494 /* Found, return the entry */
1495 return ID - InsTab->Ins;
1501 void HandleInstruction (unsigned Index)
1502 /* Handle the mnemonic with the given index */
1505 PRECONDITION (Index < InsTab->Count);
1507 /* Skip the mnemonic token */
1510 /* Call the handler */
1511 InsTab->Ins[Index].Emit (&InsTab->Ins[Index]);