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