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