]> Shamusworld >> Repos - apple2/blob - src/v65c02.cpp
Fixes to make emulator //e compatible; display can do double hires now.
[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 //              regs.pc += m;
1146 }
1147
1148 static void OpB0(void)                                                  // BCS
1149 {
1150         int16_t m = (int16_t)(int8_t)READ_IMM;
1151
1152         if (regs.cc & FLAG_C)
1153                 HANDLE_BRANCH_TAKEN(m)
1154 //              regs.pc += m;
1155 }
1156
1157 static void OpF0(void)                                                  // BEQ
1158 {
1159         int16_t m = (int16_t)(int8_t)READ_IMM;
1160
1161         if (regs.cc & FLAG_Z)
1162                 HANDLE_BRANCH_TAKEN(m)
1163 //              regs.pc += m;
1164 }
1165
1166 /*
1167 BIT     Immediate       BIT #Oper       89      2       2
1168 Zero Page               BIT Zpg         24      2       3
1169 Zero Page,X             BIT Zpg,X       34      2       4
1170 Absolute                BIT Abs         2C      3       4
1171 Absolute,X              BIT Abs,X       3C      3       4
1172 */
1173
1174 // BIT opcodes
1175
1176 /* 1. The BIT instruction copies bit 6 to the V flag, and bit 7 to the N flag (except in immediate
1177       addressing mode where V & N are untouched.) The accumulator and the operand are ANDed and the
1178       Z flag is set appropriately. */
1179
1180 #define OP_BIT_HANDLER(m) \
1181         int8_t result = regs.a & (m); \
1182         regs.cc &= ~(FLAG_N | FLAG_V); \
1183         regs.cc |= ((m) & 0xC0); \
1184         SET_Z(result)
1185
1186 static void Op89(void)                                                  // BIT #
1187 {
1188         int8_t m = READ_IMM;
1189         int8_t result = regs.a & m;
1190         SET_Z(result);
1191 }
1192
1193 static void Op24(void)                                                  // BIT ZP
1194 {
1195         int8_t m = READ_ZP;
1196         OP_BIT_HANDLER(m);
1197 }
1198
1199 static void Op34(void)                                                  // BIT ZP, X
1200 {
1201         uint8_t m = READ_ZP_X;
1202         OP_BIT_HANDLER(m);
1203 }
1204
1205 static void Op2C(void)                                                  // BIT ABS
1206 {
1207         uint8_t m = READ_ABS;
1208         OP_BIT_HANDLER(m);
1209 }
1210
1211 static void Op3C(void)                                                  // BIT ABS, X
1212 {
1213         uint8_t m = READ_ABS_X;
1214         OP_BIT_HANDLER(m);
1215 }
1216
1217 /*
1218 BMI     Relative        BMI Oper        30      2       2
1219 BNE     Relative        BNE Oper        D0      2       2
1220 BPL     Relative        BPL Oper        10      2       2
1221 BRA     Relative        BRA Oper        80      2       3
1222 */
1223
1224 // More branch opcodes
1225
1226 static void Op30(void)                                                  // BMI
1227 {
1228         int16_t m = (int16_t)(int8_t)READ_IMM;
1229
1230         if (regs.cc & FLAG_N)
1231                 HANDLE_BRANCH_TAKEN(m)
1232 //              regs.pc += m;
1233 }
1234
1235 static void OpD0(void)                                                  // BNE
1236 {
1237         int16_t m = (int16_t)(int8_t)READ_IMM;
1238
1239         if (!(regs.cc & FLAG_Z))
1240                 HANDLE_BRANCH_TAKEN(m)
1241 //              regs.pc += m;
1242 }
1243
1244 static void Op10(void)                                                  // BPL
1245 {
1246         int16_t m = (int16_t)(int8_t)READ_IMM;
1247
1248         if (!(regs.cc & FLAG_N))
1249                 HANDLE_BRANCH_TAKEN(m)
1250 //              regs.pc += m;
1251 }
1252
1253 static void Op80(void)                                                  // BRA
1254 {
1255         int16_t m = (int16_t)(int8_t)READ_IMM;
1256         HANDLE_BRANCH_TAKEN(m)
1257 //      regs.pc += m;
1258 }
1259
1260 /*
1261 BRK     Implied         BRK                     00      1       7
1262 */
1263
1264 static void Op00(void)                                                  // BRK
1265 {
1266         regs.cc |= FLAG_B;                                                      // Set B
1267         regs.pc++;                                                                      // RTI comes back to the instruction one byte after the BRK
1268         regs.WrMem(0x0100 + regs.sp--, regs.pc >> 8);   // Save PC and CC
1269         regs.WrMem(0x0100 + regs.sp--, regs.pc & 0xFF);
1270         regs.WrMem(0x0100 + regs.sp--, regs.cc);
1271         regs.cc |= FLAG_I;                                                      // Set I
1272         regs.cc &= ~FLAG_D;                                                     // & clear D
1273         regs.pc = RdMemW(0xFFFE);                                       // Grab the IRQ vector & go...
1274 }
1275
1276 /*
1277 BVC     Relative        BVC Oper        50      2       2
1278 BVS     Relative        BVS Oper        70      2       2
1279 */
1280
1281 // Even more branch opcodes
1282
1283 static void Op50(void)                                                  // BVC
1284 {
1285         int16_t m = (int16_t)(int8_t)READ_IMM;
1286
1287         if (!(regs.cc & FLAG_V))
1288                 HANDLE_BRANCH_TAKEN(m)
1289 //              regs.pc += m;
1290 }
1291
1292 static void Op70(void)                                                  // BVS
1293 {
1294         int16_t m = (int16_t)(int8_t)READ_IMM;
1295
1296         if (regs.cc & FLAG_V)
1297                 HANDLE_BRANCH_TAKEN(m)
1298 //              regs.pc += m;
1299 }
1300
1301 /*
1302 CLC     Implied         CLC                     18      1       2
1303 */
1304
1305 static void Op18(void)                                                  // CLC
1306 {
1307         regs.cc &= ~FLAG_C;
1308 }
1309
1310 /*
1311 CLD     Implied         CLD                     D8      1       2
1312 */
1313
1314 static void OpD8(void)                                                  // CLD
1315 {
1316         regs.cc &= ~FLAG_D;
1317 }
1318
1319 /*
1320 CLI     Implied         CLI                     58      1       2
1321 */
1322
1323 static void Op58(void)                                                  // CLI
1324 {
1325         regs.cc &= ~FLAG_I;
1326 }
1327
1328 /*
1329 CLV     Implied         CLV                     B8      1       2
1330 */
1331
1332 static void OpB8(void)                                                  // CLV
1333 {
1334         regs.cc &= ~FLAG_V;
1335 }
1336
1337 /*
1338 CMP     Immediate       CMP #Oper       C9      2       2
1339 Zero Page               CMP Zpg         C5      2       3
1340 Zero Page,X             CMP Zpg         D5      2       4
1341 Absolute                CMP Abs         CD      3       4
1342 Absolute,X              CMP Abs,X       DD      3       4
1343 Absolute,Y              CMP Abs,Y       D9      3       4
1344 (Zero Page,X)   CMP (Zpg,X)     C1      2       6
1345 (Zero Page),Y   CMP (Zpg),Y     D1      2       5
1346 (Zero Page)             CMP (Zpg)       D2      2       5
1347 */
1348
1349 // CMP opcodes
1350
1351 /*
1352 Here's the latest: The CMP is NOT generating the Z flag when A=$C0!
1353
1354 FABA: A0 07          LDY   #$07                 [PC=FABC, SP=01FF, CC=---B-IZ-, A=00, X=00, Y=07]
1355 FABC: C6 01          DEC   $01          [PC=FABE, SP=01FF, CC=N--B-I--, A=00, X=00, Y=07]
1356 FABE: A5 01          LDA   $01          [PC=FAC0, SP=01FF, CC=N--B-I--, A=C0, X=00, Y=07]
1357 FAC0: C9 C0          CMP   #$C0                 [PC=FAC2, SP=01FF, CC=N--B-I--, A=C0, X=00, Y=07]
1358 FAC2: F0 D7          BEQ   $FA9B                [PC=FAC4, SP=01FF, CC=N--B-I--, A=C0, X=00, Y=07]
1359 FAC4: 8D F8 07       STA   $07F8                [PC=FAC7, SP=01FF, CC=N--B-I--, A=C0, X=00, Y=07]
1360 FAC7: B1 00          LDA   ($00),Y
1361 *** Read at I/O address C007
1362                 [PC=FAC9, SP=01FF, CC=---B-IZ-, A=00, X=00, Y=07]
1363 FAC9: D9 01 FB       CMP   $FB01,Y              [PC=FACC, SP=01FF, CC=---B-I--, A=00, X=00, Y=07]
1364 FACC: D0 EC          BNE   $FABA                [PC=FABA, SP=01FF, CC=---B-I--, A=00, X=00, Y=07]
1365
1366 Should be fixed now... (was adding instead of subtracting!)
1367
1368 Small problem here... First two should set the carry while the last one should clear it. !!! FIX !!! [DONE]
1369
1370 FDF0: C9 A0          CMP   #$A0                 [PC=FDF2, SP=01F1, CC=---B-IZ-, A=A0, X=02, Y=03]
1371 FD7E: C9 E0          CMP   #$E0                 [PC=FD80, SP=01F4, CC=N--B-I--, A=A0, X=02, Y=03]
1372 FD38: C9 9B          CMP   #$9B                 [PC=FD3A, SP=01F2, CC=---B-I-C, A=A0, X=02, Y=03]
1373
1374 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.
1375 */
1376
1377 #define OP_CMP_HANDLER(m) \
1378         uint8_t result = regs.a - (m); \
1379         SET_ZNC_CMP(m, regs.a, result)
1380
1381 static void OpC9(void)                                                  // CMP #
1382 {
1383         uint8_t m = READ_IMM;
1384         OP_CMP_HANDLER(m);
1385 }
1386
1387 static void OpC5(void)                                                  // CMP ZP
1388 {
1389         uint8_t m = READ_ZP;
1390         OP_CMP_HANDLER(m);
1391 }
1392
1393 static void OpD5(void)                                                  // CMP ZP, X
1394 {
1395         uint8_t m = READ_ZP_X;
1396         OP_CMP_HANDLER(m);
1397 }
1398
1399 static void OpCD(void)                                                  // CMP ABS
1400 {
1401         uint8_t m = READ_ABS;
1402         OP_CMP_HANDLER(m);
1403 }
1404
1405 static void OpDD(void)                                                  // CMP ABS, X
1406 {
1407         uint8_t m = READ_ABS_X;
1408         OP_CMP_HANDLER(m);
1409 }
1410
1411 static void OpD9(void)                                                  // CMP ABS, Y
1412 {
1413         uint8_t m = READ_ABS_Y;
1414         OP_CMP_HANDLER(m);
1415 }
1416
1417 static void OpC1(void)                                                  // CMP (ZP, X)
1418 {
1419         uint8_t m = READ_IND_ZP_X;
1420         OP_CMP_HANDLER(m);
1421 }
1422
1423 static void OpD1(void)                                                  // CMP (ZP), Y
1424 {
1425         uint8_t m = READ_IND_ZP_Y;
1426         OP_CMP_HANDLER(m);
1427 }
1428
1429 static void OpD2(void)                                                  // CMP (ZP)
1430 {
1431         uint8_t m = READ_IND_ZP;
1432         OP_CMP_HANDLER(m);
1433 }
1434
1435 /*
1436 CPX     Immediate       CPX #Oper       E0      2       2
1437 Zero Page               CPX Zpg         E4      2       3
1438 Absolute                CPX Abs         EC      3       4
1439 */
1440
1441 // CPX opcodes
1442
1443 #define OP_CPX_HANDLER(m) \
1444         uint8_t result = regs.x - (m); \
1445         SET_ZNC_CMP(m, regs.x, result)
1446
1447 static void OpE0(void)                                                  // CPX #
1448 {
1449         uint8_t m = READ_IMM;
1450         OP_CPX_HANDLER(m);
1451 }
1452
1453 static void OpE4(void)                                                  // CPX ZP
1454 {
1455         uint8_t m = READ_ZP;
1456         OP_CPX_HANDLER(m);
1457 }
1458
1459 static void OpEC(void)                                                  // CPX ABS
1460 {
1461         uint8_t m = READ_ABS;
1462         OP_CPX_HANDLER(m);
1463 }
1464
1465 /*
1466 CPY     Immediate       CPY #Oper       C0      2       2
1467 Zero Page               CPY Zpg         C4      2       3
1468 Absolute                CPY Abs         CC      3       4
1469 */
1470
1471 // CPY opcodes
1472
1473 #define OP_CPY_HANDLER(m) \
1474         uint8_t result = regs.y - (m); \
1475         SET_ZNC_CMP(m, regs.y, result)
1476
1477 static void OpC0(void)                                                  // CPY #
1478 {
1479         uint8_t m = READ_IMM;
1480         OP_CPY_HANDLER(m);
1481 }
1482
1483 static void OpC4(void)                                                  // CPY ZP
1484 {
1485         uint8_t m = READ_ZP;
1486         OP_CPY_HANDLER(m);
1487 }
1488
1489 static void OpCC(void)                                                  // CPY ABS
1490 {
1491         uint8_t m = READ_ABS;
1492         OP_CPY_HANDLER(m);
1493 }
1494
1495 /*
1496 DEA     Accumulator     DEA                     3A      1       2
1497 */
1498
1499 static void Op3A(void)                                                  // DEA
1500 {
1501         regs.a--;
1502         SET_ZN(regs.a);
1503 }
1504
1505 /*
1506 DEC     Zero Page       DEC Zpg         C6      2       5
1507 Zero Page,X             DEC Zpg,X       D6      2       6
1508 Absolute                DEC Abs         CE      3       6
1509 Absolute,X              DEC Abs,X       DE      3       7
1510 */
1511
1512 // DEC opcodes
1513
1514 #define OP_DEC_HANDLER(m) \
1515         m--; \
1516         SET_ZN(m)
1517
1518 static void OpC6(void)                                                  // DEC ZP
1519 {
1520         uint8_t m;
1521         READ_ZP_WB(m);
1522         OP_DEC_HANDLER(m);
1523         WRITE_BACK(m);
1524 }
1525
1526 static void OpD6(void)                                                  // DEC ZP, X
1527 {
1528         uint8_t m;
1529         READ_ZP_X_WB(m);
1530         OP_DEC_HANDLER(m);
1531         WRITE_BACK(m);
1532 }
1533
1534 static void OpCE(void)                                                  // DEC ABS
1535 {
1536         uint8_t m;
1537         READ_ABS_WB(m);
1538         OP_DEC_HANDLER(m);
1539         WRITE_BACK(m);
1540 }
1541
1542 static void OpDE(void)                                                  // DEC ABS, X
1543 {
1544         uint8_t m;
1545         READ_ABS_X_WB(m);
1546         OP_DEC_HANDLER(m);
1547         WRITE_BACK(m);
1548 }
1549
1550 /*
1551 Here's one problem: DEX is setting the N flag!
1552
1553 D3EE: A2 09          LDX   #$09                 [PC=D3F0, SP=01F7, CC=---B-I-C, A=01, X=09, Y=08]
1554 D3F0: 98             TYA                [PC=D3F1, SP=01F7, CC=N--B-I-C, A=08, X=09, Y=08]
1555 D3F1: 48             PHA                [PC=D3F2, SP=01F6, CC=N--B-I-C, A=08, X=09, Y=08]
1556 D3F2: B5 93          LDA   $93,X                [PC=D3F4, SP=01F6, CC=---B-IZC, A=00, X=09, Y=08]
1557 D3F4: CA             DEX                [PC=D3F5, SP=01F6, CC=N--B-I-C, A=00, X=08, Y=08]
1558 D3F5: 10 FA          BPL   $D3F1                [PC=D3F7, SP=01F6, CC=N--B-I-C, A=00, X=08, Y=08]
1559 D3F7: 20 84 E4       JSR   $E484                [PC=E484, SP=01F4, CC=N--B-I-C, A=00, X=08, Y=08]
1560
1561 should be fixed now...
1562 */
1563
1564 /*
1565 DEX     Implied         DEX                     CA      1       2
1566 */
1567
1568 static void OpCA(void)                                                  // DEX
1569 {
1570         regs.x--;
1571         SET_ZN(regs.x);
1572 }
1573
1574 /*
1575 DEY     Implied         DEY                     88      1       2
1576 */
1577
1578 static void Op88(void)                                                  // DEY
1579 {
1580         regs.y--;
1581         SET_ZN(regs.y);
1582 }
1583
1584 /*
1585 EOR     Immediate       EOR #Oper       49      2       2
1586 Zero Page               EOR Zpg         45      2       3
1587 Zero Page,X             EOR Zpg,X       55      2       4
1588 Absolute                EOR Abs         4D      3       4
1589 Absolute,X              EOR Abs,X       5D      3       4
1590 Absolute,Y              EOR Abs,Y       59      3       4
1591 (Zero Page,X)   EOR (Zpg,X)     41      2       6
1592 (Zero Page),Y   EOR (Zpg),Y     51      2       5
1593 (Zero Page)             EOR (Zpg)       52      2       5
1594 */
1595
1596 // EOR opcodes
1597
1598 #define OP_EOR_HANDLER(m) \
1599         regs.a ^= m; \
1600         SET_ZN(regs.a)
1601
1602 static void Op49(void)                                                  // EOR #
1603 {
1604         uint8_t m = READ_IMM;
1605         OP_EOR_HANDLER(m);
1606 }
1607
1608 static void Op45(void)                                                  // EOR ZP
1609 {
1610         uint8_t m = READ_ZP;
1611         OP_EOR_HANDLER(m);
1612 }
1613
1614 static void Op55(void)                                                  // EOR ZP, X
1615 {
1616         uint8_t m = READ_ZP_X;
1617         OP_EOR_HANDLER(m);
1618 }
1619
1620 static void Op4D(void)                                                  // EOR ABS
1621 {
1622         uint8_t m = READ_ABS;
1623         OP_EOR_HANDLER(m);
1624 }
1625
1626 static void Op5D(void)                                                  // EOR ABS, X
1627 {
1628         uint8_t m = READ_ABS_X;
1629         OP_EOR_HANDLER(m);
1630 }
1631
1632 static void Op59(void)                                                  // EOR ABS, Y
1633 {
1634         uint8_t m = READ_ABS_Y;
1635         OP_EOR_HANDLER(m);
1636 }
1637
1638 static void Op41(void)                                                  // EOR (ZP, X)
1639 {
1640         uint8_t m = READ_IND_ZP_X;
1641         OP_EOR_HANDLER(m);
1642 }
1643
1644 static void Op51(void)                                                  // EOR (ZP), Y
1645 {
1646         uint8_t m = READ_IND_ZP_Y;
1647         OP_EOR_HANDLER(m);
1648 }
1649
1650 static void Op52(void)                                                  // EOR (ZP)
1651 {
1652         uint8_t m = READ_IND_ZP;
1653         OP_EOR_HANDLER(m);
1654 }
1655
1656 /*
1657 INA     Accumulator     INA                     1A      1       2
1658 */
1659
1660 static void Op1A(void)                                                  // INA
1661 {
1662         regs.a++;
1663         SET_ZN(regs.a);
1664 }
1665
1666 /*
1667 INC     Zero Page       INC Zpg         E6      2       5
1668 Zero Page,X             INC Zpg,X       F6      2       6
1669 Absolute                INC Abs         EE      3       6
1670 Absolute,X              INC Abs,X       FE      3       7
1671 */
1672
1673 // INC opcodes
1674
1675 #define OP_INC_HANDLER(m) \
1676         m++; \
1677         SET_ZN(m)
1678
1679 static void OpE6(void)                                                  // INC ZP
1680 {
1681         uint8_t m;
1682         READ_ZP_WB(m);
1683         OP_INC_HANDLER(m);
1684         WRITE_BACK(m);
1685 }
1686
1687 static void OpF6(void)                                                  // INC ZP, X
1688 {
1689         uint8_t m;
1690         READ_ZP_X_WB(m);
1691         OP_INC_HANDLER(m);
1692         WRITE_BACK(m);
1693 }
1694
1695 static void OpEE(void)                                                  // INC ABS
1696 {
1697         uint8_t m;
1698         READ_ABS_WB(m);
1699         OP_INC_HANDLER(m);
1700         WRITE_BACK(m);
1701 }
1702
1703 static void OpFE(void)                                                  // INC ABS, X
1704 {
1705         uint8_t m;
1706         READ_ABS_X_WB(m);
1707         OP_INC_HANDLER(m);
1708         WRITE_BACK(m);
1709 }
1710
1711 /*
1712 INX     Implied         INX                     E8      1       2
1713 */
1714
1715 static void OpE8(void)                                                  // INX
1716 {
1717         regs.x++;
1718         SET_ZN(regs.x);
1719 }
1720
1721 /*
1722 INY     Implied         INY                     C8      1       2
1723 */
1724
1725 static void OpC8(void)                                                  // INY
1726 {
1727         regs.y++;
1728         SET_ZN(regs.y);
1729 }
1730
1731 /*
1732 JMP     Absolute        JMP Abs         4C      3       3
1733 (Absolute)              JMP (Abs)       6C      3       5
1734 (Absolute,X)    JMP (Abs,X)     7C      3       6
1735 */
1736
1737 // JMP opcodes
1738
1739 static void Op4C(void)                                                  // JMP ABS
1740 {
1741         regs.pc = RdMemW(regs.pc);
1742 }
1743
1744 static void Op6C(void)                                                  // JMP (ABS)
1745 {
1746 //      uint16_t addr = RdMemW(regs.pc);
1747 //#ifdef __DEBUG__
1748 //WriteLog("\n[JMP ABS]: addr fetched = %04X, bytes at %04X = %02X %02X (RdMemw=%04X)\n",
1749 //      addr, addr, regs.RdMem(addr), regs.RdMem(addr+1), RdMemW(addr));
1750 //#endif
1751 //      addr = RdMemW(addr);
1752         regs.pc = RdMemW(RdMemW(regs.pc));
1753 }
1754
1755 static void Op7C(void)                                                  // JMP (ABS, X)
1756 {
1757         regs.pc = RdMemW(RdMemW(regs.pc) + regs.x);
1758 }
1759
1760 /*
1761 JSR     Absolute        JSR Abs         20      3       6
1762 */
1763
1764 //This is not jumping to the correct address... !!! FIX !!! [DONE]
1765 static void Op20(void)                                                  // JSR
1766 {
1767         uint16_t addr = RdMemW(regs.pc);
1768         regs.pc++;                                                                      // Since it pushes return address - 1...
1769         regs.WrMem(0x0100 + regs.sp--, regs.pc >> 8);
1770         regs.WrMem(0x0100 + regs.sp--, regs.pc & 0xFF);
1771         regs.pc = addr;
1772 }
1773
1774 /*
1775 LDA     Immediate       LDA #Oper       A9      2       2
1776 Zero Page               LDA Zpg         A5      2       3
1777 Zero Page,X             LDA Zpg,X       B5      2       4
1778 Absolute                LDA Abs         AD      3       4
1779 Absolute,X              LDA Abs,X       BD      3       4
1780 Absolute,Y              LDA Abs,Y       B9      3       4
1781 (Zero Page,X)   LDA (Zpg,X)     A1      2       6
1782 (Zero Page),Y   LDA (Zpg),Y     B1      2       5
1783 (Zero Page)             LDA (Zpg)       B2      2       5
1784 */
1785
1786 // LDA opcodes
1787
1788 #define OP_LDA_HANDLER(m) \
1789         regs.a = m; \
1790         SET_ZN(regs.a)
1791
1792 static void OpA9(void)                                                  // LDA #
1793 {
1794         uint8_t m = READ_IMM;
1795         OP_LDA_HANDLER(m);
1796 }
1797
1798 static void OpA5(void)                                                  // LDA ZP
1799 {
1800         uint8_t m = READ_ZP;
1801         OP_LDA_HANDLER(m);
1802 }
1803
1804 static void OpB5(void)                                                  // LDA ZP, X
1805 {
1806         uint8_t m = READ_ZP_X;
1807         OP_LDA_HANDLER(m);
1808 }
1809
1810 static void OpAD(void)                                                  // LDA ABS
1811 {
1812         uint8_t m = READ_ABS;
1813         OP_LDA_HANDLER(m);
1814 }
1815
1816 static void OpBD(void)                                                  // LDA ABS, X
1817 {
1818         uint8_t m = READ_ABS_X;
1819         OP_LDA_HANDLER(m);
1820 }
1821
1822 static void OpB9(void)                                                  // LDA ABS, Y
1823 {
1824         uint8_t m = READ_ABS_Y;
1825         OP_LDA_HANDLER(m);
1826 }
1827
1828 static void OpA1(void)                                                  // LDA (ZP, X)
1829 {
1830         uint8_t m = READ_IND_ZP_X;
1831         OP_LDA_HANDLER(m);
1832 }
1833
1834 static void OpB1(void)                                                  // LDA (ZP), Y
1835 {
1836         uint8_t m = READ_IND_ZP_Y;
1837         OP_LDA_HANDLER(m);
1838 }
1839
1840 static void OpB2(void)                                                  // LDA (ZP)
1841 {
1842         uint8_t m = READ_IND_ZP;
1843         OP_LDA_HANDLER(m);
1844 }
1845
1846 /*
1847 LDX     Immediate       LDX #Oper       A2      2       2
1848 Zero Page               LDX Zpg         A6      2       3
1849 Zero Page,Y             LDX Zpg,Y       B6      2       4
1850 Absolute                LDX Abs         AE      3       4
1851 Absolute,Y              LDX Abs,Y       BE      3       4
1852 */
1853
1854 // LDX opcodes
1855
1856 #define OP_LDX_HANDLER(m) \
1857         regs.x = m; \
1858         SET_ZN(regs.x)
1859
1860 static void OpA2(void)                                                  // LDX #
1861 {
1862         uint8_t m = READ_IMM;
1863         OP_LDX_HANDLER(m);
1864 }
1865
1866 static void OpA6(void)                                                  // LDX ZP
1867 {
1868         uint8_t m = READ_ZP;
1869         OP_LDX_HANDLER(m);
1870 }
1871
1872 static void OpB6(void)                                                  // LDX ZP, Y
1873 {
1874         uint8_t m = READ_ZP_Y;
1875         OP_LDX_HANDLER(m);
1876 }
1877
1878 static void OpAE(void)                                                  // LDX ABS
1879 {
1880         uint8_t m = READ_ABS;
1881         OP_LDX_HANDLER(m);
1882 }
1883
1884 static void OpBE(void)                                                  // LDX ABS, Y
1885 {
1886         uint8_t m = READ_ABS_Y;
1887         OP_LDX_HANDLER(m);
1888 }
1889
1890 /*
1891 LDY     Immediate       LDY #Oper       A0      2       2
1892 Zero Page               LDY Zpg         A4      2       3
1893 Zero Page,Y             LDY Zpg,X       B4      2       4
1894 Absolute                LDY Abs         AC      3       4
1895 Absolute,Y              LDY Abs,X       BC      3       4
1896 */
1897
1898 // LDY opcodes
1899
1900 #define OP_LDY_HANDLER(m) \
1901         regs.y = m; \
1902         SET_ZN(regs.y)
1903
1904 static void OpA0(void)                                                  // LDY #
1905 {
1906         uint8_t m = READ_IMM;
1907         OP_LDY_HANDLER(m);
1908 }
1909
1910 static void OpA4(void)                                                  // LDY ZP
1911 {
1912         uint8_t m = READ_ZP;
1913         OP_LDY_HANDLER(m);
1914 }
1915
1916 static void OpB4(void)                                                  // LDY ZP, X
1917 {
1918         uint8_t m = READ_ZP_X;
1919         OP_LDY_HANDLER(m);
1920 }
1921
1922 static void OpAC(void)                                                  // LDY ABS
1923 {
1924         uint8_t m = READ_ABS;
1925         OP_LDY_HANDLER(m);
1926 }
1927
1928 static void OpBC(void)                                                  // LDY ABS, X
1929 {
1930         uint8_t m = READ_ABS_X;
1931         OP_LDY_HANDLER(m);
1932 }
1933
1934 /*
1935 LSR     Accumulator     LSR A           4A      1       2
1936 Zero Page               LSR Zpg         46      2       5
1937 Zero Page,X             LSR Zpg,X       56      2       6
1938 Absolute                LSR Abs         4E      3       6
1939 Absolute,X              LSR Abs,X       5E      3       7
1940 */
1941
1942 // LSR opcodes
1943
1944 #define OP_LSR_HANDLER(m) \
1945         regs.cc = ((m) & 0x01 ? regs.cc | FLAG_C : regs.cc & ~FLAG_C); \
1946         (m) >>= 1; \
1947         CLR_N; SET_Z((m))
1948
1949 static void Op4A(void)                                                  // LSR A
1950 {
1951         OP_LSR_HANDLER(regs.a);
1952 }
1953
1954 static void Op46(void)                                                  // LSR ZP
1955 {
1956         uint8_t m;
1957         READ_ZP_WB(m);
1958         OP_LSR_HANDLER(m);
1959         WRITE_BACK(m);
1960 }
1961
1962 static void Op56(void)                                                  // LSR ZP, X
1963 {
1964         uint8_t m;
1965         READ_ZP_X_WB(m);
1966         OP_LSR_HANDLER(m);
1967         WRITE_BACK(m);
1968 }
1969
1970 static void Op4E(void)                                                  // LSR ABS
1971 {
1972         uint8_t m;
1973         READ_ABS_WB(m);
1974         OP_LSR_HANDLER(m);
1975         WRITE_BACK(m);
1976 }
1977
1978 static void Op5E(void)                                                  // LSR ABS, X
1979 {
1980         uint8_t m;
1981         READ_ABS_X_WB(m);
1982         OP_LSR_HANDLER(m);
1983         WRITE_BACK(m);
1984 }
1985
1986 /*
1987 NOP     Implied         NOP                     EA      1       2
1988 */
1989
1990 static void OpEA(void)                                                  // NOP
1991 {
1992 }
1993
1994 /*
1995 ORA     Immediate       ORA #Oper       09      2       2
1996 Zero Page               ORA Zpg         05      2       3
1997 Zero Page,X             ORA Zpg,X       15      2       4
1998 Absolute                ORA Abs         0D      3       4
1999 Absolute,X              ORA Abs,X       1D      3       4
2000 Absolute,Y              ORA Abs,Y       19      3       4
2001 (Zero Page,X)   ORA (Zpg,X)     01      2       6
2002 (Zero Page),Y   ORA (Zpg),Y     11      2       5
2003 (Zero Page)             ORA (Zpg)       12      2       5
2004 */
2005
2006 // ORA opcodes
2007
2008 #define OP_ORA_HANDLER(m) \
2009         regs.a |= m; \
2010         SET_ZN(regs.a)
2011
2012 static void Op09(void)                                                  // ORA #
2013 {
2014         uint8_t m = READ_IMM;
2015         OP_ORA_HANDLER(m);
2016 }
2017
2018 static void Op05(void)                                                  // ORA ZP
2019 {
2020         uint8_t m = READ_ZP;
2021         OP_ORA_HANDLER(m);
2022 }
2023
2024 static void Op15(void)                                                  // ORA ZP, X
2025 {
2026         uint8_t m = READ_ZP_X;
2027         OP_ORA_HANDLER(m);
2028 }
2029
2030 static void Op0D(void)                                                  // ORA ABS
2031 {
2032         uint8_t m = READ_ABS;
2033         OP_ORA_HANDLER(m);
2034 }
2035
2036 static void Op1D(void)                                                  // ORA ABS, X
2037 {
2038         uint8_t m = READ_ABS_X;
2039         OP_ORA_HANDLER(m);
2040 }
2041
2042 static void Op19(void)                                                  // ORA ABS, Y
2043 {
2044         uint8_t m = READ_ABS_Y;
2045         OP_ORA_HANDLER(m);
2046 }
2047
2048 static void Op01(void)                                                  // ORA (ZP, X)
2049 {
2050         uint8_t m = READ_IND_ZP_X;
2051         OP_ORA_HANDLER(m);
2052 }
2053
2054 static void Op11(void)                                                  // ORA (ZP), Y
2055 {
2056         uint8_t m = READ_IND_ZP_Y;
2057         OP_ORA_HANDLER(m);
2058 }
2059
2060 static void Op12(void)                                                  // ORA (ZP)
2061 {
2062         uint8_t m = READ_IND_ZP;
2063         OP_ORA_HANDLER(m);
2064 }
2065
2066 /*
2067 PHA     Implied         PHA                     48      1       3
2068 */
2069
2070 static void Op48(void)                                                  // PHA
2071 {
2072         regs.WrMem(0x0100 + regs.sp--, regs.a);
2073 }
2074
2075 static void Op08(void)                                                  // PHP
2076 {
2077         regs.cc |= FLAG_UNK;                                            // Make sure that the unused bit is always set
2078         regs.WrMem(0x0100 + regs.sp--, regs.cc);
2079 }
2080
2081 /*
2082 PHX     Implied         PHX                     DA      1       3
2083 */
2084
2085 static void OpDA(void)                                                  // PHX
2086 {
2087         regs.WrMem(0x0100 + regs.sp--, regs.x);
2088 }
2089
2090 /*
2091 PHY     Implied         PHY                     5A      1       3
2092 */
2093
2094 static void Op5A(void)                                                  // PHY
2095 {
2096         regs.WrMem(0x0100 + regs.sp--, regs.y);
2097 }
2098
2099 /*
2100 PLA     Implied         PLA                     68      1       4
2101 */
2102
2103 static void Op68(void)                                                  // PLA
2104 {
2105         regs.a = regs.RdMem(0x0100 + ++regs.sp);
2106         SET_ZN(regs.a);
2107 }
2108
2109 static void Op28(void)                                                  // PLP
2110 {
2111         regs.cc = regs.RdMem(0x0100 + ++regs.sp);
2112 }
2113
2114 /*
2115 PLX     Implied         PLX                     FA      1       4
2116 */
2117
2118 static void OpFA(void)                                                  // PLX
2119 {
2120         regs.x = regs.RdMem(0x0100 + ++regs.sp);
2121         SET_ZN(regs.x);
2122 }
2123
2124 /*
2125 PLY     Implied         PLY                     7A      1       4
2126 */
2127
2128 static void Op7A(void)                                                  // PLY
2129 {
2130         regs.y = regs.RdMem(0x0100 + ++regs.sp);
2131         SET_ZN(regs.y);
2132 }
2133
2134 /*
2135 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.
2136    RMB0  RMB1  RMB2  RMB3  RMB4  RMB5  RMB6  RMB7
2137   zp  07  17  27  37  47  57  67  77
2138      SMB0  SMB1  SMB2  SMB3  SMB4  SMB5  SMB6  SMB7
2139   zp  87  97  A7  B7  C7  D7  E7  F7
2140 */
2141
2142 // RMB opcodes
2143
2144 static void Op07(void)                                                  // RMB0 ZP
2145 {
2146         uint8_t m;
2147         READ_ZP_WB(m);
2148         m &= 0xFE;
2149         WRITE_BACK(m);
2150 }
2151
2152 static void Op17(void)                                                  // RMB1 ZP
2153 {
2154         uint8_t m;
2155         READ_ZP_WB(m);
2156         m &= 0xFD;
2157         WRITE_BACK(m);
2158 }
2159
2160 static void Op27(void)                                                  // RMB2 ZP
2161 {
2162         uint8_t m;
2163         READ_ZP_WB(m);
2164         m &= 0xFB;
2165         WRITE_BACK(m);
2166 }
2167
2168 static void Op37(void)                                                  // RMB3 ZP
2169 {
2170         uint8_t m;
2171         READ_ZP_WB(m);
2172         m &= 0xF7;
2173         WRITE_BACK(m);
2174 }
2175
2176 static void Op47(void)                                                  // RMB4 ZP
2177 {
2178         uint8_t m;
2179         READ_ZP_WB(m);
2180         m &= 0xEF;
2181         WRITE_BACK(m);
2182 }
2183
2184 static void Op57(void)                                                  // RMB5 ZP
2185 {
2186         uint8_t m;
2187         READ_ZP_WB(m);
2188         m &= 0xDF;
2189         WRITE_BACK(m);
2190 }
2191
2192 static void Op67(void)                                                  // RMB6 ZP
2193 {
2194         uint8_t m;
2195         READ_ZP_WB(m);
2196         m &= 0xBF;
2197         WRITE_BACK(m);
2198 }
2199
2200 static void Op77(void)                                                  // RMB7 ZP
2201 {
2202         uint8_t m;
2203         READ_ZP_WB(m);
2204         m &= 0x7F;
2205         WRITE_BACK(m);
2206 }
2207
2208 /*
2209 ROL     Accumulator     ROL A           2A      1       2
2210 Zero Page               ROL Zpg         26      2       5
2211 Zero Page,X             ROL Zpg,X       36      2       6
2212 Absolute                ROL Abs         2E      3       6
2213 Absolute,X              ROL Abs,X       3E      3       7
2214 */
2215
2216 // ROL opcodes
2217
2218 #define OP_ROL_HANDLER(m) \
2219         uint8_t tmp = regs.cc & 0x01; \
2220         regs.cc = ((m) & 0x80 ? regs.cc | FLAG_C : regs.cc & ~FLAG_C); \
2221         (m) = ((m) << 1) | tmp; \
2222         SET_ZN((m))
2223
2224 static void Op2A(void)                                                  // ROL A
2225 {
2226         OP_ROL_HANDLER(regs.a);
2227 }
2228
2229 static void Op26(void)                                                  // ROL ZP
2230 {
2231         uint8_t m;
2232         READ_ZP_WB(m);
2233         OP_ROL_HANDLER(m);
2234         WRITE_BACK(m);
2235 }
2236
2237 static void Op36(void)                                                  // ROL ZP, X
2238 {
2239         uint8_t m;
2240         READ_ZP_X_WB(m);
2241         OP_ROL_HANDLER(m);
2242         WRITE_BACK(m);
2243 }
2244
2245 static void Op2E(void)                                                  // ROL ABS
2246 {
2247         uint8_t m;
2248         READ_ABS_WB(m);
2249         OP_ROL_HANDLER(m);
2250         WRITE_BACK(m);
2251 }
2252
2253 static void Op3E(void)                                                  // ROL ABS, X
2254 {
2255         uint8_t m;
2256         READ_ABS_X_WB(m);
2257         OP_ROL_HANDLER(m);
2258         WRITE_BACK(m);
2259 }
2260
2261 /*
2262 ROR     Accumulator     ROR A           6A      1       2
2263 Zero Page               ROR Zpg         66      2       5
2264 Zero Page,X             ROR Zpg,X       76      2       6
2265 Absolute                ROR Abs         6E      3       6
2266 Absolute,X              ROR Abs,X       7E      3       7
2267 */
2268
2269 // ROR opcodes
2270
2271 #define OP_ROR_HANDLER(m) \
2272         uint8_t tmp = (regs.cc & 0x01) << 7; \
2273         regs.cc = ((m) & 0x01 ? regs.cc | FLAG_C : regs.cc & ~FLAG_C); \
2274         (m) = ((m) >> 1) | tmp; \
2275         SET_ZN((m))
2276
2277 static void Op6A(void)                                                  // ROR A
2278 {
2279         OP_ROR_HANDLER(regs.a);
2280 }
2281
2282 static void Op66(void)                                                  // ROR ZP
2283 {
2284         uint8_t m;
2285         READ_ZP_WB(m);
2286         OP_ROR_HANDLER(m);
2287         WRITE_BACK(m);
2288 }
2289
2290 static void Op76(void)                                                  // ROR ZP, X
2291 {
2292         uint8_t m;
2293         READ_ZP_X_WB(m);
2294         OP_ROR_HANDLER(m);
2295         WRITE_BACK(m);
2296 }
2297
2298 static void Op6E(void)                                                  // ROR ABS
2299 {
2300         uint8_t m;
2301         READ_ABS_WB(m);
2302         OP_ROR_HANDLER(m);
2303         WRITE_BACK(m);
2304 }
2305
2306 static void Op7E(void)                                                  // ROR ABS, X
2307 {
2308         uint8_t m;
2309         READ_ABS_X_WB(m);
2310         OP_ROR_HANDLER(m);
2311         WRITE_BACK(m);
2312 }
2313
2314 /*
2315 RTI     Implied         RTI                     40      1       6
2316 */
2317
2318 static void Op40(void)                                                  // RTI
2319 {
2320         regs.cc = regs.RdMem(0x0100 + ++regs.sp);
2321 //clear I (seems to be the case, either that or clear it in the IRQ setup...)
2322 //I can't find *any* verification that this is the case.
2323 //      regs.cc &= ~FLAG_I;
2324         regs.pc = regs.RdMem(0x0100 + ++regs.sp);
2325         regs.pc |= (uint16_t)(regs.RdMem(0x0100 + ++regs.sp)) << 8;
2326 }
2327
2328 /*
2329 RTS     Implied         RTS                     60      1       6
2330 */
2331
2332 static void Op60(void)                                                  // RTS
2333 {
2334         regs.pc = regs.RdMem(0x0100 + ++regs.sp);
2335         regs.pc |= (uint16_t)(regs.RdMem(0x0100 + ++regs.sp)) << 8;
2336         regs.pc++;                                                                      // Since it pushes return address - 1...
2337 //printf("*** RTS: PC = $%04X, SP= $1%02X\n", regs.pc, regs.sp);
2338 //fflush(stdout);
2339 }
2340
2341 /*
2342 SBC     Immediate       SBC #Oper       E9      2       2
2343 Zero Page               SBC Zpg         E5      2       3
2344 Zero Page,X             SBC Zpg,X       F5      2       4
2345 Absolute                SBC Abs         ED      3       4
2346 Absolute,X              SBC Abs,X       FD      3       4
2347 Absolute,Y              SBC Abs,Y       F9      3       4
2348 (Zero Page,X)   SBC (Zpg,X)     E1      2       6
2349 (Zero Page),Y   SBC (Zpg),Y     F1      2       5
2350 (Zero Page)             SBC (Zpg)       F2      2       5
2351 */
2352
2353 // SBC opcodes
2354
2355 //This is non-optimal, but it works--optimize later. :-)
2356 //This is correct except for the BCD handling... !!! FIX !!! [Possibly DONE]
2357 #define OP_SBC_HANDLER(m) \
2358         uint16_t sum = (uint16_t)regs.a - (m) - (uint16_t)((regs.cc & FLAG_C) ^ 0x01); \
2359 \
2360         if (regs.cc & FLAG_D) \
2361         { \
2362                 if ((sum & 0x0F) > 0x09) \
2363                         sum -= 0x06; \
2364 \
2365                 if ((sum & 0xF0) > 0x90) \
2366                         sum -= 0x60; \
2367         } \
2368 \
2369         regs.cc = (regs.cc & ~FLAG_C) | (((sum >> 8) ^ 0x01) & FLAG_C); \
2370         regs.cc = ((regs.a ^ (m)) & (regs.a ^ sum) & 0x80 ? regs.cc | FLAG_V : regs.cc & ~FLAG_V); \
2371         regs.a = sum & 0xFF; \
2372         SET_ZN(regs.a)
2373
2374 /*
2375 D5AF: 38             SEC                [PC=D5B0, SP=01F6, CC=---B-I-C, A=4C, X=00, Y=06]
2376
2377 *** HERE'S where it sets the D flag on a subtract... Arg!
2378
2379 D5B0: F1 9D          SBC   ($9D),Y      [PC=D5B2, SP=01F6, CC=N--BDI--, A=FE, X=00, Y=06]
2380
2381 Fixed. :-)
2382 */
2383
2384 //OLD V detection: regs.cc = ((regs.a ^ (m) ^ sum ^ (regs.cc << 7)) & 0x80 ? regs.cc | FLAG_V : regs.cc & ~FLAG_V);
2385
2386 static void OpE9(void)                                                  // SBC #
2387 {
2388         uint16_t m = READ_IMM;
2389         OP_SBC_HANDLER(m);
2390 }
2391
2392 static void OpE5(void)                                                  // SBC ZP
2393 {
2394         uint16_t m = READ_ZP;
2395         OP_SBC_HANDLER(m);
2396 }
2397
2398 static void OpF5(void)                                                  // SBC ZP, X
2399 {
2400         uint16_t m = READ_ZP_X;
2401         OP_SBC_HANDLER(m);
2402 }
2403
2404 static void OpED(void)                                                  // SBC ABS
2405 {
2406         uint16_t m = READ_ABS;
2407         OP_SBC_HANDLER(m);
2408 }
2409
2410 static void OpFD(void)                                                  // SBC ABS, X
2411 {
2412         uint16_t m = READ_ABS_X;
2413         OP_SBC_HANDLER(m);
2414 }
2415
2416 static void OpF9(void)                                                  // SBC ABS, Y
2417 {
2418         uint16_t m = READ_ABS_Y;
2419         OP_SBC_HANDLER(m);
2420 }
2421
2422 static void OpE1(void)                                                  // SBC (ZP, X)
2423 {
2424         uint16_t m = READ_IND_ZP_X;
2425         OP_SBC_HANDLER(m);
2426 }
2427
2428 static void OpF1(void)                                                  // SBC (ZP), Y
2429 {
2430         uint16_t m = READ_IND_ZP_Y;
2431         OP_SBC_HANDLER(m);
2432 }
2433
2434 static void OpF2(void)                                                  // SBC (ZP)
2435 {
2436         uint16_t m = READ_IND_ZP;
2437         OP_SBC_HANDLER(m);
2438 }
2439
2440 /*
2441 SEC     Implied         SEC                     38      1       2
2442 */
2443
2444 static void Op38(void)                                                  // SEC
2445 {
2446         regs.cc |= FLAG_C;
2447 }
2448
2449 /*
2450 SED     Implied         SED                     F8      1       2
2451 */
2452
2453 static void OpF8(void)                                                  // SED
2454 {
2455         regs.cc |= FLAG_D;
2456 }
2457
2458 /*
2459 SEI     Implied         SEI                     78      1       2
2460 */
2461
2462 static void Op78(void)                                                  // SEI
2463 {
2464         regs.cc |= FLAG_I;
2465 }
2466
2467 /*
2468 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.
2469    RMB0  RMB1  RMB2  RMB3  RMB4  RMB5  RMB6  RMB7
2470   zp  07  17  27  37  47  57  67  77
2471      SMB0  SMB1  SMB2  SMB3  SMB4  SMB5  SMB6  SMB7
2472   zp  87  97  A7  B7  C7  D7  E7  F7
2473 */
2474
2475 // SMB opcodes
2476
2477 static void Op87(void)                                                  // SMB0 ZP
2478 {
2479         uint8_t m;
2480         READ_ZP_WB(m);
2481         m |= 0x01;
2482         WRITE_BACK(m);
2483 }
2484
2485 static void Op97(void)                                                  // SMB1 ZP
2486 {
2487         uint8_t m;
2488         READ_ZP_WB(m);
2489         m |= 0x02;
2490         WRITE_BACK(m);
2491 }
2492
2493 static void OpA7(void)                                                  // SMB2 ZP
2494 {
2495         uint8_t m;
2496         READ_ZP_WB(m);
2497         m |= 0x04;
2498         WRITE_BACK(m);
2499 }
2500
2501 static void OpB7(void)                                                  // SMB3 ZP
2502 {
2503         uint8_t m;
2504         READ_ZP_WB(m);
2505         m |= 0x08;
2506         WRITE_BACK(m);
2507 }
2508
2509 static void OpC7(void)                                                  // SMB4 ZP
2510 {
2511         uint8_t m;
2512         READ_ZP_WB(m);
2513         m |= 0x10;
2514         WRITE_BACK(m);
2515 }
2516
2517 static void OpD7(void)                                                  // SMB5 ZP
2518 {
2519         uint8_t m;
2520         READ_ZP_WB(m);
2521         m |= 0x20;
2522         WRITE_BACK(m);
2523 }
2524
2525 static void OpE7(void)                                                  // SMB6 ZP
2526 {
2527         uint8_t m;
2528         READ_ZP_WB(m);
2529         m |= 0x40;
2530         WRITE_BACK(m);
2531 }
2532
2533 static void OpF7(void)                                                  // SMB7 ZP
2534 {
2535         uint8_t m;
2536         READ_ZP_WB(m);
2537         m |= 0x80;
2538         WRITE_BACK(m);
2539 }
2540
2541 /*
2542 STA     Zero Page       STA Zpg         85      2       3
2543 Zero Page,X             STA Zpg,X       95      2       4
2544 Absolute                STA Abs         8D      3       4
2545 Absolute,X              STA Abs,X       9D      3       5
2546 Absolute,Y              STA Abs,Y       99      3       5
2547 (Zero Page,X)   STA (Zpg,X)     81      2       6
2548 (Zero Page),Y   STA (Zpg),Y     91      2       6
2549 (Zero Page)             STA (Zpg)       92      2       5
2550 */
2551
2552 // STA opcodes
2553
2554 static void Op85(void)
2555 {
2556         regs.WrMem(EA_ZP, regs.a);
2557 }
2558
2559 static void Op95(void)
2560 {
2561         regs.WrMem(EA_ZP_X, regs.a);
2562 }
2563
2564 static void Op8D(void)
2565 {
2566         regs.WrMem(EA_ABS, regs.a);
2567 }
2568
2569 static void Op9D(void)
2570 {
2571         regs.WrMem(EA_ABS_X, regs.a);
2572 }
2573
2574 static void Op99(void)
2575 {
2576         regs.WrMem(EA_ABS_Y, regs.a);
2577 }
2578
2579 static void Op81(void)
2580 {
2581         regs.WrMem(EA_IND_ZP_X, regs.a);
2582 }
2583
2584 static void Op91(void)
2585 {
2586         regs.WrMem(EA_IND_ZP_Y, regs.a);
2587 }
2588
2589 static void Op92(void)
2590 {
2591         regs.WrMem(EA_IND_ZP, regs.a);
2592 }
2593
2594 /*
2595 STX     Zero Page       STX Zpg         86      2       3
2596 Zero Page,Y             STX Zpg,Y       96      2       4
2597 Absolute                STX Abs         8E      3       4
2598 */
2599
2600 // STX opcodes
2601
2602 static void Op86(void)
2603 {
2604         regs.WrMem(EA_ZP, regs.x);
2605 }
2606
2607 static void Op96(void)
2608 {
2609         regs.WrMem(EA_ZP_X, regs.x);
2610 }
2611
2612 static void Op8E(void)
2613 {
2614         regs.WrMem(EA_ABS, regs.x);
2615 }
2616
2617 /*
2618 STY     Zero Page       STY Zpg         84      2       3
2619 Zero Page,X             STY Zpg,X       94      2       4
2620 Absolute                STY Abs         8C      3       4
2621 */
2622
2623 // STY opcodes
2624
2625 static void Op84(void)
2626 {
2627         regs.WrMem(EA_ZP, regs.y);
2628 }
2629
2630 static void Op94(void)
2631 {
2632         regs.WrMem(EA_ZP_X, regs.y);
2633 }
2634
2635 static void Op8C(void)
2636 {
2637         regs.WrMem(EA_ABS, regs.y);
2638 }
2639
2640 /*
2641 STZ     Zero Page       STZ Zpg         64      2       3
2642 Zero Page,X             STZ Zpg,X       74      2       4
2643 Absolute                STZ Abs         9C      3       4
2644 Absolute,X              STZ Abs,X       9E      3       5
2645 */
2646
2647 // STZ opcodes
2648
2649 static void Op64(void)
2650 {
2651         regs.WrMem(EA_ZP, 0x00);
2652 }
2653
2654 static void Op74(void)
2655 {
2656         regs.WrMem(EA_ZP_X, 0x00);
2657 }
2658
2659 static void Op9C(void)
2660 {
2661         regs.WrMem(EA_ABS, 0x00);
2662 }
2663
2664 static void Op9E(void)
2665 {
2666         regs.WrMem(EA_ABS_X, 0x00);
2667 }
2668
2669 /*
2670 TAX     Implied         TAX                     AA      1       2
2671 */
2672
2673 static void OpAA(void)                                                  // TAX
2674 {
2675         regs.x = regs.a;
2676         SET_ZN(regs.x);
2677 }
2678
2679 /*
2680 TAY     Implied         TAY                     A8      1       2
2681 */
2682
2683 static void OpA8(void)                                                  // TAY
2684 {
2685         regs.y = regs.a;
2686         SET_ZN(regs.y);
2687 }
2688
2689 /*
2690 TRB     Zero Page       TRB Zpg         14      2       5
2691 Absolute                TRB Abs         1C      3       6
2692 */
2693
2694 // TRB opcodes
2695
2696 #define OP_TRB_HANDLER(m) \
2697         SET_Z(m & regs.a); \
2698         m &= ~regs.a
2699
2700 static void Op14(void)                                                  // TRB ZP
2701 {
2702         uint8_t m;
2703         READ_ZP_WB(m);
2704         OP_TRB_HANDLER(m);
2705         WRITE_BACK(m);
2706 }
2707
2708 static void Op1C(void)                                                  // TRB ABS
2709 {
2710         uint8_t m;
2711         READ_ABS_WB(m);
2712         OP_TRB_HANDLER(m);
2713         WRITE_BACK(m);
2714 }
2715
2716 /*
2717 TSB     Zero Page       TSB Zpg         04      2       5
2718 Absolute                TSB Abs         0C      3       6
2719 */
2720
2721 // TSB opcodes
2722
2723 #define OP_TSB_HANDLER(m) \
2724         SET_Z(m & regs.a); \
2725         m |= regs.a
2726
2727 static void Op04(void)                                                  // TSB ZP
2728 {
2729         uint8_t m;
2730         READ_ZP_WB(m);
2731         OP_TSB_HANDLER(m);
2732         WRITE_BACK(m);
2733 }
2734
2735 static void Op0C(void)                                                  // TSB ABS
2736 {
2737         uint8_t m;
2738         READ_ABS_WB(m);
2739         OP_TSB_HANDLER(m);
2740         WRITE_BACK(m);
2741 }
2742
2743 /*
2744 TSX     Implied         TSX                     BA      1       2
2745 */
2746
2747 static void OpBA(void)                                                  // TSX
2748 {
2749         regs.x = regs.sp;
2750         SET_ZN(regs.x);
2751 }
2752
2753 /*
2754 TXA     Implied         TXA                     8A      1       2
2755 */
2756
2757 static void Op8A(void)                                                  // TXA
2758 {
2759         regs.a = regs.x;
2760         SET_ZN(regs.a);
2761 }
2762
2763 /*
2764 TXS     Implied         TXS                     9A      1       2
2765 */
2766
2767 static void Op9A(void)                                                  // TXS
2768 {
2769         regs.sp = regs.x;
2770 }
2771
2772 /*
2773 TYA     Implied         TYA                     98      1       2
2774 */
2775 static void Op98(void)                                                  // TYA
2776 {
2777         regs.a = regs.y;
2778         SET_ZN(regs.a);
2779 }
2780
2781 static void Op__(void)
2782 {
2783         regs.cpuFlags |= V65C02_STATE_ILLEGAL_INST;
2784 }
2785
2786
2787 //
2788 // Ok, the exec_op[] array is globally defined here basically to save
2789 // a LOT of unnecessary typing.  Sure it's ugly, but hey, it works!
2790 //
2791 void (* exec_op[256])() = {
2792         Op00, Op01, Op__, Op__, Op04, Op05, Op06, Op07, Op08, Op09, Op0A, Op__, Op0C, Op0D, Op0E, Op0F,
2793         Op10, Op11, Op12, Op__, Op14, Op15, Op16, Op17, Op18, Op19, Op1A, Op__, Op1C, Op1D, Op1E, Op1F,
2794         Op20, Op21, Op__, Op__, Op24, Op25, Op26, Op27, Op28, Op29, Op2A, Op__, Op2C, Op2D, Op2E, Op2F,
2795         Op30, Op31, Op32, Op__, Op34, Op35, Op36, Op37, Op38, Op39, Op3A, Op__, Op3C, Op3D, Op3E, Op3F,
2796         Op40, Op41, Op__, Op__, Op__, Op45, Op46, Op47, Op48, Op49, Op4A, Op__, Op4C, Op4D, Op4E, Op4F,
2797         Op50, Op51, Op52, Op__, Op__, Op55, Op56, Op57, Op58, Op59, Op5A, Op__, Op__, Op5D, Op5E, Op5F,
2798         Op60, Op61, Op__, Op__, Op64, Op65, Op66, Op67, Op68, Op69, Op6A, Op__, Op6C, Op6D, Op6E, Op6F,
2799         Op70, Op71, Op72, Op__, Op74, Op75, Op76, Op77, Op78, Op79, Op7A, Op__, Op7C, Op7D, Op7E, Op7F,
2800         Op80, Op81, Op__, Op__, Op84, Op85, Op86, Op87, Op88, Op89, Op8A, Op__, Op8C, Op8D, Op8E, Op8F,
2801         Op90, Op91, Op92, Op__, Op94, Op95, Op96, Op97, Op98, Op99, Op9A, Op__, Op9C, Op9D, Op9E, Op9F,
2802         OpA0, OpA1, OpA2, Op__, OpA4, OpA5, OpA6, OpA7, OpA8, OpA9, OpAA, Op__, OpAC, OpAD, OpAE, OpAF,
2803         OpB0, OpB1, OpB2, Op__, OpB4, OpB5, OpB6, OpB7, OpB8, OpB9, OpBA, Op__, OpBC, OpBD, OpBE, OpBF,
2804         OpC0, OpC1, Op__, Op__, OpC4, OpC5, OpC6, OpC7, OpC8, OpC9, OpCA, Op__, OpCC, OpCD, OpCE, OpCF,
2805         OpD0, OpD1, OpD2, Op__, Op__, OpD5, OpD6, OpD7, OpD8, OpD9, OpDA, Op__, Op__, OpDD, OpDE, OpDF,
2806         OpE0, OpE1, Op__, Op__, OpE4, OpE5, OpE6, OpE7, OpE8, OpE9, OpEA, Op__, OpEC, OpED, OpEE, OpEF,
2807         OpF0, OpF1, OpF2, Op__, Op__, OpF5, OpF6, OpF7, OpF8, OpF9, OpFA, Op__, Op__, OpFD, OpFE, OpFF
2808 };
2809
2810
2811 //
2812 // Internal "memcpy" (so we don't have to link with any external libraries!)
2813 //
2814 static void myMemcpy(void * dst, void * src, uint32_t size)
2815 {
2816         uint8_t * d = (uint8_t *)dst, * s = (uint8_t *)src;
2817
2818         for(uint32_t i=0; i<size; i++)
2819                 d[i] = s[i];
2820 }
2821
2822 /*
2823 FCA8: 38        698  WAIT     SEC
2824 FCA9: 48        699  WAIT2    PHA
2825 FCAA: E9 01     700  WAIT3    SBC   #$01
2826 FCAC: D0 FC     701           BNE   WAIT3      ;1.0204 USEC
2827 FCAE: 68        702           PLA              ;(13+27/2*A+5/2*A*A)
2828 FCAF: E9 01     703           SBC   #$01
2829 FCB1: D0 F6     704           BNE   WAIT2
2830 FCB3: 60        705           RTS
2831
2832 FBD9: C9 87     592  BELL1    CMP   #$87       ;BELL CHAR? (CNTRL-G)
2833 FBDB: D0 12     593           BNE   RTS2B      ;  NO, RETURN
2834 FBDD: A9 40     594           LDA   #$40       ;DELAY .01 SECONDS
2835 FBDF: 20 A8 FC  595           JSR   WAIT
2836 FBE2: A0 C0     596           LDY   #$C0
2837 FBE4: A9 0C     597  BELL2    LDA   #$0C       ;TOGGLE SPEAKER AT
2838 FBE6: 20 A8 FC  598           JSR   WAIT       ;  1 KHZ FOR .1 SEC.
2839 FBE9: AD 30 C0  599           LDA   SPKR
2840 FBEC: 88        600           DEY
2841 FBED: D0 F5     601           BNE   BELL2
2842 FBEF: 60        602  RTS2B    RTS
2843 */
2844 //int instCount[256];
2845 #ifdef __DEBUG__
2846 bool dumpDis = false;
2847 //bool dumpDis = true;
2848 #endif
2849
2850 /*
2851 On //e, $FCAA is the delay routine. (seems to not have changed from ][+)
2852 */
2853
2854
2855 //Note: could enforce regs.clock to zero on starting the CPU with an Init() function...
2856 //bleh.
2857 //static uint32_t limit = 0;
2858
2859 // This should be in the regs struct, in case we have multiple CPUs...
2860 #warning "!!! Move overflow into regs struct !!!"
2861 static uint64_t overflow = 0;
2862 //
2863 // Function to execute 65C02 for "cycles" cycles
2864 //
2865 void Execute65C02(V65C02REGS * context, uint32_t cycles)
2866 {
2867         myMemcpy(&regs, context, sizeof(V65C02REGS));
2868
2869         // Execute here...
2870 // NOTE: There *must* be some way of doing this without requiring the caller to subtract out
2871 //       the previous run's cycles. !!! FIX !!!
2872 // Could try:
2873 //      while (regs.clock < regs.clock + cycles) <-- won't work
2874 /*
2875         // This isn't as accurate as subtracting out cycles from regs.clock...
2876         // Unless limit is a static variable, adding cycles to it each time through...
2877         uint32_t limit = regs.clock + cycles;
2878         while (regs.clock < limit)
2879 */
2880 // but have wraparound to deal with. :-/
2881 /*
2882 Let's see...
2883
2884         if (regs.clock + cycles > 0xFFFFFFFF)
2885                 wraparound = true;
2886 */
2887         uint64_t endCycles = regs.clock + (uint64_t)cycles - overflow;
2888
2889         while (regs.clock < endCycles)
2890         {
2891 #if 0
2892 /*if (regs.pc == 0x4007)
2893 {
2894         dumpDis = true;
2895 }//*/
2896 if (regs.pc == 0x444B)
2897 {
2898         WriteLog("\n*** End of wait...\n\n");
2899         dumpDis = true;
2900 }//*/
2901 if (regs.pc == 0x444E)
2902 {
2903         WriteLog("\n*** Start of wait...\n\n");
2904         dumpDis = false;
2905 }//*/
2906 #endif
2907
2908 #if 0
2909 /*if (regs.pc == 0x0801)
2910 {
2911         WriteLog("\n*** DISK BOOT subroutine...\n\n");
2912         dumpDis = true;
2913 }//*/
2914 if (regs.pc == 0xE000)
2915 {
2916 #if 0
2917         WriteLog("\n*** Dump of $E000 routine ***\n\n");
2918
2919         for(uint32_t addr=0xE000; addr<0xF000;)
2920         {
2921                 addr += Decode65C02(addr);
2922                 WriteLog("\n");
2923         }
2924 #endif
2925         WriteLog("\n*** DISK part II subroutine...\n\n");
2926         dumpDis = true;
2927 }//*/
2928 if (regs.pc == 0xD000)
2929 {
2930         WriteLog("\n*** CUSTOM DISK READ subroutine...\n\n");
2931         dumpDis = false;
2932 }//*/
2933 if (regs.pc == 0xD1BE)
2934 {
2935 //      WriteLog("\n*** DISK part II subroutine...\n\n");
2936         dumpDis = true;
2937 }//*/
2938 if (regs.pc == 0xD200)
2939 {
2940         WriteLog("\n*** CUSTOM SCREEN subroutine...\n\n");
2941         dumpDis = false;
2942 }//*/
2943 if (regs.pc == 0xD269)
2944 {
2945 //      WriteLog("\n*** DISK part II subroutine...\n\n");
2946         dumpDis = true;
2947 }//*/
2948 #endif
2949 #ifdef __DEBUGMON__
2950 //WAIT is commented out here because it's called by BELL1...
2951 if (regs.pc == 0xFCA8)
2952 {
2953         WriteLog("\n*** WAIT subroutine...\n\n");
2954         dumpDis = false;
2955 }//*/
2956 if (regs.pc == 0xFBD9)
2957 {
2958         WriteLog("\n*** BELL1 subroutine...\n\n");
2959 //      dumpDis = false;
2960 }//*/
2961 if (regs.pc == 0xFC58)
2962 {
2963         WriteLog("\n*** HOME subroutine...\n\n");
2964 //      dumpDis = false;
2965 }//*/
2966 if (regs.pc == 0xFDED)
2967 {
2968         WriteLog("\n*** COUT subroutine...\n\n");
2969         dumpDis = false;
2970 }
2971 #endif
2972 #if 0
2973 // ProDOS debugging
2974 if (regs.pc == 0x2000)
2975         dumpDis = true;
2976 #endif
2977
2978 #ifdef __DEBUG__
2979 if (dumpDis)
2980         Decode65C02(regs.pc);
2981 #endif
2982                 uint8_t opcode = regs.RdMem(regs.pc++);
2983
2984 //if (!(regs.cpuFlags & V65C02_STATE_ILLEGAL_INST))
2985 //instCount[opcode]++;
2986
2987                 exec_op[opcode]();                                                              // Execute that opcode...
2988                 regs.clock += CPUCycles[opcode];
2989 #ifdef __DEBUG__
2990 if (dumpDis)
2991         WriteLog(" [PC=%04X, SP=%04X, CC=%s%s.%s%s%s%s%s, A=%02X, X=%02X, Y=%02X]\n",
2992                 regs.pc, 0x0100 + regs.sp,
2993                 (regs.cc & FLAG_N ? "N" : "-"), (regs.cc & FLAG_V ? "V" : "-"),
2994                 (regs.cc & FLAG_B ? "B" : "-"), (regs.cc & FLAG_D ? "D" : "-"),
2995                 (regs.cc & FLAG_I ? "I" : "-"), (regs.cc & FLAG_Z ? "Z" : "-"),
2996                 (regs.cc & FLAG_C ? "C" : "-"), regs.a, regs.x, regs.y);
2997 #endif
2998
2999 #ifdef __DEBUGMON__
3000 if (regs.pc == 0xFCB3)  // WAIT exit point
3001 {
3002         dumpDis = true;
3003 }//*/
3004 /*if (regs.pc == 0xFBEF)        // BELL1 exit point
3005 {
3006         dumpDis = true;
3007 }//*/
3008 /*if (regs.pc == 0xFC22)        // HOME exit point
3009 {
3010         dumpDis = true;
3011 }//*/
3012 if (regs.pc == 0xFDFF)  // COUT exit point
3013 {
3014         dumpDis = true;
3015 }
3016 if (regs.pc == 0xFBD8)
3017 {
3018         WriteLog("\n*** BASCALC set BASL/H = $%04X\n\n", RdMemW(0x0028));
3019 }//*/
3020 #endif
3021
3022 //These should be correct now...
3023                 if (regs.cpuFlags & V65C02_ASSERT_LINE_RESET)
3024                 {
3025 #ifdef __DEBUG__
3026 WriteLog("\n*** RESET ***\n\n");
3027 #endif
3028                         // Not sure about this...
3029                         regs.sp = 0xFF;
3030                         regs.cc = FLAG_B | FLAG_I;                                      // Reset the CC register
3031                         regs.pc = RdMemW(0xFFFC);                                       // And load PC with the RESET vector
3032
3033                         context->cpuFlags &= ~V65C02_ASSERT_LINE_RESET;
3034                         regs.cpuFlags &= ~V65C02_ASSERT_LINE_RESET;
3035                 }
3036                 else if (regs.cpuFlags & V65C02_ASSERT_LINE_NMI)
3037                 {
3038 #ifdef __DEBUG__
3039 WriteLog("\n*** NMI ***\n\n");
3040 #endif
3041                         regs.WrMem(0x0100 + regs.sp--, regs.pc >> 8);   // Save PC and CC
3042                         regs.WrMem(0x0100 + regs.sp--, regs.pc & 0xFF);
3043                         regs.WrMem(0x0100 + regs.sp--, regs.cc);
3044                         regs.cc |= FLAG_I;                                                      // Set I
3045                         regs.cc &= ~FLAG_D;                                                     // & clear D
3046                         regs.pc = RdMemW(0xFFFA);                                       // And do it!
3047
3048                         regs.clock += 7;
3049                         context->cpuFlags &= ~V65C02_ASSERT_LINE_NMI;// Reset the asserted line (NMI)...
3050                         regs.cpuFlags &= ~V65C02_ASSERT_LINE_NMI;       // Reset the asserted line (NMI)...
3051                 }
3052                 else if (regs.cpuFlags & V65C02_ASSERT_LINE_IRQ)
3053                 {
3054                         if (!(regs.cc & FLAG_I))                                        // Process an interrupt (I=0)?
3055                         {
3056 #ifdef __DEBUG__
3057 WriteLog("\n*** IRQ ***\n\n");
3058 #endif
3059                                 regs.WrMem(0x0100 + regs.sp--, regs.pc >> 8);   // Save PC and CC
3060                                 regs.WrMem(0x0100 + regs.sp--, regs.pc & 0xFF);
3061                                 regs.WrMem(0x0100 + regs.sp--, regs.cc);
3062                                 regs.cc |= FLAG_I;                                              // Set I
3063                                 regs.cc &= ~FLAG_D;                                             // & clear D
3064                                 regs.pc = RdMemW(0xFFFE);                               // And do it!
3065
3066                                 regs.clock += 7;
3067                                 context->cpuFlags &= ~V65C02_ASSERT_LINE_IRQ;   // Reset the asserted line (IRQ)...
3068                                 regs.cpuFlags &= ~V65C02_ASSERT_LINE_IRQ;       // Reset the asserted line (IRQ)...
3069                         }
3070                 }
3071         }
3072
3073         // If we went longer than the passed in cycles, make a note of it so we can
3074         // subtract it out from a subsequent run. It's guaranteed to be positive,
3075         // because the condition that exits the main loop above is written such
3076         // that regs.clock has to be larger than endCycles to exit from it.
3077         overflow = regs.clock - endCycles;
3078
3079         myMemcpy(context, &regs, sizeof(V65C02REGS));
3080 }
3081
3082
3083 //
3084 // Get the clock of the currently executing CPU
3085 //
3086 uint64_t GetCurrentV65C02Clock(void)
3087 {
3088         return regs.clock;
3089 }
3090