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