]> Shamusworld >> Repos - apple2/blob - src/v65c02.cpp
02dd8461d4e4dff367f5e1271a4ee5bd10d2634a
[apple2] / src / v65c02.cpp
1 //
2 // Virtual 65C02 Emulator v1.1
3 //
4 // by James Hammons
5 // (c) 2005-2018 Underground Software
6 //
7 // JLH = James Hammons <jlhamm@acm.org>
8 //
9 // WHO  WHEN        WHAT
10 // ---  ----------  -----------------------------------------------------------
11 // JLH  01/04/2006  Added changelog ;-)
12 // JLH  01/18/2009  Fixed EA_ABS_* macros
13 //
14
15 //OK, the wraparound bug exists in both the Apple and Atari versions of Ultima
16 //II. However, the Atari version *does* occassionally pick strength while the
17 //Apple versions do not--which would seem to indicate a bug either in the RNG
18 //algorithm, the 65C02 core, or the Apple hardware. Need to investigate all
19 //three!
20
21 #define __DEBUG__
22 //#define __DEBUGMON__
23
24 #include "v65c02.h"
25
26 #ifdef __DEBUG__
27 #include "dis65c02.h"
28 #include "log.h"
29 #endif
30
31
32 // Various helper macros
33
34 #define CLR_Z                           (regs->cc &= ~FLAG_Z)
35 #define CLR_ZN                          (regs->cc &= ~(FLAG_Z | FLAG_N))
36 #define CLR_ZNC                         (regs->cc &= ~(FLAG_Z | FLAG_N | FLAG_C))
37 #define CLR_V                           (regs->cc &= ~FLAG_V)
38 #define CLR_N                           (regs->cc &= ~FLAG_N)
39 #define CLR_D                           (regs->cc &= ~FLAG_D)
40 #define SET_Z(r)                        (regs->cc = ((r) == 0 ? regs->cc | FLAG_Z : regs->cc & ~FLAG_Z))
41 #define SET_N(r)                        (regs->cc = ((r) & 0x80 ? regs->cc | FLAG_N : regs->cc & ~FLAG_N))
42 #define SET_I                           (regs->cc |= FLAG_I)
43
44 //Not sure that this code is computing the carry correctly... Investigate! [Seems to be]
45 #define SET_C_ADD(a,b)          (regs->cc = ((uint8_t)(b) > (uint8_t)(~(a)) ? regs->cc | FLAG_C : regs->cc & ~FLAG_C))
46 #define SET_C_CMP(a,b)          (regs->cc = ((uint8_t)(b) >= (uint8_t)(a) ? regs->cc | FLAG_C : regs->cc & ~FLAG_C))
47 #define SET_ZN(r)                       SET_N(r); SET_Z(r)
48 #define SET_ZNC_ADD(a,b,r)      SET_N(r); SET_Z(r); SET_C_ADD(a,b)
49 #define SET_ZNC_CMP(a,b,r)      SET_N(r); SET_Z(r); SET_C_CMP(a,b)
50
51 #define EA_IMM                          regs->pc++
52 #define EA_ZP                           regs->RdMem(regs->pc++)
53 #define EA_ZP_X                         (regs->RdMem(regs->pc++) + regs->x) & 0xFF
54 #define EA_ZP_Y                         (regs->RdMem(regs->pc++) + regs->y) & 0xFF
55 #define EA_ABS                          FetchMemW(regs->pc)
56 #define EA_ABS_X                        FetchMemW(regs->pc) + regs->x
57 #define EA_ABS_Y                        FetchMemW(regs->pc) + regs->y
58 #define EA_IND_ZP_X                     RdMemW((regs->RdMem(regs->pc++) + regs->x) & 0xFF)
59 #define EA_IND_ZP_Y                     RdMemW(regs->RdMem(regs->pc++)) + regs->y
60 #define EA_IND_ZP                       RdMemW(regs->RdMem(regs->pc++))
61
62 #define READ_IMM                        regs->RdMem(EA_IMM)
63 #define READ_ZP                         regs->RdMem(EA_ZP)
64 #define READ_ZP_X                       regs->RdMem(EA_ZP_X)
65 #define READ_ZP_Y                       regs->RdMem(EA_ZP_Y)
66 #define READ_ABS                        regs->RdMem(EA_ABS)
67 #define READ_ABS_X                      regs->RdMem(EA_ABS_X)
68 #define READ_ABS_Y                      regs->RdMem(EA_ABS_Y)
69 #define READ_IND_ZP_X           regs->RdMem(EA_IND_ZP_X)
70 #define READ_IND_ZP_Y           regs->RdMem(EA_IND_ZP_Y)
71 #define READ_IND_ZP                     regs->RdMem(EA_IND_ZP)
72
73 #define READ_IMM_WB(v)          uint16_t addr = EA_IMM;      v = regs->RdMem(addr)
74 #define READ_ZP_WB(v)           uint16_t addr = EA_ZP;       v = regs->RdMem(addr)
75 #define READ_ZP_X_WB(v)         uint16_t addr = EA_ZP_X;     v = regs->RdMem(addr)
76 #define READ_ABS_WB(v)          uint16_t addr = EA_ABS;      v = regs->RdMem(addr)
77 #define READ_ABS_X_WB(v)        uint16_t addr = EA_ABS_X;    v = regs->RdMem(addr)
78 #define READ_ABS_Y_WB(v)        uint16_t addr = EA_ABS_Y;    v = regs->RdMem(addr)
79 #define READ_IND_ZP_X_WB(v)     uint16_t addr = EA_IND_ZP_X; v = regs->RdMem(addr)
80 #define READ_IND_ZP_Y_WB(v)     uint16_t addr = EA_IND_ZP_Y; v = regs->RdMem(addr)
81 #define READ_IND_ZP_WB(v)       uint16_t addr = EA_IND_ZP;   v = regs->RdMem(addr)
82
83 #define WRITE_BACK(d)           regs->WrMem(addr, (d))
84
85
86 // Private global variables
87
88 static V65C02REGS * regs;
89
90
91 //This is probably incorrect, at least WRT to the $x7 and $xF opcodes... !!! FIX !!!
92 //Also this doesn't take into account the extra cycle it takes when an indirect
93 //fetch (ABS, ABS X/Y, ZP) crosses a page boundary, or extra cycle for BCD
94 //add/subtract...
95 #warning "Cycle counts are not 100% accurate--!!! FIX !!!"
96 static uint8_t CPUCycles[256] = {
97 #if 0
98         7, 6, 1, 1, 5, 3, 5, 1, 3, 2, 2, 1, 6, 4, 6, 1,
99         2, 5, 5, 1, 5, 4, 6, 1, 2, 4, 2, 1, 6, 4, 6, 1,
100         6, 6, 1, 1, 3, 3, 5, 1, 4, 2, 2, 1, 4, 4, 6, 1,
101         2, 5, 5, 1, 4, 4, 6, 1, 2, 4, 2, 1, 4, 4, 6, 1,
102         6, 6, 1, 1, 1, 3, 5, 1, 3, 2, 2, 1, 3, 4, 6, 1,
103         2, 5, 5, 1, 1, 4, 6, 1, 2, 4, 3, 1, 1, 4, 6, 1,
104         6, 6, 1, 1, 3, 3, 5, 1, 4, 2, 2, 1, 6, 4, 6, 1,
105         2, 5, 5, 1, 4, 4, 6, 1, 2, 4, 4, 1, 6, 4, 6, 1,
106         2, 6, 1, 1, 3, 3, 3, 1, 2, 2, 2, 1, 4, 4, 4, 1,
107         2, 6, 5, 1, 4, 4, 4, 1, 2, 5, 2, 1, 4, 5, 5, 1,
108         2, 6, 2, 1, 3, 3, 3, 1, 2, 2, 2, 1, 4, 4, 4, 1,
109         2, 5, 5, 1, 4, 4, 4, 1, 2, 4, 2, 1, 4, 4, 4, 1,
110         2, 6, 1, 1, 3, 3, 5, 1, 2, 2, 2, 1, 4, 4, 6, 1,
111         2, 5, 5, 1, 1, 4, 6, 1, 2, 4, 3, 1, 1, 4, 6, 1,
112         2, 6, 1, 1, 3, 3, 5, 1, 2, 2, 2, 1, 4, 4, 6, 1,
113         2, 5, 5, 1, 1, 4, 6, 1, 2, 4, 4, 1, 1, 4, 6, 1 };
114 #else
115         7, 6, 2, 2, 5, 3, 5, 2, 3, 2, 2, 2, 6, 4, 6, 2,
116         2, 5, 5, 2, 5, 4, 6, 2, 2, 4, 2, 2, 6, 4, 6, 2,
117         6, 6, 2, 2, 3, 3, 5, 2, 4, 2, 2, 2, 4, 2, 6, 2,
118         2, 5, 5, 2, 4, 4, 6, 2, 2, 4, 2, 2, 4, 4, 6, 2,
119         6, 6, 2, 2, 3, 3, 5, 2, 3, 2, 2, 2, 3, 4, 6, 2,
120         2, 5, 5, 2, 4, 4, 6, 2, 2, 4, 3, 2, 8, 4, 6, 2,
121         6, 6, 2, 2, 3, 3, 5, 2, 4, 2, 2, 2, 6, 4, 6, 2,
122         2, 5, 5, 2, 4, 4, 6, 2, 2, 4, 4, 2, 6, 4, 6, 2,
123         2, 6, 2, 2, 3, 3, 3, 2, 2, 2, 2, 2, 4, 4, 4, 2,
124         2, 6, 5, 2, 4, 4, 4, 2, 2, 5, 2, 2, 4, 5, 5, 2,
125         2, 6, 2, 2, 3, 3, 3, 2, 2, 2, 2, 2, 4, 4, 4, 2,
126         2, 5, 5, 2, 4, 4, 4, 2, 2, 4, 2, 2, 4, 4, 4, 2,
127         2, 6, 2, 2, 3, 3, 5, 2, 2, 2, 2, 2, 4, 4, 5, 2,
128         2, 5, 5, 2, 4, 4, 6, 2, 2, 4, 3, 2, 4, 4, 6, 2,
129         2, 6, 2, 2, 3, 3, 5, 2, 2, 2, 2, 2, 4, 4, 6, 2,
130         2, 5, 5, 2, 4, 4, 6, 2, 2, 4, 4, 2, 4, 4, 6, 2 };
131 #endif
132
133 #if 0
134 static uint8_t _6502Cycles[256] = {
135         7, 6, 2, 8, 3, 3, 5, 5, 3, 2, 2, 2, 4, 4, 6, 6,
136         2, 5, 2, 8, 4, 4, 6, 6, 2, 4, 2, 7, 4, 4, 6, 7,
137         6, 6, 2, 8, 3, 3, 5, 5, 4, 2, 2, 2, 4, 2, 6, 6,
138         2, 5, 2, 8, 4, 4, 6, 6, 2, 4, 2, 7, 4, 4, 6, 7,
139         6, 6, 2, 8, 3, 3, 5, 5, 3, 2, 2, 2, 3, 4, 6, 6,
140         2, 5, 2, 8, 4, 4, 6, 6, 2, 4, 2, 7, 4, 4, 6, 7,
141         6, 6, 2, 8, 3, 3, 5, 5, 4, 2, 2, 2, 6, 4, 6, 6,
142         2, 5, 2, 8, 4, 4, 6, 6, 2, 4, 2, 7, 4, 4, 6, 7,
143         2, 6, 2, 6, 3, 3, 3, 3, 2, 2, 2, 2, 4, 4, 4, 4,
144         2, 6, 2, 6, 4, 4, 4, 4, 2, 5, 2, 5, 5, 5, 5, 5,
145         2, 6, 2, 6, 3, 3, 3, 3, 2, 2, 2, 2, 4, 4, 4, 4,
146         2, 5, 2, 5, 4, 4, 4, 4, 2, 4, 2, 4, 4, 4, 4, 4,
147         2, 6, 2, 8, 3, 3, 5, 5, 2, 2, 2, 2, 4, 4, 5, 6,
148         2, 5, 2, 8, 4, 4, 6, 6, 2, 4, 2, 7, 4, 4, 6, 7,
149         2, 6, 2, 8, 3, 3, 5, 5, 2, 2, 2, 2, 4, 4, 6, 6,
150         2, 5, 2, 8, 4, 4, 6, 6, 2, 4, 2, 7, 4, 4, 6, 7 };
151
152 static uint8_t _65C02Cycles[256] = {
153         7, 6, 2, 2, 5, 3, 5, 2, 3, 2, 2, 2, 6, 4, 6, 2,
154         2, 5, 5, 2, 5, 4, 6, 2, 2, 4, 2, 2, 6, 4, 6, 2,
155         6, 6, 2, 2, 3, 3, 5, 2, 4, 2, 2, 2, 4, 2, 6, 2,
156         2, 5, 5, 2, 4, 4, 6, 2, 2, 4, 2, 2, 4, 4, 6, 2,
157         6, 6, 2, 2, 3, 3, 5, 2, 3, 2, 2, 2, 3, 4, 6, 2,
158         2, 5, 5, 2, 4, 4, 6, 2, 2, 4, 3, 2, 8, 4, 6, 2,
159         6, 6, 2, 2, 3, 3, 5, 2, 4, 2, 2, 2, 6, 4, 6, 2,
160         2, 5, 5, 2, 4, 4, 6, 2, 2, 4, 4, 2, 6, 4, 6, 2,
161         2, 6, 2, 2, 3, 3, 3, 2, 2, 2, 2, 2, 4, 4, 4, 2,
162         2, 6, 5, 2, 4, 4, 4, 2, 2, 5, 2, 2, 4, 5, 5, 2,
163         2, 6, 2, 2, 3, 3, 3, 2, 2, 2, 2, 2, 4, 4, 4, 2,
164         2, 5, 5, 2, 4, 4, 4, 2, 2, 4, 2, 2, 4, 4, 4, 2,
165         2, 6, 2, 2, 3, 3, 5, 2, 2, 2, 2, 2, 4, 4, 5, 2,
166         2, 5, 5, 2, 4, 4, 6, 2, 2, 4, 3, 2, 4, 4, 6, 2,
167         2, 6, 2, 2, 3, 3, 5, 2, 2, 2, 2, 2, 4, 4, 6, 2,
168         2, 5, 5, 2, 4, 4, 6, 2, 2, 4, 4, 2, 4, 4, 6, 2 };
169 #endif
170
171
172 /*
173 6502 cycles (includes illegal opcodes):
174
175                 case 0x00:       BRK         CYC(7)  break;
176                 case 0x01:       INDX ORA            CYC(6)  break;
177                 case 0x02:   INV HLT         CYC(2)  break;
178                 case 0x03:   INV INDX ASO            CYC(8)  break;
179                 case 0x04:   INV ZPG NOP             CYC(3)  break;
180                 case 0x05:       ZPG ORA             CYC(3)  break;
181                 case 0x06:       ZPG ASL_NMOS  CYC(5)  break;
182                 case 0x07:   INV ZPG ASO             CYC(5)  break;
183                 case 0x08:       PHP         CYC(3)  break;
184                 case 0x09:       IMM ORA             CYC(2)  break;
185                 case 0x0A:       ASLA        CYC(2)  break;
186                 case 0x0B:   INV IMM ANC             CYC(2)  break;
187                 case 0x0C:   INV ABSX NOP            CYC(4)  break;
188                 case 0x0D:       ABS ORA             CYC(4)  break;
189                 case 0x0E:       ABS ASL_NMOS  CYC(6)  break;
190                 case 0x0F:   INV ABS ASO             CYC(6)  break;
191                 case 0x10:       REL BPL             CYC(2)  break;
192                 case 0x11:       INDY ORA            CYC(5)  break;
193                 case 0x12:   INV HLT         CYC(2)  break;
194                 case 0x13:   INV INDY ASO            CYC(8)  break;
195                 case 0x14:   INV ZPGX NOP            CYC(4)  break;
196                 case 0x15:       ZPGX ORA            CYC(4)  break;
197                 case 0x16:       ZPGX ASL_NMOS CYC(6)  break;
198                 case 0x17:   INV ZPGX ASO            CYC(6)  break;
199                 case 0x18:       CLC         CYC(2)  break;
200                 case 0x19:       ABSY ORA            CYC(4)  break;
201                 case 0x1A:   INV NOP         CYC(2)  break;
202                 case 0x1B:   INV ABSY ASO            CYC(7)  break;
203                 case 0x1C:   INV ABSX NOP            CYC(4)  break;
204                 case 0x1D:       ABSX ORA            CYC(4)  break;
205                 case 0x1E:       ABSX ASL_NMOS CYC(6)  break;
206                 case 0x1F:   INV ABSX ASO            CYC(7)  break;
207                 case 0x20:       ABS JSR             CYC(6)  break;
208                 case 0x21:       INDX AND            CYC(6)  break;
209                 case 0x22:   INV HLT         CYC(2)  break;
210                 case 0x23:   INV INDX RLA            CYC(8)  break;
211                 case 0x24:       ZPG BIT             CYC(3)  break;
212                 case 0x25:       ZPG AND             CYC(3)  break;
213                 case 0x26:       ZPG ROL_NMOS  CYC(5)  break;
214                 case 0x27:   INV ZPG RLA             CYC(5)  break;
215                 case 0x28:       PLP         CYC(4)  break;
216                 case 0x29:       IMM AND             CYC(2)  break;
217                 case 0x2A:       ROLA        CYC(2)  break;
218                 case 0x2B:   INV IMM ANC             CYC(2)  break;
219                 case 0x2C:       ABS BIT             CYC(4)  break;
220                 case 0x2D:       ABS AND             CYC(2)  break;
221                 case 0x2E:       ABS ROL_NMOS  CYC(6)  break;
222                 case 0x2F:   INV ABS RLA             CYC(6)  break;
223                 case 0x30:       REL BMI             CYC(2)  break;
224                 case 0x31:       INDY AND            CYC(5)  break;
225                 case 0x32:   INV HLT         CYC(2)  break;
226                 case 0x33:   INV INDY RLA            CYC(8)  break;
227                 case 0x34:   INV ZPGX NOP            CYC(4)  break;
228                 case 0x35:       ZPGX AND            CYC(4)  break;
229                 case 0x36:       ZPGX ROL_NMOS CYC(6)  break;
230                 case 0x37:   INV ZPGX RLA            CYC(6)  break;
231                 case 0x38:       SEC         CYC(2)  break;
232                 case 0x39:       ABSY AND            CYC(4)  break;
233                 case 0x3A:   INV NOP         CYC(2)  break;
234                 case 0x3B:   INV ABSY RLA            CYC(7)  break;
235                 case 0x3C:   INV ABSX NOP            CYC(4)  break;
236                 case 0x3D:       ABSX AND            CYC(4)  break;
237                 case 0x3E:       ABSX ROL_NMOS CYC(6)  break;
238                 case 0x3F:   INV ABSX RLA            CYC(7)  break;
239                 case 0x40:       RTI         CYC(6)  DoIrqProfiling(uExecutedCycles); break;
240                 case 0x41:       INDX EOR            CYC(6)  break;
241                 case 0x42:   INV HLT         CYC(2)  break;
242                 case 0x43:   INV INDX LSE            CYC(8)  break;
243                 case 0x44:   INV ZPG NOP             CYC(3)  break;
244                 case 0x45:       ZPG EOR             CYC(3)  break;
245                 case 0x46:       ZPG LSR_NMOS  CYC(5)  break;
246                 case 0x47:   INV ZPG LSE             CYC(5)  break;
247                 case 0x48:       PHA         CYC(3)  break;
248                 case 0x49:       IMM EOR             CYC(2)  break;
249                 case 0x4A:       LSRA        CYC(2)  break;
250                 case 0x4B:   INV IMM ALR             CYC(2)  break;
251                 case 0x4C:       ABS JMP             CYC(3)  break;
252                 case 0x4D:       ABS EOR             CYC(4)  break;
253                 case 0x4E:       ABS LSR_NMOS  CYC(6)  break;
254                 case 0x4F:   INV ABS LSE             CYC(6)  break;
255                 case 0x50:       REL BVC             CYC(2)  break;
256                 case 0x51:       INDY EOR            CYC(5)  break;
257                 case 0x52:   INV HLT         CYC(2)  break;
258                 case 0x53:   INV INDY LSE            CYC(8)  break;
259                 case 0x54:   INV ZPGX NOP            CYC(4)  break;
260                 case 0x55:       ZPGX EOR            CYC(4)  break;
261                 case 0x56:       ZPGX LSR_NMOS CYC(6)  break;
262                 case 0x57:   INV ZPGX LSE            CYC(6)  break;
263                 case 0x58:       CLI         CYC(2)  break;
264                 case 0x59:       ABSY EOR            CYC(4)  break;
265                 case 0x5A:   INV NOP         CYC(2)  break;
266                 case 0x5B:   INV ABSY LSE            CYC(7)  break;
267                 case 0x5C:   INV ABSX NOP            CYC(4)  break;
268                 case 0x5D:       ABSX EOR            CYC(4)  break;
269                 case 0x5E:       ABSX LSR_NMOS CYC(6)  break;
270                 case 0x5F:   INV ABSX LSE            CYC(7)  break;
271                 case 0x60:       RTS         CYC(6)  break;
272                 case 0x61:       INDX ADC_NMOS CYC(6)  break;
273                 case 0x62:   INV HLT         CYC(2)  break;
274                 case 0x63:   INV INDX RRA            CYC(8)  break;
275                 case 0x64:   INV ZPG NOP             CYC(3)  break;
276                 case 0x65:       ZPG ADC_NMOS  CYC(3)  break;
277                 case 0x66:       ZPG ROR_NMOS  CYC(5)  break;
278                 case 0x67:   INV ZPG RRA             CYC(5)  break;
279                 case 0x68:       PLA         CYC(4)  break;
280                 case 0x69:       IMM ADC_NMOS  CYC(2)  break;
281                 case 0x6A:       RORA        CYC(2)  break;
282                 case 0x6B:   INV IMM ARR             CYC(2)  break;
283                 case 0x6C:       IABSNMOS JMP  CYC(6)  break;
284                 case 0x6D:       ABS ADC_NMOS  CYC(4)  break;
285                 case 0x6E:       ABS ROR_NMOS  CYC(6)  break;
286                 case 0x6F:   INV ABS RRA             CYC(6)  break;
287                 case 0x70:       REL BVS             CYC(2)  break;
288                 case 0x71:       INDY ADC_NMOS CYC(5)  break;
289                 case 0x72:   INV HLT         CYC(2)  break;
290                 case 0x73:   INV INDY RRA            CYC(8)  break;
291                 case 0x74:   INV ZPGX NOP            CYC(4)  break;
292                 case 0x75:       ZPGX ADC_NMOS CYC(4)  break;
293                 case 0x76:       ZPGX ROR_NMOS CYC(6)  break;
294                 case 0x77:   INV ZPGX RRA            CYC(6)  break;
295                 case 0x78:       SEI         CYC(2)  break;
296                 case 0x79:       ABSY ADC_NMOS CYC(4)  break;
297                 case 0x7A:   INV NOP         CYC(2)  break;
298                 case 0x7B:   INV ABSY RRA            CYC(7)  break;
299                 case 0x7C:   INV ABSX NOP            CYC(4)  break;
300                 case 0x7D:       ABSX ADC_NMOS CYC(4)  break;
301                 case 0x7E:       ABSX ROR_NMOS CYC(6)  break;
302                 case 0x7F:   INV ABSX RRA            CYC(7)  break;
303                 case 0x80:   INV IMM NOP             CYC(2)  break;
304                 case 0x81:       INDX STA            CYC(6)  break;
305                 case 0x82:   INV IMM NOP             CYC(2)  break;
306                 case 0x83:   INV INDX AXS            CYC(6)  break;
307                 case 0x84:       ZPG STY             CYC(3)  break;
308                 case 0x85:       ZPG STA             CYC(3)  break;
309                 case 0x86:       ZPG STX             CYC(3)  break;
310                 case 0x87:   INV ZPG AXS             CYC(3)  break;
311                 case 0x88:       DEY         CYC(2)  break;
312                 case 0x89:   INV IMM NOP             CYC(2)  break;
313                 case 0x8A:       TXA         CYC(2)  break;
314                 case 0x8B:   INV IMM XAA             CYC(2)  break;
315                 case 0x8C:       ABS STY             CYC(4)  break;
316                 case 0x8D:       ABS STA             CYC(4)  break;
317                 case 0x8E:       ABS STX             CYC(4)  break;
318                 case 0x8F:   INV ABS AXS             CYC(4)  break;
319                 case 0x90:       REL BCC             CYC(2)  break;
320                 case 0x91:       INDY STA            CYC(6)  break;
321                 case 0x92:   INV HLT         CYC(2)  break;
322                 case 0x93:   INV INDY AXA            CYC(6)  break;
323                 case 0x94:       ZPGX STY            CYC(4)  break;
324                 case 0x95:       ZPGX STA            CYC(4)  break;
325                 case 0x96:       ZPGY STX            CYC(4)  break;
326                 case 0x97:   INV ZPGY AXS            CYC(4)  break;
327                 case 0x98:       TYA         CYC(2)  break;
328                 case 0x99:       ABSY STA            CYC(5)  break;
329                 case 0x9A:       TXS         CYC(2)  break;
330                 case 0x9B:   INV ABSY TAS            CYC(5)  break;
331                 case 0x9C:   INV ABSX SAY            CYC(5)  break;
332                 case 0x9D:       ABSX STA            CYC(5)  break;
333                 case 0x9E:   INV ABSY XAS            CYC(5)  break;
334                 case 0x9F:   INV ABSY AXA            CYC(5)  break;
335                 case 0xA0:       IMM LDY             CYC(2)  break;
336                 case 0xA1:       INDX LDA            CYC(6)  break;
337                 case 0xA2:       IMM LDX             CYC(2)  break;
338                 case 0xA3:   INV INDX LAX            CYC(6)  break;
339                 case 0xA4:       ZPG LDY             CYC(3)  break;
340                 case 0xA5:       ZPG LDA             CYC(3)  break;
341                 case 0xA6:       ZPG LDX             CYC(3)  break;
342                 case 0xA7:   INV ZPG LAX             CYC(3)  break;
343                 case 0xA8:       TAY         CYC(2)  break;
344                 case 0xA9:       IMM LDA             CYC(2)  break;
345                 case 0xAA:       TAX         CYC(2)  break;
346                 case 0xAB:   INV IMM OAL             CYC(2)  break;
347                 case 0xAC:       ABS LDY             CYC(4)  break;
348                 case 0xAD:       ABS LDA             CYC(4)  break;
349                 case 0xAE:       ABS LDX             CYC(4)  break;
350                 case 0xAF:   INV ABS LAX             CYC(4)  break;
351                 case 0xB0:       REL BCS             CYC(2)  break;
352                 case 0xB1:       INDY LDA            CYC(5)  break;
353                 case 0xB2:   INV HLT         CYC(2)  break;
354                 case 0xB3:   INV INDY LAX            CYC(5)  break;
355                 case 0xB4:       ZPGX LDY            CYC(4)  break;
356                 case 0xB5:       ZPGX LDA            CYC(4)  break;
357                 case 0xB6:       ZPGY LDX            CYC(4)  break;
358                 case 0xB7:   INV ZPGY LAX            CYC(4)  break;
359                 case 0xB8:       CLV         CYC(2)  break;
360                 case 0xB9:       ABSY LDA            CYC(4)  break;
361                 case 0xBA:       TSX         CYC(2)  break;
362                 case 0xBB:   INV ABSY LAS            CYC(4)  break;
363                 case 0xBC:       ABSX LDY            CYC(4)  break;
364                 case 0xBD:       ABSX LDA            CYC(4)  break;
365                 case 0xBE:       ABSY LDX            CYC(4)  break;
366                 case 0xBF:   INV ABSY LAX            CYC(4)  break;
367                 case 0xC0:       IMM CPY             CYC(2)  break;
368                 case 0xC1:       INDX CMP            CYC(6)  break;
369                 case 0xC2:   INV IMM NOP             CYC(2)  break;
370                 case 0xC3:   INV INDX DCM            CYC(8)  break;
371                 case 0xC4:       ZPG CPY             CYC(3)  break;
372                 case 0xC5:       ZPG CMP             CYC(3)  break;
373                 case 0xC6:       ZPG DEC_NMOS  CYC(5)  break;
374                 case 0xC7:   INV ZPG DCM             CYC(5)  break;
375                 case 0xC8:       INY         CYC(2)  break;
376                 case 0xC9:       IMM CMP             CYC(2)  break;
377                 case 0xCA:       DEX         CYC(2)  break;
378                 case 0xCB:   INV IMM SAX             CYC(2)  break;
379                 case 0xCC:       ABS CPY             CYC(4)  break;
380                 case 0xCD:       ABS CMP             CYC(4)  break;
381                 case 0xCE:       ABS DEC_NMOS  CYC(5)  break;
382                 case 0xCF:   INV ABS DCM             CYC(6)  break;
383                 case 0xD0:       REL BNE             CYC(2)  break;
384                 case 0xD1:       INDY CMP            CYC(5)  break;
385                 case 0xD2:   INV HLT         CYC(2)  break;
386                 case 0xD3:   INV INDY DCM            CYC(8)  break;
387                 case 0xD4:   INV ZPGX NOP            CYC(4)  break;
388                 case 0xD5:       ZPGX CMP            CYC(4)  break;
389                 case 0xD6:       ZPGX DEC_NMOS CYC(6)  break;
390                 case 0xD7:   INV ZPGX DCM            CYC(6)  break;
391                 case 0xD8:       CLD         CYC(2)  break;
392                 case 0xD9:       ABSY CMP            CYC(4)  break;
393                 case 0xDA:   INV NOP         CYC(2)  break;
394                 case 0xDB:   INV ABSY DCM            CYC(7)  break;
395                 case 0xDC:   INV ABSX NOP            CYC(4)  break;
396                 case 0xDD:       ABSX CMP            CYC(4)  break;
397                 case 0xDE:       ABSX DEC_NMOS CYC(6)  break;
398                 case 0xDF:   INV ABSX DCM            CYC(7)  break;
399                 case 0xE0:       IMM CPX             CYC(2)  break;
400                 case 0xE1:       INDX SBC_NMOS CYC(6)  break;
401                 case 0xE2:   INV IMM NOP             CYC(2)  break;
402                 case 0xE3:   INV INDX INS            CYC(8)  break;
403                 case 0xE4:       ZPG CPX             CYC(3)  break;
404                 case 0xE5:       ZPG SBC_NMOS  CYC(3)  break;
405                 case 0xE6:       ZPG INC_NMOS  CYC(5)  break;
406                 case 0xE7:   INV ZPG INS             CYC(5)  break;
407                 case 0xE8:       INX         CYC(2)  break;
408                 case 0xE9:       IMM SBC_NMOS  CYC(2)  break;
409                 case 0xEA:       NOP         CYC(2)  break;
410                 case 0xEB:   INV IMM SBC_NMOS  CYC(2)  break;
411                 case 0xEC:       ABS CPX             CYC(4)  break;
412                 case 0xED:       ABS SBC_NMOS  CYC(4)  break;
413                 case 0xEE:       ABS INC_NMOS  CYC(6)  break;
414                 case 0xEF:   INV ABS INS             CYC(6)  break;
415                 case 0xF0:       REL BEQ             CYC(2)  break;
416                 case 0xF1:       INDY SBC_NMOS CYC(5)  break;
417                 case 0xF2:   INV HLT         CYC(2)  break;
418                 case 0xF3:   INV INDY INS            CYC(8)  break;
419                 case 0xF4:   INV ZPGX NOP            CYC(4)  break;
420                 case 0xF5:       ZPGX SBC_NMOS CYC(4)  break;
421                 case 0xF6:       ZPGX INC_NMOS CYC(6)  break;
422                 case 0xF7:   INV ZPGX INS            CYC(6)  break;
423                 case 0xF8:       SED         CYC(2)  break;
424                 case 0xF9:       ABSY SBC_NMOS CYC(4)  break;
425                 case 0xFA:   INV NOP         CYC(2)  break;
426                 case 0xFB:   INV ABSY INS            CYC(7)  break;
427                 case 0xFC:   INV ABSX NOP            CYC(4)  break;
428                 case 0xFD:       ABSX SBC_NMOS CYC(4)  break;
429                 case 0xFE:       ABSX INC_NMOS CYC(6)  break;
430                 case 0xFF:   INV ABSX INS            CYC(7)  break;
431
432
433 65C02 opcodes: (all illegal are NOP, but have cycle counts)
434
435                 case 0x00:       BRK         CYC(7)  break;
436                 case 0x01:       INDX ORA            CYC(6)  break;
437                 case 0x02:   INV IMM NOP             CYC(2)  break;
438                 case 0x03:   INV NOP         CYC(2)  break;
439                 case 0x04:       ZPG TSB             CYC(5)  break;
440                 case 0x05:       ZPG ORA             CYC(3)  break;
441                 case 0x06:       ZPG ASL_CMOS  CYC(5)  break;
442                 case 0x07:   INV NOP         CYC(2)  break;
443                 case 0x08:       PHP         CYC(3)  break;
444                 case 0x09:       IMM ORA             CYC(2)  break;
445                 case 0x0A:       ASLA        CYC(2)  break;
446                 case 0x0B:   INV NOP         CYC(2)  break;
447                 case 0x0C:       ABS TSB             CYC(6)  break;
448                 case 0x0D:       ABS ORA             CYC(4)  break;
449                 case 0x0E:       ABS ASL_CMOS  CYC(6)  break;
450                 case 0x0F:   INV NOP         CYC(2)  break;
451                 case 0x10:       REL BPL             CYC(2)  break;
452                 case 0x11:       INDY ORA            CYC(5)  break;
453                 case 0x12:       IZPG ORA            CYC(5)  break;
454                 case 0x13:   INV NOP         CYC(2)  break;
455                 case 0x14:       ZPG TRB             CYC(5)  break;
456                 case 0x15:       ZPGX ORA            CYC(4)  break;
457                 case 0x16:       ZPGX ASL_CMOS CYC(6)  break;
458                 case 0x17:   INV NOP         CYC(2)  break;
459                 case 0x18:       CLC         CYC(2)  break;
460                 case 0x19:       ABSY ORA            CYC(4)  break;
461                 case 0x1A:       INA         CYC(2)  break;
462                 case 0x1B:   INV NOP         CYC(2)  break;
463                 case 0x1C:       ABS TRB             CYC(6)  break;
464                 case 0x1D:       ABSX ORA            CYC(4)  break;
465                 case 0x1E:       ABSX ASL_CMOS CYC(6)  break;
466                 case 0x1F:   INV NOP         CYC(2)  break;
467                 case 0x20:       ABS JSR             CYC(6)  break;
468                 case 0x21:       INDX AND            CYC(6)  break;
469                 case 0x22:   INV IMM NOP             CYC(2)  break;
470                 case 0x23:   INV NOP         CYC(2)  break;
471                 case 0x24:       ZPG BIT             CYC(3)  break;
472                 case 0x25:       ZPG AND             CYC(3)  break;
473                 case 0x26:       ZPG ROL_CMOS  CYC(5)  break;
474                 case 0x27:   INV NOP         CYC(2)  break;
475                 case 0x28:       PLP         CYC(4)  break;
476                 case 0x29:       IMM AND             CYC(2)  break;
477                 case 0x2A:       ROLA        CYC(2)  break;
478                 case 0x2B:   INV NOP         CYC(2)  break;
479                 case 0x2C:       ABS BIT             CYC(4)  break;
480                 case 0x2D:       ABS AND             CYC(2)  break;
481                 case 0x2E:       ABS ROL_CMOS  CYC(6)  break;
482                 case 0x2F:   INV NOP         CYC(2)  break;
483                 case 0x30:       REL BMI             CYC(2)  break;
484                 case 0x31:       INDY AND            CYC(5)  break;
485                 case 0x32:       IZPG AND            CYC(5)  break;
486                 case 0x33:   INV NOP         CYC(2)  break;
487                 case 0x34:       ZPGX BIT            CYC(4)  break;
488                 case 0x35:       ZPGX AND            CYC(4)  break;
489                 case 0x36:       ZPGX ROL_CMOS CYC(6)  break;
490                 case 0x37:   INV NOP         CYC(2)  break;
491                 case 0x38:       SEC         CYC(2)  break;
492                 case 0x39:       ABSY AND            CYC(4)  break;
493                 case 0x3A:       DEA         CYC(2)  break;
494                 case 0x3B:   INV NOP         CYC(2)  break;
495                 case 0x3C:       ABSX BIT            CYC(4)  break;
496                 case 0x3D:       ABSX AND            CYC(4)  break;
497                 case 0x3E:       ABSX ROL_CMOS CYC(6)  break;
498                 case 0x3F:   INV NOP         CYC(2)  break;
499                 case 0x40:       RTI         CYC(6)  DoIrqProfiling(uExecutedCycles); break;
500                 case 0x41:       INDX EOR            CYC(6)  break;
501                 case 0x42:   INV IMM NOP             CYC(2)  break;
502                 case 0x43:   INV NOP         CYC(2)  break;
503                 case 0x44:   INV ZPG NOP             CYC(3)  break;
504                 case 0x45:       ZPG EOR             CYC(3)  break;
505                 case 0x46:       ZPG LSR_CMOS  CYC(5)  break;
506                 case 0x47:   INV NOP         CYC(2)  break;
507                 case 0x48:       PHA         CYC(3)  break;
508                 case 0x49:       IMM EOR             CYC(2)  break;
509                 case 0x4A:       LSRA        CYC(2)  break;
510                 case 0x4B:   INV NOP         CYC(2)  break;
511                 case 0x4C:       ABS JMP             CYC(3)  break;
512                 case 0x4D:       ABS EOR             CYC(4)  break;
513                 case 0x4E:       ABS LSR_CMOS  CYC(6)  break;
514                 case 0x4F:   INV NOP         CYC(2)  break;
515                 case 0x50:       REL BVC             CYC(2)  break;
516                 case 0x51:       INDY EOR            CYC(5)  break;
517                 case 0x52:       IZPG EOR            CYC(5)  break;
518                 case 0x53:   INV NOP         CYC(2)  break;
519                 case 0x54:   INV ZPGX NOP            CYC(4)  break;
520                 case 0x55:       ZPGX EOR            CYC(4)  break;
521                 case 0x56:       ZPGX LSR_CMOS CYC(6)  break;
522                 case 0x57:   INV NOP         CYC(2)  break;
523                 case 0x58:       CLI         CYC(2)  break;
524                 case 0x59:       ABSY EOR            CYC(4)  break;
525                 case 0x5A:       PHY         CYC(3)  break;
526                 case 0x5B:   INV NOP         CYC(2)  break;
527                 case 0x5C:   INV ABSX NOP            CYC(8)  break;
528                 case 0x5D:       ABSX EOR            CYC(4)  break;
529                 case 0x5E:       ABSX LSR_CMOS CYC(6)  break;
530                 case 0x5F:   INV NOP         CYC(2)  break;
531                 case 0x60:       RTS         CYC(6)  break;
532                 case 0x61:       INDX ADC_CMOS CYC(6)  break;
533                 case 0x62:   INV IMM NOP             CYC(2)  break;
534                 case 0x63:   INV NOP         CYC(2)  break;
535                 case 0x64:       ZPG STZ             CYC(3)  break;
536                 case 0x65:       ZPG ADC_CMOS  CYC(3)  break;
537                 case 0x66:       ZPG ROR_CMOS  CYC(5)  break;
538                 case 0x67:   INV NOP         CYC(2)  break;
539                 case 0x68:       PLA         CYC(4)  break;
540                 case 0x69:       IMM ADC_CMOS  CYC(2)  break;
541                 case 0x6A:       RORA        CYC(2)  break;
542                 case 0x6B:   INV NOP         CYC(2)  break;
543                 case 0x6C:       IABSCMOS JMP  CYC(6)  break;
544                 case 0x6D:       ABS ADC_CMOS  CYC(4)  break;
545                 case 0x6E:       ABS ROR_CMOS  CYC(6)  break;
546                 case 0x6F:   INV NOP         CYC(2)  break;
547                 case 0x70:       REL BVS             CYC(2)  break;
548                 case 0x71:       INDY ADC_CMOS CYC(5)  break;
549                 case 0x72:       IZPG ADC_CMOS CYC(5)  break;
550                 case 0x73:   INV NOP         CYC(2)  break;
551                 case 0x74:       ZPGX STZ            CYC(4)  break;
552                 case 0x75:       ZPGX ADC_CMOS CYC(4)  break;
553                 case 0x76:       ZPGX ROR_CMOS CYC(6)  break;
554                 case 0x77:   INV NOP         CYC(2)  break;
555                 case 0x78:       SEI         CYC(2)  break;
556                 case 0x79:       ABSY ADC_CMOS CYC(4)  break;
557                 case 0x7A:       PLY         CYC(4)  break;
558                 case 0x7B:   INV NOP         CYC(2)  break;
559                 case 0x7C:       IABSX JMP     CYC(6)  break;
560                 case 0x7D:       ABSX ADC_CMOS CYC(4)  break;
561                 case 0x7E:       ABSX ROR_CMOS CYC(6)  break;
562                 case 0x7F:   INV NOP         CYC(2)  break;
563                 case 0x80:       REL BRA             CYC(2)  break;
564                 case 0x81:       INDX STA            CYC(6)  break;
565                 case 0x82:   INV IMM NOP             CYC(2)  break;
566                 case 0x83:   INV NOP         CYC(2)  break;
567                 case 0x84:       ZPG STY             CYC(3)  break;
568                 case 0x85:       ZPG STA             CYC(3)  break;
569                 case 0x86:       ZPG STX             CYC(3)  break;
570                 case 0x87:   INV NOP         CYC(2)  break;
571                 case 0x88:       DEY         CYC(2)  break;
572                 case 0x89:       IMM BITI            CYC(2)  break;
573                 case 0x8A:       TXA         CYC(2)  break;
574                 case 0x8B:   INV NOP         CYC(2)  break;
575                 case 0x8C:       ABS STY             CYC(4)  break;
576                 case 0x8D:       ABS STA             CYC(4)  break;
577                 case 0x8E:       ABS STX             CYC(4)  break;
578                 case 0x8F:   INV NOP         CYC(2)  break;
579                 case 0x90:       REL BCC             CYC(2)  break;
580                 case 0x91:       INDY STA            CYC(6)  break;
581                 case 0x92:       IZPG STA            CYC(5)  break;
582                 case 0x93:   INV NOP         CYC(2)  break;
583                 case 0x94:       ZPGX STY            CYC(4)  break;
584                 case 0x95:       ZPGX STA            CYC(4)  break;
585                 case 0x96:       ZPGY STX            CYC(4)  break;
586                 case 0x97:   INV NOP         CYC(2)  break;
587                 case 0x98:       TYA         CYC(2)  break;
588                 case 0x99:       ABSY STA            CYC(5)  break;
589                 case 0x9A:       TXS         CYC(2)  break;
590                 case 0x9B:   INV NOP         CYC(2)  break;
591                 case 0x9C:       ABS STZ             CYC(4)  break;
592                 case 0x9D:       ABSX STA            CYC(5)  break;
593                 case 0x9E:       ABSX STZ            CYC(5)  break;
594                 case 0x9F:   INV NOP         CYC(2)  break;
595                 case 0xA0:       IMM LDY             CYC(2)  break;
596                 case 0xA1:       INDX LDA            CYC(6)  break;
597                 case 0xA2:       IMM LDX             CYC(2)  break;
598                 case 0xA3:   INV NOP         CYC(2)  break;
599                 case 0xA4:       ZPG LDY             CYC(3)  break;
600                 case 0xA5:       ZPG LDA             CYC(3)  break;
601                 case 0xA6:       ZPG LDX             CYC(3)  break;
602                 case 0xA7:   INV NOP         CYC(2)  break;
603                 case 0xA8:       TAY         CYC(2)  break;
604                 case 0xA9:       IMM LDA             CYC(2)  break;
605                 case 0xAA:       TAX         CYC(2)  break;
606                 case 0xAB:   INV NOP         CYC(2)  break;
607                 case 0xAC:       ABS LDY             CYC(4)  break;
608                 case 0xAD:       ABS LDA             CYC(4)  break;
609                 case 0xAE:       ABS LDX             CYC(4)  break;
610                 case 0xAF:   INV NOP         CYC(2)  break;
611                 case 0xB0:       REL BCS             CYC(2)  break;
612                 case 0xB1:       INDY LDA            CYC(5)  break;
613                 case 0xB2:       IZPG LDA            CYC(5)  break;
614                 case 0xB3:   INV NOP         CYC(2)  break;
615                 case 0xB4:       ZPGX LDY            CYC(4)  break;
616                 case 0xB5:       ZPGX LDA            CYC(4)  break;
617                 case 0xB6:       ZPGY LDX            CYC(4)  break;
618                 case 0xB7:   INV NOP         CYC(2)  break;
619                 case 0xB8:       CLV         CYC(2)  break;
620                 case 0xB9:       ABSY LDA            CYC(4)  break;
621                 case 0xBA:       TSX         CYC(2)  break;
622                 case 0xBB:   INV NOP         CYC(2)  break;
623                 case 0xBC:       ABSX LDY            CYC(4)  break;
624                 case 0xBD:       ABSX LDA            CYC(4)  break;
625                 case 0xBE:       ABSY LDX            CYC(4)  break;
626                 case 0xBF:   INV NOP         CYC(2)  break;
627                 case 0xC0:       IMM CPY             CYC(2)  break;
628                 case 0xC1:       INDX CMP            CYC(6)  break;
629                 case 0xC2:   INV IMM NOP             CYC(2)  break;
630                 case 0xC3:   INV NOP         CYC(2)  break;
631                 case 0xC4:       ZPG CPY             CYC(3)  break;
632                 case 0xC5:       ZPG CMP             CYC(3)  break;
633                 case 0xC6:       ZPG DEC_CMOS  CYC(5)  break;
634                 case 0xC7:   INV NOP         CYC(2)  break;
635                 case 0xC8:       INY         CYC(2)  break;
636                 case 0xC9:       IMM CMP             CYC(2)  break;
637                 case 0xCA:       DEX         CYC(2)  break;
638                 case 0xCB:   INV NOP         CYC(2)  break;
639                 case 0xCC:       ABS CPY             CYC(4)  break;
640                 case 0xCD:       ABS CMP             CYC(4)  break;
641                 case 0xCE:       ABS DEC_CMOS  CYC(5)  break;
642                 case 0xCF:   INV NOP         CYC(2)  break;
643                 case 0xD0:       REL BNE             CYC(2)  break;
644                 case 0xD1:       INDY CMP            CYC(5)  break;
645                 case 0xD2:       IZPG CMP            CYC(5)  break;
646                 case 0xD3:   INV NOP         CYC(2)  break;
647                 case 0xD4:   INV ZPGX NOP            CYC(4)  break;
648                 case 0xD5:       ZPGX CMP            CYC(4)  break;
649                 case 0xD6:       ZPGX DEC_CMOS CYC(6)  break;
650                 case 0xD7:   INV NOP         CYC(2)  break;
651                 case 0xD8:       CLD         CYC(2)  break;
652                 case 0xD9:       ABSY CMP            CYC(4)  break;
653                 case 0xDA:       PHX         CYC(3)  break;
654                 case 0xDB:   INV NOP         CYC(2)  break;
655                 case 0xDC:   INV ABSX NOP            CYC(4)  break;
656                 case 0xDD:       ABSX CMP            CYC(4)  break;
657                 case 0xDE:       ABSX DEC_CMOS CYC(6)  break;
658                 case 0xDF:   INV NOP         CYC(2)  break;
659                 case 0xE0:       IMM CPX             CYC(2)  break;
660                 case 0xE1:       INDX SBC_CMOS CYC(6)  break;
661                 case 0xE2:   INV IMM NOP             CYC(2)  break;
662                 case 0xE3:   INV NOP         CYC(2)  break;
663                 case 0xE4:       ZPG CPX             CYC(3)  break;
664                 case 0xE5:       ZPG SBC_CMOS  CYC(3)  break;
665                 case 0xE6:       ZPG INC_CMOS  CYC(5)  break;
666                 case 0xE7:   INV NOP         CYC(2)  break;
667                 case 0xE8:       INX         CYC(2)  break;
668                 case 0xE9:       IMM SBC_CMOS  CYC(2)  break;
669                 case 0xEA:       NOP         CYC(2)  break;
670                 case 0xEB:   INV NOP         CYC(2)  break;
671                 case 0xEC:       ABS CPX             CYC(4)  break;
672                 case 0xED:       ABS SBC_CMOS  CYC(4)  break;
673                 case 0xEE:       ABS INC_CMOS  CYC(6)  break;
674                 case 0xEF:   INV NOP         CYC(2)  break;
675                 case 0xF0:       REL BEQ             CYC(2)  break;
676                 case 0xF1:       INDY SBC_CMOS CYC(5)  break;
677                 case 0xF2:       IZPG SBC_CMOS CYC(5)  break;
678                 case 0xF3:   INV NOP         CYC(2)  break;
679                 case 0xF4:   INV ZPGX NOP            CYC(4)  break;
680                 case 0xF5:       ZPGX SBC_CMOS CYC(4)  break;
681                 case 0xF6:       ZPGX INC_CMOS CYC(6)  break;
682                 case 0xF7:   INV NOP         CYC(2)  break;
683                 case 0xF8:       SED         CYC(2)  break;
684                 case 0xF9:       ABSY SBC_CMOS CYC(4)  break;
685                 case 0xFA:       PLX         CYC(4)  break;
686                 case 0xFB:   INV NOP         CYC(2)  break;
687                 case 0xFC:   INV ABSX NOP            CYC(4)  break;
688                 case 0xFD:       ABSX SBC_CMOS CYC(4)  break;
689                 case 0xFE:       ABSX INC_CMOS CYC(6)  break;
690                 case 0xFF:   INV NOP         CYC(2)  break;
691 */
692
693
694 //
695 // Read a uint16_t out of 65C02 memory (big endian format)
696 //
697 static inline uint16_t RdMemW(uint16_t address)
698 {
699         return (uint16_t)(regs->RdMem(address + 1) << 8) | regs->RdMem(address + 0);
700 }
701
702
703 //
704 // Read a uint16_t out of 65C02 memory (big endian format) and increment PC
705 //
706 static inline uint16_t FetchMemW(uint16_t address)
707 {
708         regs->pc += 2;
709         return (uint16_t)(regs->RdMem(address + 1) << 8) | regs->RdMem(address + 0);
710 }
711
712
713 //
714 // 65C02 OPCODE IMPLEMENTATION
715 //
716 // NOTE: Lots of macros are used here to save a LOT of typing. Also
717 //       helps speed the debugging process. :-) Because of this, combining
718 //       certain lines may look like a good idea but would end in disaster.
719 //       You have been warned! ;-)
720 //
721
722 /*
723 Mnemonic        Addressing mode Form            Opcode  Size    Timing
724
725 ADC                     Immediate               ADC #Oper       69              2               2
726                         Zero Page               ADC Zpg         65              2               3
727                         Zero Page,X             ADC Zpg,X       75              2               4
728                         Absolute                ADC Abs         6D              3               4
729                         Absolute,X              ADC Abs,X       7D              3               4
730                         Absolute,Y              ADC Abs,Y       79              3               4
731                         (Zero Page,X)   ADC (Zpg,X)     61              2               6
732                         (Zero Page),Y   ADC (Zpg),Y     71              2               5
733                         (Zero Page)             ADC (Zpg)       72              2               5
734 */
735
736 // ADC opcodes
737
738 //This is non-optimal, but it works--optimize later. :-)
739 #define OP_ADC_HANDLER(m) \
740         uint16_t sum = (uint16_t)regs->a + (m) + (uint16_t)(regs->cc & FLAG_C); \
741 \
742         if (regs->cc & FLAG_D) \
743         { \
744                 if ((sum & 0x0F) > 0x09) \
745                         sum += 0x06; \
746 \
747                 if ((sum & 0xF0) > 0x90) \
748                         sum += 0x60; \
749         } \
750 \
751         regs->cc = (regs->cc & ~FLAG_C) | (sum >> 8); \
752         regs->cc = (~(regs->a ^ (m)) & (regs->a ^ sum) & 0x80 ? regs->cc | FLAG_V : regs->cc & ~FLAG_V); \
753         regs->a = sum & 0xFF; \
754         SET_ZN(regs->a)
755
756 static void Op69(void)                                                  // ADC #
757 {
758         uint16_t m = READ_IMM;
759         OP_ADC_HANDLER(m);
760 }
761
762 static void Op65(void)                                                  // ADC ZP
763 {
764         uint16_t m = READ_ZP;
765         OP_ADC_HANDLER(m);
766 }
767
768 static void Op75(void)                                                  // ADC ZP, X
769 {
770         uint16_t m = READ_ZP_X;
771         OP_ADC_HANDLER(m);
772 }
773
774 static void Op6D(void)                                                  // ADC ABS
775 {
776         uint16_t m = READ_ABS;
777         OP_ADC_HANDLER(m);
778 }
779
780 static void Op7D(void)                                                  // ADC ABS, X
781 {
782         uint16_t m = READ_ABS_X;
783         OP_ADC_HANDLER(m);
784 }
785
786 static void Op79(void)                                                  // ADC ABS, Y
787 {
788         uint16_t m = READ_ABS_Y;
789         OP_ADC_HANDLER(m);
790 }
791
792 static void Op61(void)                                                  // ADC (ZP, X)
793 {
794         uint16_t m = READ_IND_ZP_X;
795         OP_ADC_HANDLER(m);
796 }
797
798 static void Op71(void)                                                  // ADC (ZP), Y
799 {
800         uint16_t m = READ_IND_ZP_Y;
801         OP_ADC_HANDLER(m);
802 }
803
804 static void Op72(void)                                                  // ADC (ZP)
805 {
806         uint16_t m = READ_IND_ZP;
807         OP_ADC_HANDLER(m);
808 }
809
810 /*
811 AND     Immediate       AND #Oper       29      2       2
812 Zero Page               AND Zpg         25      2       3
813 Zero Page,X             AND Zpg,X       35      2       4
814 Absolute                AND Abs         2D      3       4
815 Absolute,X              AND Abs,X       3D      3       4
816 Absolute,Y              AND Abs,Y       39      3       4
817 (Zero Page,X)   AND (Zpg,X)     21      2       6
818 (Zero Page),Y   AND (Zpg),Y     31      2       5
819 (Zero Page)             AND (Zpg)       32      2       5
820 */
821
822 // AND opcodes
823
824 #define OP_AND_HANDLER(m) \
825         regs->a &= m; \
826         SET_ZN(regs->a)
827
828 static void Op29(void)                                                  // AND #
829 {
830         uint8_t m = READ_IMM;
831         OP_AND_HANDLER(m);
832 }
833
834 static void Op25(void)                                                  // AND ZP
835 {
836         uint8_t m = READ_ZP;
837         OP_AND_HANDLER(m);
838 }
839
840 static void Op35(void)                                                  // AND ZP, X
841 {
842         uint8_t m = READ_ZP_X;
843         OP_AND_HANDLER(m);
844 }
845
846 static void Op2D(void)                                                  // AND ABS
847 {
848         uint8_t m = READ_ABS;
849         OP_AND_HANDLER(m);
850 }
851
852 static void Op3D(void)                                                  // AND ABS, X
853 {
854         uint8_t m = READ_ABS_X;
855         OP_AND_HANDLER(m);
856 }
857
858 static void Op39(void)                                                  // AND ABS, Y
859 {
860         uint8_t m = READ_ABS_Y;
861         OP_AND_HANDLER(m);
862 }
863
864 static void Op21(void)                                                  // AND (ZP, X)
865 {
866         uint8_t m = READ_IND_ZP_X;
867         OP_AND_HANDLER(m);
868 }
869
870 static void Op31(void)                                                  // AND (ZP), Y
871 {
872         uint8_t m = READ_IND_ZP_Y;
873         OP_AND_HANDLER(m);
874 }
875
876 static void Op32(void)                                                  // AND (ZP)
877 {
878         uint8_t m = READ_IND_ZP;
879         OP_AND_HANDLER(m);
880 }
881
882 /*
883 ASL     Accumulator     ASL A           0A      1       2
884 Zero Page               ASL Zpg         06      2       5
885 Zero Page,X             ASL Zpg,X       16      2       6
886 Absolute                ASL Abs         0E      3       6
887 Absolute,X              ASL Abs,X       1E      3       7
888 */
889
890 // ASL opcodes
891
892 #define OP_ASL_HANDLER(m) \
893         regs->cc = ((m) & 0x80 ? regs->cc | FLAG_C : regs->cc & ~FLAG_C); \
894         (m) <<= 1; \
895         SET_ZN((m))
896
897 static void Op0A(void)                                                  // ASL A
898 {
899         OP_ASL_HANDLER(regs->a);
900 }
901
902 static void Op06(void)                                                  // ASL ZP
903 {
904         uint8_t m;
905         READ_ZP_WB(m);
906         OP_ASL_HANDLER(m);
907         WRITE_BACK(m);
908 }
909
910 static void Op16(void)                                                  // ASL ZP, X
911 {
912         uint8_t m;
913         READ_ZP_X_WB(m);
914         OP_ASL_HANDLER(m);
915         WRITE_BACK(m);
916 }
917
918 static void Op0E(void)                                                  // ASL ABS
919 {
920         uint8_t m;
921         READ_ABS_WB(m);
922         OP_ASL_HANDLER(m);
923         WRITE_BACK(m);
924 }
925
926 static void Op1E(void)                                                  // ASL ABS, X
927 {
928         uint8_t m;
929         READ_ABS_X_WB(m);
930         OP_ASL_HANDLER(m);
931         WRITE_BACK(m);
932 }
933
934 /*
935 BBR0    Relative        BBR0 Oper       0F      2       2
936 BBR1    Relative        BBR1 Oper       1F      2       2
937 BBR2    Relative        BBR2 Oper       2F      2       2
938 BBR3    Relative        BBR3 Oper       3F      2       2
939 BBR4    Relative        BBR4 Oper       4F      2       2
940 BBR5    Relative        BBR5 Oper       5F      2       2
941 BBR6    Relative        BBR6 Oper       6F      2       2
942 BBR7    Relative        BBR7 Oper       7F      2       2
943 BBS0    Relative        BBS0 Oper       8F      2       2
944 BBS1    Relative        BBS1 Oper       9F      2       2
945 BBS2    Relative        BBS2 Oper       AF      2       2
946 BBS3    Relative        BBS3 Oper       BF      2       2
947 BBS4    Relative        BBS4 Oper       CF      2       2
948 BBS5    Relative        BBS5 Oper       DF      2       2
949 BBS6    Relative        BBS6 Oper       EF      2       2
950 BBS7    Relative        BBS7 Oper       FF      2       2
951 */
952
953 // BBR/Sn opcodes
954
955 static void Op0F(void)                                                  // BBR0
956 {
957         int16_t m = (int16_t)(int8_t)READ_IMM;
958
959         if (!(regs->a & 0x01))
960                 regs->pc += m;
961 }
962
963 static void Op1F(void)                                                  // BBR1
964 {
965         int16_t m = (int16_t)(int8_t)READ_IMM;
966
967         if (!(regs->a & 0x02))
968                 regs->pc += m;
969 }
970
971 static void Op2F(void)                                                  // BBR2
972 {
973         int16_t m = (int16_t)(int8_t)READ_IMM;
974
975         if (!(regs->a & 0x04))
976                 regs->pc += m;
977 }
978
979 static void Op3F(void)                                                  // BBR3
980 {
981         int16_t m = (int16_t)(int8_t)READ_IMM;
982
983         if (!(regs->a & 0x08))
984                 regs->pc += m;
985 }
986
987 static void Op4F(void)                                                  // BBR4
988 {
989         int16_t m = (int16_t)(int8_t)READ_IMM;
990
991         if (!(regs->a & 0x10))
992                 regs->pc += m;
993 }
994
995 static void Op5F(void)                                                  // BBR5
996 {
997         int16_t m = (int16_t)(int8_t)READ_IMM;
998
999         if (!(regs->a & 0x20))
1000                 regs->pc += m;
1001 }
1002
1003 static void Op6F(void)                                                  // BBR6
1004 {
1005         int16_t m = (int16_t)(int8_t)READ_IMM;
1006
1007         if (!(regs->a & 0x40))
1008                 regs->pc += m;
1009 }
1010
1011 static void Op7F(void)                                                  // BBR7
1012 {
1013         int16_t m = (int16_t)(int8_t)READ_IMM;
1014
1015         if (!(regs->a & 0x80))
1016                 regs->pc += m;
1017 }
1018
1019 static void Op8F(void)                                                  // BBS0
1020 {
1021         int16_t m = (int16_t)(int8_t)READ_IMM;
1022
1023         if (regs->a & 0x01)
1024                 regs->pc += m;
1025 }
1026
1027 static void Op9F(void)                                                  // BBS1
1028 {
1029         int16_t m = (int16_t)(int8_t)READ_IMM;
1030
1031         if (regs->a & 0x02)
1032                 regs->pc += m;
1033 }
1034
1035 static void OpAF(void)                                                  // BBS2
1036 {
1037         int16_t m = (int16_t)(int8_t)READ_IMM;
1038
1039         if (regs->a & 0x04)
1040                 regs->pc += m;
1041 }
1042
1043 static void OpBF(void)                                                  // BBS3
1044 {
1045         int16_t m = (int16_t)(int8_t)READ_IMM;
1046
1047         if (regs->a & 0x08)
1048                 regs->pc += m;
1049 }
1050
1051 static void OpCF(void)                                                  // BBS4
1052 {
1053         int16_t m = (int16_t)(int8_t)READ_IMM;
1054
1055         if (regs->a & 0x10)
1056                 regs->pc += m;
1057 }
1058
1059 static void OpDF(void)                                                  // BBS5
1060 {
1061         int16_t m = (int16_t)(int8_t)READ_IMM;
1062
1063         if (regs->a & 0x20)
1064                 regs->pc += m;
1065 }
1066
1067 static void OpEF(void)                                                  // BBS6
1068 {
1069         int16_t m = (int16_t)(int8_t)READ_IMM;
1070
1071         if (regs->a & 0x40)
1072                 regs->pc += m;
1073 }
1074
1075 static void OpFF(void)                                                  // BBS7
1076 {
1077         int16_t m = (int16_t)(int8_t)READ_IMM;
1078
1079         if (regs->a & 0x80)
1080                 regs->pc += m;
1081 }
1082
1083 /*
1084 BCC     Relative        BCC Oper        90      2       2
1085 BCS     Relative        BCS Oper        B0      2       2
1086 BEQ     Relative        BEQ Oper        F0      2       2
1087 */
1088
1089 // Branch taken adds a cycle, crossing page adds one more
1090
1091 #define HANDLE_BRANCH_TAKEN(m)      \
1092 {                                   \
1093         uint16_t oldpc = regs->pc;       \
1094         regs->pc += m;                   \
1095         regs->clock++;                   \
1096 \
1097         if ((oldpc ^ regs->pc) & 0xFF00) \
1098                 regs->clock++;               \
1099 }
1100
1101 // Branch opcodes
1102
1103 static void Op90(void)                                                  // BCC
1104 {
1105         int16_t m = (int16_t)(int8_t)READ_IMM;
1106
1107         if (!(regs->cc & FLAG_C))
1108                 HANDLE_BRANCH_TAKEN(m)
1109 }
1110
1111 static void OpB0(void)                                                  // BCS
1112 {
1113         int16_t m = (int16_t)(int8_t)READ_IMM;
1114
1115         if (regs->cc & FLAG_C)
1116                 HANDLE_BRANCH_TAKEN(m)
1117 }
1118
1119 static void OpF0(void)                                                  // BEQ
1120 {
1121         int16_t m = (int16_t)(int8_t)READ_IMM;
1122
1123         if (regs->cc & FLAG_Z)
1124                 HANDLE_BRANCH_TAKEN(m)
1125 }
1126
1127 /*
1128 BIT     Immediate       BIT #Oper       89      2       2
1129 Zero Page               BIT Zpg         24      2       3
1130 Zero Page,X             BIT Zpg,X       34      2       4
1131 Absolute                BIT Abs         2C      3       4
1132 Absolute,X              BIT Abs,X       3C      3       4
1133 */
1134
1135 // BIT opcodes
1136
1137 /* 1. The BIT instruction copies bit 6 to the V flag, and bit 7 to the N flag
1138       (except in immediate addressing mode where V & N are untouched.) The
1139       accumulator and the operand are ANDed and the Z flag is set
1140       appropriately. */
1141
1142 #define OP_BIT_HANDLER(m) \
1143         int8_t result = regs->a & (m); \
1144         regs->cc &= ~(FLAG_N | FLAG_V); \
1145         regs->cc |= ((m) & 0xC0); \
1146         SET_Z(result)
1147
1148 static void Op89(void)                                                  // BIT #
1149 {
1150         int8_t m = READ_IMM;
1151         int8_t result = regs->a & m;
1152         SET_Z(result);
1153 }
1154
1155 static void Op24(void)                                                  // BIT ZP
1156 {
1157         int8_t m = READ_ZP;
1158         OP_BIT_HANDLER(m);
1159 }
1160
1161 static void Op34(void)                                                  // BIT ZP, X
1162 {
1163         uint8_t m = READ_ZP_X;
1164         OP_BIT_HANDLER(m);
1165 }
1166
1167 static void Op2C(void)                                                  // BIT ABS
1168 {
1169         uint8_t m = READ_ABS;
1170         OP_BIT_HANDLER(m);
1171 }
1172
1173 static void Op3C(void)                                                  // BIT ABS, X
1174 {
1175         uint8_t m = READ_ABS_X;
1176         OP_BIT_HANDLER(m);
1177 }
1178
1179 /*
1180 BMI     Relative        BMI Oper        30      2       2
1181 BNE     Relative        BNE Oper        D0      2       2
1182 BPL     Relative        BPL Oper        10      2       2
1183 BRA     Relative        BRA Oper        80      2       3
1184 */
1185
1186 // More branch opcodes
1187
1188 static void Op30(void)                                                  // BMI
1189 {
1190         int16_t m = (int16_t)(int8_t)READ_IMM;
1191
1192         if (regs->cc & FLAG_N)
1193                 HANDLE_BRANCH_TAKEN(m)
1194 }
1195
1196 static void OpD0(void)                                                  // BNE
1197 {
1198         int16_t m = (int16_t)(int8_t)READ_IMM;
1199
1200         if (!(regs->cc & FLAG_Z))
1201                 HANDLE_BRANCH_TAKEN(m)
1202 }
1203
1204 static void Op10(void)                                                  // BPL
1205 {
1206         int16_t m = (int16_t)(int8_t)READ_IMM;
1207
1208         if (!(regs->cc & FLAG_N))
1209                 HANDLE_BRANCH_TAKEN(m)
1210 }
1211
1212 static void Op80(void)                                                  // BRA
1213 {
1214         int16_t m = (int16_t)(int8_t)READ_IMM;
1215         HANDLE_BRANCH_TAKEN(m)
1216 }
1217
1218 /*
1219 BRK     Implied         BRK                     00      1       7
1220 */
1221
1222 static void Op00(void)                                                  // BRK
1223 {
1224 //#ifdef __DEBUG__
1225 #if 1
1226 WriteLog("\n*** BRK ***\n\n");
1227 WriteLog(" [PC=%04X, SP=%04X, CC=%s%s.%s%s%s%s%s, A=%02X, X=%02X, Y=%02X]\n",
1228         regs->pc, 0x0100 + regs->sp,
1229         (regs->cc & FLAG_N ? "N" : "-"), (regs->cc & FLAG_V ? "V" : "-"),
1230         (regs->cc & FLAG_B ? "B" : "-"), (regs->cc & FLAG_D ? "D" : "-"),
1231         (regs->cc & FLAG_I ? "I" : "-"), (regs->cc & FLAG_Z ? "Z" : "-"),
1232         (regs->cc & FLAG_C ? "C" : "-"), regs->a, regs->x, regs->y);
1233 #endif
1234         regs->cc |= FLAG_B;                                                     // Set B
1235         regs->pc++;                                                                     // RTI comes back to the instruction one byte after the BRK
1236         regs->WrMem(0x0100 + regs->sp--, regs->pc >> 8);        // Save PC and CC
1237         regs->WrMem(0x0100 + regs->sp--, regs->pc & 0xFF);
1238         regs->WrMem(0x0100 + regs->sp--, regs->cc);
1239         regs->cc |= FLAG_I;                                                     // Set I
1240         regs->cc &= ~FLAG_D;                                                    // & clear D
1241         regs->pc = RdMemW(0xFFFE);                                      // Grab the IRQ vector & go...
1242 }
1243
1244 /*
1245 BVC     Relative        BVC Oper        50      2       2
1246 BVS     Relative        BVS Oper        70      2       2
1247 */
1248
1249 // Even more branch opcodes
1250
1251 static void Op50(void)                                                  // BVC
1252 {
1253         int16_t m = (int16_t)(int8_t)READ_IMM;
1254
1255         if (!(regs->cc & FLAG_V))
1256                 HANDLE_BRANCH_TAKEN(m)
1257 }
1258
1259 static void Op70(void)                                                  // BVS
1260 {
1261         int16_t m = (int16_t)(int8_t)READ_IMM;
1262
1263         if (regs->cc & FLAG_V)
1264                 HANDLE_BRANCH_TAKEN(m)
1265 }
1266
1267 /*
1268 CLC     Implied         CLC                     18      1       2
1269 */
1270
1271 static void Op18(void)                                                  // CLC
1272 {
1273         regs->cc &= ~FLAG_C;
1274 }
1275
1276 /*
1277 CLD     Implied         CLD                     D8      1       2
1278 */
1279
1280 static void OpD8(void)                                                  // CLD
1281 {
1282         CLR_D;
1283 }
1284
1285 /*
1286 CLI     Implied         CLI                     58      1       2
1287 */
1288
1289 static void Op58(void)                                                  // CLI
1290 {
1291         regs->cc &= ~FLAG_I;
1292 }
1293
1294 /*
1295 CLV     Implied         CLV                     B8      1       2
1296 */
1297
1298 static void OpB8(void)                                                  // CLV
1299 {
1300         regs->cc &= ~FLAG_V;
1301 }
1302
1303 /*
1304 CMP     Immediate       CMP #Oper       C9      2       2
1305 Zero Page               CMP Zpg         C5      2       3
1306 Zero Page,X             CMP Zpg         D5      2       4
1307 Absolute                CMP Abs         CD      3       4
1308 Absolute,X              CMP Abs,X       DD      3       4
1309 Absolute,Y              CMP Abs,Y       D9      3       4
1310 (Zero Page,X)   CMP (Zpg,X)     C1      2       6
1311 (Zero Page),Y   CMP (Zpg),Y     D1      2       5
1312 (Zero Page)             CMP (Zpg)       D2      2       5
1313 */
1314
1315 // CMP opcodes
1316
1317 #define OP_CMP_HANDLER(m) \
1318         uint8_t result = regs->a - (m); \
1319         SET_ZNC_CMP(m, regs->a, result)
1320
1321 static void OpC9(void)                                                  // CMP #
1322 {
1323         uint8_t m = READ_IMM;
1324         OP_CMP_HANDLER(m);
1325 }
1326
1327 static void OpC5(void)                                                  // CMP ZP
1328 {
1329         uint8_t m = READ_ZP;
1330         OP_CMP_HANDLER(m);
1331 }
1332
1333 static void OpD5(void)                                                  // CMP ZP, X
1334 {
1335         uint8_t m = READ_ZP_X;
1336         OP_CMP_HANDLER(m);
1337 }
1338
1339 static void OpCD(void)                                                  // CMP ABS
1340 {
1341         uint8_t m = READ_ABS;
1342         OP_CMP_HANDLER(m);
1343 }
1344
1345 static void OpDD(void)                                                  // CMP ABS, X
1346 {
1347         uint8_t m = READ_ABS_X;
1348         OP_CMP_HANDLER(m);
1349 }
1350
1351 static void OpD9(void)                                                  // CMP ABS, Y
1352 {
1353         uint8_t m = READ_ABS_Y;
1354         OP_CMP_HANDLER(m);
1355 }
1356
1357 static void OpC1(void)                                                  // CMP (ZP, X)
1358 {
1359         uint8_t m = READ_IND_ZP_X;
1360         OP_CMP_HANDLER(m);
1361 }
1362
1363 static void OpD1(void)                                                  // CMP (ZP), Y
1364 {
1365         uint8_t m = READ_IND_ZP_Y;
1366         OP_CMP_HANDLER(m);
1367 }
1368
1369 static void OpD2(void)                                                  // CMP (ZP)
1370 {
1371         uint8_t m = READ_IND_ZP;
1372         OP_CMP_HANDLER(m);
1373 }
1374
1375 /*
1376 CPX     Immediate       CPX #Oper       E0      2       2
1377 Zero Page               CPX Zpg         E4      2       3
1378 Absolute                CPX Abs         EC      3       4
1379 */
1380
1381 // CPX opcodes
1382
1383 #define OP_CPX_HANDLER(m) \
1384         uint8_t result = regs->x - (m); \
1385         SET_ZNC_CMP(m, regs->x, result)
1386
1387 static void OpE0(void)                                                  // CPX #
1388 {
1389         uint8_t m = READ_IMM;
1390         OP_CPX_HANDLER(m);
1391 }
1392
1393 static void OpE4(void)                                                  // CPX ZP
1394 {
1395         uint8_t m = READ_ZP;
1396         OP_CPX_HANDLER(m);
1397 }
1398
1399 static void OpEC(void)                                                  // CPX ABS
1400 {
1401         uint8_t m = READ_ABS;
1402         OP_CPX_HANDLER(m);
1403 }
1404
1405 /*
1406 CPY     Immediate       CPY #Oper       C0      2       2
1407 Zero Page               CPY Zpg         C4      2       3
1408 Absolute                CPY Abs         CC      3       4
1409 */
1410
1411 // CPY opcodes
1412
1413 #define OP_CPY_HANDLER(m) \
1414         uint8_t result = regs->y - (m); \
1415         SET_ZNC_CMP(m, regs->y, result)
1416
1417 static void OpC0(void)                                                  // CPY #
1418 {
1419         uint8_t m = READ_IMM;
1420         OP_CPY_HANDLER(m);
1421 }
1422
1423 static void OpC4(void)                                                  // CPY ZP
1424 {
1425         uint8_t m = READ_ZP;
1426         OP_CPY_HANDLER(m);
1427 }
1428
1429 static void OpCC(void)                                                  // CPY ABS
1430 {
1431         uint8_t m = READ_ABS;
1432         OP_CPY_HANDLER(m);
1433 }
1434
1435 /*
1436 DEA     Accumulator     DEA                     3A      1       2
1437 */
1438
1439 static void Op3A(void)                                                  // DEA
1440 {
1441         regs->a--;
1442         SET_ZN(regs->a);
1443 }
1444
1445 /*
1446 DEC     Zero Page       DEC Zpg         C6      2       5
1447 Zero Page,X             DEC Zpg,X       D6      2       6
1448 Absolute                DEC Abs         CE      3       6
1449 Absolute,X              DEC Abs,X       DE      3       7
1450 */
1451
1452 // DEC opcodes
1453
1454 #define OP_DEC_HANDLER(m) \
1455         m--; \
1456         SET_ZN(m)
1457
1458 static void OpC6(void)                                                  // DEC ZP
1459 {
1460         uint8_t m;
1461         READ_ZP_WB(m);
1462         OP_DEC_HANDLER(m);
1463         WRITE_BACK(m);
1464 }
1465
1466 static void OpD6(void)                                                  // DEC ZP, X
1467 {
1468         uint8_t m;
1469         READ_ZP_X_WB(m);
1470         OP_DEC_HANDLER(m);
1471         WRITE_BACK(m);
1472 }
1473
1474 static void OpCE(void)                                                  // DEC ABS
1475 {
1476         uint8_t m;
1477         READ_ABS_WB(m);
1478         OP_DEC_HANDLER(m);
1479         WRITE_BACK(m);
1480 }
1481
1482 static void OpDE(void)                                                  // DEC ABS, X
1483 {
1484         uint8_t m;
1485         READ_ABS_X_WB(m);
1486         OP_DEC_HANDLER(m);
1487         WRITE_BACK(m);
1488 }
1489
1490 /*
1491 DEX     Implied         DEX                     CA      1       2
1492 */
1493
1494 static void OpCA(void)                                                  // DEX
1495 {
1496         regs->x--;
1497         SET_ZN(regs->x);
1498 }
1499
1500 /*
1501 DEY     Implied         DEY                     88      1       2
1502 */
1503
1504 static void Op88(void)                                                  // DEY
1505 {
1506         regs->y--;
1507         SET_ZN(regs->y);
1508 }
1509
1510 /*
1511 EOR     Immediate       EOR #Oper       49      2       2
1512 Zero Page               EOR Zpg         45      2       3
1513 Zero Page,X             EOR Zpg,X       55      2       4
1514 Absolute                EOR Abs         4D      3       4
1515 Absolute,X              EOR Abs,X       5D      3       4
1516 Absolute,Y              EOR Abs,Y       59      3       4
1517 (Zero Page,X)   EOR (Zpg,X)     41      2       6
1518 (Zero Page),Y   EOR (Zpg),Y     51      2       5
1519 (Zero Page)             EOR (Zpg)       52      2       5
1520 */
1521
1522 // EOR opcodes
1523
1524 #define OP_EOR_HANDLER(m) \
1525         regs->a ^= m; \
1526         SET_ZN(regs->a)
1527
1528 static void Op49(void)                                                  // EOR #
1529 {
1530         uint8_t m = READ_IMM;
1531         OP_EOR_HANDLER(m);
1532 }
1533
1534 static void Op45(void)                                                  // EOR ZP
1535 {
1536         uint8_t m = READ_ZP;
1537         OP_EOR_HANDLER(m);
1538 }
1539
1540 static void Op55(void)                                                  // EOR ZP, X
1541 {
1542         uint8_t m = READ_ZP_X;
1543         OP_EOR_HANDLER(m);
1544 }
1545
1546 static void Op4D(void)                                                  // EOR ABS
1547 {
1548         uint8_t m = READ_ABS;
1549         OP_EOR_HANDLER(m);
1550 }
1551
1552 static void Op5D(void)                                                  // EOR ABS, X
1553 {
1554         uint8_t m = READ_ABS_X;
1555         OP_EOR_HANDLER(m);
1556 }
1557
1558 static void Op59(void)                                                  // EOR ABS, Y
1559 {
1560         uint8_t m = READ_ABS_Y;
1561         OP_EOR_HANDLER(m);
1562 }
1563
1564 static void Op41(void)                                                  // EOR (ZP, X)
1565 {
1566         uint8_t m = READ_IND_ZP_X;
1567         OP_EOR_HANDLER(m);
1568 }
1569
1570 static void Op51(void)                                                  // EOR (ZP), Y
1571 {
1572         uint8_t m = READ_IND_ZP_Y;
1573         OP_EOR_HANDLER(m);
1574 }
1575
1576 static void Op52(void)                                                  // EOR (ZP)
1577 {
1578         uint8_t m = READ_IND_ZP;
1579         OP_EOR_HANDLER(m);
1580 }
1581
1582 /*
1583 INA     Accumulator     INA                     1A      1       2
1584 */
1585
1586 static void Op1A(void)                                                  // INA
1587 {
1588         regs->a++;
1589         SET_ZN(regs->a);
1590 }
1591
1592 /*
1593 INC     Zero Page       INC Zpg         E6      2       5
1594 Zero Page,X             INC Zpg,X       F6      2       6
1595 Absolute                INC Abs         EE      3       6
1596 Absolute,X              INC Abs,X       FE      3       7
1597 */
1598
1599 // INC opcodes
1600
1601 #define OP_INC_HANDLER(m) \
1602         m++; \
1603         SET_ZN(m)
1604
1605 static void OpE6(void)                                                  // INC ZP
1606 {
1607         uint8_t m;
1608         READ_ZP_WB(m);
1609         OP_INC_HANDLER(m);
1610         WRITE_BACK(m);
1611 }
1612
1613 static void OpF6(void)                                                  // INC ZP, X
1614 {
1615         uint8_t m;
1616         READ_ZP_X_WB(m);
1617         OP_INC_HANDLER(m);
1618         WRITE_BACK(m);
1619 }
1620
1621 static void OpEE(void)                                                  // INC ABS
1622 {
1623         uint8_t m;
1624         READ_ABS_WB(m);
1625         OP_INC_HANDLER(m);
1626         WRITE_BACK(m);
1627 }
1628
1629 static void OpFE(void)                                                  // INC ABS, X
1630 {
1631         uint8_t m;
1632         READ_ABS_X_WB(m);
1633         OP_INC_HANDLER(m);
1634         WRITE_BACK(m);
1635 }
1636
1637 /*
1638 INX     Implied         INX                     E8      1       2
1639 */
1640
1641 static void OpE8(void)                                                  // INX
1642 {
1643         regs->x++;
1644         SET_ZN(regs->x);
1645 }
1646
1647 /*
1648 INY     Implied         INY                     C8      1       2
1649 */
1650
1651 static void OpC8(void)                                                  // INY
1652 {
1653         regs->y++;
1654         SET_ZN(regs->y);
1655 }
1656
1657 /*
1658 JMP     Absolute        JMP Abs         4C      3       3
1659 (Absolute)              JMP (Abs)       6C      3       5
1660 (Absolute,X)    JMP (Abs,X)     7C      3       6
1661 */
1662
1663 // JMP opcodes
1664
1665 static void Op4C(void)                                                  // JMP ABS
1666 {
1667         regs->pc = RdMemW(regs->pc);
1668 }
1669
1670 static void Op6C(void)                                                  // JMP (ABS)
1671 {
1672         regs->pc = RdMemW(RdMemW(regs->pc));
1673 }
1674
1675 static void Op7C(void)                                                  // JMP (ABS, X)
1676 {
1677         regs->pc = RdMemW(RdMemW(regs->pc) + regs->x);
1678 }
1679
1680 /*
1681 JSR     Absolute        JSR Abs         20      3       6
1682 */
1683
1684 static void Op20(void)                                                  // JSR
1685 {
1686         uint16_t addr = RdMemW(regs->pc);
1687         regs->pc++;                                                                     // Since it pushes return address - 1...
1688         regs->WrMem(0x0100 + regs->sp--, regs->pc >> 8);
1689         regs->WrMem(0x0100 + regs->sp--, regs->pc & 0xFF);
1690         regs->pc = addr;
1691 }
1692
1693 /*
1694 LDA     Immediate       LDA #Oper       A9      2       2
1695 Zero Page               LDA Zpg         A5      2       3
1696 Zero Page,X             LDA Zpg,X       B5      2       4
1697 Absolute                LDA Abs         AD      3       4
1698 Absolute,X              LDA Abs,X       BD      3       4
1699 Absolute,Y              LDA Abs,Y       B9      3       4
1700 (Zero Page,X)   LDA (Zpg,X)     A1      2       6
1701 (Zero Page),Y   LDA (Zpg),Y     B1      2       5
1702 (Zero Page)             LDA (Zpg)       B2      2       5
1703 */
1704
1705 // LDA opcodes
1706
1707 #define OP_LDA_HANDLER(m) \
1708         regs->a = m; \
1709         SET_ZN(regs->a)
1710
1711 static void OpA9(void)                                                  // LDA #
1712 {
1713         uint8_t m = READ_IMM;
1714         OP_LDA_HANDLER(m);
1715 }
1716
1717 static void OpA5(void)                                                  // LDA ZP
1718 {
1719         uint8_t m = READ_ZP;
1720         OP_LDA_HANDLER(m);
1721 }
1722
1723 static void OpB5(void)                                                  // LDA ZP, X
1724 {
1725         uint8_t m = READ_ZP_X;
1726         OP_LDA_HANDLER(m);
1727 }
1728
1729 static void OpAD(void)                                                  // LDA ABS
1730 {
1731         uint8_t m = READ_ABS;
1732         OP_LDA_HANDLER(m);
1733 }
1734
1735 static void OpBD(void)                                                  // LDA ABS, X
1736 {
1737         uint8_t m = READ_ABS_X;
1738         OP_LDA_HANDLER(m);
1739 }
1740
1741 static void OpB9(void)                                                  // LDA ABS, Y
1742 {
1743         uint8_t m = READ_ABS_Y;
1744         OP_LDA_HANDLER(m);
1745 }
1746
1747 static void OpA1(void)                                                  // LDA (ZP, X)
1748 {
1749         uint8_t m = READ_IND_ZP_X;
1750         OP_LDA_HANDLER(m);
1751 }
1752
1753 static void OpB1(void)                                                  // LDA (ZP), Y
1754 {
1755         uint8_t m = READ_IND_ZP_Y;
1756         OP_LDA_HANDLER(m);
1757 }
1758
1759 static void OpB2(void)                                                  // LDA (ZP)
1760 {
1761         uint8_t m = READ_IND_ZP;
1762         OP_LDA_HANDLER(m);
1763 }
1764
1765 /*
1766 LDX     Immediate       LDX #Oper       A2      2       2
1767 Zero Page               LDX Zpg         A6      2       3
1768 Zero Page,Y             LDX Zpg,Y       B6      2       4
1769 Absolute                LDX Abs         AE      3       4
1770 Absolute,Y              LDX Abs,Y       BE      3       4
1771 */
1772
1773 // LDX opcodes
1774
1775 #define OP_LDX_HANDLER(m) \
1776         regs->x = m; \
1777         SET_ZN(regs->x)
1778
1779 static void OpA2(void)                                                  // LDX #
1780 {
1781         uint8_t m = READ_IMM;
1782         OP_LDX_HANDLER(m);
1783 }
1784
1785 static void OpA6(void)                                                  // LDX ZP
1786 {
1787         uint8_t m = READ_ZP;
1788         OP_LDX_HANDLER(m);
1789 }
1790
1791 static void OpB6(void)                                                  // LDX ZP, Y
1792 {
1793         uint8_t m = READ_ZP_Y;
1794         OP_LDX_HANDLER(m);
1795 }
1796
1797 static void OpAE(void)                                                  // LDX ABS
1798 {
1799         uint8_t m = READ_ABS;
1800         OP_LDX_HANDLER(m);
1801 }
1802
1803 static void OpBE(void)                                                  // LDX ABS, Y
1804 {
1805         uint8_t m = READ_ABS_Y;
1806         OP_LDX_HANDLER(m);
1807 }
1808
1809 /*
1810 LDY     Immediate       LDY #Oper       A0      2       2
1811 Zero Page               LDY Zpg         A4      2       3
1812 Zero Page,Y             LDY Zpg,X       B4      2       4
1813 Absolute                LDY Abs         AC      3       4
1814 Absolute,Y              LDY Abs,X       BC      3       4
1815 */
1816
1817 // LDY opcodes
1818
1819 #define OP_LDY_HANDLER(m) \
1820         regs->y = m; \
1821         SET_ZN(regs->y)
1822
1823 static void OpA0(void)                                                  // LDY #
1824 {
1825         uint8_t m = READ_IMM;
1826         OP_LDY_HANDLER(m);
1827 }
1828
1829 static void OpA4(void)                                                  // LDY ZP
1830 {
1831         uint8_t m = READ_ZP;
1832         OP_LDY_HANDLER(m);
1833 }
1834
1835 static void OpB4(void)                                                  // LDY ZP, X
1836 {
1837         uint8_t m = READ_ZP_X;
1838         OP_LDY_HANDLER(m);
1839 }
1840
1841 static void OpAC(void)                                                  // LDY ABS
1842 {
1843         uint8_t m = READ_ABS;
1844         OP_LDY_HANDLER(m);
1845 }
1846
1847 static void OpBC(void)                                                  // LDY ABS, X
1848 {
1849         uint8_t m = READ_ABS_X;
1850         OP_LDY_HANDLER(m);
1851 }
1852
1853 /*
1854 LSR     Accumulator     LSR A           4A      1       2
1855 Zero Page               LSR Zpg         46      2       5
1856 Zero Page,X             LSR Zpg,X       56      2       6
1857 Absolute                LSR Abs         4E      3       6
1858 Absolute,X              LSR Abs,X       5E      3       7
1859 */
1860
1861 // LSR opcodes
1862
1863 #define OP_LSR_HANDLER(m) \
1864         regs->cc = ((m) & 0x01 ? regs->cc | FLAG_C : regs->cc & ~FLAG_C); \
1865         (m) >>= 1; \
1866         CLR_N; SET_Z((m))
1867
1868 static void Op4A(void)                                                  // LSR A
1869 {
1870         OP_LSR_HANDLER(regs->a);
1871 }
1872
1873 static void Op46(void)                                                  // LSR ZP
1874 {
1875         uint8_t m;
1876         READ_ZP_WB(m);
1877         OP_LSR_HANDLER(m);
1878         WRITE_BACK(m);
1879 }
1880
1881 static void Op56(void)                                                  // LSR ZP, X
1882 {
1883         uint8_t m;
1884         READ_ZP_X_WB(m);
1885         OP_LSR_HANDLER(m);
1886         WRITE_BACK(m);
1887 }
1888
1889 static void Op4E(void)                                                  // LSR ABS
1890 {
1891         uint8_t m;
1892         READ_ABS_WB(m);
1893         OP_LSR_HANDLER(m);
1894         WRITE_BACK(m);
1895 }
1896
1897 static void Op5E(void)                                                  // LSR ABS, X
1898 {
1899         uint8_t m;
1900         READ_ABS_X_WB(m);
1901         OP_LSR_HANDLER(m);
1902         WRITE_BACK(m);
1903 }
1904
1905 /*
1906 NOP     Implied         NOP                     EA      1       2
1907 */
1908
1909 static void OpEA(void)                                                  // NOP
1910 {
1911 }
1912
1913 /*
1914 ORA     Immediate       ORA #Oper       09      2       2
1915 Zero Page               ORA Zpg         05      2       3
1916 Zero Page,X             ORA Zpg,X       15      2       4
1917 Absolute                ORA Abs         0D      3       4
1918 Absolute,X              ORA Abs,X       1D      3       4
1919 Absolute,Y              ORA Abs,Y       19      3       4
1920 (Zero Page,X)   ORA (Zpg,X)     01      2       6
1921 (Zero Page),Y   ORA (Zpg),Y     11      2       5
1922 (Zero Page)             ORA (Zpg)       12      2       5
1923 */
1924
1925 // ORA opcodes
1926
1927 #define OP_ORA_HANDLER(m) \
1928         regs->a |= m; \
1929         SET_ZN(regs->a)
1930
1931 static void Op09(void)                                                  // ORA #
1932 {
1933         uint8_t m = READ_IMM;
1934         OP_ORA_HANDLER(m);
1935 }
1936
1937 static void Op05(void)                                                  // ORA ZP
1938 {
1939         uint8_t m = READ_ZP;
1940         OP_ORA_HANDLER(m);
1941 }
1942
1943 static void Op15(void)                                                  // ORA ZP, X
1944 {
1945         uint8_t m = READ_ZP_X;
1946         OP_ORA_HANDLER(m);
1947 }
1948
1949 static void Op0D(void)                                                  // ORA ABS
1950 {
1951         uint8_t m = READ_ABS;
1952         OP_ORA_HANDLER(m);
1953 }
1954
1955 static void Op1D(void)                                                  // ORA ABS, X
1956 {
1957         uint8_t m = READ_ABS_X;
1958         OP_ORA_HANDLER(m);
1959 }
1960
1961 static void Op19(void)                                                  // ORA ABS, Y
1962 {
1963         uint8_t m = READ_ABS_Y;
1964         OP_ORA_HANDLER(m);
1965 }
1966
1967 static void Op01(void)                                                  // ORA (ZP, X)
1968 {
1969         uint8_t m = READ_IND_ZP_X;
1970         OP_ORA_HANDLER(m);
1971 }
1972
1973 static void Op11(void)                                                  // ORA (ZP), Y
1974 {
1975         uint8_t m = READ_IND_ZP_Y;
1976         OP_ORA_HANDLER(m);
1977 }
1978
1979 static void Op12(void)                                                  // ORA (ZP)
1980 {
1981         uint8_t m = READ_IND_ZP;
1982         OP_ORA_HANDLER(m);
1983 }
1984
1985 /*
1986 PHA     Implied         PHA                     48      1       3
1987 */
1988
1989 static void Op48(void)                                                  // PHA
1990 {
1991         regs->WrMem(0x0100 + regs->sp--, regs->a);
1992 }
1993
1994 static void Op08(void)                                                  // PHP
1995 {
1996         regs->cc |= FLAG_UNK;                                           // Make sure that the unused bit is always set
1997         regs->WrMem(0x0100 + regs->sp--, regs->cc);
1998 }
1999
2000 /*
2001 PHX     Implied         PHX                     DA      1       3
2002 */
2003
2004 static void OpDA(void)                                                  // PHX
2005 {
2006         regs->WrMem(0x0100 + regs->sp--, regs->x);
2007 }
2008
2009 /*
2010 PHY     Implied         PHY                     5A      1       3
2011 */
2012
2013 static void Op5A(void)                                                  // PHY
2014 {
2015         regs->WrMem(0x0100 + regs->sp--, regs->y);
2016 }
2017
2018 /*
2019 PLA     Implied         PLA                     68      1       4
2020 */
2021
2022 static void Op68(void)                                                  // PLA
2023 {
2024         regs->a = regs->RdMem(0x0100 + ++regs->sp);
2025         SET_ZN(regs->a);
2026 }
2027
2028 static void Op28(void)                                                  // PLP
2029 {
2030         regs->cc = regs->RdMem(0x0100 + ++regs->sp);
2031 }
2032
2033 /*
2034 PLX     Implied         PLX                     FA      1       4
2035 */
2036
2037 static void OpFA(void)                                                  // PLX
2038 {
2039         regs->x = regs->RdMem(0x0100 + ++regs->sp);
2040         SET_ZN(regs->x);
2041 }
2042
2043 /*
2044 PLY     Implied         PLY                     7A      1       4
2045 */
2046
2047 static void Op7A(void)                                                  // PLY
2048 {
2049         regs->y = regs->RdMem(0x0100 + ++regs->sp);
2050         SET_ZN(regs->y);
2051 }
2052
2053 /*
2054 The bit set and clear instructions have the form xyyy0111, where x is 0 to clear a bit or 1 to set it, and yyy is which bit at the memory location to set or clear.
2055    RMB0  RMB1  RMB2  RMB3  RMB4  RMB5  RMB6  RMB7
2056   zp  07  17  27  37  47  57  67  77
2057      SMB0  SMB1  SMB2  SMB3  SMB4  SMB5  SMB6  SMB7
2058   zp  87  97  A7  B7  C7  D7  E7  F7
2059 */
2060
2061 // RMB opcodes
2062
2063 static void Op07(void)                                                  // RMB0 ZP
2064 {
2065         uint8_t m;
2066         READ_ZP_WB(m);
2067         m &= 0xFE;
2068         WRITE_BACK(m);
2069 }
2070
2071 static void Op17(void)                                                  // RMB1 ZP
2072 {
2073         uint8_t m;
2074         READ_ZP_WB(m);
2075         m &= 0xFD;
2076         WRITE_BACK(m);
2077 }
2078
2079 static void Op27(void)                                                  // RMB2 ZP
2080 {
2081         uint8_t m;
2082         READ_ZP_WB(m);
2083         m &= 0xFB;
2084         WRITE_BACK(m);
2085 }
2086
2087 static void Op37(void)                                                  // RMB3 ZP
2088 {
2089         uint8_t m;
2090         READ_ZP_WB(m);
2091         m &= 0xF7;
2092         WRITE_BACK(m);
2093 }
2094
2095 static void Op47(void)                                                  // RMB4 ZP
2096 {
2097         uint8_t m;
2098         READ_ZP_WB(m);
2099         m &= 0xEF;
2100         WRITE_BACK(m);
2101 }
2102
2103 static void Op57(void)                                                  // RMB5 ZP
2104 {
2105         uint8_t m;
2106         READ_ZP_WB(m);
2107         m &= 0xDF;
2108         WRITE_BACK(m);
2109 }
2110
2111 static void Op67(void)                                                  // RMB6 ZP
2112 {
2113         uint8_t m;
2114         READ_ZP_WB(m);
2115         m &= 0xBF;
2116         WRITE_BACK(m);
2117 }
2118
2119 static void Op77(void)                                                  // RMB7 ZP
2120 {
2121         uint8_t m;
2122         READ_ZP_WB(m);
2123         m &= 0x7F;
2124         WRITE_BACK(m);
2125 }
2126
2127 /*
2128 ROL     Accumulator     ROL A           2A      1       2
2129 Zero Page               ROL Zpg         26      2       5
2130 Zero Page,X             ROL Zpg,X       36      2       6
2131 Absolute                ROL Abs         2E      3       6
2132 Absolute,X              ROL Abs,X       3E      3       7
2133 */
2134
2135 // ROL opcodes
2136
2137 #define OP_ROL_HANDLER(m) \
2138         uint8_t tmp = regs->cc & 0x01; \
2139         regs->cc = ((m) & 0x80 ? regs->cc | FLAG_C : regs->cc & ~FLAG_C); \
2140         (m) = ((m) << 1) | tmp; \
2141         SET_ZN((m))
2142
2143 static void Op2A(void)                                                  // ROL A
2144 {
2145         OP_ROL_HANDLER(regs->a);
2146 }
2147
2148 static void Op26(void)                                                  // ROL ZP
2149 {
2150         uint8_t m;
2151         READ_ZP_WB(m);
2152         OP_ROL_HANDLER(m);
2153         WRITE_BACK(m);
2154 }
2155
2156 static void Op36(void)                                                  // ROL ZP, X
2157 {
2158         uint8_t m;
2159         READ_ZP_X_WB(m);
2160         OP_ROL_HANDLER(m);
2161         WRITE_BACK(m);
2162 }
2163
2164 static void Op2E(void)                                                  // ROL ABS
2165 {
2166         uint8_t m;
2167         READ_ABS_WB(m);
2168         OP_ROL_HANDLER(m);
2169         WRITE_BACK(m);
2170 }
2171
2172 static void Op3E(void)                                                  // ROL ABS, X
2173 {
2174         uint8_t m;
2175         READ_ABS_X_WB(m);
2176         OP_ROL_HANDLER(m);
2177         WRITE_BACK(m);
2178 }
2179
2180 /*
2181 ROR     Accumulator     ROR A           6A      1       2
2182 Zero Page               ROR Zpg         66      2       5
2183 Zero Page,X             ROR Zpg,X       76      2       6
2184 Absolute                ROR Abs         6E      3       6
2185 Absolute,X              ROR Abs,X       7E      3       7
2186 */
2187
2188 // ROR opcodes
2189
2190 #define OP_ROR_HANDLER(m) \
2191         uint8_t tmp = (regs->cc & 0x01) << 7; \
2192         regs->cc = ((m) & 0x01 ? regs->cc | FLAG_C : regs->cc & ~FLAG_C); \
2193         (m) = ((m) >> 1) | tmp; \
2194         SET_ZN((m))
2195
2196 static void Op6A(void)                                                  // ROR A
2197 {
2198         OP_ROR_HANDLER(regs->a);
2199 }
2200
2201 static void Op66(void)                                                  // ROR ZP
2202 {
2203         uint8_t m;
2204         READ_ZP_WB(m);
2205         OP_ROR_HANDLER(m);
2206         WRITE_BACK(m);
2207 }
2208
2209 static void Op76(void)                                                  // ROR ZP, X
2210 {
2211         uint8_t m;
2212         READ_ZP_X_WB(m);
2213         OP_ROR_HANDLER(m);
2214         WRITE_BACK(m);
2215 }
2216
2217 static void Op6E(void)                                                  // ROR ABS
2218 {
2219         uint8_t m;
2220         READ_ABS_WB(m);
2221         OP_ROR_HANDLER(m);
2222         WRITE_BACK(m);
2223 }
2224
2225 static void Op7E(void)                                                  // ROR ABS, X
2226 {
2227         uint8_t m;
2228         READ_ABS_X_WB(m);
2229         OP_ROR_HANDLER(m);
2230         WRITE_BACK(m);
2231 }
2232
2233 /*
2234 RTI     Implied         RTI                     40      1       6
2235 */
2236
2237 static void Op40(void)                                                  // RTI
2238 {
2239         regs->cc = regs->RdMem(0x0100 + ++regs->sp);
2240         regs->pc = regs->RdMem(0x0100 + ++regs->sp);
2241         regs->pc |= (uint16_t)(regs->RdMem(0x0100 + ++regs->sp)) << 8;
2242 }
2243
2244 /*
2245 RTS     Implied         RTS                     60      1       6
2246 */
2247
2248 static void Op60(void)                                                  // RTS
2249 {
2250         regs->pc = regs->RdMem(0x0100 + ++regs->sp);
2251         regs->pc |= (uint16_t)(regs->RdMem(0x0100 + ++regs->sp)) << 8;
2252         regs->pc++;                                                                     // Since it pushes return address - 1...
2253 }
2254
2255 /*
2256 SBC     Immediate       SBC #Oper       E9      2       2
2257 Zero Page               SBC Zpg         E5      2       3
2258 Zero Page,X             SBC Zpg,X       F5      2       4
2259 Absolute                SBC Abs         ED      3       4
2260 Absolute,X              SBC Abs,X       FD      3       4
2261 Absolute,Y              SBC Abs,Y       F9      3       4
2262 (Zero Page,X)   SBC (Zpg,X)     E1      2       6
2263 (Zero Page),Y   SBC (Zpg),Y     F1      2       5
2264 (Zero Page)             SBC (Zpg)       F2      2       5
2265 */
2266
2267 // SBC opcodes
2268
2269 //This is non-optimal, but it works--optimize later. :-)
2270 //This is correct except for the BCD handling... !!! FIX !!! [Possibly DONE]
2271 #define OP_SBC_HANDLER(m) \
2272         uint16_t sum = (uint16_t)regs->a - (m) - (uint16_t)((regs->cc & FLAG_C) ^ 0x01); \
2273 \
2274         if (regs->cc & FLAG_D) \
2275         { \
2276                 if ((sum & 0x0F) > 0x09) \
2277                         sum -= 0x06; \
2278 \
2279                 if ((sum & 0xF0) > 0x90) \
2280                         sum -= 0x60; \
2281         } \
2282 \
2283         regs->cc = (regs->cc & ~FLAG_C) | (((sum >> 8) ^ 0x01) & FLAG_C); \
2284         regs->cc = ((regs->a ^ (m)) & (regs->a ^ sum) & 0x80 ? regs->cc | FLAG_V : regs->cc & ~FLAG_V); \
2285         regs->a = sum & 0xFF; \
2286         SET_ZN(regs->a)
2287
2288 static void OpE9(void)                                                  // SBC #
2289 {
2290         uint16_t m = READ_IMM;
2291         OP_SBC_HANDLER(m);
2292 }
2293
2294 static void OpE5(void)                                                  // SBC ZP
2295 {
2296         uint16_t m = READ_ZP;
2297         OP_SBC_HANDLER(m);
2298 }
2299
2300 static void OpF5(void)                                                  // SBC ZP, X
2301 {
2302         uint16_t m = READ_ZP_X;
2303         OP_SBC_HANDLER(m);
2304 }
2305
2306 static void OpED(void)                                                  // SBC ABS
2307 {
2308         uint16_t m = READ_ABS;
2309         OP_SBC_HANDLER(m);
2310 }
2311
2312 static void OpFD(void)                                                  // SBC ABS, X
2313 {
2314         uint16_t m = READ_ABS_X;
2315         OP_SBC_HANDLER(m);
2316 }
2317
2318 static void OpF9(void)                                                  // SBC ABS, Y
2319 {
2320         uint16_t m = READ_ABS_Y;
2321         OP_SBC_HANDLER(m);
2322 }
2323
2324 static void OpE1(void)                                                  // SBC (ZP, X)
2325 {
2326         uint16_t m = READ_IND_ZP_X;
2327         OP_SBC_HANDLER(m);
2328 }
2329
2330 static void OpF1(void)                                                  // SBC (ZP), Y
2331 {
2332         uint16_t m = READ_IND_ZP_Y;
2333         OP_SBC_HANDLER(m);
2334 }
2335
2336 static void OpF2(void)                                                  // SBC (ZP)
2337 {
2338         uint16_t m = READ_IND_ZP;
2339         OP_SBC_HANDLER(m);
2340 }
2341
2342 /*
2343 SEC     Implied         SEC                     38      1       2
2344 */
2345
2346 static void Op38(void)                                                  // SEC
2347 {
2348         regs->cc |= FLAG_C;
2349 }
2350
2351 /*
2352 SED     Implied         SED                     F8      1       2
2353 */
2354
2355 static void OpF8(void)                                                  // SED
2356 {
2357         regs->cc |= FLAG_D;
2358 }
2359
2360 /*
2361 SEI     Implied         SEI                     78      1       2
2362 */
2363
2364 static void Op78(void)                                                  // SEI
2365 {
2366         SET_I;
2367 }
2368
2369 /*
2370 The bit set and clear instructions have the form xyyy0111, where x is 0 to clear a bit or 1 to set it, and yyy is which bit at the memory location to set or clear.
2371    RMB0  RMB1  RMB2  RMB3  RMB4  RMB5  RMB6  RMB7
2372   zp  07  17  27  37  47  57  67  77
2373      SMB0  SMB1  SMB2  SMB3  SMB4  SMB5  SMB6  SMB7
2374   zp  87  97  A7  B7  C7  D7  E7  F7
2375 */
2376
2377 // SMB opcodes
2378
2379 static void Op87(void)                                                  // SMB0 ZP
2380 {
2381         uint8_t m;
2382         READ_ZP_WB(m);
2383         m |= 0x01;
2384         WRITE_BACK(m);
2385 }
2386
2387 static void Op97(void)                                                  // SMB1 ZP
2388 {
2389         uint8_t m;
2390         READ_ZP_WB(m);
2391         m |= 0x02;
2392         WRITE_BACK(m);
2393 }
2394
2395 static void OpA7(void)                                                  // SMB2 ZP
2396 {
2397         uint8_t m;
2398         READ_ZP_WB(m);
2399         m |= 0x04;
2400         WRITE_BACK(m);
2401 }
2402
2403 static void OpB7(void)                                                  // SMB3 ZP
2404 {
2405         uint8_t m;
2406         READ_ZP_WB(m);
2407         m |= 0x08;
2408         WRITE_BACK(m);
2409 }
2410
2411 static void OpC7(void)                                                  // SMB4 ZP
2412 {
2413         uint8_t m;
2414         READ_ZP_WB(m);
2415         m |= 0x10;
2416         WRITE_BACK(m);
2417 }
2418
2419 static void OpD7(void)                                                  // SMB5 ZP
2420 {
2421         uint8_t m;
2422         READ_ZP_WB(m);
2423         m |= 0x20;
2424         WRITE_BACK(m);
2425 }
2426
2427 static void OpE7(void)                                                  // SMB6 ZP
2428 {
2429         uint8_t m;
2430         READ_ZP_WB(m);
2431         m |= 0x40;
2432         WRITE_BACK(m);
2433 }
2434
2435 static void OpF7(void)                                                  // SMB7 ZP
2436 {
2437         uint8_t m;
2438         READ_ZP_WB(m);
2439         m |= 0x80;
2440         WRITE_BACK(m);
2441 }
2442
2443 /*
2444 STA     Zero Page       STA Zpg         85      2       3
2445 Zero Page,X             STA Zpg,X       95      2       4
2446 Absolute                STA Abs         8D      3       4
2447 Absolute,X              STA Abs,X       9D      3       5
2448 Absolute,Y              STA Abs,Y       99      3       5
2449 (Zero Page,X)   STA (Zpg,X)     81      2       6
2450 (Zero Page),Y   STA (Zpg),Y     91      2       6
2451 (Zero Page)             STA (Zpg)       92      2       5
2452 */
2453
2454 // STA opcodes
2455
2456 static void Op85(void)
2457 {
2458         regs->WrMem(EA_ZP, regs->a);
2459 }
2460
2461 static void Op95(void)
2462 {
2463         regs->WrMem(EA_ZP_X, regs->a);
2464 }
2465
2466 static void Op8D(void)
2467 {
2468         regs->WrMem(EA_ABS, regs->a);
2469 }
2470
2471 static void Op9D(void)
2472 {
2473         regs->WrMem(EA_ABS_X, regs->a);
2474 }
2475
2476 static void Op99(void)
2477 {
2478         regs->WrMem(EA_ABS_Y, regs->a);
2479 }
2480
2481 static void Op81(void)
2482 {
2483         regs->WrMem(EA_IND_ZP_X, regs->a);
2484 }
2485
2486 static void Op91(void)
2487 {
2488         regs->WrMem(EA_IND_ZP_Y, regs->a);
2489 }
2490
2491 static void Op92(void)
2492 {
2493         regs->WrMem(EA_IND_ZP, regs->a);
2494 }
2495
2496 /*
2497 STX     Zero Page       STX Zpg         86      2       3
2498 Zero Page,Y             STX Zpg,Y       96      2       4
2499 Absolute                STX Abs         8E      3       4
2500 */
2501
2502 // STX opcodes
2503
2504 static void Op86(void)
2505 {
2506         regs->WrMem(EA_ZP, regs->x);
2507 }
2508
2509 static void Op96(void)
2510 {
2511         regs->WrMem(EA_ZP_Y, regs->x);
2512 }
2513
2514 static void Op8E(void)
2515 {
2516         regs->WrMem(EA_ABS, regs->x);
2517 }
2518
2519 /*
2520 STY     Zero Page       STY Zpg         84      2       3
2521 Zero Page,X             STY Zpg,X       94      2       4
2522 Absolute                STY Abs         8C      3       4
2523 */
2524
2525 // STY opcodes
2526
2527 static void Op84(void)
2528 {
2529         regs->WrMem(EA_ZP, regs->y);
2530 }
2531
2532 static void Op94(void)
2533 {
2534         regs->WrMem(EA_ZP_X, regs->y);
2535 }
2536
2537 static void Op8C(void)
2538 {
2539         regs->WrMem(EA_ABS, regs->y);
2540 }
2541
2542 /*
2543 STZ     Zero Page       STZ Zpg         64      2       3
2544 Zero Page,X             STZ Zpg,X       74      2       4
2545 Absolute                STZ Abs         9C      3       4
2546 Absolute,X              STZ Abs,X       9E      3       5
2547 */
2548
2549 // STZ opcodes
2550
2551 static void Op64(void)
2552 {
2553         regs->WrMem(EA_ZP, 0x00);
2554 }
2555
2556 static void Op74(void)
2557 {
2558         regs->WrMem(EA_ZP_X, 0x00);
2559 }
2560
2561 static void Op9C(void)
2562 {
2563         regs->WrMem(EA_ABS, 0x00);
2564 }
2565
2566 static void Op9E(void)
2567 {
2568         regs->WrMem(EA_ABS_X, 0x00);
2569 }
2570
2571 /*
2572 TAX     Implied         TAX                     AA      1       2
2573 */
2574
2575 static void OpAA(void)                                                  // TAX
2576 {
2577         regs->x = regs->a;
2578         SET_ZN(regs->x);
2579 }
2580
2581 /*
2582 TAY     Implied         TAY                     A8      1       2
2583 */
2584
2585 static void OpA8(void)                                                  // TAY
2586 {
2587         regs->y = regs->a;
2588         SET_ZN(regs->y);
2589 }
2590
2591 /*
2592 TRB     Zero Page       TRB Zpg         14      2       5
2593 Absolute                TRB Abs         1C      3       6
2594 */
2595
2596 // TRB opcodes
2597
2598 #define OP_TRB_HANDLER(m) \
2599         SET_Z(m & regs->a); \
2600         m &= ~regs->a
2601
2602 static void Op14(void)                                                  // TRB ZP
2603 {
2604         uint8_t m;
2605         READ_ZP_WB(m);
2606         OP_TRB_HANDLER(m);
2607         WRITE_BACK(m);
2608 }
2609
2610 static void Op1C(void)                                                  // TRB ABS
2611 {
2612         uint8_t m;
2613         READ_ABS_WB(m);
2614         OP_TRB_HANDLER(m);
2615         WRITE_BACK(m);
2616 }
2617
2618 /*
2619 TSB     Zero Page       TSB Zpg         04      2       5
2620 Absolute                TSB Abs         0C      3       6
2621 */
2622
2623 // TSB opcodes
2624
2625 #define OP_TSB_HANDLER(m) \
2626         SET_Z(m & regs->a); \
2627         m |= regs->a
2628
2629 static void Op04(void)                                                  // TSB ZP
2630 {
2631         uint8_t m;
2632         READ_ZP_WB(m);
2633         OP_TSB_HANDLER(m);
2634         WRITE_BACK(m);
2635 }
2636
2637 static void Op0C(void)                                                  // TSB ABS
2638 {
2639         uint8_t m;
2640         READ_ABS_WB(m);
2641         OP_TSB_HANDLER(m);
2642         WRITE_BACK(m);
2643 }
2644
2645 /*
2646 TSX     Implied         TSX                     BA      1       2
2647 */
2648
2649 static void OpBA(void)                                                  // TSX
2650 {
2651         regs->x = regs->sp;
2652         SET_ZN(regs->x);
2653 }
2654
2655 /*
2656 TXA     Implied         TXA                     8A      1       2
2657 */
2658
2659 static void Op8A(void)                                                  // TXA
2660 {
2661         regs->a = regs->x;
2662         SET_ZN(regs->a);
2663 }
2664
2665 /*
2666 TXS     Implied         TXS                     9A      1       2
2667 */
2668
2669 static void Op9A(void)                                                  // TXS
2670 {
2671         regs->sp = regs->x;
2672 }
2673
2674 /*
2675 TYA     Implied         TYA                     98      1       2
2676 */
2677 static void Op98(void)                                                  // TYA
2678 {
2679         regs->a = regs->y;
2680         SET_ZN(regs->a);
2681 }
2682
2683 static void Op__(void)
2684 {
2685         regs->cpuFlags |= V65C02_STATE_ILLEGAL_INST;
2686 }
2687
2688
2689 //
2690 // Ok, the exec_op[] array is globally defined here basically to save
2691 // a LOT of unnecessary typing.  Sure it's ugly, but hey, it works!
2692 //
2693 static void (* exec_op[256])() = {
2694         Op00, Op01, Op__, Op__, Op04, Op05, Op06, Op07, Op08, Op09, Op0A, Op__, Op0C, Op0D, Op0E, Op0F,
2695         Op10, Op11, Op12, Op__, Op14, Op15, Op16, Op17, Op18, Op19, Op1A, Op__, Op1C, Op1D, Op1E, Op1F,
2696         Op20, Op21, Op__, Op__, Op24, Op25, Op26, Op27, Op28, Op29, Op2A, Op__, Op2C, Op2D, Op2E, Op2F,
2697         Op30, Op31, Op32, Op__, Op34, Op35, Op36, Op37, Op38, Op39, Op3A, Op__, Op3C, Op3D, Op3E, Op3F,
2698         Op40, Op41, Op__, Op__, Op__, Op45, Op46, Op47, Op48, Op49, Op4A, Op__, Op4C, Op4D, Op4E, Op4F,
2699         Op50, Op51, Op52, Op__, Op__, Op55, Op56, Op57, Op58, Op59, Op5A, Op__, Op__, Op5D, Op5E, Op5F,
2700         Op60, Op61, Op__, Op__, Op64, Op65, Op66, Op67, Op68, Op69, Op6A, Op__, Op6C, Op6D, Op6E, Op6F,
2701         Op70, Op71, Op72, Op__, Op74, Op75, Op76, Op77, Op78, Op79, Op7A, Op__, Op7C, Op7D, Op7E, Op7F,
2702         Op80, Op81, Op__, Op__, Op84, Op85, Op86, Op87, Op88, Op89, Op8A, Op__, Op8C, Op8D, Op8E, Op8F,
2703         Op90, Op91, Op92, Op__, Op94, Op95, Op96, Op97, Op98, Op99, Op9A, Op__, Op9C, Op9D, Op9E, Op9F,
2704         OpA0, OpA1, OpA2, Op__, OpA4, OpA5, OpA6, OpA7, OpA8, OpA9, OpAA, Op__, OpAC, OpAD, OpAE, OpAF,
2705         OpB0, OpB1, OpB2, Op__, OpB4, OpB5, OpB6, OpB7, OpB8, OpB9, OpBA, Op__, OpBC, OpBD, OpBE, OpBF,
2706         OpC0, OpC1, Op__, Op__, OpC4, OpC5, OpC6, OpC7, OpC8, OpC9, OpCA, Op__, OpCC, OpCD, OpCE, OpCF,
2707         OpD0, OpD1, OpD2, Op__, Op__, OpD5, OpD6, OpD7, OpD8, OpD9, OpDA, Op__, Op__, OpDD, OpDE, OpDF,
2708         OpE0, OpE1, Op__, Op__, OpE4, OpE5, OpE6, OpE7, OpE8, OpE9, OpEA, Op__, OpEC, OpED, OpEE, OpEF,
2709         OpF0, OpF1, OpF2, Op__, Op__, OpF5, OpF6, OpF7, OpF8, OpF9, OpFA, Op__, Op__, OpFD, OpFE, OpFF
2710 };
2711
2712
2713 /*
2714 FCA8: 38        698  WAIT     SEC
2715 FCA9: 48        699  WAIT2    PHA
2716 FCAA: E9 01     700  WAIT3    SBC   #$01
2717 FCAC: D0 FC     701           BNE   WAIT3      ;1.0204 USEC
2718 FCAE: 68        702           PLA              ;(13+27/2*A+5/2*A*A)
2719 FCAF: E9 01     703           SBC   #$01
2720 FCB1: D0 F6     704           BNE   WAIT2
2721 FCB3: 60        705           RTS
2722
2723 FBD9: C9 87     592  BELL1    CMP   #$87       ;BELL CHAR? (CNTRL-G)
2724 FBDB: D0 12     593           BNE   RTS2B      ;  NO, RETURN
2725 FBDD: A9 40     594           LDA   #$40       ;DELAY .01 SECONDS
2726 FBDF: 20 A8 FC  595           JSR   WAIT
2727 FBE2: A0 C0     596           LDY   #$C0
2728 FBE4: A9 0C     597  BELL2    LDA   #$0C       ;TOGGLE SPEAKER AT
2729 FBE6: 20 A8 FC  598           JSR   WAIT       ;  1 KHZ FOR .1 SEC.
2730 FBE9: AD 30 C0  599           LDA   SPKR
2731 FBEC: 88        600           DEY
2732 FBED: D0 F5     601           BNE   BELL2
2733 FBEF: 60        602  RTS2B    RTS
2734 */
2735 //int instCount[256];
2736 #ifdef __DEBUG__
2737 bool dumpDis = false;
2738 //bool dumpDis = true;
2739 #endif
2740
2741 /*
2742 On //e, $FCAA is the delay routine. (seems to not have changed from ][+)
2743 */
2744
2745 #define DO_BACKTRACE
2746 #ifdef DO_BACKTRACE
2747 #define BACKTRACE_SIZE 16384
2748 uint32_t btQueuePtr = 0;
2749 V65C02REGS btQueue[BACKTRACE_SIZE];
2750 uint8_t btQueueInst[BACKTRACE_SIZE][4];
2751 #endif
2752
2753
2754 //
2755 // Function to execute 65C02 for "cycles" cycles
2756 //
2757 void Execute65C02(V65C02REGS * context, uint32_t cycles)
2758 {
2759         regs = context;
2760
2761         // Calculate number of clock cycles to run for
2762         uint64_t endCycles = regs->clock + (uint64_t)cycles - regs->overflow;
2763
2764         while (regs->clock < endCycles)
2765         {
2766 #if 0
2767 static bool weGo = false;
2768 if (regs->pc == 0x80AE)
2769 {
2770         dumpDis = true;
2771         weGo = true;
2772 }
2773 else if (regs->pc == 0xFCA8 && weGo)
2774 {
2775         dumpDis = false;
2776         WriteLog("\n*** DELAY (A=$%02X)\n\n", regs->a);
2777 }
2778 else if (regs->pc == 0xFCB3 && weGo)
2779 {
2780         dumpDis = true;
2781 }
2782 #endif
2783 #if 0
2784 /*if (regs->pc == 0x4007)
2785 {
2786         dumpDis = true;
2787 }//*/
2788 if (regs->pc == 0x444B)
2789 {
2790         WriteLog("\n*** End of wait...\n\n");
2791         dumpDis = true;
2792 }//*/
2793 if (regs->pc == 0x444E)
2794 {
2795         WriteLog("\n*** Start of wait...\n\n");
2796         dumpDis = false;
2797 }//*/
2798 #endif
2799 /*if (regs->pc >= 0xC600 && regs->pc <=0xC6FF)
2800 {
2801         dumpDis = true;
2802 }
2803 else
2804         dumpDis = false;//*/
2805 /*if (regs->pc == 0xE039)
2806 {
2807         dumpDis = true;
2808 }//*/
2809
2810 #if 0
2811 /*if (regs->pc == 0x0801)
2812 {
2813         WriteLog("\n*** DISK BOOT subroutine...\n\n");
2814         dumpDis = true;
2815 }//*/
2816 if (regs->pc == 0xE000)
2817 {
2818 #if 0
2819         WriteLog("\n*** Dump of $E000 routine ***\n\n");
2820
2821         for(uint32_t addr=0xE000; addr<0xF000;)
2822         {
2823                 addr += Decode65C02(addr);
2824                 WriteLog("\n");
2825         }
2826 #endif
2827         WriteLog("\n*** DISK part II subroutine...\n\n");
2828         dumpDis = true;
2829 }//*/
2830 if (regs->pc == 0xD000)
2831 {
2832         WriteLog("\n*** CUSTOM DISK READ subroutine...\n\n");
2833         dumpDis = false;
2834 }//*/
2835 if (regs->pc == 0xD1BE)
2836 {
2837 //      WriteLog("\n*** DISK part II subroutine...\n\n");
2838         dumpDis = true;
2839 }//*/
2840 if (regs->pc == 0xD200)
2841 {
2842         WriteLog("\n*** CUSTOM SCREEN subroutine...\n\n");
2843         dumpDis = false;
2844 }//*/
2845 if (regs->pc == 0xD269)
2846 {
2847 //      WriteLog("\n*** DISK part II subroutine...\n\n");
2848         dumpDis = true;
2849 }//*/
2850 #endif
2851 //if (regs->pc == 0xE08E)
2852 /*if (regs->pc == 0xAD33)
2853 {
2854         WriteLog("\n*** After loader ***\n\n");
2855         dumpDis = true;
2856 }//*/
2857 /*if (regs->pc == 0x0418)
2858 {
2859         WriteLog("\n*** CUSTOM DISK READ subroutine...\n\n");
2860         dumpDis = false;
2861 }
2862 if (regs->pc == 0x0)
2863 {
2864         dumpDis = true;
2865 }//*/
2866 #ifdef __DEBUGMON__
2867 //WAIT is commented out here because it's called by BELL1...
2868 if (regs->pc == 0xFCA8)
2869 {
2870         WriteLog("\n*** WAIT subroutine...\n\n");
2871         dumpDis = false;
2872 }//*/
2873 if (regs->pc == 0xFBD9)
2874 {
2875         WriteLog("\n*** BELL1 subroutine...\n\n");
2876 //      dumpDis = false;
2877 }//*/
2878 if (regs->pc == 0xFC58)
2879 {
2880         WriteLog("\n*** HOME subroutine...\n\n");
2881 //      dumpDis = false;
2882 }//*/
2883 if (regs->pc == 0xFDED)
2884 {
2885         WriteLog("\n*** COUT subroutine...\n\n");
2886         dumpDis = false;
2887 }
2888 #endif
2889 #if 0
2890 // ProDOS debugging
2891 if (regs->pc == 0x2000)
2892         dumpDis = true;
2893 #endif
2894
2895 #ifdef __DEBUG__
2896 static char disbuf[80];
2897 if (dumpDis)
2898 {
2899         Decode65C02(regs, disbuf, regs->pc);
2900         WriteLog("%s", disbuf);
2901 }
2902 #endif
2903                 uint8_t opcode = regs->RdMem(regs->pc++);
2904
2905 //if (!(regs->cpuFlags & V65C02_STATE_ILLEGAL_INST))
2906 //instCount[opcode]++;
2907
2908                 // We need this because the opcode function could add 1 or 2 cycles
2909                 // which aren't accounted for in CPUCycles[].
2910                 uint64_t clockSave = regs->clock;
2911
2912                 // Execute that opcode...
2913                 exec_op[opcode]();
2914                 regs->clock += CPUCycles[opcode];
2915
2916                 // Tell the timer function (if any) how many PHI2s have elapsed...
2917                 if (regs->Timer)
2918                         regs->Timer(regs->clock - clockSave);
2919
2920 #ifdef __DEBUG__
2921 if (dumpDis)
2922         WriteLog(" [SP=01%02X, CC=%s%s.%s%s%s%s%s, A=%02X, X=%02X, Y=%02X]\n",
2923                 regs->sp,
2924                 (regs->cc & FLAG_N ? "N" : "-"), (regs->cc & FLAG_V ? "V" : "-"),
2925                 (regs->cc & FLAG_B ? "B" : "-"), (regs->cc & FLAG_D ? "D" : "-"),
2926                 (regs->cc & FLAG_I ? "I" : "-"), (regs->cc & FLAG_Z ? "Z" : "-"),
2927                 (regs->cc & FLAG_C ? "C" : "-"), regs->a, regs->x, regs->y);
2928 #endif
2929
2930 #ifdef __DEBUGMON__
2931 if (regs->pc == 0xFCB3) // WAIT exit point
2932 {
2933         dumpDis = true;
2934 }//*/
2935 /*if (regs->pc == 0xFBEF)       // BELL1 exit point
2936 {
2937         dumpDis = true;
2938 }//*/
2939 /*if (regs->pc == 0xFC22)       // HOME exit point
2940 {
2941         dumpDis = true;
2942 }//*/
2943 if (regs->pc == 0xFDFF) // COUT exit point
2944 {
2945         dumpDis = true;
2946 }
2947 if (regs->pc == 0xFBD8)
2948 {
2949         WriteLog("\n*** BASCALC set BASL/H = $%04X\n\n", RdMemW(0x0028));
2950 }//*/
2951 #endif
2952
2953 //These should be correct now...
2954                 if (regs->cpuFlags & V65C02_ASSERT_LINE_RESET)
2955                 {
2956                         // Not sure about this...
2957                         regs->sp = 0xFF;
2958                         regs->cc = FLAG_I;                              // Reset the CC register
2959                         regs->pc = RdMemW(0xFFFC);              // And load PC with RESET vector
2960
2961                         regs->cpuFlags = 0;                             // Clear CPU flags...
2962 #ifdef __DEBUG__
2963 WriteLog("\n*** RESET *** (PC = $%04X)\n\n", regs->pc);
2964 #endif
2965                 }
2966                 else if (regs->cpuFlags & V65C02_ASSERT_LINE_NMI)
2967                 {
2968 #ifdef __DEBUG__
2969 WriteLog("\n*** NMI ***\n\n");
2970 #endif
2971                         regs->WrMem(0x0100 + regs->sp--, regs->pc >> 8);        // Save PC & CC
2972                         regs->WrMem(0x0100 + regs->sp--, regs->pc & 0xFF);
2973                         regs->WrMem(0x0100 + regs->sp--, regs->cc);
2974                         SET_I;
2975                         CLR_D;
2976                         regs->pc = RdMemW(0xFFFA);              // Jump to NMI vector
2977
2978                         regs->clock += 7;
2979                         regs->cpuFlags &= ~V65C02_ASSERT_LINE_NMI;      // Reset NMI line
2980                 }
2981                 else if ((regs->cpuFlags & V65C02_ASSERT_LINE_IRQ)
2982                         // IRQs are maskable, so check if the I flag is clear
2983                         && (!(regs->cc & FLAG_I)))
2984                 {
2985 #ifdef __DEBUG__
2986 WriteLog("\n*** IRQ ***\n\n");
2987 WriteLog("Clock=$%X\n", regs->clock);
2988 //dumpDis = true;
2989 #endif
2990                         regs->WrMem(0x0100 + regs->sp--, regs->pc >> 8);        // Save PC & CC
2991                         regs->WrMem(0x0100 + regs->sp--, regs->pc & 0xFF);
2992                         regs->WrMem(0x0100 + regs->sp--, regs->cc);
2993                         SET_I;
2994                         CLR_D;
2995                         regs->pc = RdMemW(0xFFFE);              // Jump to IRQ vector
2996
2997                         regs->clock += 7;
2998                         regs->cpuFlags &= ~V65C02_ASSERT_LINE_IRQ;      // Reset IRQ line
2999                 }
3000         }
3001
3002         // If we went longer than the passed in cycles, make a note of it so we can
3003         // subtract it out from a subsequent run.  It's guaranteed to be non-
3004         // negative, because the condition that exits the main loop above is
3005         // written such that regs->clock has to be equal or larger than endCycles
3006         // to exit from it.
3007         regs->overflow = regs->clock - endCycles;
3008 }
3009