1 |
cebix |
1.1 |
/* |
2 |
|
|
* mon_6502.cpp - 6502 disassembler |
3 |
|
|
* |
4 |
|
|
* (C) 1997-1999 Christian Bauer |
5 |
|
|
*/ |
6 |
|
|
|
7 |
|
|
#include <stdio.h> |
8 |
|
|
|
9 |
|
|
#include "mon.h" |
10 |
|
|
#include "mon_6502.h" |
11 |
|
|
|
12 |
|
|
|
13 |
|
|
// Addressing modes |
14 |
|
|
enum { |
15 |
|
|
A_IMPL, |
16 |
|
|
A_ACCU, // A |
17 |
|
|
A_IMM, // #zz |
18 |
|
|
A_REL, // Branches |
19 |
|
|
A_ZERO, // zz |
20 |
|
|
A_ZEROX, // zz,x |
21 |
|
|
A_ZEROY, // zz,y |
22 |
|
|
A_ABS, // zzzz |
23 |
|
|
A_ABSX, // zzzz,x |
24 |
|
|
A_ABSY, // zzzz,y |
25 |
|
|
A_IND, // (zzzz) |
26 |
|
|
A_INDX, // (zz,x) |
27 |
|
|
A_INDY // (zz),y |
28 |
|
|
}; |
29 |
|
|
|
30 |
|
|
// Mnemonics |
31 |
|
|
enum { |
32 |
|
|
M_ADC, M_AND, M_ASL, M_BCC, M_BCS, M_BEQ, M_BIT, M_BMI, M_BNE, M_BPL, |
33 |
|
|
M_BRK, M_BVC, M_BVS, M_CLC, M_CLD, M_CLI, M_CLV, M_CMP, M_CPX, M_CPY, |
34 |
|
|
M_DEC, M_DEX, M_DEY, M_EOR, M_INC, M_INX, M_INY, M_JMP, M_JSR, M_LDA, |
35 |
|
|
M_LDX, M_LDY, M_LSR, M_NOP, M_ORA, M_PHA, M_PHP, M_PLA, M_PLP, M_ROL, |
36 |
|
|
M_ROR, M_RTI, M_RTS, M_SBC, M_SEC, M_SED, M_SEI, M_STA, M_STX, M_STY, |
37 |
|
|
M_TAX, M_TAY, M_TSX, M_TXA, M_TXS, M_TYA, |
38 |
|
|
|
39 |
|
|
M_ILLEGAL, // Undocumented opcodes start here |
40 |
|
|
|
41 |
|
|
M_IANC, M_IANE, M_IARR, M_IASR, M_IDCP, M_IISB, M_IJAM, M_INOP, M_ILAS, |
42 |
|
|
M_ILAX, M_ILXA, M_IRLA, M_IRRA, M_ISAX, M_ISBC, M_ISBX, M_ISHA, M_ISHS, |
43 |
|
|
M_ISHX, M_ISHY, M_ISLO, M_ISRE, |
44 |
|
|
|
45 |
|
|
M_MAXIMUM // Highest element |
46 |
|
|
}; |
47 |
|
|
|
48 |
|
|
// Mnemonic for each opcode |
49 |
|
|
static const char mnemonic[256] = { |
50 |
|
|
M_BRK , M_ORA , M_IJAM, M_ISLO, M_INOP, M_ORA, M_ASL , M_ISLO, // 00 |
51 |
|
|
M_PHP , M_ORA , M_ASL , M_IANC, M_INOP, M_ORA, M_ASL , M_ISLO, |
52 |
|
|
M_BPL , M_ORA , M_IJAM, M_ISLO, M_INOP, M_ORA, M_ASL , M_ISLO, // 10 |
53 |
|
|
M_CLC , M_ORA , M_INOP, M_ISLO, M_INOP, M_ORA, M_ASL , M_ISLO, |
54 |
|
|
M_JSR , M_AND , M_IJAM, M_IRLA, M_BIT , M_AND, M_ROL , M_IRLA, // 20 |
55 |
|
|
M_PLP , M_AND , M_ROL , M_IANC, M_BIT , M_AND, M_ROL , M_IRLA, |
56 |
|
|
M_BMI , M_AND , M_IJAM, M_IRLA, M_INOP, M_AND, M_ROL , M_IRLA, // 30 |
57 |
|
|
M_SEC , M_AND , M_INOP, M_IRLA, M_INOP, M_AND, M_ROL , M_IRLA, |
58 |
|
|
M_RTI , M_EOR , M_IJAM, M_ISRE, M_INOP, M_EOR, M_LSR , M_ISRE, // 40 |
59 |
|
|
M_PHA , M_EOR , M_LSR , M_IASR, M_JMP , M_EOR, M_LSR , M_ISRE, |
60 |
|
|
M_BVC , M_EOR , M_IJAM, M_ISRE, M_INOP, M_EOR, M_LSR , M_ISRE, // 50 |
61 |
|
|
M_CLI , M_EOR , M_INOP, M_ISRE, M_INOP, M_EOR, M_LSR , M_ISRE, |
62 |
|
|
M_RTS , M_ADC , M_IJAM, M_IRRA, M_INOP, M_ADC, M_ROR , M_IRRA, // 60 |
63 |
|
|
M_PLA , M_ADC , M_ROR , M_IARR, M_JMP , M_ADC, M_ROR , M_IRRA, |
64 |
|
|
M_BVS , M_ADC , M_IJAM, M_IRRA, M_INOP, M_ADC, M_ROR , M_IRRA, // 70 |
65 |
|
|
M_SEI , M_ADC , M_INOP, M_IRRA, M_INOP, M_ADC, M_ROR , M_IRRA, |
66 |
|
|
M_INOP, M_STA , M_INOP, M_ISAX, M_STY , M_STA, M_STX , M_ISAX, // 80 |
67 |
|
|
M_DEY , M_INOP, M_TXA , M_IANE, M_STY , M_STA, M_STX , M_ISAX, |
68 |
|
|
M_BCC , M_STA , M_IJAM, M_ISHA, M_STY , M_STA, M_STX , M_ISAX, // 90 |
69 |
|
|
M_TYA , M_STA , M_TXS , M_ISHS, M_ISHY, M_STA, M_ISHX, M_ISHA, |
70 |
|
|
M_LDY , M_LDA , M_LDX , M_ILAX, M_LDY , M_LDA, M_LDX , M_ILAX, // a0 |
71 |
|
|
M_TAY , M_LDA , M_TAX , M_ILXA, M_LDY , M_LDA, M_LDX , M_ILAX, |
72 |
|
|
M_BCS , M_LDA , M_IJAM, M_ILAX, M_LDY , M_LDA, M_LDX , M_ILAX, // b0 |
73 |
|
|
M_CLV , M_LDA , M_TSX , M_ILAS, M_LDY , M_LDA, M_LDX , M_ILAX, |
74 |
|
|
M_CPY , M_CMP , M_INOP, M_IDCP, M_CPY , M_CMP, M_DEC , M_IDCP, // c0 |
75 |
|
|
M_INY , M_CMP , M_DEX , M_ISBX, M_CPY , M_CMP, M_DEC , M_IDCP, |
76 |
|
|
M_BNE , M_CMP , M_IJAM, M_IDCP, M_INOP, M_CMP, M_DEC , M_IDCP, // d0 |
77 |
|
|
M_CLD , M_CMP , M_INOP, M_IDCP, M_INOP, M_CMP, M_DEC , M_IDCP, |
78 |
|
|
M_CPX , M_SBC , M_INOP, M_IISB, M_CPX , M_SBC, M_INC , M_IISB, // e0 |
79 |
|
|
M_INX , M_SBC , M_NOP , M_ISBC, M_CPX , M_SBC, M_INC , M_IISB, |
80 |
|
|
M_BEQ , M_SBC , M_IJAM, M_IISB, M_INOP, M_SBC, M_INC , M_IISB, // f0 |
81 |
|
|
M_SED , M_SBC , M_INOP, M_IISB, M_INOP, M_SBC, M_INC , M_IISB |
82 |
|
|
}; |
83 |
|
|
|
84 |
|
|
// Addressing mode for each opcode |
85 |
|
|
static const char adr_mode[256] = { |
86 |
|
|
A_IMPL, A_INDX, A_IMPL, A_INDX, A_ZERO , A_ZERO , A_ZERO , A_ZERO, // 00 |
87 |
|
|
A_IMPL, A_IMM , A_ACCU, A_IMM , A_ABS , A_ABS , A_ABS , A_ABS, |
88 |
|
|
A_REL , A_INDY, A_IMPL, A_INDY, A_ZEROX, A_ZEROX, A_ZEROX, A_ZEROX, // 10 |
89 |
|
|
A_IMPL, A_ABSY, A_IMPL, A_ABSY, A_ABSX , A_ABSX , A_ABSX , A_ABSX, |
90 |
|
|
A_ABS , A_INDX, A_IMPL, A_INDX, A_ZERO , A_ZERO , A_ZERO , A_ZERO, // 20 |
91 |
|
|
A_IMPL, A_IMM , A_ACCU, A_IMM , A_ABS , A_ABS , A_ABS , A_ABS, |
92 |
|
|
A_REL , A_INDY, A_IMPL, A_INDY, A_ZEROX, A_ZEROX, A_ZEROX, A_ZEROX, // 30 |
93 |
|
|
A_IMPL, A_ABSY, A_IMPL, A_ABSY, A_ABSX , A_ABSX , A_ABSX , A_ABSX, |
94 |
|
|
A_IMPL, A_INDX, A_IMPL, A_INDX, A_ZERO , A_ZERO , A_ZERO , A_ZERO, // 40 |
95 |
|
|
A_IMPL, A_IMM , A_ACCU, A_IMM , A_ABS , A_ABS , A_ABS , A_ABS, |
96 |
|
|
A_REL , A_INDY, A_IMPL, A_INDY, A_ZEROX, A_ZEROX, A_ZEROX, A_ZEROX, // 50 |
97 |
|
|
A_IMPL, A_ABSY, A_IMPL, A_ABSY, A_ABSX , A_ABSX , A_ABSX , A_ABSX, |
98 |
|
|
A_IMPL, A_INDX, A_IMPL, A_INDX, A_ZERO , A_ZERO , A_ZERO , A_ZERO, // 60 |
99 |
|
|
A_IMPL, A_IMM , A_ACCU, A_IMM , A_IND , A_ABS , A_ABS , A_ABS, |
100 |
|
|
A_REL , A_INDY, A_IMPL, A_INDY, A_ZEROX, A_ZEROX, A_ZEROX, A_ZEROX, // 70 |
101 |
|
|
A_IMPL, A_ABSY, A_IMPL, A_ABSY, A_ABSX , A_ABSX , A_ABSX , A_ABSX, |
102 |
|
|
A_IMM , A_INDX, A_IMM , A_INDX, A_ZERO , A_ZERO , A_ZERO , A_ZERO, // 80 |
103 |
|
|
A_IMPL, A_IMM , A_IMPL, A_IMM , A_ABS , A_ABS , A_ABS , A_ABS, |
104 |
|
|
A_REL , A_INDY, A_IMPL, A_INDY, A_ZEROX, A_ZEROX, A_ZEROY, A_ZEROY, // 90 |
105 |
|
|
A_IMPL, A_ABSY, A_IMPL, A_ABSY, A_ABSX , A_ABSX , A_ABSY , A_ABSY, |
106 |
|
|
A_IMM , A_INDX, A_IMM , A_INDX, A_ZERO , A_ZERO , A_ZERO , A_ZERO, // a0 |
107 |
|
|
A_IMPL, A_IMM , A_IMPL, A_IMM , A_ABS , A_ABS , A_ABS , A_ABS, |
108 |
|
|
A_REL , A_INDY, A_IMPL, A_INDY, A_ZEROX, A_ZEROX, A_ZEROY, A_ZEROY, // b0 |
109 |
|
|
A_IMPL, A_ABSY, A_IMPL, A_ABSY, A_ABSX , A_ABSX , A_ABSY , A_ABSY, |
110 |
|
|
A_IMM , A_INDX, A_IMM , A_INDX, A_ZERO , A_ZERO , A_ZERO , A_ZERO, // c0 |
111 |
|
|
A_IMPL, A_IMM , A_IMPL, A_IMM , A_ABS , A_ABS , A_ABS , A_ABS, |
112 |
|
|
A_REL , A_INDY, A_IMPL, A_INDY, A_ZEROX, A_ZEROX, A_ZEROX, A_ZEROX, // d0 |
113 |
|
|
A_IMPL, A_ABSY, A_IMPL, A_ABSY, A_ABSX , A_ABSX , A_ABSX , A_ABSX, |
114 |
|
|
A_IMM , A_INDX, A_IMM , A_INDX, A_ZERO , A_ZERO , A_ZERO , A_ZERO, // e0 |
115 |
|
|
A_IMPL, A_IMM , A_IMPL, A_IMM , A_ABS , A_ABS , A_ABS , A_ABS, |
116 |
|
|
A_REL , A_INDY, A_IMPL, A_INDY, A_ZEROX, A_ZEROX, A_ZEROX, A_ZEROX, // f0 |
117 |
|
|
A_IMPL, A_ABSY, A_IMPL, A_ABSY, A_ABSX , A_ABSX , A_ABSX , A_ABSX |
118 |
|
|
}; |
119 |
|
|
|
120 |
|
|
// Chars for each mnemonic |
121 |
|
|
static const char mnem_1[] = "aaabbbbbbbbbbcccccccdddeiiijjllllnopppprrrrssssssstttttt?aaaadijnlllrrsssssssss"; |
122 |
|
|
static const char mnem_2[] = "dnscceimnprvvllllmppeeeonnnmsdddsorhhlloottbeeetttaasxxy?nnrscsaoaaxlrabbhhhhlr"; |
123 |
|
|
static const char mnem_3[] = "cdlcsqtielkcscdivpxycxyrcxypraxyrpaapaplrisccdiaxyxyxasa?cerrpbmpsxaaaxcxasxyoe"; |
124 |
|
|
|
125 |
|
|
// Instruction length for each addressing mode |
126 |
|
|
static const char adr_length[] = {1, 1, 2, 2, 2, 2, 2, 3, 3, 3, 3, 2, 2}; |
127 |
|
|
|
128 |
|
|
|
129 |
|
|
/* |
130 |
|
|
* Disassemble one instruction, return number of bytes |
131 |
|
|
*/ |
132 |
|
|
|
133 |
|
|
int disass_6502(FILE *f, uint32 adr, uint8 op, uint8 lo, uint8 hi) |
134 |
|
|
{ |
135 |
|
|
char mode = adr_mode[op], mnem = mnemonic[op]; |
136 |
|
|
|
137 |
|
|
// Display instruction bytes in hex |
138 |
|
|
switch (adr_length[mode]) { |
139 |
|
|
case 1: |
140 |
|
|
fprintf(f, "%02x\t\t", op); |
141 |
|
|
break; |
142 |
|
|
|
143 |
|
|
case 2: |
144 |
|
|
fprintf(f, "%02x %02x\t\t", op, lo); |
145 |
|
|
break; |
146 |
|
|
|
147 |
|
|
case 3: |
148 |
|
|
fprintf(f, "%02x %02x %02x\t", op, lo, hi); |
149 |
|
|
break; |
150 |
|
|
} |
151 |
|
|
|
152 |
|
|
// Tag undocumented opcodes with an asterisk |
153 |
|
|
if (mnem > M_ILLEGAL) |
154 |
|
|
fputc('*', f); |
155 |
|
|
else |
156 |
|
|
fputc(' ', f); |
157 |
|
|
|
158 |
|
|
// Print mnemonic |
159 |
|
|
fprintf(f, "%c%c%c ", mnem_1[mnem], mnem_2[mnem], mnem_3[mnem]); |
160 |
|
|
|
161 |
|
|
// Print argument |
162 |
|
|
switch (mode) { |
163 |
|
|
case A_IMPL: |
164 |
|
|
break; |
165 |
|
|
|
166 |
|
|
case A_ACCU: |
167 |
|
|
fprintf(f, "a"); |
168 |
|
|
break; |
169 |
|
|
|
170 |
|
|
case A_IMM: |
171 |
|
|
fprintf(f, "#$%02x", lo); |
172 |
|
|
break; |
173 |
|
|
|
174 |
|
|
case A_REL: |
175 |
|
|
fprintf(f, "$%04lx", (adr + 2) + (int8)lo); |
176 |
|
|
break; |
177 |
|
|
|
178 |
|
|
case A_ZERO: |
179 |
|
|
fprintf(f, "$%02x", lo); |
180 |
|
|
break; |
181 |
|
|
|
182 |
|
|
case A_ZEROX: |
183 |
|
|
fprintf(f, "$%02x,x", lo); |
184 |
|
|
break; |
185 |
|
|
|
186 |
|
|
case A_ZEROY: |
187 |
|
|
fprintf(f, "$%02x,y", lo); |
188 |
|
|
break; |
189 |
|
|
|
190 |
|
|
case A_ABS: |
191 |
|
|
fprintf(f, "$%04x", (hi << 8) | lo); |
192 |
|
|
break; |
193 |
|
|
|
194 |
|
|
case A_ABSX: |
195 |
|
|
fprintf(f, "$%04x,x", (hi << 8) | lo); |
196 |
|
|
break; |
197 |
|
|
|
198 |
|
|
case A_ABSY: |
199 |
|
|
fprintf(f, "$%04x,y", (hi << 8) | lo); |
200 |
|
|
break; |
201 |
|
|
|
202 |
|
|
case A_IND: |
203 |
|
|
fprintf(f, "($%04x)", (hi << 8) | lo); |
204 |
|
|
break; |
205 |
|
|
|
206 |
|
|
case A_INDX: |
207 |
|
|
fprintf(f, "($%02x,x)", lo); |
208 |
|
|
break; |
209 |
|
|
|
210 |
|
|
case A_INDY: |
211 |
|
|
fprintf(f, "($%02x),y", lo); |
212 |
|
|
break; |
213 |
|
|
} |
214 |
|
|
|
215 |
|
|
fputc('\n', f); |
216 |
|
|
return adr_length[mode]; |
217 |
|
|
} |