c62d2810 |
1 | /* FCE Ultra - NES/Famicom Emulator |
2 | * |
3 | * Copyright notice for this file: |
4 | * Copyright (C) 2002 Ben Parnell |
5 | * |
6 | * This program is free software; you can redistribute it and/or modify |
7 | * it under the terms of the GNU General Public License as published by |
8 | * the Free Software Foundation; either version 2 of the License, or |
9 | * (at your option) any later version. |
10 | * |
11 | * This program is distributed in the hope that it will be useful, |
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
14 | * GNU General Public License for more details. |
15 | * |
16 | * You should have received a copy of the GNU General Public License |
17 | * along with this program; if not, write to the Free Software |
18 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
19 | */ |
20 | |
21 | case 0x00: /* BRK */ |
22 | _PC++; |
23 | PUSH(_PC>>8); |
24 | PUSH(_PC); |
8fa5eb33 |
25 | _P|=B_FLAG; |
26 | PUSH(_P|U_FLAG); |
c62d2810 |
27 | _P|=I_FLAG; |
28 | _PC=RdMem(0xFFFE); |
29 | _PC|=RdMem(0xFFFF)<<8; |
30 | break; |
31 | |
32 | case 0x40: /* RTI */ |
33 | _P=POP(); |
34 | _PI=_P; |
35 | _PC=POP(); |
36 | _PC|=POP()<<8; |
37 | break; |
c0bf6f9f |
38 | |
c62d2810 |
39 | case 0x60: /* RTS */ |
40 | _PC=POP(); |
41 | _PC|=POP()<<8; |
42 | _PC++; |
43 | break; |
44 | |
45 | case 0x48: /* PHA */ |
46 | PUSH(_A); |
47 | break; |
48 | case 0x08: /* PHP */ |
49 | PUSH(_P|U_FLAG|B_FLAG); |
50 | break; |
51 | case 0x68: /* PLA */ |
52 | _A=POP(); |
53 | X_ZN(_A); |
54 | break; |
55 | case 0x28: /* PLP */ |
56 | _P=POP(); |
57 | break; |
58 | case 0x4C: |
59 | { |
c62d2810 |
60 | unsigned int npc; |
e5f8a1a9 |
61 | /* |
62 | uint16 ptmp=_PC; |
c62d2810 |
63 | npc=RdMem(ptmp); |
64 | ptmp++; |
65 | npc|=RdMem(ptmp)<<8; |
e5f8a1a9 |
66 | */ |
67 | npc=RdMem(_PC++); |
68 | npc|=RdMem(_PC++)<<8; |
c62d2810 |
69 | _PC=npc; |
70 | } |
71 | break; /* JMP ABSOLUTE */ |
c0bf6f9f |
72 | case 0x6C: |
c62d2810 |
73 | { |
74 | uint32 tmp; |
75 | GetAB(tmp); |
76 | _PC=RdMem(tmp); |
77 | _PC|=RdMem( ((tmp+1)&0x00FF) | (tmp&0xFF00))<<8; |
78 | } |
79 | break; |
80 | case 0x20: /* JSR */ |
81 | { |
e5f8a1a9 |
82 | uint32 npc; |
c62d2810 |
83 | npc=RdMem(_PC++); |
84 | PUSH(_PC>>8); |
85 | PUSH(_PC); |
e5f8a1a9 |
86 | npc|=RdMem(_PC++)<<8; |
87 | _PC=npc; |
c62d2810 |
88 | } |
89 | break; |
90 | |
91 | case 0xAA: /* TAX */ |
92 | _X=_A; |
93 | X_ZN(_A); |
94 | break; |
95 | |
96 | case 0x8A: /* TXA */ |
97 | _A=_X; |
98 | X_ZN(_A); |
99 | break; |
100 | |
101 | case 0xA8: /* TAY */ |
102 | _Y=_A; |
103 | X_ZN(_A); |
104 | break; |
105 | case 0x98: /* TYA */ |
106 | _A=_Y; |
107 | X_ZN(_A); |
108 | break; |
109 | |
110 | case 0xBA: /* TSX */ |
111 | _X=_S; |
112 | X_ZN(_X); |
113 | break; |
114 | case 0x9A: /* TXS */ |
115 | _S=_X; |
116 | break; |
117 | |
118 | case 0xCA: /* DEX */ |
119 | _X--; |
120 | X_ZN(_X); |
121 | break; |
122 | case 0x88: /* DEY */ |
123 | _Y--; |
124 | X_ZN(_Y); |
125 | break; |
126 | |
127 | case 0xE8: /* INX */ |
128 | _X++; |
129 | X_ZN(_X); |
130 | break; |
131 | case 0xC8: /* INY */ |
132 | _Y++; |
133 | X_ZN(_Y); |
134 | break; |
135 | |
136 | case 0x18: /* CLC */ |
137 | _P&=~C_FLAG; |
138 | break; |
139 | case 0xD8: /* CLD */ |
140 | _P&=~D_FLAG; |
141 | break; |
142 | case 0x58: /* CLI */ |
143 | _P&=~I_FLAG; |
144 | break; |
145 | case 0xB8: /* CLV */ |
146 | _P&=~V_FLAG; |
147 | break; |
148 | |
149 | case 0x38: /* SEC */ |
150 | _P|=C_FLAG; |
151 | break; |
152 | case 0xF8: /* SED */ |
153 | _P|=D_FLAG; |
154 | break; |
155 | case 0x78: /* SEI */ |
156 | _P|=I_FLAG; |
157 | break; |
158 | |
159 | case 0xEA: /* NOP */ |
160 | break; |
161 | |
162 | case 0x0A: RMW_A(ASL); |
163 | case 0x06: RMW_ZP(ASL); |
164 | case 0x16: RMW_ZPX(ASL); |
165 | case 0x0E: RMW_AB(ASL); |
166 | case 0x1E: RMW_ABX(ASL); |
167 | |
168 | case 0xC6: RMW_ZP(DEC); |
169 | case 0xD6: RMW_ZPX(DEC); |
170 | case 0xCE: RMW_AB(DEC); |
171 | case 0xDE: RMW_ABX(DEC); |
172 | |
173 | case 0xE6: RMW_ZP(INC); |
174 | case 0xF6: RMW_ZPX(INC); |
175 | case 0xEE: RMW_AB(INC); |
176 | case 0xFE: RMW_ABX(INC); |
177 | |
178 | case 0x4A: RMW_A(LSR); |
179 | case 0x46: RMW_ZP(LSR); |
180 | case 0x56: RMW_ZPX(LSR); |
181 | case 0x4E: RMW_AB(LSR); |
182 | case 0x5E: RMW_ABX(LSR); |
183 | |
184 | case 0x2A: RMW_A(ROL); |
185 | case 0x26: RMW_ZP(ROL); |
186 | case 0x36: RMW_ZPX(ROL); |
187 | case 0x2E: RMW_AB(ROL); |
188 | case 0x3E: RMW_ABX(ROL); |
189 | |
190 | case 0x6A: RMW_A(ROR); |
191 | case 0x66: RMW_ZP(ROR); |
192 | case 0x76: RMW_ZPX(ROR); |
193 | case 0x6E: RMW_AB(ROR); |
194 | case 0x7E: RMW_ABX(ROR); |
195 | |
196 | case 0x69: LD_IM(ADC); |
197 | case 0x65: LD_ZP(ADC); |
198 | case 0x75: LD_ZPX(ADC); |
199 | case 0x6D: LD_AB(ADC); |
200 | case 0x7D: LD_ABX(ADC); |
201 | case 0x79: LD_ABY(ADC); |
202 | case 0x61: LD_IX(ADC); |
203 | case 0x71: LD_IY(ADC); |
204 | |
205 | case 0x29: LD_IM(AND); |
206 | case 0x25: LD_ZP(AND); |
207 | case 0x35: LD_ZPX(AND); |
208 | case 0x2D: LD_AB(AND); |
209 | case 0x3D: LD_ABX(AND); |
210 | case 0x39: LD_ABY(AND); |
211 | case 0x21: LD_IX(AND); |
212 | case 0x31: LD_IY(AND); |
213 | |
214 | case 0x24: LD_ZP(BIT); |
215 | case 0x2C: LD_AB(BIT); |
216 | |
217 | case 0xC9: LD_IM(CMP); |
218 | case 0xC5: LD_ZP(CMP); |
219 | case 0xD5: LD_ZPX(CMP); |
220 | case 0xCD: LD_AB(CMP); |
221 | case 0xDD: LD_ABX(CMP); |
222 | case 0xD9: LD_ABY(CMP); |
223 | case 0xC1: LD_IX(CMP); |
224 | case 0xD1: LD_IY(CMP); |
225 | |
226 | case 0xE0: LD_IM(CPX); |
227 | case 0xE4: LD_ZP(CPX); |
228 | case 0xEC: LD_AB(CPX); |
229 | |
230 | case 0xC0: LD_IM(CPY); |
231 | case 0xC4: LD_ZP(CPY); |
232 | case 0xCC: LD_AB(CPY); |
233 | |
234 | case 0x49: LD_IM(EOR); |
235 | case 0x45: LD_ZP(EOR); |
236 | case 0x55: LD_ZPX(EOR); |
237 | case 0x4D: LD_AB(EOR); |
238 | case 0x5D: LD_ABX(EOR); |
239 | case 0x59: LD_ABY(EOR); |
240 | case 0x41: LD_IX(EOR); |
241 | case 0x51: LD_IY(EOR); |
242 | |
243 | case 0xA9: LD_IM(LDA); |
244 | case 0xA5: LD_ZP(LDA); |
245 | case 0xB5: LD_ZPX(LDA); |
246 | case 0xAD: LD_AB(LDA); |
247 | case 0xBD: LD_ABX(LDA); |
248 | case 0xB9: LD_ABY(LDA); |
249 | case 0xA1: LD_IX(LDA); |
250 | case 0xB1: LD_IY(LDA); |
251 | |
252 | case 0xA2: LD_IM(LDX); |
253 | case 0xA6: LD_ZP(LDX); |
254 | case 0xB6: LD_ZPY(LDX); |
255 | case 0xAE: LD_AB(LDX); |
256 | case 0xBE: LD_ABY(LDX); |
257 | |
258 | case 0xA0: LD_IM(LDY); |
259 | case 0xA4: LD_ZP(LDY); |
260 | case 0xB4: LD_ZPX(LDY); |
261 | case 0xAC: LD_AB(LDY); |
262 | case 0xBC: LD_ABX(LDY); |
263 | |
264 | case 0x09: LD_IM(ORA); |
265 | case 0x05: LD_ZP(ORA); |
266 | case 0x15: LD_ZPX(ORA); |
267 | case 0x0D: LD_AB(ORA); |
268 | case 0x1D: LD_ABX(ORA); |
269 | case 0x19: LD_ABY(ORA); |
270 | case 0x01: LD_IX(ORA); |
271 | case 0x11: LD_IY(ORA); |
272 | |
273 | case 0xEB: /* (undocumented) */ |
274 | case 0xE9: LD_IM(SBC); |
275 | case 0xE5: LD_ZP(SBC); |
276 | case 0xF5: LD_ZPX(SBC); |
277 | case 0xED: LD_AB(SBC); |
278 | case 0xFD: LD_ABX(SBC); |
279 | case 0xF9: LD_ABY(SBC); |
280 | case 0xE1: LD_IX(SBC); |
281 | case 0xF1: LD_IY(SBC); |
282 | |
283 | case 0x85: ST_ZP(_A); |
284 | case 0x95: ST_ZPX(_A); |
285 | case 0x8D: ST_AB(_A); |
286 | case 0x9D: ST_ABX(_A); |
287 | case 0x99: ST_ABY(_A); |
288 | case 0x81: ST_IX(_A); |
289 | case 0x91: ST_IY(_A); |
290 | |
291 | case 0x86: ST_ZP(_X); |
292 | case 0x96: ST_ZPY(_X); |
293 | case 0x8E: ST_AB(_X); |
294 | |
295 | case 0x84: ST_ZP(_Y); |
296 | case 0x94: ST_ZPX(_Y); |
297 | case 0x8C: ST_AB(_Y); |
298 | |
299 | /* BCC */ |
300 | case 0x90: if(_P&C_FLAG) _PC++; else {JR();} break; |
301 | |
302 | /* BCS */ |
303 | case 0xB0: if(_P&C_FLAG) {JR();} else _PC++; break; |
304 | |
305 | /* BEQ */ |
306 | case 0xF0: if(_P&Z_FLAG) {JR();} else _PC++; break; |
307 | |
308 | /* BNE */ |
309 | case 0xD0: if(_P&Z_FLAG) _PC++; else {JR();} break; |
310 | |
311 | /* BMI */ |
312 | case 0x30: if(_P&N_FLAG) {JR();} else _PC++; break; |
313 | |
314 | /* BPL */ |
315 | case 0x10: if(_P&N_FLAG) _PC++; else {JR();} break; |
316 | |
317 | /* BVC */ |
318 | case 0x50: if(_P&V_FLAG) _PC++; else {JR();} break; |
319 | |
320 | /* BVS */ |
321 | case 0x70: if(_P&V_FLAG) {JR();} else _PC++; break; |
322 | |
323 | /* Here comes the undocumented instructions. Note that this implementation |
324 | may be "wrong". If so, please tell me. |
325 | */ |
326 | |
327 | /* AAC */ |
328 | case 0x2B: |
329 | case 0x0B: LD_IM(AND;_P&=~C_FLAG;_P|=_A>>7); |
330 | |
331 | /* AAX */ |
332 | case 0x87: ST_ZP(_A&_X); |
333 | case 0x97: ST_ZPY(_A&_X); |
334 | case 0x8F: ST_AB(_A&_X); |
335 | case 0x83: ST_IX(_A&_X); |
336 | |
337 | /* ARR - ARGH, MATEY! */ |
c0bf6f9f |
338 | case 0x6B: { |
339 | uint8 arrtmp; |
c62d2810 |
340 | LD_IM(AND;_P&=~V_FLAG;_P|=(_A^(_A>>1))&0x40;arrtmp=_A>>7;_A>>=1;_A|=(_P&C_FLAG)<<7;_P&=~C_FLAG;_P|=arrtmp;X_ZN(_A)); |
341 | } |
342 | /* ASR */ |
343 | case 0x4B: LD_IM(AND;LSRA); |
344 | |
345 | /* ATX(OAL) Is this(OR with $EE) correct? */ |
346 | case 0xAB: LD_IM(_A|=0xEE;AND;_X=_A); |
347 | |
c0bf6f9f |
348 | /* AXS */ |
c62d2810 |
349 | case 0xCB: LD_IM(AXS); |
350 | |
351 | /* DCP */ |
4fdfab07 |
352 | case 0xC7: RMW_ZP(DEC;CMP); |
353 | case 0xD7: RMW_ZPX(DEC;CMP); |
354 | case 0xCF: RMW_AB(DEC;CMP); |
355 | case 0xDF: RMW_ABX(DEC;CMP); |
356 | case 0xDB: RMW_ABY(DEC;CMP); |
357 | case 0xC3: RMW_IX(DEC;CMP); |
358 | case 0xD3: RMW_IY(DEC;CMP); |
c62d2810 |
359 | |
360 | /* ISC */ |
4fdfab07 |
361 | case 0xE7: RMW_ZP(INC;SBC); |
362 | case 0xF7: RMW_ZPX(INC;SBC); |
363 | case 0xEF: RMW_AB(INC;SBC); |
364 | case 0xFF: RMW_ABX(INC;SBC); |
365 | case 0xFB: RMW_ABY(INC;SBC); |
366 | case 0xE3: RMW_IX(INC;SBC); |
367 | case 0xF3: RMW_IY(INC;SBC); |
c62d2810 |
368 | |
369 | /* DOP */ |
370 | |
371 | case 0x04: _PC++;break; |
372 | case 0x14: _PC++;break; |
373 | case 0x34: _PC++;break; |
374 | case 0x44: _PC++;break; |
375 | case 0x54: _PC++;break; |
376 | case 0x64: _PC++;break; |
377 | case 0x74: _PC++;break; |
378 | |
379 | case 0x80: _PC++;break; |
380 | case 0x82: _PC++;break; |
381 | case 0x89: _PC++;break; |
382 | case 0xC2: _PC++;break; |
383 | case 0xD4: _PC++;break; |
384 | case 0xE2: _PC++;break; |
385 | case 0xF4: _PC++;break; |
386 | |
387 | /* KIL */ |
388 | |
389 | case 0x02: |
390 | case 0x12: |
391 | case 0x22: |
392 | case 0x32: |
393 | case 0x42: |
394 | case 0x52: |
395 | case 0x62: |
396 | case 0x72: |
397 | case 0x92: |
398 | case 0xB2: |
399 | case 0xD2: |
400 | case 0xF2:ADDCYC(0xFF); |
401 | _jammed=1; |
402 | _PC--; |
403 | break; |
404 | |
405 | /* LAR */ |
406 | case 0xBB: RMW_ABY(_S&=x;_A=_X=_S;X_ZN(_X)); |
407 | |
408 | /* LAX */ |
409 | case 0xA7: LD_ZP(LDA;LDX); |
410 | case 0xB7: LD_ZPY(LDA;LDX); |
411 | case 0xAF: LD_AB(LDA;LDX); |
412 | case 0xBF: LD_ABY(LDA;LDX); |
413 | case 0xA3: LD_IX(LDA;LDX); |
414 | case 0xB3: LD_IY(LDA;LDX); |
415 | |
416 | /* NOP */ |
417 | case 0x1A: |
418 | case 0x3A: |
419 | case 0x5A: |
420 | case 0x7A: |
421 | case 0xDA: |
422 | case 0xFA: break; |
423 | |
424 | /* RLA */ |
425 | case 0x27: RMW_ZP(ROL;AND); |
426 | case 0x37: RMW_ZPX(ROL;AND); |
427 | case 0x2F: RMW_AB(ROL;AND); |
428 | case 0x3F: RMW_ABX(ROL;AND); |
429 | case 0x3B: RMW_ABY(ROL;AND); |
430 | case 0x23: RMW_IX(ROL;AND); |
431 | case 0x33: RMW_IY(ROL;AND); |
432 | |
433 | /* RRA */ |
434 | case 0x67: RMW_ZP(ROR;ADC); |
435 | case 0x77: RMW_ZPX(ROR;ADC); |
436 | case 0x6F: RMW_AB(ROR;ADC); |
437 | case 0x7F: RMW_ABX(ROR;ADC); |
438 | case 0x7B: RMW_ABY(ROR;ADC); |
439 | case 0x63: RMW_IX(ROR;ADC); |
440 | case 0x73: RMW_IY(ROR;ADC); |
441 | |
442 | /* SLO */ |
443 | case 0x07: RMW_ZP(ASL;ORA); |
444 | case 0x17: RMW_ZPX(ASL;ORA); |
445 | case 0x0F: RMW_AB(ASL;ORA); |
446 | case 0x1F: RMW_ABX(ASL;ORA); |
447 | case 0x1B: RMW_ABY(ASL;ORA); |
448 | case 0x03: RMW_IX(ASL;ORA); |
449 | case 0x13: RMW_IY(ASL;ORA); |
450 | |
451 | /* SRE */ |
452 | case 0x47: RMW_ZP(LSR;EOR); |
453 | case 0x57: RMW_ZPX(LSR;EOR); |
454 | case 0x4F: RMW_AB(LSR;EOR); |
455 | case 0x5F: RMW_ABX(LSR;EOR); |
456 | case 0x5B: RMW_ABY(LSR;EOR); |
457 | case 0x43: RMW_IX(LSR;EOR); |
458 | case 0x53: RMW_IY(LSR;EOR); |
459 | |
460 | /* AXA - SHA */ |
461 | case 0x93: ST_IY(_A&_X&(((A-_Y)>>8)+1)); |
462 | case 0x9F: ST_ABY(_A&_X&(((A-_Y)>>8)+1)); |
463 | |
464 | /* SYA */ |
465 | case 0x9C: ST_ABX(_Y&(((A-_X)>>8)+1)); |
466 | |
467 | /* SXA */ |
468 | case 0x9E: ST_ABY(_X&(((A-_Y)>>8)+1)); |
469 | |
470 | /* XAS */ |
471 | case 0x9B: _S=_A&_X;ST_ABY(_S& (((A-_Y)>>8)+1) ); |
472 | |
473 | /* TOP */ |
474 | case 0x0C: LD_AB(;); |
c0bf6f9f |
475 | case 0x1C: |
476 | case 0x3C: |
477 | case 0x5C: |
478 | case 0x7C: |
479 | case 0xDC: |
c62d2810 |
480 | case 0xFC: LD_ABX(;); |
481 | |
482 | /* XAA - BIG QUESTION MARK HERE */ |
483 | case 0x8B: _A|=0xEE; _A&=_X; LD_IM(AND); |