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
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,
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
)
400 struct nes6502_opcode
*opcode
;
401 enum nes6502_instruction insn
;
402 uint32 oper
, address
;
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
:
424 report ("#$%02X\n", mem
[pos
++]);
427 report (" $%02X\n", mem
[pos
++]);
429 case ADDR_ZERO_PAGE_X
:
430 report (" $%02X, X\n", mem
[pos
++]);
432 case ADDR_ZERO_PAGE_Y
:
433 report (" $%02X, Y\n", mem
[pos
++]);
436 oper
= (uint32
) mem
[pos
++];
437 oper
+= ((uint32
) mem
[pos
++]) << 8;
438 report (" $%04X\n", oper
);
440 case ADDR_ABSOLUTE_X
:
441 oper
= (uint32
) mem
[pos
++];
442 oper
+= ((uint32
) mem
[pos
++]) << 8;
443 report (" $%04X, X\n", oper
);
445 case ADDR_ABSOLUTE_Y
:
446 oper
= (uint32
) mem
[pos
++];
447 oper
+= ((uint32
) mem
[pos
++]) << 8;
448 report (" $%04X, Y\n", oper
);
451 oper
= (uint32
) mem
[pos
++];
452 oper
+= ((uint32
) mem
[pos
++]) << 8;
453 report ("($%04X)\n", oper
);
455 case ADDR_INDIRECT_X
:
456 report ("($%02X, X)\n", mem
[pos
++]);
458 case ADDR_INDIRECT_Y
:
459 report ("($%02X), Y\n", mem
[pos
++]);
462 address
= mem
[pos
++];
463 if (address
& 0x80) address
|= 0xFF00;
464 address
= (address
+ offset
) & 0xFFFF;
465 report (" $%04X\n", address
);
476 #ifdef TEST_DISASSEMBLE
477 int main (int argc
, char **argv
)
480 uint32 offset
= 0, pos
= 0;
483 if (argc
<= 1) return -1;
484 if (argc
> 2) offset
= atoi (argv
[2]);
485 mem
= (uint8
*) read_file (argv
[1], &size
);
488 pos
+= nes6502_disassemble (&mem
[pos
], offset
+ pos
, 1);
492 #endif /* TEST_DISASSEMBLE */