Retirando os externs
[NesEmulator.git] / nes6502i.c
blobbdca8f736cb31e33b702c210f256fac020310fa0
2 #include "nes6502.h"
3 #include "nes6502i.h"
4 #include "utils.h"
6 /* Helper Definitions */
7 #define I_JS I_JP | I_ST
8 #define I_RW I_RD | I_WR
9 #define I_UR I_UN | I_RD
10 #define I_UW I_UN | I_WR
11 #define I_UM I_RD | I_WR | I_UN
12 #define I_UP I_UN | I_JP
14 /* Now for flags */
15 #define C_FLAG NES6502_C_FLAG
16 #define Z_FLAG NES6502_Z_FLAG
17 #define I_FLAG NES6502_I_FLAG
18 #define D_FLAG NES6502_D_FLAG
19 #define B_FLAG NES6502_B_FLAG
20 #define R_FLAG NES6502_R_FLAG
21 #define V_FLAG NES6502_V_FLAG
22 #define N_FLAG NES6502_N_FLAG
25 #define BI_FLAGS B_FLAG | I_FLAG
26 #define ZN_FLAGS Z_FLAG | N_FLAG
27 #define ZNV_FLAGS ZN_FLAGS | V_FLAG
28 #define CZN_FLAGS ZN_FLAGS | C_FLAG
29 #define CZNV_FLAGS CZN_FLAGS | V_FLAG
30 #define CZNVDI_FLAGS CZNV_FLAGS | D_FLAG | I_FLAG
31 #define ALL_FLAGS CZNVDI_FLAGS | B_FLAG
33 /* Now for registers */
34 #define R_AX R_A | R_X
35 #define R_AXS R_A | R_X | R_S
38 struct nes6502_instruction_detail nes6502_instructions[] = {
39 { "AAC", I_UN , 0 , R_A , CZN_FLAGS , 0 },
40 { "AAX", I_UW , 0 , R_AX , 0 , 0 },
41 { "ADC", I_RD , R_A , R_A , CZNV_FLAGS , C_FLAG },
42 { "AND", I_RD , R_A , R_A , ZN_FLAGS , 0 },
43 { "ARR", I_UN , R_A , R_A , CZNV_FLAGS , C_FLAG },
44 { "ASL", I_RW , 0 , 0 , CZN_FLAGS , 0 },
45 { "ASR", I_UN , R_A , R_A , CZN_FLAGS , 0 },
46 { "ATX", I_UN , R_AX, R_AX , ZN_FLAGS , 0 },
47 { "AXA", I_UW , 0 , R_AX , 0 , 0 },
48 { "AXS", I_UN , R_X , R_AX , CZN_FLAGS , 0 },
49 { "BCC", I_JP , 0 , 0 , 0 , C_FLAG },
50 { "BCS", I_JP , 0 , 0 , 0 , C_FLAG },
51 { "BEQ", I_JP , 0 , 0 , 0 , Z_FLAG },
52 { "BIT", I_RD , 0 , R_A , ZNV_FLAGS , 0 },
53 { "BMI", I_JP , 0 , 0 , 0 , N_FLAG },
54 { "BNE", I_JP , 0 , 0 , 0 , Z_FLAG },
55 { "BPL", I_JP , 0 , 0 , 0 , N_FLAG },
56 { "BRK", I_JS , 0 , 0 , BI_FLAGS , CZNVDI_FLAGS },
57 { "BVC", I_JP , 0 , 0 , 0 , V_FLAG },
58 { "BVS", I_JP , 0 , 0 , 0 , V_FLAG },
59 { "CLC", 0 , 0 , 0 , C_FLAG , 0 },
60 { "CLD", 0 , 0 , 0 , D_FLAG , 0 },
61 { "CLI", 0 , 0 , 0 , I_FLAG , 0 },
62 { "CLV", 0 , 0 , 0 , V_FLAG , 0 },
63 { "CMP", I_RD , 0 , R_A , CZN_FLAGS , 0 },
64 { "CPX", I_RD , 0 , R_X , CZN_FLAGS , 0 },
65 { "CPY", I_RD , 0 , R_Y , CZN_FLAGS , 0 },
66 { "DCP", I_UM , 0 , R_A , CZN_FLAGS , 0 },
67 { "DEC", I_RW , 0 , 0 , ZN_FLAGS , 0 },
68 { "DEX", I_RW , R_X , R_X , ZN_FLAGS , 0 },
69 { "DEY", I_RW , R_Y , R_Y , ZN_FLAGS , 0 },
70 { "DOP", I_UR , 0 , 0 , 0 , 0 },
71 { "EOR", I_RD , R_A , R_A , ZN_FLAGS , 0 },
72 { "HLT", I_UP , 0 , 0 , 0 , 0 },
73 { "INC", I_RW , 0 , 0 , ZN_FLAGS , 0 },
74 { "INX", I_RW , R_X , R_X , ZN_FLAGS , 0 },
75 { "INY", I_RW , R_Y , R_Y , ZN_FLAGS , 0 },
76 { "ISC", I_UM , R_A , R_A , CZNV_FLAGS , C_FLAG },
77 { "JMP", I_JP , 0 , 0 , 0 , 0 },
78 { "JSR", I_JS , 0 , 0 , 0 , 0 },
79 { "LAR", I_UR , R_AXS, R_S , ZN_FLAGS , 0 },
80 { "LAX", I_UR , R_AX, 0 , ZN_FLAGS , 0 },
81 { "LDA", I_RD , R_A , 0 , ZN_FLAGS , 0 },
82 { "LDX", I_RD , R_X , 0 , ZN_FLAGS , 0 },
83 { "LDY", I_RD , R_Y , 0 , ZN_FLAGS , 0 },
84 { "LSR", I_RW , 0 , 0 , CZN_FLAGS , 0 },
85 { "NOP", 0 , 0 , 0 , 0 , 0 },
86 { "ORA", I_RD , R_A , R_A , ZN_FLAGS , 0 },
87 { "PHA", I_ST , 0 , R_A , 0 , 0 },
88 { "PHP", I_ST , 0 , 0 , 0 , ALL_FLAGS },
89 { "PLA", I_ST , R_A , 0 , ZN_FLAGS , 0 },
90 { "PLP", I_ST , 0 , 0 , ALL_FLAGS , 0 },
91 { "RLA", I_UM , R_A , R_A , CZN_FLAGS , C_FLAG },
92 { "ROL", I_RW , 0 , 0 , CZN_FLAGS , C_FLAG },
93 { "ROR", I_RW , 0 , 0 , CZN_FLAGS , C_FLAG },
94 { "RRA", I_UM , R_A , R_A , CZNV_FLAGS , C_FLAG },
95 { "RTI", I_JS , 0 , 0 , ALL_FLAGS , 0 },
96 { "RTS", I_JS , 0 , 0 , 0 , 0 },
97 { "SBC", I_RD , R_A , R_A , CZNV_FLAGS , C_FLAG },
98 { "SEC", 0 , 0 , 0 , C_FLAG , 0 },
99 { "SED", 0 , 0 , 0 , D_FLAG , 0 },
100 { "SEI", 0 , 0 , 0 , I_FLAG , 0 },
101 { "SLO", I_UM , R_A , R_A , CZN_FLAGS , 0 },
102 { "SRE", I_UM , R_A , R_A , CZN_FLAGS , 0 },
103 { "STA", I_WR , 0 , R_A , 0 , 0 },
104 { "STX", I_WR , 0 , R_X , 0 , 0 },
105 { "STY", I_WR , 0 , R_Y , 0 , 0 },
106 { "SXA", I_UW , 0 , R_X , 0 , 0 },
107 { "SYA", I_UW , 0 , R_Y , 0 , 0 },
108 { "TAX", 0 , R_X , R_A , ZN_FLAGS , 0 },
109 { "TAY", 0 , R_Y , R_A , ZN_FLAGS , 0 },
110 { "TOP", I_UR , 0 , 0 , 0 , 0 },
111 { "TSX", 0 , R_X , R_S , ZN_FLAGS , 0 },
112 { "TXA", 0 , R_A , R_X , ZN_FLAGS , 0 },
113 { "TXS", 0 , R_S , R_X , 0 , 0 },
114 { "TYA", 0 , R_A , R_Y , ZN_FLAGS , 0 },
115 { "XAA", I_UN , R_A , R_AX , ZN_FLAGS , 0 },
116 { "XAS", I_UW , R_S , R_AX , 0 , 0 }
120 int nes6502_addressing_length[] = {
121 /* ADDR_ACCUMULATOR */ 1,
122 /* ADDR_IMMEDIATE */ 2,
123 /* ADDR_ZERO_PAGE */ 2,
124 /* ADDR_ZERO_PAGE_X */ 2,
125 /* ADDR_ZERO_PAGE_Y */ 2,
126 /* ADDR_ABSOLUTE */ 3,
127 /* ADDR_ABSOLUTE_X */ 3,
128 /* ADDR_ABSOLUTE_Y */ 3,
129 /* ADDR_INDIRECT */ 3,
130 /* ADDR_INDIRECT_X */ 2,
131 /* ADDR_INDIRECT_Y */ 2,
132 /* ADDR_RELATIVE */ 2,
133 /* ADDR_IMPLIED */ 1
136 struct nes6502_opcode nes6502_opcodes[] = {
137 {/* 0x00 */ ADDR_IMPLIED , INSN_BRK, 7},
138 {/* 0x01 */ ADDR_INDIRECT_X , INSN_ORA, 6},
139 {/* 0x02 */ ADDR_IMPLIED , INSN_HLT, 0},
140 {/* 0x03 */ ADDR_INDIRECT_X , INSN_SLO, 8},
141 {/* 0x04 */ ADDR_ZERO_PAGE , INSN_DOP, 3},
142 {/* 0x05 */ ADDR_ZERO_PAGE , INSN_ORA, 3},
143 {/* 0x06 */ ADDR_ZERO_PAGE , INSN_ASL, 5},
144 {/* 0x07 */ ADDR_ZERO_PAGE , INSN_SLO, 5},
145 {/* 0x08 */ ADDR_IMPLIED , INSN_PHP, 3},
146 {/* 0x09 */ ADDR_IMMEDIATE , INSN_ORA, 2},
147 {/* 0x0a */ ADDR_ACCUMULATOR , INSN_ASL, 2},
148 {/* 0x0b */ ADDR_IMMEDIATE , INSN_AAC, 2},
149 {/* 0x0c */ ADDR_ABSOLUTE , INSN_TOP, 4},
150 {/* 0x0d */ ADDR_ABSOLUTE , INSN_ORA, 4},
151 {/* 0x0e */ ADDR_ABSOLUTE , INSN_ASL, 6},
152 {/* 0x0f */ ADDR_ABSOLUTE , INSN_SLO, 6},
153 {/* 0x10 */ ADDR_RELATIVE , INSN_BPL, 2},
154 {/* 0x11 */ ADDR_INDIRECT_Y , INSN_ORA, 5},
155 {/* 0x12 */ ADDR_IMPLIED , INSN_HLT, 0},
156 {/* 0x13 */ ADDR_INDIRECT_Y , INSN_SLO, 8},
157 {/* 0x14 */ ADDR_ZERO_PAGE_X , INSN_DOP, 4},
158 {/* 0x15 */ ADDR_ZERO_PAGE_X , INSN_ORA, 4},
159 {/* 0x16 */ ADDR_ZERO_PAGE_X , INSN_ASL, 6},
160 {/* 0x17 */ ADDR_ZERO_PAGE_X , INSN_SLO, 6},
161 {/* 0x18 */ ADDR_IMPLIED , INSN_CLC, 2},
162 {/* 0x19 */ ADDR_ABSOLUTE_Y , INSN_ORA, 4},
163 {/* 0x1a */ ADDR_IMPLIED , INSN_NOP, 2},
164 {/* 0x1b */ ADDR_ABSOLUTE_Y , INSN_SLO, 7},
165 {/* 0x1c */ ADDR_ABSOLUTE_X , INSN_TOP, 4},
166 {/* 0x1d */ ADDR_ABSOLUTE_X , INSN_ORA, 4},
167 {/* 0x1e */ ADDR_ABSOLUTE_X , INSN_ASL, 7},
168 {/* 0x1f */ ADDR_ABSOLUTE_X , INSN_SLO, 7},
169 {/* 0x20 */ ADDR_ABSOLUTE , INSN_JSR, 6},
170 {/* 0x21 */ ADDR_INDIRECT_X , INSN_AND, 6},
171 {/* 0x22 */ ADDR_IMPLIED , INSN_HLT, 0},
172 {/* 0x23 */ ADDR_INDIRECT_X , INSN_RLA, 8},
173 {/* 0x24 */ ADDR_ZERO_PAGE , INSN_BIT, 3},
174 {/* 0x25 */ ADDR_ZERO_PAGE , INSN_AND, 3},
175 {/* 0x26 */ ADDR_ZERO_PAGE , INSN_ROL, 5},
176 {/* 0x27 */ ADDR_ZERO_PAGE , INSN_RLA, 5},
177 {/* 0x28 */ ADDR_IMPLIED , INSN_PLP, 4},
178 {/* 0x29 */ ADDR_IMMEDIATE , INSN_AND, 2},
179 {/* 0x2a */ ADDR_ACCUMULATOR , INSN_ROL, 2},
180 {/* 0x2b */ ADDR_IMMEDIATE , INSN_AAC, 2},
181 {/* 0x2c */ ADDR_ABSOLUTE , INSN_BIT, 4},
182 {/* 0x2d */ ADDR_ABSOLUTE , INSN_AND, 4},
183 {/* 0x2e */ ADDR_ABSOLUTE , INSN_ROL, 6},
184 {/* 0x2f */ ADDR_ABSOLUTE , INSN_RLA, 6},
185 {/* 0x30 */ ADDR_RELATIVE , INSN_BMI, 2},
186 {/* 0x31 */ ADDR_INDIRECT_Y , INSN_AND, 5},
187 {/* 0x32 */ ADDR_IMPLIED , INSN_HLT, 0},
188 {/* 0x33 */ ADDR_INDIRECT_Y , INSN_RLA, 8},
189 {/* 0x34 */ ADDR_ZERO_PAGE_X , INSN_DOP, 4},
190 {/* 0x35 */ ADDR_ZERO_PAGE_X , INSN_AND, 4},
191 {/* 0x36 */ ADDR_ZERO_PAGE_X , INSN_ROL, 6},
192 {/* 0x37 */ ADDR_ZERO_PAGE_X , INSN_RLA, 6},
193 {/* 0x38 */ ADDR_IMPLIED , INSN_SEC, 2},
194 {/* 0x39 */ ADDR_ABSOLUTE_Y , INSN_AND, 4},
195 {/* 0x3a */ ADDR_IMPLIED , INSN_NOP, 2},
196 {/* 0x3b */ ADDR_ABSOLUTE_Y , INSN_RLA, 7},
197 {/* 0x3c */ ADDR_ABSOLUTE_X , INSN_TOP, 4},
198 {/* 0x3d */ ADDR_ABSOLUTE_X , INSN_AND, 4},
199 {/* 0x3e */ ADDR_ABSOLUTE_X , INSN_ROL, 7},
200 {/* 0x3f */ ADDR_ABSOLUTE_X , INSN_RLA, 7},
201 {/* 0x40 */ ADDR_IMPLIED , INSN_RTI, 6},
202 {/* 0x41 */ ADDR_INDIRECT_X , INSN_EOR, 6},
203 {/* 0x42 */ ADDR_IMPLIED , INSN_HLT, 0},
204 {/* 0x43 */ ADDR_INDIRECT_X , INSN_SRE, 8},
205 {/* 0x44 */ ADDR_ZERO_PAGE , INSN_DOP, 3},
206 {/* 0x45 */ ADDR_ZERO_PAGE , INSN_EOR, 3},
207 {/* 0x46 */ ADDR_ZERO_PAGE , INSN_LSR, 5},
208 {/* 0x47 */ ADDR_ZERO_PAGE , INSN_SRE, 5},
209 {/* 0x48 */ ADDR_IMPLIED , INSN_PHA, 3},
210 {/* 0x49 */ ADDR_IMMEDIATE , INSN_EOR, 2},
211 {/* 0x4a */ ADDR_ACCUMULATOR , INSN_LSR, 2},
212 {/* 0x4b */ ADDR_IMMEDIATE , INSN_ASR, 2},
213 {/* 0x4c */ ADDR_ABSOLUTE , INSN_JMP, 3},
214 {/* 0x4d */ ADDR_ABSOLUTE , INSN_EOR, 4},
215 {/* 0x4e */ ADDR_ABSOLUTE , INSN_LSR, 6},
216 {/* 0x4f */ ADDR_ABSOLUTE , INSN_SRE, 6},
217 {/* 0x50 */ ADDR_RELATIVE , INSN_BVC, 2},
218 {/* 0x51 */ ADDR_INDIRECT_Y , INSN_EOR, 5},
219 {/* 0x52 */ ADDR_IMPLIED , INSN_HLT, 0},
220 {/* 0x53 */ ADDR_INDIRECT_Y , INSN_SRE, 8},
221 {/* 0x54 */ ADDR_ZERO_PAGE_X , INSN_DOP, 4},
222 {/* 0x55 */ ADDR_ZERO_PAGE_X , INSN_EOR, 4},
223 {/* 0x56 */ ADDR_ZERO_PAGE_X , INSN_LSR, 6},
224 {/* 0x57 */ ADDR_ZERO_PAGE_X , INSN_SRE, 6},
225 {/* 0x58 */ ADDR_IMPLIED , INSN_CLI, 2},
226 {/* 0x59 */ ADDR_ABSOLUTE_Y , INSN_EOR, 4},
227 {/* 0x5a */ ADDR_IMPLIED , INSN_NOP, 2},
228 {/* 0x5b */ ADDR_ABSOLUTE_Y , INSN_SRE, 7},
229 {/* 0x5c */ ADDR_ABSOLUTE_X , INSN_TOP, 4},
230 {/* 0x5d */ ADDR_ABSOLUTE_X , INSN_EOR, 4},
231 {/* 0x5e */ ADDR_ABSOLUTE_X , INSN_LSR, 7},
232 {/* 0x5f */ ADDR_ABSOLUTE_X , INSN_SRE, 7},
233 {/* 0x60 */ ADDR_IMPLIED , INSN_RTS, 6},
234 {/* 0x61 */ ADDR_INDIRECT_X , INSN_ADC, 6},
235 {/* 0x62 */ ADDR_IMPLIED , INSN_HLT, 0},
236 {/* 0x63 */ ADDR_INDIRECT_X , INSN_RRA, 8},
237 {/* 0x64 */ ADDR_ZERO_PAGE , INSN_DOP, 3},
238 {/* 0x65 */ ADDR_ZERO_PAGE , INSN_ADC, 3},
239 {/* 0x66 */ ADDR_ZERO_PAGE , INSN_ROR, 5},
240 {/* 0x67 */ ADDR_ZERO_PAGE , INSN_RRA, 5},
241 {/* 0x68 */ ADDR_IMPLIED , INSN_PLA, 4},
242 {/* 0x69 */ ADDR_IMMEDIATE , INSN_ADC, 2},
243 {/* 0x6a */ ADDR_ACCUMULATOR , INSN_ROR, 2},
244 {/* 0x6b */ ADDR_IMMEDIATE , INSN_ARR, 2},
245 {/* 0x6c */ ADDR_INDIRECT , INSN_JMP, 5},
246 {/* 0x6d */ ADDR_ABSOLUTE , INSN_ADC, 4},
247 {/* 0x6e */ ADDR_ABSOLUTE , INSN_ROR, 6},
248 {/* 0x6f */ ADDR_ABSOLUTE , INSN_RRA, 6},
249 {/* 0x70 */ ADDR_RELATIVE , INSN_BVS, 2},
250 {/* 0x71 */ ADDR_INDIRECT_Y , INSN_ADC, 5},
251 {/* 0x72 */ ADDR_IMPLIED , INSN_HLT, 0},
252 {/* 0x73 */ ADDR_INDIRECT_Y , INSN_RRA, 8},
253 {/* 0x74 */ ADDR_ZERO_PAGE_X , INSN_DOP, 4},
254 {/* 0x75 */ ADDR_ZERO_PAGE_X , INSN_ADC, 4},
255 {/* 0x76 */ ADDR_ZERO_PAGE_X , INSN_ROR, 6},
256 {/* 0x77 */ ADDR_ZERO_PAGE_X , INSN_RRA, 6},
257 {/* 0x78 */ ADDR_IMPLIED , INSN_SEI, 2},
258 {/* 0x79 */ ADDR_ABSOLUTE_Y , INSN_ADC, 4},
259 {/* 0x7a */ ADDR_IMPLIED , INSN_NOP, 2},
260 {/* 0x7b */ ADDR_ABSOLUTE_Y , INSN_RRA, 7},
261 {/* 0x7c */ ADDR_ABSOLUTE_X , INSN_TOP, 4},
262 {/* 0x7d */ ADDR_ABSOLUTE_X , INSN_ADC, 4},
263 {/* 0x7e */ ADDR_ABSOLUTE_X , INSN_ROR, 7},
264 {/* 0x7f */ ADDR_ABSOLUTE_X , INSN_RRA, 7},
265 {/* 0x80 */ ADDR_IMMEDIATE , INSN_DOP, 2},
266 {/* 0x81 */ ADDR_INDIRECT_X , INSN_STA, 6},
267 {/* 0x82 */ ADDR_IMMEDIATE , INSN_DOP, 2},
268 {/* 0x83 */ ADDR_INDIRECT_X , INSN_AAX, 6},
269 {/* 0x84 */ ADDR_ZERO_PAGE , INSN_STY, 3},
270 {/* 0x85 */ ADDR_ZERO_PAGE , INSN_STA, 3},
271 {/* 0x86 */ ADDR_ZERO_PAGE , INSN_STX, 3},
272 {/* 0x87 */ ADDR_ZERO_PAGE , INSN_AAX, 3},
273 {/* 0x88 */ ADDR_IMPLIED , INSN_DEY, 2},
274 {/* 0x89 */ ADDR_IMMEDIATE , INSN_DOP, 2},
275 {/* 0x8a */ ADDR_IMPLIED , INSN_TXA, 2},
276 {/* 0x8b */ ADDR_IMMEDIATE , INSN_XAA, 2},
277 {/* 0x8c */ ADDR_ABSOLUTE , INSN_STY, 4},
278 {/* 0x8d */ ADDR_ABSOLUTE , INSN_STA, 4},
279 {/* 0x8e */ ADDR_ABSOLUTE , INSN_STX, 4},
280 {/* 0x8f */ ADDR_ABSOLUTE , INSN_AAX, 4},
281 {/* 0x90 */ ADDR_RELATIVE , INSN_BCC, 2},
282 {/* 0x91 */ ADDR_INDIRECT_Y , INSN_STA, 6},
283 {/* 0x92 */ ADDR_IMPLIED , INSN_HLT, 0},
284 {/* 0x93 */ ADDR_INDIRECT_Y , INSN_AXA, 6},
285 {/* 0x94 */ ADDR_ZERO_PAGE_X , INSN_STY, 4},
286 {/* 0x95 */ ADDR_ZERO_PAGE_X , INSN_STA, 4},
287 {/* 0x96 */ ADDR_ZERO_PAGE_Y , INSN_STX, 4},
288 {/* 0x97 */ ADDR_ZERO_PAGE_Y , INSN_AAX, 4},
289 {/* 0x98 */ ADDR_IMPLIED , INSN_TYA, 2},
290 {/* 0x99 */ ADDR_ABSOLUTE_Y , INSN_STA, 5},
291 {/* 0x9a */ ADDR_IMPLIED , INSN_TXS, 2},
292 {/* 0x9b */ ADDR_ABSOLUTE_Y , INSN_XAS, 5},
293 {/* 0x9c */ ADDR_ABSOLUTE_X , INSN_SYA, 5},
294 {/* 0x9d */ ADDR_ABSOLUTE_X , INSN_STA, 5},
295 {/* 0x9e */ ADDR_ABSOLUTE_Y , INSN_SXA, 5},
296 {/* 0x9f */ ADDR_ABSOLUTE_Y , INSN_AXA, 5},
297 {/* 0xa0 */ ADDR_IMMEDIATE , INSN_LDY, 2},
298 {/* 0xa1 */ ADDR_INDIRECT_X , INSN_LDA, 6},
299 {/* 0xa2 */ ADDR_IMMEDIATE , INSN_LDX, 2},
300 {/* 0xa3 */ ADDR_INDIRECT_X , INSN_LAX, 6},
301 {/* 0xa4 */ ADDR_ZERO_PAGE , INSN_LDY, 3},
302 {/* 0xa5 */ ADDR_ZERO_PAGE , INSN_LDA, 3},
303 {/* 0xa6 */ ADDR_ZERO_PAGE , INSN_LDX, 3},
304 {/* 0xa7 */ ADDR_ZERO_PAGE , INSN_LAX, 3},
305 {/* 0xa8 */ ADDR_IMPLIED , INSN_TAY, 2},
306 {/* 0xa9 */ ADDR_IMMEDIATE , INSN_LDA, 2},
307 {/* 0xaa */ ADDR_IMPLIED , INSN_TAX, 2},
308 {/* 0xab */ ADDR_IMMEDIATE , INSN_ATX, 2},
309 {/* 0xac */ ADDR_ABSOLUTE , INSN_LDY, 4},
310 {/* 0xad */ ADDR_ABSOLUTE , INSN_LDA, 4},
311 {/* 0xae */ ADDR_ABSOLUTE , INSN_LDX, 4},
312 {/* 0xaf */ ADDR_ABSOLUTE , INSN_LAX, 4},
313 {/* 0xb0 */ ADDR_RELATIVE , INSN_BCS, 2},
314 {/* 0xb1 */ ADDR_INDIRECT_Y , INSN_LDA, 5},
315 {/* 0xb2 */ ADDR_IMPLIED , INSN_HLT, 0},
316 {/* 0xb3 */ ADDR_INDIRECT_Y , INSN_LAX, 5},
317 {/* 0xb4 */ ADDR_ZERO_PAGE_X , INSN_LDY, 4},
318 {/* 0xb5 */ ADDR_ZERO_PAGE_X , INSN_LDA, 4},
319 {/* 0xb6 */ ADDR_ZERO_PAGE_Y , INSN_LDX, 4},
320 {/* 0xb7 */ ADDR_ZERO_PAGE_Y , INSN_LAX, 4},
321 {/* 0xb8 */ ADDR_IMPLIED , INSN_CLV, 2},
322 {/* 0xb9 */ ADDR_ABSOLUTE_Y , INSN_LDA, 4},
323 {/* 0xba */ ADDR_IMPLIED , INSN_TSX, 2},
324 {/* 0xbb */ ADDR_ABSOLUTE_Y , INSN_LAR, 4},
325 {/* 0xbc */ ADDR_ABSOLUTE_X , INSN_LDY, 4},
326 {/* 0xbd */ ADDR_ABSOLUTE_X , INSN_LDA, 4},
327 {/* 0xbe */ ADDR_ABSOLUTE_Y , INSN_LDX, 4},
328 {/* 0xbf */ ADDR_ABSOLUTE_Y , INSN_LAX, 4},
329 {/* 0xc0 */ ADDR_IMMEDIATE , INSN_CPY, 2},
330 {/* 0xc1 */ ADDR_INDIRECT_X , INSN_CMP, 6},
331 {/* 0xc2 */ ADDR_IMMEDIATE , INSN_DOP, 2},
332 {/* 0xc3 */ ADDR_INDIRECT_X , INSN_DCP, 8},
333 {/* 0xc4 */ ADDR_ZERO_PAGE , INSN_CPY, 3},
334 {/* 0xc5 */ ADDR_ZERO_PAGE , INSN_CMP, 3},
335 {/* 0xc6 */ ADDR_ZERO_PAGE , INSN_DEC, 5},
336 {/* 0xc7 */ ADDR_ZERO_PAGE , INSN_DCP, 5},
337 {/* 0xc8 */ ADDR_IMPLIED , INSN_INY, 2},
338 {/* 0xc9 */ ADDR_IMMEDIATE , INSN_CMP, 2},
339 {/* 0xca */ ADDR_IMPLIED , INSN_DEX, 2},
340 {/* 0xcb */ ADDR_IMMEDIATE , INSN_AXS, 2},
341 {/* 0xcc */ ADDR_ABSOLUTE , INSN_CPY, 4},
342 {/* 0xcd */ ADDR_ABSOLUTE , INSN_CMP, 4},
343 {/* 0xce */ ADDR_ABSOLUTE , INSN_DEC, 6},
344 {/* 0xcf */ ADDR_ABSOLUTE , INSN_DCP, 6},
345 {/* 0xd0 */ ADDR_RELATIVE , INSN_BNE, 2},
346 {/* 0xd1 */ ADDR_INDIRECT_Y , INSN_CMP, 5},
347 {/* 0xd2 */ ADDR_IMPLIED , INSN_HLT, 0},
348 {/* 0xd3 */ ADDR_INDIRECT_Y , INSN_DCP, 8},
349 {/* 0xd4 */ ADDR_ZERO_PAGE_X , INSN_DOP, 4},
350 {/* 0xd5 */ ADDR_ZERO_PAGE_X , INSN_CMP, 4},
351 {/* 0xd6 */ ADDR_ZERO_PAGE_X , INSN_DEC, 6},
352 {/* 0xd7 */ ADDR_ZERO_PAGE_X , INSN_DCP, 6},
353 {/* 0xd8 */ ADDR_IMPLIED , INSN_CLD, 2},
354 {/* 0xd9 */ ADDR_ABSOLUTE_Y , INSN_CMP, 4},
355 {/* 0xda */ ADDR_IMPLIED , INSN_NOP, 2},
356 {/* 0xdb */ ADDR_ABSOLUTE_Y , INSN_DCP, 7},
357 {/* 0xdc */ ADDR_ABSOLUTE_X , INSN_TOP, 4},
358 {/* 0xdd */ ADDR_ABSOLUTE_X , INSN_CMP, 4},
359 {/* 0xde */ ADDR_ABSOLUTE_X , INSN_DEC, 7},
360 {/* 0xdf */ ADDR_ABSOLUTE_X , INSN_DCP, 7},
361 {/* 0xe0 */ ADDR_IMMEDIATE , INSN_CPX, 2},
362 {/* 0xe1 */ ADDR_INDIRECT_X , INSN_SBC, 6},
363 {/* 0xe2 */ ADDR_IMMEDIATE , INSN_DOP, 2},
364 {/* 0xe3 */ ADDR_INDIRECT_X , INSN_ISC, 8},
365 {/* 0xe4 */ ADDR_ZERO_PAGE , INSN_CPX, 3},
366 {/* 0xe5 */ ADDR_ZERO_PAGE , INSN_SBC, 3},
367 {/* 0xe6 */ ADDR_ZERO_PAGE , INSN_INC, 5},
368 {/* 0xe7 */ ADDR_ZERO_PAGE , INSN_ISC, 5},
369 {/* 0xe8 */ ADDR_IMPLIED , INSN_INX, 2},
370 {/* 0xe9 */ ADDR_IMMEDIATE , INSN_SBC, 2},
371 {/* 0xea */ ADDR_IMPLIED , INSN_NOP, 2},
372 {/* 0xeb */ ADDR_IMMEDIATE , INSN_SBC, 2},
373 {/* 0xec */ ADDR_ABSOLUTE , INSN_CPX, 4},
374 {/* 0xed */ ADDR_ABSOLUTE , INSN_SBC, 4},
375 {/* 0xee */ ADDR_ABSOLUTE , INSN_INC, 6},
376 {/* 0xef */ ADDR_ABSOLUTE , INSN_ISC, 6},
377 {/* 0xf0 */ ADDR_RELATIVE , INSN_BEQ, 2},
378 {/* 0xf1 */ ADDR_INDIRECT_Y , INSN_SBC, 5},
379 {/* 0xf2 */ ADDR_IMPLIED , INSN_HLT, 0},
380 {/* 0xf3 */ ADDR_INDIRECT_Y , INSN_ISC, 8},
381 {/* 0xf4 */ ADDR_ZERO_PAGE_X , INSN_DOP, 4},
382 {/* 0xf5 */ ADDR_ZERO_PAGE_X , INSN_SBC, 4},
383 {/* 0xf6 */ ADDR_ZERO_PAGE_X , INSN_INC, 6},
384 {/* 0xf7 */ ADDR_ZERO_PAGE_X , INSN_ISC, 6},
385 {/* 0xf8 */ ADDR_IMPLIED , INSN_SED, 2},
386 {/* 0xf9 */ ADDR_ABSOLUTE_Y , INSN_SBC, 4},
387 {/* 0xfa */ ADDR_IMPLIED , INSN_NOP, 2},
388 {/* 0xfb */ ADDR_ABSOLUTE_Y , INSN_ISC, 7},
389 {/* 0xfc */ ADDR_ABSOLUTE_X , INSN_TOP, 4},
390 {/* 0xfd */ ADDR_ABSOLUTE_X , INSN_SBC, 4},
391 {/* 0xfe */ ADDR_ABSOLUTE_X , INSN_INC, 7},
392 {/* 0xff */ ADDR_ABSOLUTE_X , INSN_ISC, 7}
396 uint32 nes6502_disassemble (uint8 *mem, uint32 offset, int count)
398 uint32 pos = 0;
399 while (count--) {
400 struct nes6502_opcode *opcode;
401 enum nes6502_instruction insn;
402 uint32 oper, address;
403 uint8 opc;
405 opc = mem[pos++];
406 opcode = &nes6502_opcodes[opc];
407 insn = opcode->instruction;
409 report ("$%04X: [ $%02X ", offset, opc);
410 switch (nes6502_addressing_length[opcode->addressing]) {
411 case 1: report ("] "); break;
412 case 2: report ("$%02X ] ", mem[pos]); break;
413 case 3: report ("$%02X $%02X ] ", mem[pos], mem[pos + 1]); break;
416 report ("%s ", nes6502_instructions[insn].name);
417 offset += nes6502_addressing_length[opcode->addressing];
419 switch (opcode->addressing) {
420 case ADDR_ACCUMULATOR:
421 report (" A\n");
422 break;
423 case ADDR_IMMEDIATE:
424 report ("#$%02X\n", mem[pos++]);
425 break;
426 case ADDR_ZERO_PAGE:
427 report (" $%02X\n", mem[pos++]);
428 break;
429 case ADDR_ZERO_PAGE_X:
430 report (" $%02X, X\n", mem[pos++]);
431 break;
432 case ADDR_ZERO_PAGE_Y:
433 report (" $%02X, Y\n", mem[pos++]);
434 break;
435 case ADDR_ABSOLUTE:
436 oper = (uint32) mem[pos++];
437 oper += ((uint32) mem[pos++]) << 8;
438 report (" $%04X\n", oper);
439 break;
440 case ADDR_ABSOLUTE_X:
441 oper = (uint32) mem[pos++];
442 oper += ((uint32) mem[pos++]) << 8;
443 report (" $%04X, X\n", oper);
444 break;
445 case ADDR_ABSOLUTE_Y:
446 oper = (uint32) mem[pos++];
447 oper += ((uint32) mem[pos++]) << 8;
448 report (" $%04X, Y\n", oper);
449 break;
450 case ADDR_INDIRECT:
451 oper = (uint32) mem[pos++];
452 oper += ((uint32) mem[pos++]) << 8;
453 report ("($%04X)\n", oper);
454 break;
455 case ADDR_INDIRECT_X:
456 report ("($%02X, X)\n", mem[pos++]);
457 break;
458 case ADDR_INDIRECT_Y:
459 report ("($%02X), Y\n", mem[pos++]);
460 break;
461 case ADDR_RELATIVE:
462 address = mem[pos++];
463 if (address & 0x80) address |= 0xFF00;
464 address = (address + offset) & 0xFFFF;
465 report (" $%04X\n", address);
466 break;
467 case ADDR_IMPLIED:
468 report ("\n");
469 break;
472 return pos;
476 #ifdef TEST_DISASSEMBLE
477 int main (int argc, char **argv)
479 size_t size;
480 uint32 offset = 0, pos = 0;
481 uint8 *mem;
483 if (argc <= 1) return -1;
484 if (argc > 2) offset = atoi (argv[2]);
485 mem = (uint8 *) read_file (argv[1], &size);
487 while (pos < size) {
488 pos += nes6502_disassemble (&mem[pos], offset + pos, 1);
490 return 0;
492 #endif /* TEST_DISASSEMBLE */