1 /*****************************************************************************/
2 /* */
3 /* 6502.c */
4 /* */
5 /* CPU core for the 6502 */
6 /* */
7 /* */
8 /* */
9 /* (C) 2003-2012, Ullrich von Bassewitz */
10 /* Roemerstrasse 52 */
11 /* D-70794 Filderstadt */
12 /* EMail: uz@cc65.org */
13 /* */
14 /* Mar-2017, Christian Krueger, added support for 65SC02 */
15 /* */
16 /* This software is provided 'as-is', without any expressed or implied */
17 /* warranty. In no event will the authors be held liable for any damages */
18 /* arising from the use of this software. */
19 /* */
20 /* Permission is granted to anyone to use this software for any purpose, */
21 /* including commercial applications, and to alter it and redistribute it */
22 /* freely, subject to the following restrictions: */
23 /* */
24 /* 1. The origin of this software must not be misrepresented; you must not */
25 /* claim that you wrote the original software. If you use this software */
26 /* in a product, an acknowledgment in the product documentation would be */
27 /* appreciated but is not required. */
28 /* 2. Altered source versions must be plainly marked as such, and must not */
29 /* be misrepresented as being the original software. */
30 /* 3. This notice may not be removed or altered from any source */
31 /* distribution. */
32 /* */
33 /*****************************************************************************/
34
35 /* Known bugs and limitations of the 65C02 simulation:
36 * support currently only on the level of 65SC02:
37 BBRx, BBSx, RMBx, SMBx, WAI, and STP are unsupported
38 * BCD flag handling equals 6502 (unchecked if bug is simulated or wrong for
39 6502)
40 */
41
42 #include "memory.h"
43 #include "error.h"
44 #include "6502.h"
45 #include "paravirt.h"
46
47
48
49 /*****************************************************************************/
50 /* Data */
51 /*****************************************************************************/
52
53
54
55 /* Current CPU */
56 CPUType CPU;
57
58 /* Type of an opcode handler function */
59 typedef void (*OPFunc) (void);
60
61 /* The CPU registers */
62 static CPURegs Regs;
63
64 /* Cycles for the current insn */
65 static unsigned Cycles;
66
67 /* Total number of CPU cycles exec'd */
68 static unsigned long TotalCycles;
69
70 /* NMI request active */
71 static unsigned HaveNMIRequest;
72
73 /* IRQ request active */
74 static unsigned HaveIRQRequest;
75
76 /* flag to print cycles at program termination */
77 int PrintCycles;
78
79
80 /*****************************************************************************/
81 /* Helper functions and macros */
82 /*****************************************************************************/
83
84
85
86 /* Return the flags as boolean values (0/1) */
87 #define GET_CF() ((Regs.SR & CF) != 0)
88 #define GET_ZF() ((Regs.SR & ZF) != 0)
89 #define GET_IF() ((Regs.SR & IF) != 0)
90 #define GET_DF() ((Regs.SR & DF) != 0)
91 #define GET_OF() ((Regs.SR & OF) != 0)
92 #define GET_SF() ((Regs.SR & SF) != 0)
93
94 /* Set the flags. The parameter is a boolean flag that says if the flag should be
95 ** set or reset.
96 */
97 #define SET_CF(f) do { if (f) { Regs.SR |= CF; } else { Regs.SR &= ~CF; } } while (0)
98 #define SET_ZF(f) do { if (f) { Regs.SR |= ZF; } else { Regs.SR &= ~ZF; } } while (0)
99 #define SET_IF(f) do { if (f) { Regs.SR |= IF; } else { Regs.SR &= ~IF; } } while (0)
100 #define SET_DF(f) do { if (f) { Regs.SR |= DF; } else { Regs.SR &= ~DF; } } while (0)
101 #define SET_OF(f) do { if (f) { Regs.SR |= OF; } else { Regs.SR &= ~OF; } } while (0)
102 #define SET_SF(f) do { if (f) { Regs.SR |= SF; } else { Regs.SR &= ~SF; } } while (0)
103
104 /* Special test and set macros. The meaning of the parameter depends on the
105 ** actual flag that should be set or reset.
106 */
107 #define TEST_ZF(v) SET_ZF (((v) & 0xFF) == 0)
108 #define TEST_SF(v) SET_SF (((v) & 0x80) != 0)
109 #define TEST_CF(v) SET_CF (((v) & 0xFF00) != 0)
110
111 /* Program counter halves */
112 #define PCL (Regs.PC & 0xFF)
113 #define PCH ((Regs.PC >> 8) & 0xFF)
114
115 /* Stack operations */
116 #define PUSH(Val) MemWriteByte (0x0100 | (Regs.SP-- & 0xFF), Val)
117 #define POP() MemReadByte (0x0100 | (++Regs.SP & 0xFF))
118
119 /* Test for page cross */
120 #define PAGE_CROSS(addr,offs) ((((addr) & 0xFF) + offs) >= 0x100)
121
122 /* #imm */
123 #define AC_OP_IMM(op) \
124 Cycles = 2; \
125 Regs.AC = Regs.AC op MemReadByte (Regs.PC+1); \
126 TEST_ZF (Regs.AC); \
127 TEST_SF (Regs.AC); \
128 Regs.PC += 2
129
130 /* zp */
131 #define AC_OP_ZP(op) \
132 Cycles = 3; \
133 Regs.AC = Regs.AC op MemReadByte (MemReadByte (Regs.PC+1)); \
134 TEST_ZF (Regs.AC); \
135 TEST_SF (Regs.AC); \
136 Regs.PC += 2
137
138 /* zp,x */
139 #define AC_OP_ZPX(op) \
140 unsigned char ZPAddr; \
141 Cycles = 4; \
142 ZPAddr = MemReadByte (Regs.PC+1) + Regs.XR; \
143 Regs.AC = Regs.AC op MemReadByte (ZPAddr); \
144 TEST_ZF (Regs.AC); \
145 TEST_SF (Regs.AC); \
146 Regs.PC += 2
147
148 /* zp,y */
149 #define AC_OP_ZPY(op) \
150 unsigned char ZPAddr; \
151 Cycles = 4; \
152 ZPAddr = MemReadByte (Regs.PC+1) + Regs.YR; \
153 Regs.AC = Regs.AC op MemReadByte (ZPAddr); \
154 TEST_ZF (Regs.AC); \
155 TEST_SF (Regs.AC); \
156 Regs.PC += 2
157
158 /* abs */
159 #define AC_OP_ABS(op) \
160 unsigned Addr; \
161 Cycles = 4; \
162 Addr = MemReadWord (Regs.PC+1); \
163 Regs.AC = Regs.AC op MemReadByte (Addr); \
164 TEST_ZF (Regs.AC); \
165 TEST_SF (Regs.AC); \
166 Regs.PC += 3
167
168 /* abs,x */
169 #define AC_OP_ABSX(op) \
170 unsigned Addr; \
171 Cycles = 4; \
172 Addr = MemReadWord (Regs.PC+1); \
173 if (PAGE_CROSS (Addr, Regs.XR)) { \
174 ++Cycles; \
175 } \
176 Regs.AC = Regs.AC op MemReadByte (Addr + Regs.XR); \
177 TEST_ZF (Regs.AC); \
178 TEST_SF (Regs.AC); \
179 Regs.PC += 3
180
181 /* abs,y */
182 #define AC_OP_ABSY(op) \
183 unsigned Addr; \
184 Cycles = 4; \
185 Addr = MemReadWord (Regs.PC+1); \
186 if (PAGE_CROSS (Addr, Regs.YR)) { \
187 ++Cycles; \
188 } \
189 Regs.AC = Regs.AC op MemReadByte (Addr + Regs.YR); \
190 TEST_ZF (Regs.AC); \
191 TEST_SF (Regs.AC); \
192 Regs.PC += 3
193
194 /* (zp,x) */
195 #define AC_OP_ZPXIND(op) \
196 unsigned char ZPAddr; \
197 unsigned Addr; \
198 Cycles = 6; \
199 ZPAddr = MemReadByte (Regs.PC+1) + Regs.XR; \
200 Addr = MemReadZPWord (ZPAddr); \
201 Regs.AC = Regs.AC op MemReadByte (Addr); \
202 TEST_ZF (Regs.AC); \
203 TEST_SF (Regs.AC); \
204 Regs.PC += 2
205
206 /* (zp),y */
207 #define AC_OP_ZPINDY(op) \
208 unsigned char ZPAddr; \
209 unsigned Addr; \
210 Cycles = 5; \
211 ZPAddr = MemReadByte (Regs.PC+1); \
212 Addr = MemReadZPWord (ZPAddr); \
213 if (PAGE_CROSS (Addr, Regs.YR)) { \
214 ++Cycles; \
215 } \
216 Addr += Regs.YR; \
217 Regs.AC = Regs.AC op MemReadByte (Addr); \
218 TEST_ZF (Regs.AC); \
219 TEST_SF (Regs.AC); \
220 Regs.PC += 2
221
222 /* (zp) */
223 #define AC_OP_ZPIND(op) \
224 unsigned char ZPAddr; \
225 unsigned Addr; \
226 Cycles = 5; \
227 ZPAddr = MemReadByte (Regs.PC+1); \
228 Addr = MemReadZPWord (ZPAddr); \
229 Regs.AC = Regs.AC op MemReadByte (Addr); \
230 TEST_ZF (Regs.AC); \
231 TEST_SF (Regs.AC); \
232 Regs.PC += 2
233
234 /* ADC */
235 #define ADC(v) \
236 do { \
237 unsigned old = Regs.AC; \
238 unsigned rhs = (v & 0xFF); \
239 if (GET_DF ()) { \
240 unsigned lo; \
241 int res; \
242 lo = (old & 0x0F) + (rhs & 0x0F) + GET_CF (); \
243 if (lo >= 0x0A) { \
244 lo = ((lo + 0x06) & 0x0F) + 0x10; \
245 } \
246 Regs.AC = (old & 0xF0) + (rhs & 0xF0) + lo; \
247 res = (signed char)(old & 0xF0) + \
248 (signed char)(rhs & 0xF0) + \
249 (signed char)lo; \
250 TEST_ZF (old + rhs + GET_CF ()); \
251 TEST_SF (Regs.AC); \
252 if (Regs.AC >= 0xA0) { \
253 Regs.AC += 0x60; \
254 } \
255 TEST_CF (Regs.AC); \
256 SET_OF ((res < -128) || (res > 127)); \
257 if (CPU != CPU_6502) { \
258 ++Cycles; \
259 } \
260 } else { \
261 Regs.AC += rhs + GET_CF (); \
262 TEST_ZF (Regs.AC); \
263 TEST_SF (Regs.AC); \
264 TEST_CF (Regs.AC); \
265 SET_OF (!((old ^ rhs) & 0x80) && \
266 ((old ^ Regs.AC) & 0x80)); \
267 Regs.AC &= 0xFF; \
268 } \
269 } while (0)
270
271 /* branches */
272 #define BRANCH(cond) \
273 Cycles = 2; \
274 if (cond) { \
275 signed char Offs; \
276 unsigned char OldPCH; \
277 ++Cycles; \
278 Offs = (signed char) MemReadByte (Regs.PC+1); \
279 OldPCH = PCH; \
280 Regs.PC += 2 + (int) Offs; \
281 if (PCH != OldPCH) { \
282 ++Cycles; \
283 } \
284 } else { \
285 Regs.PC += 2; \
286 }
287
288 /* compares */
289 #define CMP(v1, v2) \
290 do { \
291 unsigned Result = v1 - v2; \
292 TEST_ZF (Result & 0xFF); \
293 TEST_SF (Result); \
294 SET_CF (Result <= 0xFF); \
295 } while (0)
296
297
298 /* ROL */
299 #define ROL(Val) \
300 Val <<= 1; \
301 if (GET_CF ()) { \
302 Val |= 0x01; \
303 } \
304 TEST_ZF (Val); \
305 TEST_SF (Val); \
306 TEST_CF (Val)
307
308 /* ROR */
309 #define ROR(Val) \
310 if (GET_CF ()) { \
311 Val |= 0x100; \
312 } \
313 SET_CF (Val & 0x01); \
314 Val >>= 1; \
315 TEST_ZF (Val); \
316 TEST_SF (Val)
317
318 /* SBC */
319 #define SBC(v) \
320 do { \
321 unsigned old = Regs.AC; \
322 unsigned rhs = (v & 0xFF); \
323 if (GET_DF ()) { \
324 unsigned lo; \
325 int res; \
326 lo = (old & 0x0F) - (rhs & 0x0F) + GET_CF () - 1; \
327 if (lo & 0x80) { \
328 lo = ((lo - 0x06) & 0x0F) - 0x10; \
329 } \
330 Regs.AC = (old & 0xF0) - (rhs & 0xF0) + lo; \
331 if (Regs.AC & 0x80) { \
332 Regs.AC -= 0x60; \
333 } \
334 res = Regs.AC - rhs + (!GET_CF ()); \
335 TEST_ZF (res); \
336 TEST_SF (res); \
337 SET_CF (res <= 0xFF); \
338 SET_OF (((old^rhs) & (old^res) & 0x80)); \
339 if (CPU != CPU_6502) { \
340 ++Cycles; \
341 } \
342 } else { \
343 Regs.AC -= rhs + (!GET_CF ()); \
344 TEST_ZF (Regs.AC); \
345 TEST_SF (Regs.AC); \
346 SET_CF (Regs.AC <= 0xFF); \
347 SET_OF (((old^rhs) & (old^Regs.AC) & 0x80)); \
348 Regs.AC &= 0xFF; \
349 } \
350 } while (0)
351
352
353
354 /*****************************************************************************/
355 /* Opcode handling functions */
356 /*****************************************************************************/
357
358
359
OPC_Illegal(void)360 static void OPC_Illegal (void)
361 {
362 Error ("Illegal opcode $%02X at address $%04X",
363 MemReadByte (Regs.PC), Regs.PC);
364 }
365
366
367
OPC_6502_00(void)368 static void OPC_6502_00 (void)
369 /* Opcode $00: BRK */
370 {
371 Cycles = 7;
372 Regs.PC += 2;
373 PUSH (PCH);
374 PUSH (PCL);
375 PUSH (Regs.SR);
376 SET_IF (1);
377 if (CPU != CPU_6502)
378 {
379 SET_DF (0);
380 }
381 Regs.PC = MemReadWord (0xFFFE);
382 }
383
384
385
OPC_6502_01(void)386 static void OPC_6502_01 (void)
387 /* Opcode $01: ORA (ind,x) */
388 {
389 AC_OP_ZPXIND (|);
390 }
391
392
393
OPC_65SC02_04(void)394 static void OPC_65SC02_04 (void)
395 /* Opcode $04: TSB zp */
396 {
397 unsigned char ZPAddr;
398 unsigned char Val;
399 Cycles = 5;
400 ZPAddr = MemReadByte (Regs.PC+1);
401 Val = MemReadByte (ZPAddr);
402 SET_ZF ((Val & Regs.AC) == 0);
403 MemWriteByte (ZPAddr, (unsigned char)(Val | Regs.AC));
404 Regs.PC += 2;
405 }
406
407
408
OPC_6502_05(void)409 static void OPC_6502_05 (void)
410 /* Opcode $05: ORA zp */
411 {
412 AC_OP_ZP (|);
413 }
414
415
416
OPC_6502_06(void)417 static void OPC_6502_06 (void)
418 /* Opcode $06: ASL zp */
419 {
420 unsigned char ZPAddr;
421 unsigned Val;
422 Cycles = 5;
423 ZPAddr = MemReadByte (Regs.PC+1);
424 Val = MemReadByte (ZPAddr) << 1;
425 MemWriteByte (ZPAddr, (unsigned char) Val);
426 TEST_ZF (Val & 0xFF);
427 TEST_SF (Val);
428 SET_CF (Val & 0x100);
429 Regs.PC += 2;
430 }
431
432
433
OPC_6502_08(void)434 static void OPC_6502_08 (void)
435 /* Opcode $08: PHP */
436 {
437 Cycles = 3;
438 PUSH (Regs.SR);
439 Regs.PC += 1;
440 }
441
442
443
OPC_6502_09(void)444 static void OPC_6502_09 (void)
445 /* Opcode $09: ORA #imm */
446 {
447 AC_OP_IMM (|);
448 }
449
450
451
OPC_6502_0A(void)452 static void OPC_6502_0A (void)
453 /* Opcode $0A: ASL a */
454 {
455 Cycles = 2;
456 Regs.AC <<= 1;
457 TEST_ZF (Regs.AC & 0xFF);
458 TEST_SF (Regs.AC);
459 SET_CF (Regs.AC & 0x100);
460 Regs.AC &= 0xFF;
461 Regs.PC += 1;
462 }
463
464
465
OPC_65SC02_0C(void)466 static void OPC_65SC02_0C (void)
467 /* Opcode $0C: TSB abs */
468 {
469 unsigned Addr;
470 unsigned char Val;
471 Cycles = 6;
472 Addr = MemReadWord (Regs.PC+1);
473 Val = MemReadByte (Addr);
474 SET_ZF ((Val & Regs.AC) == 0);
475 MemWriteByte (Addr, (unsigned char) (Val | Regs.AC));
476 Regs.PC += 3;
477 }
478
479
480
OPC_6502_0D(void)481 static void OPC_6502_0D (void)
482 /* Opcode $0D: ORA abs */
483 {
484 AC_OP_ABS (|);
485 }
486
487
488
OPC_6502_0E(void)489 static void OPC_6502_0E (void)
490 /* Opcode $0E: ALS abs */
491 {
492 unsigned Addr;
493 unsigned Val;
494 Cycles = 6;
495 Addr = MemReadWord (Regs.PC+1);
496 Val = MemReadByte (Addr) << 1;
497 MemWriteByte (Addr, (unsigned char) Val);
498 TEST_ZF (Val & 0xFF);
499 TEST_SF (Val);
500 SET_CF (Val & 0x100);
501 Regs.PC += 3;
502 }
503
504
505
OPC_6502_10(void)506 static void OPC_6502_10 (void)
507 /* Opcode $10: BPL */
508 {
509 BRANCH (!GET_SF ());
510 }
511
512
513
OPC_6502_11(void)514 static void OPC_6502_11 (void)
515 /* Opcode $11: ORA (zp),y */
516 {
517 AC_OP_ZPINDY (|);
518 }
519
520
521
OPC_65SC02_12(void)522 static void OPC_65SC02_12 (void)
523 /* Opcode $12: ORA (zp) */
524 {
525 AC_OP_ZPIND (|);
526 }
527
528
529
OPC_65SC02_14(void)530 static void OPC_65SC02_14 (void)
531 /* Opcode $14: TRB zp */
532 {
533 unsigned char ZPAddr;
534 unsigned char Val;
535 Cycles = 5;
536 ZPAddr = MemReadByte (Regs.PC+1);
537 Val = MemReadByte (ZPAddr);
538 SET_ZF ((Val & Regs.AC) == 0);
539 MemWriteByte (ZPAddr, (unsigned char)(Val & ~Regs.AC));
540 Regs.PC += 2;
541 }
542
543
544
OPC_6502_15(void)545 static void OPC_6502_15 (void)
546 /* Opcode $15: ORA zp,x */
547 {
548 AC_OP_ZPX (|);
549 }
550
551
552
OPC_6502_16(void)553 static void OPC_6502_16 (void)
554 /* Opcode $16: ASL zp,x */
555 {
556 unsigned char ZPAddr;
557 unsigned Val;
558 Cycles = 6;
559 ZPAddr = MemReadByte (Regs.PC+1) + Regs.XR;
560 Val = MemReadByte (ZPAddr) << 1;
561 MemWriteByte (ZPAddr, (unsigned char) Val);
562 TEST_ZF (Val & 0xFF);
563 TEST_SF (Val);
564 SET_CF (Val & 0x100);
565 Regs.PC += 2;
566 }
567
568
569
OPC_6502_18(void)570 static void OPC_6502_18 (void)
571 /* Opcode $18: CLC */
572 {
573 Cycles = 2;
574 SET_CF (0);
575 Regs.PC += 1;
576 }
577
578
579
OPC_6502_19(void)580 static void OPC_6502_19 (void)
581 /* Opcode $19: ORA abs,y */
582 {
583 AC_OP_ABSY (|);
584 }
585
586
587
OPC_65SC02_1A(void)588 static void OPC_65SC02_1A (void)
589 /* Opcode $1A: INC a */
590 {
591 Cycles = 2;
592 Regs.AC = (Regs.AC + 1) & 0xFF;
593 TEST_ZF (Regs.AC);
594 TEST_SF (Regs.AC);
595 Regs.PC += 1;
596 }
597
598
599
OPC_65SC02_1C(void)600 static void OPC_65SC02_1C (void)
601 /* Opcode $1C: TRB abs */
602 {
603 unsigned Addr;
604 unsigned char Val;
605 Cycles = 6;
606 Addr = MemReadWord (Regs.PC+1);
607 Val = MemReadByte (Addr);
608 SET_ZF ((Val & Regs.AC) == 0);
609 MemWriteByte (Addr, (unsigned char) (Val & ~Regs.AC));
610 Regs.PC += 3;
611 }
612
613
614
OPC_6502_1D(void)615 static void OPC_6502_1D (void)
616 /* Opcode $1D: ORA abs,x */
617 {
618 AC_OP_ABSX (|);
619 }
620
621
622
OPC_6502_1E(void)623 static void OPC_6502_1E (void)
624 /* Opcode $1E: ASL abs,x */
625 {
626 unsigned Addr;
627 unsigned Val;
628 Cycles = 7;
629 Addr = MemReadWord (Regs.PC+1) + Regs.XR;
630 if (CPU != CPU_6502 && !PAGE_CROSS (Addr, Regs.XR))
631 --Cycles;
632 Val = MemReadByte (Addr) << 1;
633 MemWriteByte (Addr, (unsigned char) Val);
634 TEST_ZF (Val & 0xFF);
635 TEST_SF (Val);
636 SET_CF (Val & 0x100);
637 Regs.PC += 3;
638 }
639
640
641
OPC_6502_20(void)642 static void OPC_6502_20 (void)
643 /* Opcode $20: JSR */
644 {
645 unsigned Addr;
646 Cycles = 6;
647 Addr = MemReadWord (Regs.PC+1);
648 Regs.PC += 2;
649 PUSH (PCH);
650 PUSH (PCL);
651 Regs.PC = Addr;
652
653 ParaVirtHooks (&Regs);
654 }
655
656
657
OPC_6502_21(void)658 static void OPC_6502_21 (void)
659 /* Opcode $21: AND (zp,x) */
660 {
661 AC_OP_ZPXIND (&);
662 }
663
664
665
OPC_6502_24(void)666 static void OPC_6502_24 (void)
667 /* Opcode $24: BIT zp */
668 {
669 unsigned char ZPAddr;
670 unsigned char Val;
671 Cycles = 3;
672 ZPAddr = MemReadByte (Regs.PC+1);
673 Val = MemReadByte (ZPAddr);
674 SET_SF (Val & 0x80);
675 SET_OF (Val & 0x40);
676 SET_ZF ((Val & Regs.AC) == 0);
677 Regs.PC += 2;
678 }
679
680
681
OPC_6502_25(void)682 static void OPC_6502_25 (void)
683 /* Opcode $25: AND zp */
684 {
685 AC_OP_ZP (&);
686 }
687
688
689
OPC_6502_26(void)690 static void OPC_6502_26 (void)
691 /* Opcode $26: ROL zp */
692 {
693 unsigned char ZPAddr;
694 unsigned Val;
695 Cycles = 5;
696 ZPAddr = MemReadByte (Regs.PC+1);
697 Val = MemReadByte (ZPAddr);
698 ROL (Val);
699 MemWriteByte (ZPAddr, Val);
700 Regs.PC += 2;
701 }
702
703
704
OPC_6502_28(void)705 static void OPC_6502_28 (void)
706 /* Opcode $28: PLP */
707 {
708 Cycles = 4;
709
710 /* Bits 5 and 4 aren't used, and always are 1! */
711 Regs.SR = (POP () | 0x30);
712 Regs.PC += 1;
713 }
714
715
716
OPC_6502_29(void)717 static void OPC_6502_29 (void)
718 /* Opcode $29: AND #imm */
719 {
720 AC_OP_IMM (&);
721 }
722
723
724
OPC_6502_2A(void)725 static void OPC_6502_2A (void)
726 /* Opcode $2A: ROL a */
727 {
728 Cycles = 2;
729 ROL (Regs.AC);
730 Regs.AC &= 0xFF;
731 Regs.PC += 1;
732 }
733
734
735
OPC_6502_2C(void)736 static void OPC_6502_2C (void)
737 /* Opcode $2C: BIT abs */
738 {
739 unsigned Addr;
740 unsigned char Val;
741 Cycles = 4;
742 Addr = MemReadWord (Regs.PC+1);
743 Val = MemReadByte (Addr);
744 SET_SF (Val & 0x80);
745 SET_OF (Val & 0x40);
746 SET_ZF ((Val & Regs.AC) == 0);
747 Regs.PC += 3;
748 }
749
750
751
OPC_6502_2D(void)752 static void OPC_6502_2D (void)
753 /* Opcode $2D: AND abs */
754 {
755 AC_OP_ABS (&);
756 }
757
758
759
OPC_6502_2E(void)760 static void OPC_6502_2E (void)
761 /* Opcode $2E: ROL abs */
762 {
763 unsigned Addr;
764 unsigned Val;
765 Cycles = 6;
766 Addr = MemReadWord (Regs.PC+1);
767 Val = MemReadByte (Addr);
768 ROL (Val);
769 MemWriteByte (Addr, Val);
770 Regs.PC += 3;
771 }
772
773
774
OPC_6502_30(void)775 static void OPC_6502_30 (void)
776 /* Opcode $30: BMI */
777 {
778 BRANCH (GET_SF ());
779 }
780
781
782
OPC_6502_31(void)783 static void OPC_6502_31 (void)
784 /* Opcode $31: AND (zp),y */
785 {
786 AC_OP_ZPINDY (&);
787 }
788
789
790
OPC_65SC02_32(void)791 static void OPC_65SC02_32 (void)
792 /* Opcode $32: AND (zp) */
793 {
794 AC_OP_ZPIND (&);
795 }
796
797
798
OPC_65SC02_34(void)799 static void OPC_65SC02_34 (void)
800 /* Opcode $34: BIT zp,x */
801 {
802 unsigned char ZPAddr;
803 unsigned char Val;
804 Cycles = 4;
805 ZPAddr = MemReadByte (Regs.PC+1) + Regs.XR;
806 Val = MemReadByte (ZPAddr);
807 SET_SF (Val & 0x80);
808 SET_OF (Val & 0x40);
809 SET_ZF ((Val & Regs.AC) == 0);
810 Regs.PC += 2;
811 }
812
813
814
OPC_6502_35(void)815 static void OPC_6502_35 (void)
816 /* Opcode $35: AND zp,x */
817 {
818 AC_OP_ZPX (&);
819 }
820
821
822
OPC_6502_36(void)823 static void OPC_6502_36 (void)
824 /* Opcode $36: ROL zp,x */
825 {
826 unsigned char ZPAddr;
827 unsigned Val;
828 Cycles = 6;
829 ZPAddr = MemReadByte (Regs.PC+1) + Regs.XR;
830 Val = MemReadByte (ZPAddr);
831 ROL (Val);
832 MemWriteByte (ZPAddr, Val);
833 Regs.PC += 2;
834 }
835
836
837
OPC_6502_38(void)838 static void OPC_6502_38 (void)
839 /* Opcode $38: SEC */
840 {
841 Cycles = 2;
842 SET_CF (1);
843 Regs.PC += 1;
844 }
845
846
847
OPC_6502_39(void)848 static void OPC_6502_39 (void)
849 /* Opcode $39: AND abs,y */
850 {
851 AC_OP_ABSY (&);
852 }
853
854
855
OPC_65SC02_3A(void)856 static void OPC_65SC02_3A (void)
857 /* Opcode $3A: DEC a */
858 {
859 Cycles = 2;
860 Regs.AC = (Regs.AC - 1) & 0xFF;
861 TEST_ZF (Regs.AC);
862 TEST_SF (Regs.AC);
863 Regs.PC += 1;
864 }
865
866
867
OPC_65SC02_3C(void)868 static void OPC_65SC02_3C (void)
869 /* Opcode $3C: BIT abs,x */
870 {
871 unsigned Addr;
872 unsigned char Val;
873 Cycles = 4;
874 Addr = MemReadWord (Regs.PC+1);
875 if (PAGE_CROSS (Addr, Regs.XR))
876 ++Cycles;
877 Val = MemReadByte (Addr + Regs.XR);
878 SET_SF (Val & 0x80);
879 SET_OF (Val & 0x40);
880 SET_ZF ((Val & Regs.AC) == 0);
881 Regs.PC += 3;
882 }
883
884
885
OPC_6502_3D(void)886 static void OPC_6502_3D (void)
887 /* Opcode $3D: AND abs,x */
888 {
889 AC_OP_ABSX (&);
890 }
891
892
893
OPC_6502_3E(void)894 static void OPC_6502_3E (void)
895 /* Opcode $3E: ROL abs,x */
896 {
897 unsigned Addr;
898 unsigned Val;
899 Cycles = 7;
900 Addr = MemReadWord (Regs.PC+1) + Regs.XR;
901 if (CPU != CPU_6502 && !PAGE_CROSS (Addr, Regs.XR))
902 --Cycles;
903 Val = MemReadByte (Addr);
904 ROL (Val);
905 MemWriteByte (Addr, Val);
906 Regs.PC += 2;
907 }
908
909
910
OPC_6502_40(void)911 static void OPC_6502_40 (void)
912 /* Opcode $40: RTI */
913 {
914 Cycles = 6;
915
916 /* Bits 5 and 4 aren't used, and always are 1! */
917 Regs.SR = POP () | 0x30;
918 Regs.PC = POP (); /* PCL */
919 Regs.PC |= (POP () << 8); /* PCH */
920 }
921
922
923
OPC_6502_41(void)924 static void OPC_6502_41 (void)
925 /* Opcode $41: EOR (zp,x) */
926 {
927 AC_OP_ZPXIND (^);
928 }
929
930
931
OPC_65C02_44(void)932 static void OPC_65C02_44 (void)
933 /* Opcode $44: 'zp' 3 cycle NOP */
934 {
935 Cycles = 3;
936 Regs.PC += 2;
937 }
938
939
940
OPC_6502_45(void)941 static void OPC_6502_45 (void)
942 /* Opcode $45: EOR zp */
943 {
944 AC_OP_ZP (^);
945 }
946
947
948
OPC_6502_46(void)949 static void OPC_6502_46 (void)
950 /* Opcode $46: LSR zp */
951 {
952 unsigned char ZPAddr;
953 unsigned char Val;
954 Cycles = 5;
955 ZPAddr = MemReadByte (Regs.PC+1);
956 Val = MemReadByte (ZPAddr);
957 SET_CF (Val & 0x01);
958 Val >>= 1;
959 MemWriteByte (ZPAddr, Val);
960 TEST_ZF (Val);
961 TEST_SF (Val);
962 Regs.PC += 2;
963 }
964
965
966
OPC_6502_48(void)967 static void OPC_6502_48 (void)
968 /* Opcode $48: PHA */
969 {
970 Cycles = 3;
971 PUSH (Regs.AC);
972 Regs.PC += 1;
973 }
974
975
976
OPC_6502_49(void)977 static void OPC_6502_49 (void)
978 /* Opcode $49: EOR #imm */
979 {
980 AC_OP_IMM (^);
981 }
982
983
984
OPC_6502_4A(void)985 static void OPC_6502_4A (void)
986 /* Opcode $4A: LSR a */
987 {
988 Cycles = 2;
989 SET_CF (Regs.AC & 0x01);
990 Regs.AC >>= 1;
991 TEST_ZF (Regs.AC);
992 TEST_SF (Regs.AC);
993 Regs.PC += 1;
994 }
995
996
997
OPC_6502_4C(void)998 static void OPC_6502_4C (void)
999 /* Opcode $4C: JMP abs */
1000 {
1001 Cycles = 3;
1002 Regs.PC = MemReadWord (Regs.PC+1);
1003
1004 ParaVirtHooks (&Regs);
1005 }
1006
1007
1008
OPC_6502_4D(void)1009 static void OPC_6502_4D (void)
1010 /* Opcode $4D: EOR abs */
1011 {
1012 AC_OP_ABS (^);
1013 }
1014
1015
1016
OPC_6502_4E(void)1017 static void OPC_6502_4E (void)
1018 /* Opcode $4E: LSR abs */
1019 {
1020 unsigned Addr;
1021 unsigned char Val;
1022 Cycles = 6;
1023 Addr = MemReadWord (Regs.PC+1);
1024 Val = MemReadByte (Addr);
1025 SET_CF (Val & 0x01);
1026 Val >>= 1;
1027 MemWriteByte (Addr, Val);
1028 TEST_ZF (Val);
1029 TEST_SF (Val);
1030 Regs.PC += 3;
1031 }
1032
1033
1034
OPC_6502_50(void)1035 static void OPC_6502_50 (void)
1036 /* Opcode $50: BVC */
1037 {
1038 BRANCH (!GET_OF ());
1039 }
1040
1041
1042
OPC_6502_51(void)1043 static void OPC_6502_51 (void)
1044 /* Opcode $51: EOR (zp),y */
1045 {
1046 AC_OP_ZPINDY (^);
1047 }
1048
1049
1050
OPC_65SC02_52(void)1051 static void OPC_65SC02_52 (void)
1052 /* Opcode $52: EOR (zp) */
1053 {
1054 AC_OP_ZPIND (^);
1055 }
1056
1057
1058
OPC_6502_55(void)1059 static void OPC_6502_55 (void)
1060 /* Opcode $55: EOR zp,x */
1061 {
1062 AC_OP_ZPX (^);
1063 }
1064
1065
1066
OPC_6502_56(void)1067 static void OPC_6502_56 (void)
1068 /* Opcode $56: LSR zp,x */
1069 {
1070 unsigned char ZPAddr;
1071 unsigned char Val;
1072 Cycles = 6;
1073 ZPAddr = MemReadByte (Regs.PC+1) + Regs.XR;
1074 Val = MemReadByte (ZPAddr);
1075 SET_CF (Val & 0x01);
1076 Val >>= 1;
1077 MemWriteByte (ZPAddr, Val);
1078 TEST_ZF (Val);
1079 TEST_SF (Val);
1080 Regs.PC += 2;
1081 }
1082
1083
1084
OPC_6502_58(void)1085 static void OPC_6502_58 (void)
1086 /* Opcode $58: CLI */
1087 {
1088 Cycles = 2;
1089 SET_IF (0);
1090 Regs.PC += 1;
1091 }
1092
1093
1094
OPC_6502_59(void)1095 static void OPC_6502_59 (void)
1096 /* Opcode $59: EOR abs,y */
1097 {
1098 AC_OP_ABSY (^);
1099 }
1100
1101
1102
OPC_65SC02_5A(void)1103 static void OPC_65SC02_5A (void)
1104 /* Opcode $5A: PHY */
1105 {
1106 Cycles = 3;
1107 PUSH (Regs.YR);
1108 Regs.PC += 1;
1109 }
1110
1111
1112
OPC_65C02_5C(void)1113 static void OPC_65C02_5C (void)
1114 /* Opcode $5C: 'Absolute' 8 cycle NOP */
1115 {
1116 Cycles = 8;
1117 Regs.PC += 3;
1118 }
1119
1120
1121
OPC_6502_5D(void)1122 static void OPC_6502_5D (void)
1123 /* Opcode $5D: EOR abs,x */
1124 {
1125 AC_OP_ABSX (^);
1126 }
1127
1128
1129
OPC_6502_5E(void)1130 static void OPC_6502_5E (void)
1131 /* Opcode $5E: LSR abs,x */
1132 {
1133 unsigned Addr;
1134 unsigned char Val;
1135 Cycles = 7;
1136 Addr = MemReadWord (Regs.PC+1) + Regs.XR;
1137 if (CPU != CPU_6502 && !PAGE_CROSS (Addr, Regs.XR))
1138 --Cycles;
1139 Val = MemReadByte (Addr);
1140 SET_CF (Val & 0x01);
1141 Val >>= 1;
1142 MemWriteByte (Addr, Val);
1143 TEST_ZF (Val);
1144 TEST_SF (Val);
1145 Regs.PC += 3;
1146 }
1147
1148
1149
OPC_6502_60(void)1150 static void OPC_6502_60 (void)
1151 /* Opcode $60: RTS */
1152 {
1153 Cycles = 6;
1154 Regs.PC = POP (); /* PCL */
1155 Regs.PC |= (POP () << 8); /* PCH */
1156 Regs.PC += 1;
1157 }
1158
1159
1160
OPC_6502_61(void)1161 static void OPC_6502_61 (void)
1162 /* Opcode $61: ADC (zp,x) */
1163 {
1164 unsigned char ZPAddr;
1165 unsigned Addr;
1166 Cycles = 6;
1167 ZPAddr = MemReadByte (Regs.PC+1) + Regs.XR;
1168 Addr = MemReadZPWord (ZPAddr);
1169 ADC (MemReadByte (Addr));
1170 Regs.PC += 2;
1171 }
1172
1173
1174
OPC_65SC02_64(void)1175 static void OPC_65SC02_64 (void)
1176 /* Opcode $64: STZ zp */
1177 {
1178 unsigned char ZPAddr;
1179 Cycles = 3;
1180 ZPAddr = MemReadByte (Regs.PC+1);
1181 MemWriteByte (ZPAddr, 0);
1182 Regs.PC += 2;
1183 }
1184
1185
1186
OPC_6502_65(void)1187 static void OPC_6502_65 (void)
1188 /* Opcode $65: ADC zp */
1189 {
1190 unsigned char ZPAddr;
1191 Cycles = 3;
1192 ZPAddr = MemReadByte (Regs.PC+1);
1193 ADC (MemReadByte (ZPAddr));
1194 Regs.PC += 2;
1195 }
1196
1197
1198
OPC_6502_66(void)1199 static void OPC_6502_66 (void)
1200 /* Opcode $66: ROR zp */
1201 {
1202 unsigned char ZPAddr;
1203 unsigned Val;
1204 Cycles = 5;
1205 ZPAddr = MemReadByte (Regs.PC+1);
1206 Val = MemReadByte (ZPAddr);
1207 ROR (Val);
1208 MemWriteByte (ZPAddr, Val);
1209 Regs.PC += 2;
1210 }
1211
1212
1213
OPC_6502_68(void)1214 static void OPC_6502_68 (void)
1215 /* Opcode $68: PLA */
1216 {
1217 Cycles = 4;
1218 Regs.AC = POP ();
1219 TEST_ZF (Regs.AC);
1220 TEST_SF (Regs.AC);
1221 Regs.PC += 1;
1222 }
1223
1224
1225
OPC_6502_69(void)1226 static void OPC_6502_69 (void)
1227 /* Opcode $69: ADC #imm */
1228 {
1229 Cycles = 2;
1230 ADC (MemReadByte (Regs.PC+1));
1231 Regs.PC += 2;
1232 }
1233
1234
1235
OPC_6502_6A(void)1236 static void OPC_6502_6A (void)
1237 /* Opcode $6A: ROR a */
1238 {
1239 Cycles = 2;
1240 ROR (Regs.AC);
1241 Regs.PC += 1;
1242 }
1243
1244
1245
OPC_6502_6C(void)1246 static void OPC_6502_6C (void)
1247 /* Opcode $6C: JMP (ind) */
1248 {
1249 unsigned PC, Lo, Hi;
1250 PC = Regs.PC;
1251 Lo = MemReadWord (PC+1);
1252
1253 if (CPU == CPU_6502)
1254 {
1255 /* Emulate the 6502 bug */
1256 Cycles = 5;
1257 Regs.PC = MemReadByte (Lo);
1258 Hi = (Lo & 0xFF00) | ((Lo + 1) & 0xFF);
1259 Regs.PC |= (MemReadByte (Hi) << 8);
1260
1261 /* Output a warning if the bug is triggered */
1262 if (Hi != Lo + 1)
1263 {
1264 Warning ("6502 indirect jump bug triggered at $%04X, ind addr = $%04X",
1265 PC, Lo);
1266 }
1267 }
1268 else
1269 {
1270 Cycles = 6;
1271 Regs.PC = MemReadWord(Lo);
1272 }
1273
1274 ParaVirtHooks (&Regs);
1275 }
1276
1277
1278
OPC_65C02_6C(void)1279 static void OPC_65C02_6C (void)
1280 /* Opcode $6C: JMP (ind) */
1281 {
1282 /* 6502 bug fixed here */
1283 Cycles = 5;
1284 Regs.PC = MemReadWord (MemReadWord (Regs.PC+1));
1285
1286 ParaVirtHooks (&Regs);
1287 }
1288
1289
1290
OPC_6502_6D(void)1291 static void OPC_6502_6D (void)
1292 /* Opcode $6D: ADC abs */
1293 {
1294 unsigned Addr;
1295 Cycles = 4;
1296 Addr = MemReadWord (Regs.PC+1);
1297 ADC (MemReadByte (Addr));
1298 Regs.PC += 3;
1299 }
1300
1301
1302
OPC_6502_6E(void)1303 static void OPC_6502_6E (void)
1304 /* Opcode $6E: ROR abs */
1305 {
1306 unsigned Addr;
1307 unsigned Val;
1308 Cycles = 6;
1309 Addr = MemReadWord (Regs.PC+1);
1310 Val = MemReadByte (Addr);
1311 ROR (Val);
1312 MemWriteByte (Addr, Val);
1313 Regs.PC += 3;
1314 }
1315
1316
1317
OPC_6502_70(void)1318 static void OPC_6502_70 (void)
1319 /* Opcode $70: BVS */
1320 {
1321 BRANCH (GET_OF ());
1322 }
1323
1324
1325
OPC_6502_71(void)1326 static void OPC_6502_71 (void)
1327 /* Opcode $71: ADC (zp),y */
1328 {
1329 unsigned char ZPAddr;
1330 unsigned Addr;
1331 Cycles = 5;
1332 ZPAddr = MemReadByte (Regs.PC+1);
1333 Addr = MemReadZPWord (ZPAddr);
1334 if (PAGE_CROSS (Addr, Regs.YR)) {
1335 ++Cycles;
1336 }
1337 ADC (MemReadByte (Addr + Regs.YR));
1338 Regs.PC += 2;
1339 }
1340
1341
1342
OPC_65SC02_72(void)1343 static void OPC_65SC02_72 (void)
1344 /* Opcode $72: ADC (zp) */
1345 {
1346 unsigned char ZPAddr;
1347 unsigned Addr;
1348 Cycles = 5;
1349 ZPAddr = MemReadByte (Regs.PC+1);
1350 Addr = MemReadZPWord (ZPAddr);
1351 ADC (MemReadByte (Addr));
1352 Regs.PC += 2;
1353 }
1354
1355
1356
OPC_65SC02_74(void)1357 static void OPC_65SC02_74 (void)
1358 /* Opcode $74: STZ zp,x */
1359 {
1360 unsigned char ZPAddr;
1361 Cycles = 4;
1362 ZPAddr = MemReadByte (Regs.PC+1) + Regs.XR;
1363 MemWriteByte (ZPAddr, 0);
1364 Regs.PC += 2;
1365 }
1366
1367
1368
OPC_6502_75(void)1369 static void OPC_6502_75 (void)
1370 /* Opcode $75: ADC zp,x */
1371 {
1372 unsigned char ZPAddr;
1373 Cycles = 4;
1374 ZPAddr = MemReadByte (Regs.PC+1) + Regs.XR;
1375 ADC (MemReadByte (ZPAddr));
1376 Regs.PC += 2;
1377 }
1378
1379
1380
OPC_6502_76(void)1381 static void OPC_6502_76 (void)
1382 /* Opcode $76: ROR zp,x */
1383 {
1384 unsigned char ZPAddr;
1385 unsigned Val;
1386 Cycles = 6;
1387 ZPAddr = MemReadByte (Regs.PC+1) + Regs.XR;
1388 Val = MemReadByte (ZPAddr);
1389 ROR (Val);
1390 MemWriteByte (ZPAddr, Val);
1391 Regs.PC += 2;
1392 }
1393
1394
1395
OPC_6502_78(void)1396 static void OPC_6502_78 (void)
1397 /* Opcode $78: SEI */
1398 {
1399 Cycles = 2;
1400 SET_IF (1);
1401 Regs.PC += 1;
1402 }
1403
1404
1405
OPC_6502_79(void)1406 static void OPC_6502_79 (void)
1407 /* Opcode $79: ADC abs,y */
1408 {
1409 unsigned Addr;
1410 Cycles = 4;
1411 Addr = MemReadWord (Regs.PC+1);
1412 if (PAGE_CROSS (Addr, Regs.YR)) {
1413 ++Cycles;
1414 }
1415 ADC (MemReadByte (Addr + Regs.YR));
1416 Regs.PC += 3;
1417 }
1418
1419
1420
OPC_65SC02_7A(void)1421 static void OPC_65SC02_7A (void)
1422 /* Opcode $7A: PLY */
1423 {
1424 Cycles = 4;
1425 Regs.YR = POP ();
1426 TEST_ZF (Regs.YR);
1427 TEST_SF (Regs.YR);
1428 Regs.PC += 1;
1429 }
1430
1431
1432
OPC_65SC02_7C(void)1433 static void OPC_65SC02_7C (void)
1434 /* Opcode $7C: JMP (ind,X) */
1435 {
1436 unsigned PC, Adr;
1437 Cycles = 6;
1438 PC = Regs.PC;
1439 Adr = MemReadWord (PC+1);
1440 Regs.PC = MemReadWord(Adr+Regs.XR);
1441
1442 ParaVirtHooks (&Regs);
1443 }
1444
1445
1446
OPC_6502_7D(void)1447 static void OPC_6502_7D (void)
1448 /* Opcode $7D: ADC abs,x */
1449 {
1450 unsigned Addr;
1451 Cycles = 4;
1452 Addr = MemReadWord (Regs.PC+1);
1453 if (PAGE_CROSS (Addr, Regs.XR)) {
1454 ++Cycles;
1455 }
1456 ADC (MemReadByte (Addr + Regs.XR));
1457 Regs.PC += 3;
1458 }
1459
1460
1461
OPC_6502_7E(void)1462 static void OPC_6502_7E (void)
1463 /* Opcode $7E: ROR abs,x */
1464 {
1465 unsigned Addr;
1466 unsigned Val;
1467 Cycles = 7;
1468 Addr = MemReadWord (Regs.PC+1) + Regs.XR;
1469 if (CPU != CPU_6502 && !PAGE_CROSS (Addr, Regs.XR))
1470 --Cycles;
1471 Val = MemReadByte (Addr);
1472 ROR (Val);
1473 MemWriteByte (Addr, Val);
1474 Regs.PC += 3;
1475 }
1476
1477
1478
OPC_65SC02_80(void)1479 static void OPC_65SC02_80 (void)
1480 /* Opcode $80: BRA */
1481 {
1482 BRANCH (1);
1483 }
1484
1485
1486
OPC_6502_81(void)1487 static void OPC_6502_81 (void)
1488 /* Opcode $81: STA (zp,x) */
1489 {
1490 unsigned char ZPAddr;
1491 unsigned Addr;
1492 Cycles = 6;
1493 ZPAddr = MemReadByte (Regs.PC+1) + Regs.XR;
1494 Addr = MemReadZPWord (ZPAddr);
1495 MemWriteByte (Addr, Regs.AC);
1496 Regs.PC += 2;
1497 }
1498
1499
1500
OPC_6502_84(void)1501 static void OPC_6502_84 (void)
1502 /* Opcode $84: STY zp */
1503 {
1504 unsigned char ZPAddr;
1505 Cycles = 3;
1506 ZPAddr = MemReadByte (Regs.PC+1);
1507 MemWriteByte (ZPAddr, Regs.YR);
1508 Regs.PC += 2;
1509 }
1510
1511
1512
OPC_6502_85(void)1513 static void OPC_6502_85 (void)
1514 /* Opcode $85: STA zp */
1515 {
1516 unsigned char ZPAddr;
1517 Cycles = 3;
1518 ZPAddr = MemReadByte (Regs.PC+1);
1519 MemWriteByte (ZPAddr, Regs.AC);
1520 Regs.PC += 2;
1521 }
1522
1523
1524
OPC_6502_86(void)1525 static void OPC_6502_86 (void)
1526 /* Opcode $86: STX zp */
1527 {
1528 unsigned char ZPAddr;
1529 Cycles = 3;
1530 ZPAddr = MemReadByte (Regs.PC+1);
1531 MemWriteByte (ZPAddr, Regs.XR);
1532 Regs.PC += 2;
1533 }
1534
1535
1536
OPC_6502_88(void)1537 static void OPC_6502_88 (void)
1538 /* Opcode $88: DEY */
1539 {
1540 Cycles = 2;
1541 Regs.YR = (Regs.YR - 1) & 0xFF;
1542 TEST_ZF (Regs.YR);
1543 TEST_SF (Regs.YR);
1544 Regs.PC += 1;
1545 }
1546
1547
1548
OPC_65SC02_89(void)1549 static void OPC_65SC02_89 (void)
1550 /* Opcode $89: BIT #imm */
1551 {
1552 unsigned char Val;
1553 Cycles = 2;
1554 Val = MemReadByte (Regs.PC+1);
1555 SET_SF (Val & 0x80);
1556 SET_OF (Val & 0x40);
1557 SET_ZF ((Val & Regs.AC) == 0);
1558 Regs.PC += 2;
1559 }
1560
1561
1562
OPC_6502_8A(void)1563 static void OPC_6502_8A (void)
1564 /* Opcode $8A: TXA */
1565 {
1566 Cycles = 2;
1567 Regs.AC = Regs.XR;
1568 TEST_ZF (Regs.AC);
1569 TEST_SF (Regs.AC);
1570 Regs.PC += 1;
1571 }
1572
1573
1574
OPC_6502_8C(void)1575 static void OPC_6502_8C (void)
1576 /* Opcode $8C: STY abs */
1577 {
1578 unsigned Addr;
1579 Cycles = 4;
1580 Addr = MemReadWord (Regs.PC+1);
1581 MemWriteByte (Addr, Regs.YR);
1582 Regs.PC += 3;
1583 }
1584
1585
1586
OPC_6502_8D(void)1587 static void OPC_6502_8D (void)
1588 /* Opcode $8D: STA abs */
1589 {
1590 unsigned Addr;
1591 Cycles = 4;
1592 Addr = MemReadWord (Regs.PC+1);
1593 MemWriteByte (Addr, Regs.AC);
1594 Regs.PC += 3;
1595 }
1596
1597
1598
OPC_6502_8E(void)1599 static void OPC_6502_8E (void)
1600 /* Opcode $8E: STX abs */
1601 {
1602 unsigned Addr;
1603 Cycles = 4;
1604 Addr = MemReadWord (Regs.PC+1);
1605 MemWriteByte (Addr, Regs.XR);
1606 Regs.PC += 3;
1607 }
1608
1609
1610
OPC_6502_90(void)1611 static void OPC_6502_90 (void)
1612 /* Opcode $90: BCC */
1613 {
1614 BRANCH (!GET_CF ());
1615 }
1616
1617
1618
OPC_6502_91(void)1619 static void OPC_6502_91 (void)
1620 /* Opcode $91: sta (zp),y */
1621 {
1622 unsigned char ZPAddr;
1623 unsigned Addr;
1624 Cycles = 6;
1625 ZPAddr = MemReadByte (Regs.PC+1);
1626 Addr = MemReadZPWord (ZPAddr) + Regs.YR;
1627 MemWriteByte (Addr, Regs.AC);
1628 Regs.PC += 2;
1629 }
1630
1631
1632
OPC_65SC02_92(void)1633 static void OPC_65SC02_92 (void)
1634 /* Opcode $92: sta (zp) */
1635 {
1636 unsigned char ZPAddr;
1637 unsigned Addr;
1638 Cycles = 5;
1639 ZPAddr = MemReadByte (Regs.PC+1);
1640 Addr = MemReadZPWord (ZPAddr);
1641 MemWriteByte (Addr, Regs.AC);
1642 Regs.PC += 2;
1643 }
1644
1645
1646
OPC_6502_94(void)1647 static void OPC_6502_94 (void)
1648 /* Opcode $94: STY zp,x */
1649 {
1650 unsigned char ZPAddr;
1651 Cycles = 4;
1652 ZPAddr = MemReadByte (Regs.PC+1) + Regs.XR;
1653 MemWriteByte (ZPAddr, Regs.YR);
1654 Regs.PC += 2;
1655 }
1656
1657
1658
OPC_6502_95(void)1659 static void OPC_6502_95 (void)
1660 /* Opcode $95: STA zp,x */
1661 {
1662 unsigned char ZPAddr;
1663 Cycles = 4;
1664 ZPAddr = MemReadByte (Regs.PC+1) + Regs.XR;
1665 MemWriteByte (ZPAddr, Regs.AC);
1666 Regs.PC += 2;
1667 }
1668
1669
1670
OPC_6502_96(void)1671 static void OPC_6502_96 (void)
1672 /* Opcode $96: stx zp,y */
1673 {
1674 unsigned char ZPAddr;
1675 Cycles = 4;
1676 ZPAddr = MemReadByte (Regs.PC+1) + Regs.YR;
1677 MemWriteByte (ZPAddr, Regs.XR);
1678 Regs.PC += 2;
1679 }
1680
1681
1682
OPC_6502_98(void)1683 static void OPC_6502_98 (void)
1684 /* Opcode $98: TYA */
1685 {
1686 Cycles = 2;
1687 Regs.AC = Regs.YR;
1688 TEST_ZF (Regs.AC);
1689 TEST_SF (Regs.AC);
1690 Regs.PC += 1;
1691 }
1692
1693
1694
OPC_6502_99(void)1695 static void OPC_6502_99 (void)
1696 /* Opcode $99: STA abs,y */
1697 {
1698 unsigned Addr;
1699 Cycles = 5;
1700 Addr = MemReadWord (Regs.PC+1) + Regs.YR;
1701 MemWriteByte (Addr, Regs.AC);
1702 Regs.PC += 3;
1703 }
1704
1705
1706
OPC_6502_9A(void)1707 static void OPC_6502_9A (void)
1708 /* Opcode $9A: TXS */
1709 {
1710 Cycles = 2;
1711 Regs.SP = Regs.XR;
1712 Regs.PC += 1;
1713 }
1714
1715
1716
OPC_65SC02_9C(void)1717 static void OPC_65SC02_9C (void)
1718 /* Opcode $9C: STZ abs */
1719 {
1720 unsigned Addr;
1721 Cycles = 4;
1722 Addr = MemReadWord (Regs.PC+1);
1723 MemWriteByte (Addr, 0);
1724 Regs.PC += 3;
1725 }
1726
1727
1728
OPC_6502_9D(void)1729 static void OPC_6502_9D (void)
1730 /* Opcode $9D: STA abs,x */
1731 {
1732 unsigned Addr;
1733 Cycles = 5;
1734 Addr = MemReadWord (Regs.PC+1) + Regs.XR;
1735 MemWriteByte (Addr, Regs.AC);
1736 Regs.PC += 3;
1737 }
1738
1739
1740
OPC_65SC02_9E(void)1741 static void OPC_65SC02_9E (void)
1742 /* Opcode $9E: STZ abs,x */
1743 {
1744 unsigned Addr;
1745 Cycles = 5;
1746 Addr = MemReadWord (Regs.PC+1) + Regs.XR;
1747 MemWriteByte (Addr, 0);
1748 Regs.PC += 3;
1749 }
1750
1751
1752
OPC_6502_A0(void)1753 static void OPC_6502_A0 (void)
1754 /* Opcode $A0: LDY #imm */
1755 {
1756 Cycles = 2;
1757 Regs.YR = MemReadByte (Regs.PC+1);
1758 TEST_ZF (Regs.YR);
1759 TEST_SF (Regs.YR);
1760 Regs.PC += 2;
1761 }
1762
1763
1764
OPC_6502_A1(void)1765 static void OPC_6502_A1 (void)
1766 /* Opcode $A1: LDA (zp,x) */
1767 {
1768 unsigned char ZPAddr;
1769 unsigned Addr;
1770 Cycles = 6;
1771 ZPAddr = MemReadByte (Regs.PC+1) + Regs.XR;
1772 Addr = MemReadZPWord (ZPAddr);
1773 Regs.AC = MemReadByte (Addr);
1774 TEST_ZF (Regs.AC);
1775 TEST_SF (Regs.AC);
1776 Regs.PC += 2;
1777 }
1778
1779
1780
OPC_6502_A2(void)1781 static void OPC_6502_A2 (void)
1782 /* Opcode $A2: LDX #imm */
1783 {
1784 Cycles = 2;
1785 Regs.XR = MemReadByte (Regs.PC+1);
1786 TEST_ZF (Regs.XR);
1787 TEST_SF (Regs.XR);
1788 Regs.PC += 2;
1789 }
1790
1791
1792
OPC_6502_A4(void)1793 static void OPC_6502_A4 (void)
1794 /* Opcode $A4: LDY zp */
1795 {
1796 unsigned char ZPAddr;
1797 Cycles = 3;
1798 ZPAddr = MemReadByte (Regs.PC+1);
1799 Regs.YR = MemReadByte (ZPAddr);
1800 TEST_ZF (Regs.YR);
1801 TEST_SF (Regs.YR);
1802 Regs.PC += 2;
1803 }
1804
1805
1806
OPC_6502_A5(void)1807 static void OPC_6502_A5 (void)
1808 /* Opcode $A5: LDA zp */
1809 {
1810 unsigned char ZPAddr;
1811 Cycles = 3;
1812 ZPAddr = MemReadByte (Regs.PC+1);
1813 Regs.AC = MemReadByte (ZPAddr);
1814 TEST_ZF (Regs.AC);
1815 TEST_SF (Regs.AC);
1816 Regs.PC += 2;
1817 }
1818
1819
1820
OPC_6502_A6(void)1821 static void OPC_6502_A6 (void)
1822 /* Opcode $A6: LDX zp */
1823 {
1824 unsigned char ZPAddr;
1825 Cycles = 3;
1826 ZPAddr = MemReadByte (Regs.PC+1);
1827 Regs.XR = MemReadByte (ZPAddr);
1828 TEST_ZF (Regs.XR);
1829 TEST_SF (Regs.XR);
1830 Regs.PC += 2;
1831 }
1832
1833
1834
OPC_6502_A8(void)1835 static void OPC_6502_A8 (void)
1836 /* Opcode $A8: TAY */
1837 {
1838 Cycles = 2;
1839 Regs.YR = Regs.AC;
1840 TEST_ZF (Regs.YR);
1841 TEST_SF (Regs.YR);
1842 Regs.PC += 1;
1843 }
1844
1845
1846
OPC_6502_A9(void)1847 static void OPC_6502_A9 (void)
1848 /* Opcode $A9: LDA #imm */
1849 {
1850 Cycles = 2;
1851 Regs.AC = MemReadByte (Regs.PC+1);
1852 TEST_ZF (Regs.AC);
1853 TEST_SF (Regs.AC);
1854 Regs.PC += 2;
1855 }
1856
1857
1858
OPC_6502_AA(void)1859 static void OPC_6502_AA (void)
1860 /* Opcode $AA: TAX */
1861 {
1862 Cycles = 2;
1863 Regs.XR = Regs.AC;
1864 TEST_ZF (Regs.XR);
1865 TEST_SF (Regs.XR);
1866 Regs.PC += 1;
1867 }
1868
1869
1870
OPC_6502_AC(void)1871 static void OPC_6502_AC (void)
1872 /* Opcode $Regs.AC: LDY abs */
1873 {
1874 unsigned Addr;
1875 Cycles = 4;
1876 Addr = MemReadWord (Regs.PC+1);
1877 Regs.YR = MemReadByte (Addr);
1878 TEST_ZF (Regs.YR);
1879 TEST_SF (Regs.YR);
1880 Regs.PC += 3;
1881 }
1882
1883
1884
OPC_6502_AD(void)1885 static void OPC_6502_AD (void)
1886 /* Opcode $AD: LDA abs */
1887 {
1888 unsigned Addr;
1889 Cycles = 4;
1890 Addr = MemReadWord (Regs.PC+1);
1891 Regs.AC = MemReadByte (Addr);
1892 TEST_ZF (Regs.AC);
1893 TEST_SF (Regs.AC);
1894 Regs.PC += 3;
1895 }
1896
1897
1898
OPC_6502_AE(void)1899 static void OPC_6502_AE (void)
1900 /* Opcode $AE: LDX abs */
1901 {
1902 unsigned Addr;
1903 Cycles = 4;
1904 Addr = MemReadWord (Regs.PC+1);
1905 Regs.XR = MemReadByte (Addr);
1906 TEST_ZF (Regs.XR);
1907 TEST_SF (Regs.XR);
1908 Regs.PC += 3;
1909 }
1910
1911
1912
OPC_6502_B0(void)1913 static void OPC_6502_B0 (void)
1914 /* Opcode $B0: BCS */
1915 {
1916 BRANCH (GET_CF ());
1917 }
1918
1919
1920
OPC_6502_B1(void)1921 static void OPC_6502_B1 (void)
1922 /* Opcode $B1: LDA (zp),y */
1923 {
1924 unsigned char ZPAddr;
1925 unsigned Addr;
1926 Cycles = 5;
1927 ZPAddr = MemReadByte (Regs.PC+1);
1928 Addr = MemReadZPWord (ZPAddr);
1929 if (PAGE_CROSS (Addr, Regs.YR)) {
1930 ++Cycles;
1931 }
1932 Regs.AC = MemReadByte (Addr + Regs.YR);
1933 TEST_ZF (Regs.AC);
1934 TEST_SF (Regs.AC);
1935 Regs.PC += 2;
1936 }
1937
1938
1939
OPC_65SC02_B2(void)1940 static void OPC_65SC02_B2 (void)
1941 /* Opcode $B2: LDA (zp) */
1942 {
1943 unsigned char ZPAddr;
1944 unsigned Addr;
1945 Cycles = 5;
1946 ZPAddr = MemReadByte (Regs.PC+1);
1947 Addr = MemReadZPWord (ZPAddr);
1948 Regs.AC = MemReadByte (Addr);
1949 TEST_ZF (Regs.AC);
1950 TEST_SF (Regs.AC);
1951 Regs.PC += 2;
1952 }
1953
1954
1955
OPC_6502_B4(void)1956 static void OPC_6502_B4 (void)
1957 /* Opcode $B4: LDY zp,x */
1958 {
1959 unsigned char ZPAddr;
1960 Cycles = 4;
1961 ZPAddr = MemReadByte (Regs.PC+1) + Regs.XR;
1962 Regs.YR = MemReadByte (ZPAddr);
1963 TEST_ZF (Regs.YR);
1964 TEST_SF (Regs.YR);
1965 Regs.PC += 2;
1966 }
1967
1968
1969
OPC_6502_B5(void)1970 static void OPC_6502_B5 (void)
1971 /* Opcode $B5: LDA zp,x */
1972 {
1973 unsigned char ZPAddr;
1974 Cycles = 4;
1975 ZPAddr = MemReadByte (Regs.PC+1) + Regs.XR;
1976 Regs.AC = MemReadByte (ZPAddr);
1977 TEST_ZF (Regs.AC);
1978 TEST_SF (Regs.AC);
1979 Regs.PC += 2;
1980 }
1981
1982
1983
OPC_6502_B6(void)1984 static void OPC_6502_B6 (void)
1985 /* Opcode $B6: LDX zp,y */
1986 {
1987 unsigned char ZPAddr;
1988 Cycles = 4;
1989 ZPAddr = MemReadByte (Regs.PC+1) + Regs.YR;
1990 Regs.XR = MemReadByte (ZPAddr);
1991 TEST_ZF (Regs.XR);
1992 TEST_SF (Regs.XR);
1993 Regs.PC += 2;
1994 }
1995
1996
1997
OPC_6502_B8(void)1998 static void OPC_6502_B8 (void)
1999 /* Opcode $B8: CLV */
2000 {
2001 Cycles = 2;
2002 SET_OF (0);
2003 Regs.PC += 1;
2004 }
2005
2006
2007
OPC_6502_B9(void)2008 static void OPC_6502_B9 (void)
2009 /* Opcode $B9: LDA abs,y */
2010 {
2011 unsigned Addr;
2012 Cycles = 4;
2013 Addr = MemReadWord (Regs.PC+1);
2014 if (PAGE_CROSS (Addr, Regs.YR)) {
2015 ++Cycles;
2016 }
2017 Regs.AC = MemReadByte (Addr + Regs.YR);
2018 TEST_ZF (Regs.AC);
2019 TEST_SF (Regs.AC);
2020 Regs.PC += 3;
2021 }
2022
2023
2024
OPC_6502_BA(void)2025 static void OPC_6502_BA (void)
2026 /* Opcode $BA: TSX */
2027 {
2028 Cycles = 2;
2029 Regs.XR = Regs.SP & 0xFF;
2030 TEST_ZF (Regs.XR);
2031 TEST_SF (Regs.XR);
2032 Regs.PC += 1;
2033 }
2034
2035
2036
OPC_6502_BC(void)2037 static void OPC_6502_BC (void)
2038 /* Opcode $BC: LDY abs,x */
2039 {
2040 unsigned Addr;
2041 Cycles = 4;
2042 Addr = MemReadWord (Regs.PC+1);
2043 if (PAGE_CROSS (Addr, Regs.XR)) {
2044 ++Cycles;
2045 }
2046 Regs.YR = MemReadByte (Addr + Regs.XR);
2047 TEST_ZF (Regs.YR);
2048 TEST_SF (Regs.YR);
2049 Regs.PC += 3;
2050 }
2051
2052
2053
OPC_6502_BD(void)2054 static void OPC_6502_BD (void)
2055 /* Opcode $BD: LDA abs,x */
2056 {
2057 unsigned Addr;
2058 Cycles = 4;
2059 Addr = MemReadWord (Regs.PC+1);
2060 if (PAGE_CROSS (Addr, Regs.XR)) {
2061 ++Cycles;
2062 }
2063 Regs.AC = MemReadByte (Addr + Regs.XR);
2064 TEST_ZF (Regs.AC);
2065 TEST_SF (Regs.AC);
2066 Regs.PC += 3;
2067 }
2068
2069
2070
OPC_6502_BE(void)2071 static void OPC_6502_BE (void)
2072 /* Opcode $BE: LDX abs,y */
2073 {
2074 unsigned Addr;
2075 Cycles = 4;
2076 Addr = MemReadWord (Regs.PC+1);
2077 if (PAGE_CROSS (Addr, Regs.YR)) {
2078 ++Cycles;
2079 }
2080 Regs.XR = MemReadByte (Addr + Regs.YR);
2081 TEST_ZF (Regs.XR);
2082 TEST_SF (Regs.XR);
2083 Regs.PC += 3;
2084 }
2085
2086
2087
OPC_6502_C0(void)2088 static void OPC_6502_C0 (void)
2089 /* Opcode $C0: CPY #imm */
2090 {
2091 Cycles = 2;
2092 CMP (Regs.YR, MemReadByte (Regs.PC+1));
2093 Regs.PC += 2;
2094 }
2095
2096
2097
OPC_6502_C1(void)2098 static void OPC_6502_C1 (void)
2099 /* Opcode $C1: CMP (zp,x) */
2100 {
2101 unsigned char ZPAddr;
2102 unsigned Addr;
2103 Cycles = 6;
2104 ZPAddr = MemReadByte (Regs.PC+1) + Regs.XR;
2105 Addr = MemReadZPWord (ZPAddr);
2106 CMP (Regs.AC, MemReadByte (Addr));
2107 Regs.PC += 2;
2108 }
2109
2110
2111
OPC_6502_C4(void)2112 static void OPC_6502_C4 (void)
2113 /* Opcode $C4: CPY zp */
2114 {
2115 unsigned char ZPAddr;
2116 Cycles = 3;
2117 ZPAddr = MemReadByte (Regs.PC+1);
2118 CMP (Regs.YR, MemReadByte (ZPAddr));
2119 Regs.PC += 2;
2120 }
2121
2122
2123
OPC_6502_C5(void)2124 static void OPC_6502_C5 (void)
2125 /* Opcode $C5: CMP zp */
2126 {
2127 unsigned char ZPAddr;
2128 Cycles = 3;
2129 ZPAddr = MemReadByte (Regs.PC+1);
2130 CMP (Regs.AC, MemReadByte (ZPAddr));
2131 Regs.PC += 2;
2132 }
2133
2134
2135
OPC_6502_C6(void)2136 static void OPC_6502_C6 (void)
2137 /* Opcode $C6: DEC zp */
2138 {
2139 unsigned char ZPAddr;
2140 unsigned char Val;
2141 Cycles = 5;
2142 ZPAddr = MemReadByte (Regs.PC+1);
2143 Val = MemReadByte (ZPAddr) - 1;
2144 MemWriteByte (ZPAddr, Val);
2145 TEST_ZF (Val);
2146 TEST_SF (Val);
2147 Regs.PC += 2;
2148 }
2149
2150
2151
OPC_6502_C8(void)2152 static void OPC_6502_C8 (void)
2153 /* Opcode $C8: INY */
2154 {
2155 Cycles = 2;
2156 Regs.YR = (Regs.YR + 1) & 0xFF;
2157 TEST_ZF (Regs.YR);
2158 TEST_SF (Regs.YR);
2159 Regs.PC += 1;
2160 }
2161
2162
2163
OPC_6502_C9(void)2164 static void OPC_6502_C9 (void)
2165 /* Opcode $C9: CMP #imm */
2166 {
2167 Cycles = 2;
2168 CMP (Regs.AC, MemReadByte (Regs.PC+1));
2169 Regs.PC += 2;
2170 }
2171
2172
2173
OPC_6502_CA(void)2174 static void OPC_6502_CA (void)
2175 /* Opcode $CA: DEX */
2176 {
2177 Cycles = 2;
2178 Regs.XR = (Regs.XR - 1) & 0xFF;
2179 TEST_ZF (Regs.XR);
2180 TEST_SF (Regs.XR);
2181 Regs.PC += 1;
2182 }
2183
2184
2185
OPC_6502_CC(void)2186 static void OPC_6502_CC (void)
2187 /* Opcode $CC: CPY abs */
2188 {
2189 unsigned Addr;
2190 Cycles = 4;
2191 Addr = MemReadWord (Regs.PC+1);
2192 CMP (Regs.YR, MemReadByte (Addr));
2193 Regs.PC += 3;
2194 }
2195
2196
2197
OPC_6502_CD(void)2198 static void OPC_6502_CD (void)
2199 /* Opcode $CD: CMP abs */
2200 {
2201 unsigned Addr;
2202 Cycles = 4;
2203 Addr = MemReadWord (Regs.PC+1);
2204 CMP (Regs.AC, MemReadByte (Addr));
2205 Regs.PC += 3;
2206 }
2207
2208
2209
OPC_6502_CE(void)2210 static void OPC_6502_CE (void)
2211 /* Opcode $CE: DEC abs */
2212 {
2213 unsigned Addr;
2214 unsigned char Val;
2215 Cycles = 6;
2216 Addr = MemReadWord (Regs.PC+1);
2217 Val = MemReadByte (Addr) - 1;
2218 MemWriteByte (Addr, Val);
2219 TEST_ZF (Val);
2220 TEST_SF (Val);
2221 Regs.PC += 3;
2222 }
2223
2224
2225
OPC_6502_D0(void)2226 static void OPC_6502_D0 (void)
2227 /* Opcode $D0: BNE */
2228 {
2229 BRANCH (!GET_ZF ());
2230 }
2231
2232
2233
OPC_6502_D1(void)2234 static void OPC_6502_D1 (void)
2235 /* Opcode $D1: CMP (zp),y */
2236 {
2237 unsigned ZPAddr;
2238 unsigned Addr;
2239 Cycles = 5;
2240 ZPAddr = MemReadByte (Regs.PC+1);
2241 Addr = MemReadWord (ZPAddr);
2242 if (PAGE_CROSS (Addr, Regs.YR)) {
2243 ++Cycles;
2244 }
2245 CMP (Regs.AC, MemReadByte (Addr + Regs.YR));
2246 Regs.PC += 2;
2247 }
2248
2249
2250
OPC_65SC02_D2(void)2251 static void OPC_65SC02_D2 (void)
2252 /* Opcode $D2: CMP (zp) */
2253 {
2254 unsigned ZPAddr;
2255 unsigned Addr;
2256 Cycles = 5;
2257 ZPAddr = MemReadByte (Regs.PC+1);
2258 Addr = MemReadWord (ZPAddr);
2259 CMP (Regs.AC, MemReadByte (Addr));
2260 Regs.PC += 2;
2261 }
2262
2263
2264
OPC_6502_D5(void)2265 static void OPC_6502_D5 (void)
2266 /* Opcode $D5: CMP zp,x */
2267 {
2268 unsigned char ZPAddr;
2269 Cycles = 4;
2270 ZPAddr = MemReadByte (Regs.PC+1) + Regs.XR;
2271 CMP (Regs.AC, MemReadByte (ZPAddr));
2272 Regs.PC += 2;
2273 }
2274
2275
2276
OPC_6502_D6(void)2277 static void OPC_6502_D6 (void)
2278 /* Opcode $D6: DEC zp,x */
2279 {
2280 unsigned char ZPAddr;
2281 unsigned char Val;
2282 Cycles = 6;
2283 ZPAddr = MemReadByte (Regs.PC+1) + Regs.XR;
2284 Val = MemReadByte (ZPAddr) - 1;
2285 MemWriteByte (ZPAddr, Val);
2286 TEST_ZF (Val);
2287 TEST_SF (Val);
2288 Regs.PC += 2;
2289 }
2290
2291
2292
OPC_6502_D8(void)2293 static void OPC_6502_D8 (void)
2294 /* Opcode $D8: CLD */
2295 {
2296 Cycles = 2;
2297 SET_DF (0);
2298 Regs.PC += 1;
2299 }
2300
2301
2302
OPC_6502_D9(void)2303 static void OPC_6502_D9 (void)
2304 /* Opcode $D9: CMP abs,y */
2305 {
2306 unsigned Addr;
2307 Cycles = 4;
2308 Addr = MemReadWord (Regs.PC+1);
2309 if (PAGE_CROSS (Addr, Regs.YR)) {
2310 ++Cycles;
2311 }
2312 CMP (Regs.AC, MemReadByte (Addr + Regs.YR));
2313 Regs.PC += 3;
2314 }
2315
2316
2317
OPC_65SC02_DA(void)2318 static void OPC_65SC02_DA (void)
2319 /* Opcode $DA: PHX */
2320 {
2321 Cycles = 3;
2322 PUSH (Regs.XR);
2323 Regs.PC += 1;
2324 }
2325
2326
2327
OPC_6502_DD(void)2328 static void OPC_6502_DD (void)
2329 /* Opcode $DD: CMP abs,x */
2330 {
2331 unsigned Addr;
2332 Cycles = 4;
2333 Addr = MemReadWord (Regs.PC+1);
2334 if (PAGE_CROSS (Addr, Regs.XR)) {
2335 ++Cycles;
2336 }
2337 CMP (Regs.AC, MemReadByte (Addr + Regs.XR));
2338 Regs.PC += 3;
2339 }
2340
2341
2342
OPC_6502_DE(void)2343 static void OPC_6502_DE (void)
2344 /* Opcode $DE: DEC abs,x */
2345 {
2346 unsigned Addr;
2347 unsigned char Val;
2348 Cycles = 7;
2349 Addr = MemReadWord (Regs.PC+1) + Regs.XR;
2350 Val = MemReadByte (Addr) - 1;
2351 MemWriteByte (Addr, Val);
2352 TEST_ZF (Val);
2353 TEST_SF (Val);
2354 Regs.PC += 3;
2355 }
2356
2357
2358
OPC_6502_E0(void)2359 static void OPC_6502_E0 (void)
2360 /* Opcode $E0: CPX #imm */
2361 {
2362 Cycles = 2;
2363 CMP (Regs.XR, MemReadByte (Regs.PC+1));
2364 Regs.PC += 2;
2365 }
2366
2367
2368
OPC_6502_E1(void)2369 static void OPC_6502_E1 (void)
2370 /* Opcode $E1: SBC (zp,x) */
2371 {
2372 unsigned char ZPAddr;
2373 unsigned Addr;
2374 Cycles = 6;
2375 ZPAddr = MemReadByte (Regs.PC+1) + Regs.XR;
2376 Addr = MemReadZPWord (ZPAddr);
2377 SBC (MemReadByte (Addr));
2378 Regs.PC += 2;
2379 }
2380
2381
2382
OPC_6502_E4(void)2383 static void OPC_6502_E4 (void)
2384 /* Opcode $E4: CPX zp */
2385 {
2386 unsigned char ZPAddr;
2387 Cycles = 3;
2388 ZPAddr = MemReadByte (Regs.PC+1);
2389 CMP (Regs.XR, MemReadByte (ZPAddr));
2390 Regs.PC += 2;
2391 }
2392
2393
2394
OPC_6502_E5(void)2395 static void OPC_6502_E5 (void)
2396 /* Opcode $E5: SBC zp */
2397 {
2398 unsigned char ZPAddr;
2399 Cycles = 3;
2400 ZPAddr = MemReadByte (Regs.PC+1);
2401 SBC (MemReadByte (ZPAddr));
2402 Regs.PC += 2;
2403 }
2404
2405
2406
OPC_6502_E6(void)2407 static void OPC_6502_E6 (void)
2408 /* Opcode $E6: INC zp */
2409 {
2410 unsigned char ZPAddr;
2411 unsigned char Val;
2412 Cycles = 5;
2413 ZPAddr = MemReadByte (Regs.PC+1);
2414 Val = MemReadByte (ZPAddr) + 1;
2415 MemWriteByte (ZPAddr, Val);
2416 TEST_ZF (Val);
2417 TEST_SF (Val);
2418 Regs.PC += 2;
2419 }
2420
2421
2422
OPC_6502_E8(void)2423 static void OPC_6502_E8 (void)
2424 /* Opcode $E8: INX */
2425 {
2426 Cycles = 2;
2427 Regs.XR = (Regs.XR + 1) & 0xFF;
2428 TEST_ZF (Regs.XR);
2429 TEST_SF (Regs.XR);
2430 Regs.PC += 1;
2431 }
2432
2433
2434
OPC_6502_E9(void)2435 static void OPC_6502_E9 (void)
2436 /* Opcode $E9: SBC #imm */
2437 {
2438 Cycles = 2;
2439 SBC (MemReadByte (Regs.PC+1));
2440 Regs.PC += 2;
2441 }
2442
2443
2444
OPC_6502_EA(void)2445 static void OPC_6502_EA (void)
2446 /* Opcode $EA: NOP */
2447 {
2448 /* This one is easy... */
2449 Cycles = 2;
2450 Regs.PC += 1;
2451 }
2452
2453
2454
OPC_65C02_NOP11(void)2455 static void OPC_65C02_NOP11(void)
2456 /* Opcode 'Illegal' 1 cycle NOP */
2457 {
2458 Cycles = 1;
2459 Regs.PC += 1;
2460 }
2461
2462
2463
OPC_65C02_NOP22(void)2464 static void OPC_65C02_NOP22 (void)
2465 /* Opcode 'Illegal' 2 byte 2 cycle NOP */
2466 {
2467 Cycles = 2;
2468 Regs.PC += 2;
2469 }
2470
2471
2472
OPC_65C02_NOP24(void)2473 static void OPC_65C02_NOP24 (void)
2474 /* Opcode 'Illegal' 2 byte 4 cycle NOP */
2475 {
2476 Cycles = 4;
2477 Regs.PC += 2;
2478 }
2479
2480
2481
OPC_65C02_NOP34(void)2482 static void OPC_65C02_NOP34 (void)
2483 /* Opcode 'Illegal' 3 byte 4 cycle NOP */
2484 {
2485 Cycles = 4;
2486 Regs.PC += 3;
2487 }
2488
2489
2490
OPC_6502_EC(void)2491 static void OPC_6502_EC (void)
2492 /* Opcode $EC: CPX abs */
2493 {
2494 unsigned Addr;
2495 Cycles = 4;
2496 Addr = MemReadWord (Regs.PC+1);
2497 CMP (Regs.XR, MemReadByte (Addr));
2498 Regs.PC += 3;
2499 }
2500
2501
2502
OPC_6502_ED(void)2503 static void OPC_6502_ED (void)
2504 /* Opcode $ED: SBC abs */
2505 {
2506 unsigned Addr;
2507 Cycles = 4;
2508 Addr = MemReadWord (Regs.PC+1);
2509 SBC (MemReadByte (Addr));
2510 Regs.PC += 3;
2511 }
2512
2513
2514
OPC_6502_EE(void)2515 static void OPC_6502_EE (void)
2516 /* Opcode $EE: INC abs */
2517 {
2518 unsigned Addr;
2519 unsigned char Val;
2520 Cycles = 6;
2521 Addr = MemReadWord (Regs.PC+1);
2522 Val = MemReadByte (Addr) + 1;
2523 MemWriteByte (Addr, Val);
2524 TEST_ZF (Val);
2525 TEST_SF (Val);
2526 Regs.PC += 3;
2527 }
2528
2529
2530
OPC_6502_F0(void)2531 static void OPC_6502_F0 (void)
2532 /* Opcode $F0: BEQ */
2533 {
2534 BRANCH (GET_ZF ());
2535 }
2536
2537
2538
OPC_6502_F1(void)2539 static void OPC_6502_F1 (void)
2540 /* Opcode $F1: SBC (zp),y */
2541 {
2542 unsigned char ZPAddr;
2543 unsigned Addr;
2544 Cycles = 5;
2545 ZPAddr = MemReadByte (Regs.PC+1);
2546 Addr = MemReadZPWord (ZPAddr);
2547 if (PAGE_CROSS (Addr, Regs.YR)) {
2548 ++Cycles;
2549 }
2550 SBC (MemReadByte (Addr + Regs.YR));
2551 Regs.PC += 2;
2552 }
2553
2554
2555
OPC_65SC02_F2(void)2556 static void OPC_65SC02_F2 (void)
2557 /* Opcode $F2: SBC (zp) */
2558 {
2559 unsigned char ZPAddr;
2560 unsigned Addr;
2561 Cycles = 5;
2562 ZPAddr = MemReadByte (Regs.PC+1);
2563 Addr = MemReadZPWord (ZPAddr);
2564 SBC (MemReadByte (Addr));
2565 Regs.PC += 2;
2566 }
2567
2568
2569
OPC_6502_F5(void)2570 static void OPC_6502_F5 (void)
2571 /* Opcode $F5: SBC zp,x */
2572 {
2573 unsigned char ZPAddr;
2574 Cycles = 4;
2575 ZPAddr = MemReadByte (Regs.PC+1) + Regs.XR;
2576 SBC (MemReadByte (ZPAddr));
2577 Regs.PC += 2;
2578 }
2579
2580
2581
OPC_6502_F6(void)2582 static void OPC_6502_F6 (void)
2583 /* Opcode $F6: INC zp,x */
2584 {
2585 unsigned char ZPAddr;
2586 unsigned char Val;
2587 Cycles = 6;
2588 ZPAddr = MemReadByte (Regs.PC+1) + Regs.XR;
2589 Val = MemReadByte (ZPAddr) + 1;
2590 MemWriteByte (ZPAddr, Val);
2591 TEST_ZF (Val);
2592 TEST_SF (Val);
2593 Regs.PC += 2;
2594 }
2595
2596
2597
OPC_6502_F8(void)2598 static void OPC_6502_F8 (void)
2599 /* Opcode $F8: SED */
2600 {
2601 Cycles = 2;
2602 SET_DF (1);
2603 Regs.PC += 1;
2604 }
2605
2606
2607
OPC_6502_F9(void)2608 static void OPC_6502_F9 (void)
2609 /* Opcode $F9: SBC abs,y */
2610 {
2611 unsigned Addr;
2612 Cycles = 4;
2613 Addr = MemReadWord (Regs.PC+1);
2614 if (PAGE_CROSS (Addr, Regs.YR)) {
2615 ++Cycles;
2616 }
2617 SBC (MemReadByte (Addr + Regs.YR));
2618 Regs.PC += 3;
2619 }
2620
2621
2622
OPC_65SC02_FA(void)2623 static void OPC_65SC02_FA (void)
2624 /* Opcode $7A: PLX */
2625 {
2626 Cycles = 4;
2627 Regs.XR = POP ();
2628 TEST_ZF (Regs.XR);
2629 TEST_SF (Regs.XR);
2630 Regs.PC += 1;
2631 }
2632
2633
2634
OPC_6502_FD(void)2635 static void OPC_6502_FD (void)
2636 /* Opcode $FD: SBC abs,x */
2637 {
2638 unsigned Addr;
2639 Cycles = 4;
2640 Addr = MemReadWord (Regs.PC+1);
2641 if (PAGE_CROSS (Addr, Regs.XR)) {
2642 ++Cycles;
2643 }
2644 SBC (MemReadByte (Addr + Regs.XR));
2645 Regs.PC += 3;
2646 }
2647
2648
2649
OPC_6502_FE(void)2650 static void OPC_6502_FE (void)
2651 /* Opcode $FE: INC abs,x */
2652 {
2653 unsigned Addr;
2654 unsigned char Val;
2655 Cycles = 7;
2656 Addr = MemReadWord (Regs.PC+1) + Regs.XR;
2657 Val = MemReadByte (Addr) + 1;
2658 MemWriteByte (Addr, Val);
2659 TEST_ZF (Val);
2660 TEST_SF (Val);
2661 Regs.PC += 3;
2662 }
2663
2664
2665
2666 /*****************************************************************************/
2667 /* Opcode handler tables */
2668 /*****************************************************************************/
2669
2670
2671
2672 /* Opcode handler table for the 6502 */
2673 static const OPFunc OP6502Table[256] = {
2674 OPC_6502_00,
2675 OPC_6502_01,
2676 OPC_Illegal,
2677 OPC_Illegal,
2678 OPC_Illegal,
2679 OPC_6502_05,
2680 OPC_6502_06,
2681 OPC_Illegal,
2682 OPC_6502_08,
2683 OPC_6502_09,
2684 OPC_6502_0A,
2685 OPC_Illegal,
2686 OPC_Illegal,
2687 OPC_6502_0D,
2688 OPC_6502_0E,
2689 OPC_Illegal,
2690 OPC_6502_10,
2691 OPC_6502_11,
2692 OPC_Illegal,
2693 OPC_Illegal,
2694 OPC_Illegal,
2695 OPC_6502_15,
2696 OPC_6502_16,
2697 OPC_Illegal,
2698 OPC_6502_18,
2699 OPC_6502_19,
2700 OPC_Illegal,
2701 OPC_Illegal,
2702 OPC_Illegal,
2703 OPC_6502_1D,
2704 OPC_6502_1E,
2705 OPC_Illegal,
2706 OPC_6502_20,
2707 OPC_6502_21,
2708 OPC_Illegal,
2709 OPC_Illegal,
2710 OPC_6502_24,
2711 OPC_6502_25,
2712 OPC_6502_26,
2713 OPC_Illegal,
2714 OPC_6502_28,
2715 OPC_6502_29,
2716 OPC_6502_2A,
2717 OPC_Illegal,
2718 OPC_6502_2C,
2719 OPC_6502_2D,
2720 OPC_6502_2E,
2721 OPC_Illegal,
2722 OPC_6502_30,
2723 OPC_6502_31,
2724 OPC_Illegal,
2725 OPC_Illegal,
2726 OPC_Illegal,
2727 OPC_6502_35,
2728 OPC_6502_36,
2729 OPC_Illegal,
2730 OPC_6502_38,
2731 OPC_6502_39,
2732 OPC_Illegal,
2733 OPC_Illegal,
2734 OPC_Illegal,
2735 OPC_6502_3D,
2736 OPC_6502_3E,
2737 OPC_Illegal,
2738 OPC_6502_40,
2739 OPC_6502_41,
2740 OPC_Illegal,
2741 OPC_Illegal,
2742 OPC_Illegal,
2743 OPC_6502_45,
2744 OPC_6502_46,
2745 OPC_Illegal,
2746 OPC_6502_48,
2747 OPC_6502_49,
2748 OPC_6502_4A,
2749 OPC_Illegal,
2750 OPC_6502_4C,
2751 OPC_6502_4D,
2752 OPC_6502_4E,
2753 OPC_Illegal,
2754 OPC_6502_50,
2755 OPC_6502_51,
2756 OPC_Illegal,
2757 OPC_Illegal,
2758 OPC_Illegal,
2759 OPC_6502_55,
2760 OPC_6502_56,
2761 OPC_Illegal,
2762 OPC_6502_58,
2763 OPC_6502_59,
2764 OPC_Illegal,
2765 OPC_Illegal,
2766 OPC_Illegal,
2767 OPC_6502_5D,
2768 OPC_6502_5E,
2769 OPC_Illegal,
2770 OPC_6502_60,
2771 OPC_6502_61,
2772 OPC_Illegal,
2773 OPC_Illegal,
2774 OPC_Illegal,
2775 OPC_6502_65,
2776 OPC_6502_66,
2777 OPC_Illegal,
2778 OPC_6502_68,
2779 OPC_6502_69,
2780 OPC_6502_6A,
2781 OPC_Illegal,
2782 OPC_6502_6C,
2783 OPC_6502_6D,
2784 OPC_6502_6E,
2785 OPC_Illegal,
2786 OPC_6502_70,
2787 OPC_6502_71,
2788 OPC_Illegal,
2789 OPC_Illegal,
2790 OPC_Illegal,
2791 OPC_6502_75,
2792 OPC_6502_76,
2793 OPC_Illegal,
2794 OPC_6502_78,
2795 OPC_6502_79,
2796 OPC_Illegal,
2797 OPC_Illegal,
2798 OPC_Illegal,
2799 OPC_6502_7D,
2800 OPC_6502_7E,
2801 OPC_Illegal,
2802 OPC_Illegal,
2803 OPC_6502_81,
2804 OPC_Illegal,
2805 OPC_Illegal,
2806 OPC_6502_84,
2807 OPC_6502_85,
2808 OPC_6502_86,
2809 OPC_Illegal,
2810 OPC_6502_88,
2811 OPC_Illegal,
2812 OPC_6502_8A,
2813 OPC_Illegal,
2814 OPC_6502_8C,
2815 OPC_6502_8D,
2816 OPC_6502_8E,
2817 OPC_Illegal,
2818 OPC_6502_90,
2819 OPC_6502_91,
2820 OPC_Illegal,
2821 OPC_Illegal,
2822 OPC_6502_94,
2823 OPC_6502_95,
2824 OPC_6502_96,
2825 OPC_Illegal,
2826 OPC_6502_98,
2827 OPC_6502_99,
2828 OPC_6502_9A,
2829 OPC_Illegal,
2830 OPC_Illegal,
2831 OPC_6502_9D,
2832 OPC_Illegal,
2833 OPC_Illegal,
2834 OPC_6502_A0,
2835 OPC_6502_A1,
2836 OPC_6502_A2,
2837 OPC_Illegal,
2838 OPC_6502_A4,
2839 OPC_6502_A5,
2840 OPC_6502_A6,
2841 OPC_Illegal,
2842 OPC_6502_A8,
2843 OPC_6502_A9,
2844 OPC_6502_AA,
2845 OPC_Illegal,
2846 OPC_6502_AC,
2847 OPC_6502_AD,
2848 OPC_6502_AE,
2849 OPC_Illegal,
2850 OPC_6502_B0,
2851 OPC_6502_B1,
2852 OPC_Illegal,
2853 OPC_Illegal,
2854 OPC_6502_B4,
2855 OPC_6502_B5,
2856 OPC_6502_B6,
2857 OPC_Illegal,
2858 OPC_6502_B8,
2859 OPC_6502_B9,
2860 OPC_6502_BA,
2861 OPC_Illegal,
2862 OPC_6502_BC,
2863 OPC_6502_BD,
2864 OPC_6502_BE,
2865 OPC_Illegal,
2866 OPC_6502_C0,
2867 OPC_6502_C1,
2868 OPC_Illegal,
2869 OPC_Illegal,
2870 OPC_6502_C4,
2871 OPC_6502_C5,
2872 OPC_6502_C6,
2873 OPC_Illegal,
2874 OPC_6502_C8,
2875 OPC_6502_C9,
2876 OPC_6502_CA,
2877 OPC_Illegal,
2878 OPC_6502_CC,
2879 OPC_6502_CD,
2880 OPC_6502_CE,
2881 OPC_Illegal,
2882 OPC_6502_D0,
2883 OPC_6502_D1,
2884 OPC_Illegal,
2885 OPC_Illegal,
2886 OPC_Illegal,
2887 OPC_6502_D5,
2888 OPC_6502_D6,
2889 OPC_Illegal,
2890 OPC_6502_D8,
2891 OPC_6502_D9,
2892 OPC_Illegal,
2893 OPC_Illegal,
2894 OPC_Illegal,
2895 OPC_6502_DD,
2896 OPC_6502_DE,
2897 OPC_Illegal,
2898 OPC_6502_E0,
2899 OPC_6502_E1,
2900 OPC_Illegal,
2901 OPC_Illegal,
2902 OPC_6502_E4,
2903 OPC_6502_E5,
2904 OPC_6502_E6,
2905 OPC_Illegal,
2906 OPC_6502_E8,
2907 OPC_6502_E9,
2908 OPC_6502_EA,
2909 OPC_Illegal,
2910 OPC_6502_EC,
2911 OPC_6502_ED,
2912 OPC_6502_EE,
2913 OPC_Illegal,
2914 OPC_6502_F0,
2915 OPC_6502_F1,
2916 OPC_Illegal,
2917 OPC_Illegal,
2918 OPC_Illegal,
2919 OPC_6502_F5,
2920 OPC_6502_F6,
2921 OPC_Illegal,
2922 OPC_6502_F8,
2923 OPC_6502_F9,
2924 OPC_Illegal,
2925 OPC_Illegal,
2926 OPC_Illegal,
2927 OPC_6502_FD,
2928 OPC_6502_FE,
2929 OPC_Illegal,
2930 };
2931
2932
2933
2934 /* Opcode handler table for the 65C02 */
2935 static const OPFunc OP65C02Table[256] = {
2936 OPC_6502_00,
2937 OPC_6502_01,
2938 OPC_65C02_NOP22, // $02
2939 OPC_65C02_NOP11, // $03
2940 OPC_65SC02_04,
2941 OPC_6502_05,
2942 OPC_6502_06,
2943 OPC_Illegal, // $07: RMB0 currently unsupported
2944 OPC_6502_08,
2945 OPC_6502_09,
2946 OPC_6502_0A,
2947 OPC_65C02_NOP11, // $0B
2948 OPC_65SC02_0C,
2949 OPC_6502_0D,
2950 OPC_6502_0E,
2951 OPC_Illegal, // $0F: BBR0 currently unsupported
2952 OPC_6502_10,
2953 OPC_6502_11,
2954 OPC_65SC02_12,
2955 OPC_65C02_NOP11, // $13
2956 OPC_65SC02_14,
2957 OPC_6502_15,
2958 OPC_6502_16,
2959 OPC_Illegal, // $17: RMB1 currently unsupported
2960 OPC_6502_18,
2961 OPC_6502_19,
2962 OPC_65SC02_1A,
2963 OPC_65C02_NOP11, // $1B
2964 OPC_65SC02_1C,
2965 OPC_6502_1D,
2966 OPC_6502_1E,
2967 OPC_Illegal, // $1F: BBR1 currently unsupported
2968 OPC_6502_20,
2969 OPC_6502_21,
2970 OPC_65C02_NOP22, // $22
2971 OPC_65C02_NOP11, // $23
2972 OPC_6502_24,
2973 OPC_6502_25,
2974 OPC_6502_26,
2975 OPC_Illegal, // $27: RMB2 currently unsupported
2976 OPC_6502_28,
2977 OPC_6502_29,
2978 OPC_6502_2A,
2979 OPC_65C02_NOP11, // $2B
2980 OPC_6502_2C,
2981 OPC_6502_2D,
2982 OPC_6502_2E,
2983 OPC_Illegal, // $2F: BBR2 currently unsupported
2984 OPC_6502_30,
2985 OPC_6502_31,
2986 OPC_65SC02_32,
2987 OPC_65C02_NOP11, // $33
2988 OPC_65SC02_34,
2989 OPC_6502_35,
2990 OPC_6502_36,
2991 OPC_Illegal, // $37: RMB3 currently unsupported
2992 OPC_6502_38,
2993 OPC_6502_39,
2994 OPC_65SC02_3A,
2995 OPC_65C02_NOP11, // $3B
2996 OPC_65SC02_3C,
2997 OPC_6502_3D,
2998 OPC_6502_3E,
2999 OPC_Illegal, // $3F: BBR3 currently unsupported
3000 OPC_6502_40,
3001 OPC_6502_41,
3002 OPC_65C02_NOP22, // $42
3003 OPC_65C02_NOP11, // $43
3004 OPC_65C02_44, // $44
3005 OPC_6502_45,
3006 OPC_6502_46,
3007 OPC_Illegal, // $47: RMB4 currently unsupported
3008 OPC_6502_48,
3009 OPC_6502_49,
3010 OPC_6502_4A,
3011 OPC_65C02_NOP11, // $4B
3012 OPC_6502_4C,
3013 OPC_6502_4D,
3014 OPC_6502_4E,
3015 OPC_Illegal, // $4F: BBR4 currently unsupported
3016 OPC_6502_50,
3017 OPC_6502_51,
3018 OPC_65SC02_52,
3019 OPC_65C02_NOP11, // $53
3020 OPC_65C02_NOP24, // $54
3021 OPC_6502_55,
3022 OPC_6502_56,
3023 OPC_Illegal, // $57: RMB5 currently unsupported
3024 OPC_6502_58,
3025 OPC_6502_59,
3026 OPC_65SC02_5A,
3027 OPC_65C02_NOP11, // $5B
3028 OPC_65C02_5C,
3029 OPC_6502_5D,
3030 OPC_6502_5E,
3031 OPC_Illegal, // $5F: BBR5 currently unsupported
3032 OPC_6502_60,
3033 OPC_6502_61,
3034 OPC_65C02_NOP22, // $62
3035 OPC_65C02_NOP11, // $63
3036 OPC_65SC02_64,
3037 OPC_6502_65,
3038 OPC_6502_66,
3039 OPC_Illegal, // $67: RMB6 currently unsupported
3040 OPC_6502_68,
3041 OPC_6502_69,
3042 OPC_6502_6A,
3043 OPC_65C02_NOP11, // $6B
3044 OPC_65C02_6C,
3045 OPC_6502_6D,
3046 OPC_6502_6E,
3047 OPC_Illegal, // $6F: BBR6 currently unsupported
3048 OPC_6502_70,
3049 OPC_6502_71,
3050 OPC_65SC02_72,
3051 OPC_65C02_NOP11, // $73
3052 OPC_65SC02_74,
3053 OPC_6502_75,
3054 OPC_6502_76,
3055 OPC_Illegal, // $77: RMB7 currently unsupported
3056 OPC_6502_78,
3057 OPC_6502_79,
3058 OPC_65SC02_7A,
3059 OPC_65C02_NOP11, // $7B
3060 OPC_65SC02_7C,
3061 OPC_6502_7D,
3062 OPC_6502_7E,
3063 OPC_Illegal, // $7F: BBR7 currently unsupported
3064 OPC_65SC02_80,
3065 OPC_6502_81,
3066 OPC_65C02_NOP22, // $82
3067 OPC_65C02_NOP11, // $83
3068 OPC_6502_84,
3069 OPC_6502_85,
3070 OPC_6502_86,
3071 OPC_Illegal, // $87: SMB0 currently unsupported
3072 OPC_6502_88,
3073 OPC_65SC02_89,
3074 OPC_6502_8A,
3075 OPC_65C02_NOP11, // $8B
3076 OPC_6502_8C,
3077 OPC_6502_8D,
3078 OPC_6502_8E,
3079 OPC_Illegal, // $8F: BBS0 currently unsupported
3080 OPC_6502_90,
3081 OPC_6502_91,
3082 OPC_65SC02_92,
3083 OPC_65C02_NOP11, // $93
3084 OPC_6502_94,
3085 OPC_6502_95,
3086 OPC_6502_96,
3087 OPC_Illegal, // $97: SMB1 currently unsupported
3088 OPC_6502_98,
3089 OPC_6502_99,
3090 OPC_6502_9A,
3091 OPC_65C02_NOP11, // $9B
3092 OPC_65SC02_9C,
3093 OPC_6502_9D,
3094 OPC_65SC02_9E,
3095 OPC_Illegal, // $9F: BBS1 currently unsupported
3096 OPC_6502_A0,
3097 OPC_6502_A1,
3098 OPC_6502_A2,
3099 OPC_65C02_NOP11, // $A3
3100 OPC_6502_A4,
3101 OPC_6502_A5,
3102 OPC_6502_A6,
3103 OPC_Illegal, // $A7: SMB2 currently unsupported
3104 OPC_6502_A8,
3105 OPC_6502_A9,
3106 OPC_6502_AA,
3107 OPC_65C02_NOP11, // $AB
3108 OPC_6502_AC,
3109 OPC_6502_AD,
3110 OPC_6502_AE,
3111 OPC_Illegal, // $AF: BBS2 currently unsupported
3112 OPC_6502_B0,
3113 OPC_6502_B1,
3114 OPC_65SC02_B2,
3115 OPC_65C02_NOP11, // $B3
3116 OPC_6502_B4,
3117 OPC_6502_B5,
3118 OPC_6502_B6,
3119 OPC_Illegal, // $B7: SMB3 currently unsupported
3120 OPC_6502_B8,
3121 OPC_6502_B9,
3122 OPC_6502_BA,
3123 OPC_65C02_NOP11, // $BB
3124 OPC_6502_BC,
3125 OPC_6502_BD,
3126 OPC_6502_BE,
3127 OPC_Illegal, // $BF: BBS3 currently unsupported
3128 OPC_6502_C0,
3129 OPC_6502_C1,
3130 OPC_65C02_NOP22, // $C2
3131 OPC_65C02_NOP11, // $C3
3132 OPC_6502_C4,
3133 OPC_6502_C5,
3134 OPC_6502_C6,
3135 OPC_Illegal, // $C7: SMB4 currently unsupported
3136 OPC_6502_C8,
3137 OPC_6502_C9,
3138 OPC_6502_CA,
3139 OPC_Illegal, // $CB: WAI currently unsupported
3140 OPC_6502_CC,
3141 OPC_6502_CD,
3142 OPC_6502_CE,
3143 OPC_Illegal, // $CF: BBS4 currently unsupported
3144 OPC_6502_D0,
3145 OPC_6502_D1,
3146 OPC_65SC02_D2,
3147 OPC_65C02_NOP11, // $D3
3148 OPC_65C02_NOP24, // $D4
3149 OPC_6502_D5,
3150 OPC_6502_D6,
3151 OPC_Illegal, // $D7: SMB5 currently unsupported
3152 OPC_6502_D8,
3153 OPC_6502_D9,
3154 OPC_65SC02_DA,
3155 OPC_Illegal, // $DB: STP currently unsupported
3156 OPC_65C02_NOP34, // $DC
3157 OPC_6502_DD,
3158 OPC_6502_DE,
3159 OPC_Illegal, // $DF: BBS5 currently unsupported
3160 OPC_6502_E0,
3161 OPC_6502_E1,
3162 OPC_65C02_NOP22, // $E2
3163 OPC_65C02_NOP11, // $E3
3164 OPC_6502_E4,
3165 OPC_6502_E5,
3166 OPC_6502_E6,
3167 OPC_Illegal, // $E7: SMB6 currently unsupported
3168 OPC_6502_E8,
3169 OPC_6502_E9,
3170 OPC_6502_EA,
3171 OPC_65C02_NOP11, // $EB
3172 OPC_6502_EC,
3173 OPC_6502_ED,
3174 OPC_6502_EE,
3175 OPC_Illegal, // $EF: BBS6 currently unsupported
3176 OPC_6502_F0,
3177 OPC_6502_F1,
3178 OPC_65SC02_F2,
3179 OPC_65C02_NOP11, // $F3
3180 OPC_65C02_NOP24, // $F4
3181 OPC_6502_F5,
3182 OPC_6502_F6,
3183 OPC_Illegal, // $F7: SMB7 currently unsupported
3184 OPC_6502_F8,
3185 OPC_6502_F9,
3186 OPC_65SC02_FA,
3187 OPC_65C02_NOP11, // $FB
3188 OPC_65C02_NOP34, // $FC
3189 OPC_6502_FD,
3190 OPC_6502_FE,
3191 OPC_Illegal, // $FF: BBS7 currently unsupported
3192 };
3193
3194
3195
3196 /* Tables with opcode handlers */
3197 static const OPFunc* Handlers[2] = {OP6502Table, OP65C02Table};
3198
3199
3200
3201 /*****************************************************************************/
3202 /* Code */
3203 /*****************************************************************************/
3204
3205
3206
IRQRequest(void)3207 void IRQRequest (void)
3208 /* Generate an IRQ */
3209 {
3210 /* Remember the request */
3211 HaveIRQRequest = 1;
3212 }
3213
3214
3215
NMIRequest(void)3216 void NMIRequest (void)
3217 /* Generate an NMI */
3218 {
3219 /* Remember the request */
3220 HaveNMIRequest = 1;
3221 }
3222
3223
3224
Reset(void)3225 void Reset (void)
3226 /* Generate a CPU RESET */
3227 {
3228 /* Reset the CPU */
3229 HaveIRQRequest = 0;
3230 HaveNMIRequest = 0;
3231
3232 /* Bits 5 and 4 aren't used, and always are 1! */
3233 Regs.SR = 0x30;
3234 Regs.PC = MemReadWord (0xFFFC);
3235 }
3236
3237
3238
ExecuteInsn(void)3239 unsigned ExecuteInsn (void)
3240 /* Execute one CPU instruction */
3241 {
3242 /* If we have an NMI request, handle it */
3243 if (HaveNMIRequest) {
3244
3245 HaveNMIRequest = 0;
3246 PUSH (PCH);
3247 PUSH (PCL);
3248 PUSH (Regs.SR & ~BF);
3249 SET_IF (1);
3250 if (CPU != CPU_6502)
3251 {
3252 SET_DF (0);
3253 }
3254 Regs.PC = MemReadWord (0xFFFA);
3255 Cycles = 7;
3256
3257 } else if (HaveIRQRequest && GET_IF () == 0) {
3258
3259 HaveIRQRequest = 0;
3260 PUSH (PCH);
3261 PUSH (PCL);
3262 PUSH (Regs.SR & ~BF);
3263 SET_IF (1);
3264 if (CPU != CPU_6502)
3265 {
3266 SET_DF (0);
3267 }
3268 Regs.PC = MemReadWord (0xFFFE);
3269 Cycles = 7;
3270
3271 } else {
3272
3273 /* Normal instruction - read the next opcode */
3274 unsigned char OPC = MemReadByte (Regs.PC);
3275
3276 /* Execute it */
3277 Handlers[CPU][OPC] ();
3278 }
3279
3280 /* Count cycles */
3281 TotalCycles += Cycles;
3282
3283 /* Return the number of clock cycles needed by this insn */
3284 return Cycles;
3285 }
3286
3287
3288
GetCycles(void)3289 unsigned long GetCycles (void)
3290 /* Return the total number of cycles executed */
3291 {
3292 /* Return the total number of cycles */
3293 return TotalCycles;
3294 }
3295