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