2 // Virtual 65C02 Emulator v1.0
5 // (c) 2005 Underground Software
7 // JLH = James L. Hammons <jlhamm@acm.org>
10 // --- ---------- ------------------------------------------------------------
11 // JLH 01/04/2006 Added changelog ;-)
12 // JLH 01/18/2009 Fixed EA_ABS_* macros
15 //OK, the wraparound bug exists in both the Apple and Atari versions of Ultima II.
16 //However, the Atari version *does* occassionally pick strength while the Apple
17 //versions do not--which would seem to indicate a bug either in the RNG algorithm,
18 //the 65C02 core, or the Apple hardware. Need to investigate all three!
21 //#define __DEBUGMON__
32 #define CLR_Z (regs.cc &= ~FLAG_Z)
33 #define CLR_ZN (regs.cc &= ~(FLAG_Z | FLAG_N))
34 #define CLR_ZNC (regs.cc &= ~(FLAG_Z | FLAG_N | FLAG_C))
35 #define CLR_V (regs.cc &= ~FLAG_V)
36 #define CLR_N (regs.cc &= ~FLAG_N)
37 #define SET_Z(r) (regs.cc = ((r) == 0 ? regs.cc | FLAG_Z : regs.cc & ~FLAG_Z))
38 #define SET_N(r) (regs.cc = ((r) & 0x80 ? regs.cc | FLAG_N : regs.cc & ~FLAG_N))
40 //Not sure that this code is computing the carry correctly... Investigate! [Seems to be]
41 #define SET_C_ADD(a,b) (regs.cc = ((uint8_t)(b) > (uint8_t)(~(a)) ? regs.cc | FLAG_C : regs.cc & ~FLAG_C))
42 //#define SET_C_SUB(a,b) (regs.cc = ((uint8_t)(b) >= (uint8_t)(a) ? regs.cc | FLAG_C : regs.cc & ~FLAG_C))
43 #define SET_C_CMP(a,b) (regs.cc = ((uint8_t)(b) >= (uint8_t)(a) ? regs.cc | FLAG_C : regs.cc & ~FLAG_C))
44 #define SET_ZN(r) SET_N(r); SET_Z(r)
45 #define SET_ZNC_ADD(a,b,r) SET_N(r); SET_Z(r); SET_C_ADD(a,b)
46 //#define SET_ZNC_SUB(a,b,r) SET_N(r); SET_Z(r); SET_C_SUB(a,b)
47 #define SET_ZNC_CMP(a,b,r) SET_N(r); SET_Z(r); SET_C_CMP(a,b)
49 //Small problem with the EA_ macros: ABS macros don't increment the PC!!! !!! FIX !!!
50 //NB: It's properly handled by everything that uses it, so it works, even if it's klunky
51 //Small problem with fixing it is that you can't do it in a single instruction, i.e.,
52 //you have to read the value THEN you have to increment the PC. Unless there's another
55 #define EA_IMM regs.pc++
56 #define EA_ZP regs.RdMem(regs.pc++)
57 #define EA_ZP_X (regs.RdMem(regs.pc++) + regs.x) & 0xFF
58 #define EA_ZP_Y (regs.RdMem(regs.pc++) + regs.y) & 0xFF
59 #define EA_ABS FetchMemW(regs.pc)
60 #define EA_ABS_X FetchMemW(regs.pc) + regs.x
61 #define EA_ABS_Y FetchMemW(regs.pc) + regs.y
62 #define EA_IND_ZP_X RdMemW((regs.RdMem(regs.pc++) + regs.x) & 0xFF)
63 #define EA_IND_ZP_Y RdMemW(regs.RdMem(regs.pc++)) + regs.y
64 #define EA_IND_ZP RdMemW(regs.RdMem(regs.pc++))
66 #define READ_IMM regs.RdMem(EA_IMM)
67 #define READ_ZP regs.RdMem(EA_ZP)
68 #define READ_ZP_X regs.RdMem(EA_ZP_X)
69 #define READ_ZP_Y regs.RdMem(EA_ZP_Y)
70 #define READ_ABS regs.RdMem(EA_ABS)
71 #define READ_ABS_X regs.RdMem(EA_ABS_X)
72 #define READ_ABS_Y regs.RdMem(EA_ABS_Y)
73 #define READ_IND_ZP_X regs.RdMem(EA_IND_ZP_X)
74 #define READ_IND_ZP_Y regs.RdMem(EA_IND_ZP_Y)
75 #define READ_IND_ZP regs.RdMem(EA_IND_ZP)
77 #define READ_IMM_WB(v) uint16_t addr = EA_IMM; v = regs.RdMem(addr)
78 #define READ_ZP_WB(v) uint16_t addr = EA_ZP; v = regs.RdMem(addr)
79 #define READ_ZP_X_WB(v) uint16_t addr = EA_ZP_X; v = regs.RdMem(addr)
80 #define READ_ABS_WB(v) uint16_t addr = EA_ABS; v = regs.RdMem(addr)
81 #define READ_ABS_X_WB(v) uint16_t addr = EA_ABS_X; v = regs.RdMem(addr)
82 #define READ_ABS_Y_WB(v) uint16_t addr = EA_ABS_Y; v = regs.RdMem(addr)
83 #define READ_IND_ZP_X_WB(v) uint16_t addr = EA_IND_ZP_X; v = regs.RdMem(addr)
84 #define READ_IND_ZP_Y_WB(v) uint16_t addr = EA_IND_ZP_Y; v = regs.RdMem(addr)
85 #define READ_IND_ZP_WB(v) uint16_t addr = EA_IND_ZP; v = regs.RdMem(addr)
87 #define WRITE_BACK(d) regs.WrMem(addr, (d))
89 // Private global variables
91 static V65C02REGS regs;
93 //This is probably incorrect, at least WRT to the $x7 and $xF opcodes... !!! FIX !!!
94 //Also this doesn't take into account the extra cycle it takes when an indirect fetch
95 //(ABS, ABS X/Y, ZP) crosses a page boundary, or extra cycle for BCD add/subtract...
96 #warning "Cycle counts are not accurate--!!! FIX !!!"
97 static uint8_t CPUCycles[256] = {
99 7, 6, 1, 1, 5, 3, 5, 1, 3, 2, 2, 1, 6, 4, 6, 1,
100 2, 5, 5, 1, 5, 4, 6, 1, 2, 4, 2, 1, 6, 4, 6, 1,
101 6, 6, 1, 1, 3, 3, 5, 1, 4, 2, 2, 1, 4, 4, 6, 1,
102 2, 5, 5, 1, 4, 4, 6, 1, 2, 4, 2, 1, 4, 4, 6, 1,
103 6, 6, 1, 1, 1, 3, 5, 1, 3, 2, 2, 1, 3, 4, 6, 1,
104 2, 5, 5, 1, 1, 4, 6, 1, 2, 4, 3, 1, 1, 4, 6, 1,
105 6, 6, 1, 1, 3, 3, 5, 1, 4, 2, 2, 1, 6, 4, 6, 1,
106 2, 5, 5, 1, 4, 4, 6, 1, 2, 4, 4, 1, 6, 4, 6, 1,
107 2, 6, 1, 1, 3, 3, 3, 1, 2, 2, 2, 1, 4, 4, 4, 1,
108 2, 6, 5, 1, 4, 4, 4, 1, 2, 5, 2, 1, 4, 5, 5, 1,
109 2, 6, 2, 1, 3, 3, 3, 1, 2, 2, 2, 1, 4, 4, 4, 1,
110 2, 5, 5, 1, 4, 4, 4, 1, 2, 4, 2, 1, 4, 4, 4, 1,
111 2, 6, 1, 1, 3, 3, 5, 1, 2, 2, 2, 1, 4, 4, 6, 1,
112 2, 5, 5, 1, 1, 4, 6, 1, 2, 4, 3, 1, 1, 4, 6, 1,
113 2, 6, 1, 1, 3, 3, 5, 1, 2, 2, 2, 1, 4, 4, 6, 1,
114 2, 5, 5, 1, 1, 4, 6, 1, 2, 4, 4, 1, 1, 4, 6, 1 };
116 7, 6, 2, 2, 5, 3, 5, 2, 3, 2, 2, 2, 6, 4, 6, 2,
117 2, 5, 5, 2, 5, 4, 6, 2, 2, 4, 2, 2, 6, 4, 6, 2,
118 6, 6, 2, 2, 3, 3, 5, 2, 4, 2, 2, 2, 4, 2, 6, 2,
119 2, 5, 5, 2, 4, 4, 6, 2, 2, 4, 2, 2, 4, 4, 6, 2,
120 6, 6, 2, 2, 3, 3, 5, 2, 3, 2, 2, 2, 3, 4, 6, 2,
121 2, 5, 5, 2, 4, 4, 6, 2, 2, 4, 3, 2, 8, 4, 6, 2,
122 6, 6, 2, 2, 3, 3, 5, 2, 4, 2, 2, 2, 6, 4, 6, 2,
123 2, 5, 5, 2, 4, 4, 6, 2, 2, 4, 4, 2, 6, 4, 6, 2,
124 2, 6, 2, 2, 3, 3, 3, 2, 2, 2, 2, 2, 4, 4, 4, 2,
125 2, 6, 5, 2, 4, 4, 4, 2, 2, 5, 2, 2, 4, 5, 5, 2,
126 2, 6, 2, 2, 3, 3, 3, 2, 2, 2, 2, 2, 4, 4, 4, 2,
127 2, 5, 5, 2, 4, 4, 4, 2, 2, 4, 2, 2, 4, 4, 4, 2,
128 2, 6, 2, 2, 3, 3, 5, 2, 2, 2, 2, 2, 4, 4, 5, 2,
129 2, 5, 5, 2, 4, 4, 6, 2, 2, 4, 3, 2, 4, 4, 6, 2,
130 2, 6, 2, 2, 3, 3, 5, 2, 2, 2, 2, 2, 4, 4, 6, 2,
131 2, 5, 5, 2, 4, 4, 6, 2, 2, 4, 4, 2, 4, 4, 6, 2 };
134 static uint8_t _6502Cycles[256] = {
135 7, 6, 2, 8, 3, 3, 5, 5, 3, 2, 2, 2, 4, 4, 6, 6,
136 2, 5, 2, 8, 4, 4, 6, 6, 2, 4, 2, 7, 4, 4, 6, 7,
137 6, 6, 2, 8, 3, 3, 5, 5, 4, 2, 2, 2, 4, 2, 6, 6,
138 2, 5, 2, 8, 4, 4, 6, 6, 2, 4, 2, 7, 4, 4, 6, 7,
139 6, 6, 2, 8, 3, 3, 5, 5, 3, 2, 2, 2, 3, 4, 6, 6,
140 2, 5, 2, 8, 4, 4, 6, 6, 2, 4, 2, 7, 4, 4, 6, 7,
141 6, 6, 2, 8, 3, 3, 5, 5, 4, 2, 2, 2, 6, 4, 6, 6,
142 2, 5, 2, 8, 4, 4, 6, 6, 2, 4, 2, 7, 4, 4, 6, 7,
143 2, 6, 2, 6, 3, 3, 3, 3, 2, 2, 2, 2, 4, 4, 4, 4,
144 2, 6, 2, 6, 4, 4, 4, 4, 2, 5, 2, 5, 5, 5, 5, 5,
145 2, 6, 2, 6, 3, 3, 3, 3, 2, 2, 2, 2, 4, 4, 4, 4,
146 2, 5, 2, 5, 4, 4, 4, 4, 2, 4, 2, 4, 4, 4, 4, 4,
147 2, 6, 2, 8, 3, 3, 5, 5, 2, 2, 2, 2, 4, 4, 5, 6,
148 2, 5, 2, 8, 4, 4, 6, 6, 2, 4, 2, 7, 4, 4, 6, 7,
149 2, 6, 2, 8, 3, 3, 5, 5, 2, 2, 2, 2, 4, 4, 6, 6,
150 2, 5, 2, 8, 4, 4, 6, 6, 2, 4, 2, 7, 4, 4, 6, 7 };
152 static uint8_t _65C02Cycles[256] = {
153 7, 6, 2, 2, 5, 3, 5, 2, 3, 2, 2, 2, 6, 4, 6, 2,
154 2, 5, 5, 2, 5, 4, 6, 2, 2, 4, 2, 2, 6, 4, 6, 2,
155 6, 6, 2, 2, 3, 3, 5, 2, 4, 2, 2, 2, 4, 2, 6, 2,
156 2, 5, 5, 2, 4, 4, 6, 2, 2, 4, 2, 2, 4, 4, 6, 2,
157 6, 6, 2, 2, 3, 3, 5, 2, 3, 2, 2, 2, 3, 4, 6, 2,
158 2, 5, 5, 2, 4, 4, 6, 2, 2, 4, 3, 2, 8, 4, 6, 2,
159 6, 6, 2, 2, 3, 3, 5, 2, 4, 2, 2, 2, 6, 4, 6, 2,
160 2, 5, 5, 2, 4, 4, 6, 2, 2, 4, 4, 2, 6, 4, 6, 2,
161 2, 6, 2, 2, 3, 3, 3, 2, 2, 2, 2, 2, 4, 4, 4, 2,
162 2, 6, 5, 2, 4, 4, 4, 2, 2, 5, 2, 2, 4, 5, 5, 2,
163 2, 6, 2, 2, 3, 3, 3, 2, 2, 2, 2, 2, 4, 4, 4, 2,
164 2, 5, 5, 2, 4, 4, 4, 2, 2, 4, 2, 2, 4, 4, 4, 2,
165 2, 6, 2, 2, 3, 3, 5, 2, 2, 2, 2, 2, 4, 4, 5, 2,
166 2, 5, 5, 2, 4, 4, 6, 2, 2, 4, 3, 2, 4, 4, 6, 2,
167 2, 6, 2, 2, 3, 3, 5, 2, 2, 2, 2, 2, 4, 4, 6, 2,
168 2, 5, 5, 2, 4, 4, 6, 2, 2, 4, 4, 2, 4, 4, 6, 2 };
172 // +1 if branch taken
173 // +1 if page boundary crossed
174 #define BRANCH_TAKEN { \
177 if ((base ^ regs.pc) & 0xFF00) \
186 if ((oldc ^ regs.pc) & 0xFF00)
193 6502 cycles (includes illegal opcodes):
195 case 0x00: BRK CYC(7) break;
196 case 0x01: INDX ORA CYC(6) break;
197 case 0x02: INV HLT CYC(2) break;
198 case 0x03: INV INDX ASO CYC(8) break;
199 case 0x04: INV ZPG NOP CYC(3) break;
200 case 0x05: ZPG ORA CYC(3) break;
201 case 0x06: ZPG ASL_NMOS CYC(5) break;
202 case 0x07: INV ZPG ASO CYC(5) break;
203 case 0x08: PHP CYC(3) break;
204 case 0x09: IMM ORA CYC(2) break;
205 case 0x0A: ASLA CYC(2) break;
206 case 0x0B: INV IMM ANC CYC(2) break;
207 case 0x0C: INV ABSX NOP CYC(4) break;
208 case 0x0D: ABS ORA CYC(4) break;
209 case 0x0E: ABS ASL_NMOS CYC(6) break;
210 case 0x0F: INV ABS ASO CYC(6) break;
211 case 0x10: REL BPL CYC(2) break;
212 case 0x11: INDY ORA CYC(5) break;
213 case 0x12: INV HLT CYC(2) break;
214 case 0x13: INV INDY ASO CYC(8) break;
215 case 0x14: INV ZPGX NOP CYC(4) break;
216 case 0x15: ZPGX ORA CYC(4) break;
217 case 0x16: ZPGX ASL_NMOS CYC(6) break;
218 case 0x17: INV ZPGX ASO CYC(6) break;
219 case 0x18: CLC CYC(2) break;
220 case 0x19: ABSY ORA CYC(4) break;
221 case 0x1A: INV NOP CYC(2) break;
222 case 0x1B: INV ABSY ASO CYC(7) break;
223 case 0x1C: INV ABSX NOP CYC(4) break;
224 case 0x1D: ABSX ORA CYC(4) break;
225 case 0x1E: ABSX ASL_NMOS CYC(6) break;
226 case 0x1F: INV ABSX ASO CYC(7) break;
227 case 0x20: ABS JSR CYC(6) break;
228 case 0x21: INDX AND CYC(6) break;
229 case 0x22: INV HLT CYC(2) break;
230 case 0x23: INV INDX RLA CYC(8) break;
231 case 0x24: ZPG BIT CYC(3) break;
232 case 0x25: ZPG AND CYC(3) break;
233 case 0x26: ZPG ROL_NMOS CYC(5) break;
234 case 0x27: INV ZPG RLA CYC(5) break;
235 case 0x28: PLP CYC(4) break;
236 case 0x29: IMM AND CYC(2) break;
237 case 0x2A: ROLA CYC(2) break;
238 case 0x2B: INV IMM ANC CYC(2) break;
239 case 0x2C: ABS BIT CYC(4) break;
240 case 0x2D: ABS AND CYC(2) break;
241 case 0x2E: ABS ROL_NMOS CYC(6) break;
242 case 0x2F: INV ABS RLA CYC(6) break;
243 case 0x30: REL BMI CYC(2) break;
244 case 0x31: INDY AND CYC(5) break;
245 case 0x32: INV HLT CYC(2) break;
246 case 0x33: INV INDY RLA CYC(8) break;
247 case 0x34: INV ZPGX NOP CYC(4) break;
248 case 0x35: ZPGX AND CYC(4) break;
249 case 0x36: ZPGX ROL_NMOS CYC(6) break;
250 case 0x37: INV ZPGX RLA CYC(6) break;
251 case 0x38: SEC CYC(2) break;
252 case 0x39: ABSY AND CYC(4) break;
253 case 0x3A: INV NOP CYC(2) break;
254 case 0x3B: INV ABSY RLA CYC(7) break;
255 case 0x3C: INV ABSX NOP CYC(4) break;
256 case 0x3D: ABSX AND CYC(4) break;
257 case 0x3E: ABSX ROL_NMOS CYC(6) break;
258 case 0x3F: INV ABSX RLA CYC(7) break;
259 case 0x40: RTI CYC(6) DoIrqProfiling(uExecutedCycles); break;
260 case 0x41: INDX EOR CYC(6) break;
261 case 0x42: INV HLT CYC(2) break;
262 case 0x43: INV INDX LSE CYC(8) break;
263 case 0x44: INV ZPG NOP CYC(3) break;
264 case 0x45: ZPG EOR CYC(3) break;
265 case 0x46: ZPG LSR_NMOS CYC(5) break;
266 case 0x47: INV ZPG LSE CYC(5) break;
267 case 0x48: PHA CYC(3) break;
268 case 0x49: IMM EOR CYC(2) break;
269 case 0x4A: LSRA CYC(2) break;
270 case 0x4B: INV IMM ALR CYC(2) break;
271 case 0x4C: ABS JMP CYC(3) break;
272 case 0x4D: ABS EOR CYC(4) break;
273 case 0x4E: ABS LSR_NMOS CYC(6) break;
274 case 0x4F: INV ABS LSE CYC(6) break;
275 case 0x50: REL BVC CYC(2) break;
276 case 0x51: INDY EOR CYC(5) break;
277 case 0x52: INV HLT CYC(2) break;
278 case 0x53: INV INDY LSE CYC(8) break;
279 case 0x54: INV ZPGX NOP CYC(4) break;
280 case 0x55: ZPGX EOR CYC(4) break;
281 case 0x56: ZPGX LSR_NMOS CYC(6) break;
282 case 0x57: INV ZPGX LSE CYC(6) break;
283 case 0x58: CLI CYC(2) break;
284 case 0x59: ABSY EOR CYC(4) break;
285 case 0x5A: INV NOP CYC(2) break;
286 case 0x5B: INV ABSY LSE CYC(7) break;
287 case 0x5C: INV ABSX NOP CYC(4) break;
288 case 0x5D: ABSX EOR CYC(4) break;
289 case 0x5E: ABSX LSR_NMOS CYC(6) break;
290 case 0x5F: INV ABSX LSE CYC(7) break;
291 case 0x60: RTS CYC(6) break;
292 case 0x61: INDX ADC_NMOS CYC(6) break;
293 case 0x62: INV HLT CYC(2) break;
294 case 0x63: INV INDX RRA CYC(8) break;
295 case 0x64: INV ZPG NOP CYC(3) break;
296 case 0x65: ZPG ADC_NMOS CYC(3) break;
297 case 0x66: ZPG ROR_NMOS CYC(5) break;
298 case 0x67: INV ZPG RRA CYC(5) break;
299 case 0x68: PLA CYC(4) break;
300 case 0x69: IMM ADC_NMOS CYC(2) break;
301 case 0x6A: RORA CYC(2) break;
302 case 0x6B: INV IMM ARR CYC(2) break;
303 case 0x6C: IABSNMOS JMP CYC(6) break;
304 case 0x6D: ABS ADC_NMOS CYC(4) break;
305 case 0x6E: ABS ROR_NMOS CYC(6) break;
306 case 0x6F: INV ABS RRA CYC(6) break;
307 case 0x70: REL BVS CYC(2) break;
308 case 0x71: INDY ADC_NMOS CYC(5) break;
309 case 0x72: INV HLT CYC(2) break;
310 case 0x73: INV INDY RRA CYC(8) break;
311 case 0x74: INV ZPGX NOP CYC(4) break;
312 case 0x75: ZPGX ADC_NMOS CYC(4) break;
313 case 0x76: ZPGX ROR_NMOS CYC(6) break;
314 case 0x77: INV ZPGX RRA CYC(6) break;
315 case 0x78: SEI CYC(2) break;
316 case 0x79: ABSY ADC_NMOS CYC(4) break;
317 case 0x7A: INV NOP CYC(2) break;
318 case 0x7B: INV ABSY RRA CYC(7) break;
319 case 0x7C: INV ABSX NOP CYC(4) break;
320 case 0x7D: ABSX ADC_NMOS CYC(4) break;
321 case 0x7E: ABSX ROR_NMOS CYC(6) break;
322 case 0x7F: INV ABSX RRA CYC(7) break;
323 case 0x80: INV IMM NOP CYC(2) break;
324 case 0x81: INDX STA CYC(6) break;
325 case 0x82: INV IMM NOP CYC(2) break;
326 case 0x83: INV INDX AXS CYC(6) break;
327 case 0x84: ZPG STY CYC(3) break;
328 case 0x85: ZPG STA CYC(3) break;
329 case 0x86: ZPG STX CYC(3) break;
330 case 0x87: INV ZPG AXS CYC(3) break;
331 case 0x88: DEY CYC(2) break;
332 case 0x89: INV IMM NOP CYC(2) break;
333 case 0x8A: TXA CYC(2) break;
334 case 0x8B: INV IMM XAA CYC(2) break;
335 case 0x8C: ABS STY CYC(4) break;
336 case 0x8D: ABS STA CYC(4) break;
337 case 0x8E: ABS STX CYC(4) break;
338 case 0x8F: INV ABS AXS CYC(4) break;
339 case 0x90: REL BCC CYC(2) break;
340 case 0x91: INDY STA CYC(6) break;
341 case 0x92: INV HLT CYC(2) break;
342 case 0x93: INV INDY AXA CYC(6) break;
343 case 0x94: ZPGX STY CYC(4) break;
344 case 0x95: ZPGX STA CYC(4) break;
345 case 0x96: ZPGY STX CYC(4) break;
346 case 0x97: INV ZPGY AXS CYC(4) break;
347 case 0x98: TYA CYC(2) break;
348 case 0x99: ABSY STA CYC(5) break;
349 case 0x9A: TXS CYC(2) break;
350 case 0x9B: INV ABSY TAS CYC(5) break;
351 case 0x9C: INV ABSX SAY CYC(5) break;
352 case 0x9D: ABSX STA CYC(5) break;
353 case 0x9E: INV ABSY XAS CYC(5) break;
354 case 0x9F: INV ABSY AXA CYC(5) break;
355 case 0xA0: IMM LDY CYC(2) break;
356 case 0xA1: INDX LDA CYC(6) break;
357 case 0xA2: IMM LDX CYC(2) break;
358 case 0xA3: INV INDX LAX CYC(6) break;
359 case 0xA4: ZPG LDY CYC(3) break;
360 case 0xA5: ZPG LDA CYC(3) break;
361 case 0xA6: ZPG LDX CYC(3) break;
362 case 0xA7: INV ZPG LAX CYC(3) break;
363 case 0xA8: TAY CYC(2) break;
364 case 0xA9: IMM LDA CYC(2) break;
365 case 0xAA: TAX CYC(2) break;
366 case 0xAB: INV IMM OAL CYC(2) break;
367 case 0xAC: ABS LDY CYC(4) break;
368 case 0xAD: ABS LDA CYC(4) break;
369 case 0xAE: ABS LDX CYC(4) break;
370 case 0xAF: INV ABS LAX CYC(4) break;
371 case 0xB0: REL BCS CYC(2) break;
372 case 0xB1: INDY LDA CYC(5) break;
373 case 0xB2: INV HLT CYC(2) break;
374 case 0xB3: INV INDY LAX CYC(5) break;
375 case 0xB4: ZPGX LDY CYC(4) break;
376 case 0xB5: ZPGX LDA CYC(4) break;
377 case 0xB6: ZPGY LDX CYC(4) break;
378 case 0xB7: INV ZPGY LAX CYC(4) break;
379 case 0xB8: CLV CYC(2) break;
380 case 0xB9: ABSY LDA CYC(4) break;
381 case 0xBA: TSX CYC(2) break;
382 case 0xBB: INV ABSY LAS CYC(4) break;
383 case 0xBC: ABSX LDY CYC(4) break;
384 case 0xBD: ABSX LDA CYC(4) break;
385 case 0xBE: ABSY LDX CYC(4) break;
386 case 0xBF: INV ABSY LAX CYC(4) break;
387 case 0xC0: IMM CPY CYC(2) break;
388 case 0xC1: INDX CMP CYC(6) break;
389 case 0xC2: INV IMM NOP CYC(2) break;
390 case 0xC3: INV INDX DCM CYC(8) break;
391 case 0xC4: ZPG CPY CYC(3) break;
392 case 0xC5: ZPG CMP CYC(3) break;
393 case 0xC6: ZPG DEC_NMOS CYC(5) break;
394 case 0xC7: INV ZPG DCM CYC(5) break;
395 case 0xC8: INY CYC(2) break;
396 case 0xC9: IMM CMP CYC(2) break;
397 case 0xCA: DEX CYC(2) break;
398 case 0xCB: INV IMM SAX CYC(2) break;
399 case 0xCC: ABS CPY CYC(4) break;
400 case 0xCD: ABS CMP CYC(4) break;
401 case 0xCE: ABS DEC_NMOS CYC(5) break;
402 case 0xCF: INV ABS DCM CYC(6) break;
403 case 0xD0: REL BNE CYC(2) break;
404 case 0xD1: INDY CMP CYC(5) break;
405 case 0xD2: INV HLT CYC(2) break;
406 case 0xD3: INV INDY DCM CYC(8) break;
407 case 0xD4: INV ZPGX NOP CYC(4) break;
408 case 0xD5: ZPGX CMP CYC(4) break;
409 case 0xD6: ZPGX DEC_NMOS CYC(6) break;
410 case 0xD7: INV ZPGX DCM CYC(6) break;
411 case 0xD8: CLD CYC(2) break;
412 case 0xD9: ABSY CMP CYC(4) break;
413 case 0xDA: INV NOP CYC(2) break;
414 case 0xDB: INV ABSY DCM CYC(7) break;
415 case 0xDC: INV ABSX NOP CYC(4) break;
416 case 0xDD: ABSX CMP CYC(4) break;
417 case 0xDE: ABSX DEC_NMOS CYC(6) break;
418 case 0xDF: INV ABSX DCM CYC(7) break;
419 case 0xE0: IMM CPX CYC(2) break;
420 case 0xE1: INDX SBC_NMOS CYC(6) break;
421 case 0xE2: INV IMM NOP CYC(2) break;
422 case 0xE3: INV INDX INS CYC(8) break;
423 case 0xE4: ZPG CPX CYC(3) break;
424 case 0xE5: ZPG SBC_NMOS CYC(3) break;
425 case 0xE6: ZPG INC_NMOS CYC(5) break;
426 case 0xE7: INV ZPG INS CYC(5) break;
427 case 0xE8: INX CYC(2) break;
428 case 0xE9: IMM SBC_NMOS CYC(2) break;
429 case 0xEA: NOP CYC(2) break;
430 case 0xEB: INV IMM SBC_NMOS CYC(2) break;
431 case 0xEC: ABS CPX CYC(4) break;
432 case 0xED: ABS SBC_NMOS CYC(4) break;
433 case 0xEE: ABS INC_NMOS CYC(6) break;
434 case 0xEF: INV ABS INS CYC(6) break;
435 case 0xF0: REL BEQ CYC(2) break;
436 case 0xF1: INDY SBC_NMOS CYC(5) break;
437 case 0xF2: INV HLT CYC(2) break;
438 case 0xF3: INV INDY INS CYC(8) break;
439 case 0xF4: INV ZPGX NOP CYC(4) break;
440 case 0xF5: ZPGX SBC_NMOS CYC(4) break;
441 case 0xF6: ZPGX INC_NMOS CYC(6) break;
442 case 0xF7: INV ZPGX INS CYC(6) break;
443 case 0xF8: SED CYC(2) break;
444 case 0xF9: ABSY SBC_NMOS CYC(4) break;
445 case 0xFA: INV NOP CYC(2) break;
446 case 0xFB: INV ABSY INS CYC(7) break;
447 case 0xFC: INV ABSX NOP CYC(4) break;
448 case 0xFD: ABSX SBC_NMOS CYC(4) break;
449 case 0xFE: ABSX INC_NMOS CYC(6) break;
450 case 0xFF: INV ABSX INS CYC(7) break;
453 65C02 opcodes: (all illegal are NOP, but have cycle counts)
455 case 0x00: BRK CYC(7) break;
456 case 0x01: INDX ORA CYC(6) break;
457 case 0x02: INV IMM NOP CYC(2) break;
458 case 0x03: INV NOP CYC(2) break;
459 case 0x04: ZPG TSB CYC(5) break;
460 case 0x05: ZPG ORA CYC(3) break;
461 case 0x06: ZPG ASL_CMOS CYC(5) break;
462 case 0x07: INV NOP CYC(2) break;
463 case 0x08: PHP CYC(3) break;
464 case 0x09: IMM ORA CYC(2) break;
465 case 0x0A: ASLA CYC(2) break;
466 case 0x0B: INV NOP CYC(2) break;
467 case 0x0C: ABS TSB CYC(6) break;
468 case 0x0D: ABS ORA CYC(4) break;
469 case 0x0E: ABS ASL_CMOS CYC(6) break;
470 case 0x0F: INV NOP CYC(2) break;
471 case 0x10: REL BPL CYC(2) break;
472 case 0x11: INDY ORA CYC(5) break;
473 case 0x12: IZPG ORA CYC(5) break;
474 case 0x13: INV NOP CYC(2) break;
475 case 0x14: ZPG TRB CYC(5) break;
476 case 0x15: ZPGX ORA CYC(4) break;
477 case 0x16: ZPGX ASL_CMOS CYC(6) break;
478 case 0x17: INV NOP CYC(2) break;
479 case 0x18: CLC CYC(2) break;
480 case 0x19: ABSY ORA CYC(4) break;
481 case 0x1A: INA CYC(2) break;
482 case 0x1B: INV NOP CYC(2) break;
483 case 0x1C: ABS TRB CYC(6) break;
484 case 0x1D: ABSX ORA CYC(4) break;
485 case 0x1E: ABSX ASL_CMOS CYC(6) break;
486 case 0x1F: INV NOP CYC(2) break;
487 case 0x20: ABS JSR CYC(6) break;
488 case 0x21: INDX AND CYC(6) break;
489 case 0x22: INV IMM NOP CYC(2) break;
490 case 0x23: INV NOP CYC(2) break;
491 case 0x24: ZPG BIT CYC(3) break;
492 case 0x25: ZPG AND CYC(3) break;
493 case 0x26: ZPG ROL_CMOS CYC(5) break;
494 case 0x27: INV NOP CYC(2) break;
495 case 0x28: PLP CYC(4) break;
496 case 0x29: IMM AND CYC(2) break;
497 case 0x2A: ROLA CYC(2) break;
498 case 0x2B: INV NOP CYC(2) break;
499 case 0x2C: ABS BIT CYC(4) break;
500 case 0x2D: ABS AND CYC(2) break;
501 case 0x2E: ABS ROL_CMOS CYC(6) break;
502 case 0x2F: INV NOP CYC(2) break;
503 case 0x30: REL BMI CYC(2) break;
504 case 0x31: INDY AND CYC(5) break;
505 case 0x32: IZPG AND CYC(5) break;
506 case 0x33: INV NOP CYC(2) break;
507 case 0x34: ZPGX BIT CYC(4) break;
508 case 0x35: ZPGX AND CYC(4) break;
509 case 0x36: ZPGX ROL_CMOS CYC(6) break;
510 case 0x37: INV NOP CYC(2) break;
511 case 0x38: SEC CYC(2) break;
512 case 0x39: ABSY AND CYC(4) break;
513 case 0x3A: DEA CYC(2) break;
514 case 0x3B: INV NOP CYC(2) break;
515 case 0x3C: ABSX BIT CYC(4) break;
516 case 0x3D: ABSX AND CYC(4) break;
517 case 0x3E: ABSX ROL_CMOS CYC(6) break;
518 case 0x3F: INV NOP CYC(2) break;
519 case 0x40: RTI CYC(6) DoIrqProfiling(uExecutedCycles); break;
520 case 0x41: INDX EOR CYC(6) break;
521 case 0x42: INV IMM NOP CYC(2) break;
522 case 0x43: INV NOP CYC(2) break;
523 case 0x44: INV ZPG NOP CYC(3) break;
524 case 0x45: ZPG EOR CYC(3) break;
525 case 0x46: ZPG LSR_CMOS CYC(5) break;
526 case 0x47: INV NOP CYC(2) break;
527 case 0x48: PHA CYC(3) break;
528 case 0x49: IMM EOR CYC(2) break;
529 case 0x4A: LSRA CYC(2) break;
530 case 0x4B: INV NOP CYC(2) break;
531 case 0x4C: ABS JMP CYC(3) break;
532 case 0x4D: ABS EOR CYC(4) break;
533 case 0x4E: ABS LSR_CMOS CYC(6) break;
534 case 0x4F: INV NOP CYC(2) break;
535 case 0x50: REL BVC CYC(2) break;
536 case 0x51: INDY EOR CYC(5) break;
537 case 0x52: IZPG EOR CYC(5) break;
538 case 0x53: INV NOP CYC(2) break;
539 case 0x54: INV ZPGX NOP CYC(4) break;
540 case 0x55: ZPGX EOR CYC(4) break;
541 case 0x56: ZPGX LSR_CMOS CYC(6) break;
542 case 0x57: INV NOP CYC(2) break;
543 case 0x58: CLI CYC(2) break;
544 case 0x59: ABSY EOR CYC(4) break;
545 case 0x5A: PHY CYC(3) break;
546 case 0x5B: INV NOP CYC(2) break;
547 case 0x5C: INV ABSX NOP CYC(8) break;
548 case 0x5D: ABSX EOR CYC(4) break;
549 case 0x5E: ABSX LSR_CMOS CYC(6) break;
550 case 0x5F: INV NOP CYC(2) break;
551 case 0x60: RTS CYC(6) break;
552 case 0x61: INDX ADC_CMOS CYC(6) break;
553 case 0x62: INV IMM NOP CYC(2) break;
554 case 0x63: INV NOP CYC(2) break;
555 case 0x64: ZPG STZ CYC(3) break;
556 case 0x65: ZPG ADC_CMOS CYC(3) break;
557 case 0x66: ZPG ROR_CMOS CYC(5) break;
558 case 0x67: INV NOP CYC(2) break;
559 case 0x68: PLA CYC(4) break;
560 case 0x69: IMM ADC_CMOS CYC(2) break;
561 case 0x6A: RORA CYC(2) break;
562 case 0x6B: INV NOP CYC(2) break;
563 case 0x6C: IABSCMOS JMP CYC(6) break;
564 case 0x6D: ABS ADC_CMOS CYC(4) break;
565 case 0x6E: ABS ROR_CMOS CYC(6) break;
566 case 0x6F: INV NOP CYC(2) break;
567 case 0x70: REL BVS CYC(2) break;
568 case 0x71: INDY ADC_CMOS CYC(5) break;
569 case 0x72: IZPG ADC_CMOS CYC(5) break;
570 case 0x73: INV NOP CYC(2) break;
571 case 0x74: ZPGX STZ CYC(4) break;
572 case 0x75: ZPGX ADC_CMOS CYC(4) break;
573 case 0x76: ZPGX ROR_CMOS CYC(6) break;
574 case 0x77: INV NOP CYC(2) break;
575 case 0x78: SEI CYC(2) break;
576 case 0x79: ABSY ADC_CMOS CYC(4) break;
577 case 0x7A: PLY CYC(4) break;
578 case 0x7B: INV NOP CYC(2) break;
579 case 0x7C: IABSX JMP CYC(6) break;
580 case 0x7D: ABSX ADC_CMOS CYC(4) break;
581 case 0x7E: ABSX ROR_CMOS CYC(6) break;
582 case 0x7F: INV NOP CYC(2) break;
583 case 0x80: REL BRA CYC(2) break;
584 case 0x81: INDX STA CYC(6) break;
585 case 0x82: INV IMM NOP CYC(2) break;
586 case 0x83: INV NOP CYC(2) break;
587 case 0x84: ZPG STY CYC(3) break;
588 case 0x85: ZPG STA CYC(3) break;
589 case 0x86: ZPG STX CYC(3) break;
590 case 0x87: INV NOP CYC(2) break;
591 case 0x88: DEY CYC(2) break;
592 case 0x89: IMM BITI CYC(2) break;
593 case 0x8A: TXA CYC(2) break;
594 case 0x8B: INV NOP CYC(2) break;
595 case 0x8C: ABS STY CYC(4) break;
596 case 0x8D: ABS STA CYC(4) break;
597 case 0x8E: ABS STX CYC(4) break;
598 case 0x8F: INV NOP CYC(2) break;
599 case 0x90: REL BCC CYC(2) break;
600 case 0x91: INDY STA CYC(6) break;
601 case 0x92: IZPG STA CYC(5) break;
602 case 0x93: INV NOP CYC(2) break;
603 case 0x94: ZPGX STY CYC(4) break;
604 case 0x95: ZPGX STA CYC(4) break;
605 case 0x96: ZPGY STX CYC(4) break;
606 case 0x97: INV NOP CYC(2) break;
607 case 0x98: TYA CYC(2) break;
608 case 0x99: ABSY STA CYC(5) break;
609 case 0x9A: TXS CYC(2) break;
610 case 0x9B: INV NOP CYC(2) break;
611 case 0x9C: ABS STZ CYC(4) break;
612 case 0x9D: ABSX STA CYC(5) break;
613 case 0x9E: ABSX STZ CYC(5) break;
614 case 0x9F: INV NOP CYC(2) break;
615 case 0xA0: IMM LDY CYC(2) break;
616 case 0xA1: INDX LDA CYC(6) break;
617 case 0xA2: IMM LDX CYC(2) break;
618 case 0xA3: INV NOP CYC(2) break;
619 case 0xA4: ZPG LDY CYC(3) break;
620 case 0xA5: ZPG LDA CYC(3) break;
621 case 0xA6: ZPG LDX CYC(3) break;
622 case 0xA7: INV NOP CYC(2) break;
623 case 0xA8: TAY CYC(2) break;
624 case 0xA9: IMM LDA CYC(2) break;
625 case 0xAA: TAX CYC(2) break;
626 case 0xAB: INV NOP CYC(2) break;
627 case 0xAC: ABS LDY CYC(4) break;
628 case 0xAD: ABS LDA CYC(4) break;
629 case 0xAE: ABS LDX CYC(4) break;
630 case 0xAF: INV NOP CYC(2) break;
631 case 0xB0: REL BCS CYC(2) break;
632 case 0xB1: INDY LDA CYC(5) break;
633 case 0xB2: IZPG LDA CYC(5) break;
634 case 0xB3: INV NOP CYC(2) break;
635 case 0xB4: ZPGX LDY CYC(4) break;
636 case 0xB5: ZPGX LDA CYC(4) break;
637 case 0xB6: ZPGY LDX CYC(4) break;
638 case 0xB7: INV NOP CYC(2) break;
639 case 0xB8: CLV CYC(2) break;
640 case 0xB9: ABSY LDA CYC(4) break;
641 case 0xBA: TSX CYC(2) break;
642 case 0xBB: INV NOP CYC(2) break;
643 case 0xBC: ABSX LDY CYC(4) break;
644 case 0xBD: ABSX LDA CYC(4) break;
645 case 0xBE: ABSY LDX CYC(4) break;
646 case 0xBF: INV NOP CYC(2) break;
647 case 0xC0: IMM CPY CYC(2) break;
648 case 0xC1: INDX CMP CYC(6) break;
649 case 0xC2: INV IMM NOP CYC(2) break;
650 case 0xC3: INV NOP CYC(2) break;
651 case 0xC4: ZPG CPY CYC(3) break;
652 case 0xC5: ZPG CMP CYC(3) break;
653 case 0xC6: ZPG DEC_CMOS CYC(5) break;
654 case 0xC7: INV NOP CYC(2) break;
655 case 0xC8: INY CYC(2) break;
656 case 0xC9: IMM CMP CYC(2) break;
657 case 0xCA: DEX CYC(2) break;
658 case 0xCB: INV NOP CYC(2) break;
659 case 0xCC: ABS CPY CYC(4) break;
660 case 0xCD: ABS CMP CYC(4) break;
661 case 0xCE: ABS DEC_CMOS CYC(5) break;
662 case 0xCF: INV NOP CYC(2) break;
663 case 0xD0: REL BNE CYC(2) break;
664 case 0xD1: INDY CMP CYC(5) break;
665 case 0xD2: IZPG CMP CYC(5) break;
666 case 0xD3: INV NOP CYC(2) break;
667 case 0xD4: INV ZPGX NOP CYC(4) break;
668 case 0xD5: ZPGX CMP CYC(4) break;
669 case 0xD6: ZPGX DEC_CMOS CYC(6) break;
670 case 0xD7: INV NOP CYC(2) break;
671 case 0xD8: CLD CYC(2) break;
672 case 0xD9: ABSY CMP CYC(4) break;
673 case 0xDA: PHX CYC(3) break;
674 case 0xDB: INV NOP CYC(2) break;
675 case 0xDC: INV ABSX NOP CYC(4) break;
676 case 0xDD: ABSX CMP CYC(4) break;
677 case 0xDE: ABSX DEC_CMOS CYC(6) break;
678 case 0xDF: INV NOP CYC(2) break;
679 case 0xE0: IMM CPX CYC(2) break;
680 case 0xE1: INDX SBC_CMOS CYC(6) break;
681 case 0xE2: INV IMM NOP CYC(2) break;
682 case 0xE3: INV NOP CYC(2) break;
683 case 0xE4: ZPG CPX CYC(3) break;
684 case 0xE5: ZPG SBC_CMOS CYC(3) break;
685 case 0xE6: ZPG INC_CMOS CYC(5) break;
686 case 0xE7: INV NOP CYC(2) break;
687 case 0xE8: INX CYC(2) break;
688 case 0xE9: IMM SBC_CMOS CYC(2) break;
689 case 0xEA: NOP CYC(2) break;
690 case 0xEB: INV NOP CYC(2) break;
691 case 0xEC: ABS CPX CYC(4) break;
692 case 0xED: ABS SBC_CMOS CYC(4) break;
693 case 0xEE: ABS INC_CMOS CYC(6) break;
694 case 0xEF: INV NOP CYC(2) break;
695 case 0xF0: REL BEQ CYC(2) break;
696 case 0xF1: INDY SBC_CMOS CYC(5) break;
697 case 0xF2: IZPG SBC_CMOS CYC(5) break;
698 case 0xF3: INV NOP CYC(2) break;
699 case 0xF4: INV ZPGX NOP CYC(4) break;
700 case 0xF5: ZPGX SBC_CMOS CYC(4) break;
701 case 0xF6: ZPGX INC_CMOS CYC(6) break;
702 case 0xF7: INV NOP CYC(2) break;
703 case 0xF8: SED CYC(2) break;
704 case 0xF9: ABSY SBC_CMOS CYC(4) break;
705 case 0xFA: PLX CYC(4) break;
706 case 0xFB: INV NOP CYC(2) break;
707 case 0xFC: INV ABSX NOP CYC(4) break;
708 case 0xFD: ABSX SBC_CMOS CYC(4) break;
709 case 0xFE: ABSX INC_CMOS CYC(6) break;
710 case 0xFF: INV NOP CYC(2) break;
713 // Private function prototypes
715 static uint16_t RdMemW(uint16_t);
716 static uint16_t FetchMemW(uint16_t addr);
719 // Read a uint16_t out of 65C02 memory (big endian format)
721 static inline uint16_t RdMemW(uint16_t address)
723 return (uint16_t)(regs.RdMem(address + 1) << 8) | regs.RdMem(address + 0);
727 // Read a uint16_t out of 65C02 memory (big endian format) and increment PC
729 static inline uint16_t FetchMemW(uint16_t address)
732 return (uint16_t)(regs.RdMem(address + 1) << 8) | regs.RdMem(address + 0);
737 // 65C02 OPCODE IMPLEMENTATION
739 // NOTE: Lots of macros are used here to save a LOT of typing. Also
740 // helps speed the debugging process. :-) Because of this, combining
741 // certain lines may look like a good idea but would end in disaster.
742 // You have been warned! ;-)
746 Mnemonic Addressing mode Form Opcode Size Timing
748 ADC Immediate ADC #Oper 69 2 2
749 Zero Page ADC Zpg 65 2 3
750 Zero Page,X ADC Zpg,X 75 2 4
751 Absolute ADC Abs 6D 3 4
752 Absolute,X ADC Abs,X 7D 3 4
753 Absolute,Y ADC Abs,Y 79 3 4
754 (Zero Page,X) ADC (Zpg,X) 61 2 6
755 (Zero Page),Y ADC (Zpg),Y 71 2 5
756 (Zero Page) ADC (Zpg) 72 2 5
761 //This is non-optimal, but it works--optimize later. :-)
762 #define OP_ADC_HANDLER(m) \
763 uint16_t sum = (uint16_t)regs.a + (m) + (uint16_t)(regs.cc & FLAG_C); \
765 if (regs.cc & FLAG_D) \
767 if ((sum & 0x0F) > 0x09) \
770 if ((sum & 0xF0) > 0x90) \
774 regs.cc = (regs.cc & ~FLAG_C) | (sum >> 8); \
775 regs.cc = (~(regs.a ^ (m)) & (regs.a ^ sum) & 0x80 ? regs.cc | FLAG_V : regs.cc & ~FLAG_V); \
776 regs.a = sum & 0xFF; \
779 //OLD V detection: regs.cc = ((regs.a ^ (m) ^ sum ^ (regs.cc << 7)) & 0x80 ? regs.cc | FLAG_V : regs.cc & ~FLAG_V);
781 static void Op69(void) // ADC #
783 uint16_t m = READ_IMM;
787 static void Op65(void) // ADC ZP
789 uint16_t m = READ_ZP;
793 static void Op75(void) // ADC ZP, X
795 uint16_t m = READ_ZP_X;
799 static void Op6D(void) // ADC ABS
801 uint16_t m = READ_ABS;
805 static void Op7D(void) // ADC ABS, X
807 uint16_t m = READ_ABS_X;
811 static void Op79(void) // ADC ABS, Y
813 uint16_t m = READ_ABS_Y;
817 static void Op61(void) // ADC (ZP, X)
819 uint16_t m = READ_IND_ZP_X;
823 static void Op71(void) // ADC (ZP), Y
825 uint16_t m = READ_IND_ZP_Y;
829 static void Op72(void) // ADC (ZP)
831 uint16_t m = READ_IND_ZP;
836 AND Immediate AND #Oper 29 2 2
837 Zero Page AND Zpg 25 2 3
838 Zero Page,X AND Zpg,X 35 2 4
839 Absolute AND Abs 2D 3 4
840 Absolute,X AND Abs,X 3D 3 4
841 Absolute,Y AND Abs,Y 39 3 4
842 (Zero Page,X) AND (Zpg,X) 21 2 6
843 (Zero Page),Y AND (Zpg),Y 31 2 5
844 (Zero Page) AND (Zpg) 32 2 5
849 #define OP_AND_HANDLER(m) \
853 static void Op29(void) // AND #
855 uint8_t m = READ_IMM;
859 static void Op25(void) // AND ZP
865 static void Op35(void) // AND ZP, X
867 uint8_t m = READ_ZP_X;
871 static void Op2D(void) // AND ABS
873 uint8_t m = READ_ABS;
877 static void Op3D(void) // AND ABS, X
879 uint8_t m = READ_ABS_X;
883 static void Op39(void) // AND ABS, Y
885 uint8_t m = READ_ABS_Y;
889 static void Op21(void) // AND (ZP, X)
891 uint8_t m = READ_IND_ZP_X;
895 static void Op31(void) // AND (ZP), Y
897 uint8_t m = READ_IND_ZP_Y;
901 static void Op32(void) // AND (ZP)
903 uint8_t m = READ_IND_ZP;
908 ASL Accumulator ASL A 0A 1 2
909 Zero Page ASL Zpg 06 2 5
910 Zero Page,X ASL Zpg,X 16 2 6
911 Absolute ASL Abs 0E 3 6
912 Absolute,X ASL Abs,X 1E 3 7
915 /*static void Op78(void) // LSL ABS
917 uint8_t tmp; uint16_t addr;
919 tmp = regs.RdMem(addr);
920 (tmp&0x80 ? regs.cc |= 0x01 : regs.cc &= 0xFE); // Shift hi bit into Carry
922 regs.WrMem(addr, tmp);
923 (tmp == 0 ? regs.cc |= 0x04 : regs.cc &= 0xFB); // Adjust Zero flag
924 (tmp&0x80 ? regs.cc |= 0x08 : regs.cc &= 0xF7); // Adjust Negative flag
929 #define OP_ASL_HANDLER(m) \
930 regs.cc = ((m) & 0x80 ? regs.cc | FLAG_C : regs.cc & ~FLAG_C); \
934 static void Op0A(void) // ASL A
936 OP_ASL_HANDLER(regs.a);
939 static void Op06(void) // ASL ZP
947 static void Op16(void) // ASL ZP, X
955 static void Op0E(void) // ASL ABS
963 static void Op1E(void) // ASL ABS, X
972 BBR0 Relative BBR0 Oper 0F 2 2
973 BBR1 Relative BBR1 Oper 1F 2 2
974 BBR2 Relative BBR2 Oper 2F 2 2
975 BBR3 Relative BBR3 Oper 3F 2 2
976 BBR4 Relative BBR4 Oper 4F 2 2
977 BBR5 Relative BBR5 Oper 5F 2 2
978 BBR6 Relative BBR6 Oper 6F 2 2
979 BBR7 Relative BBR7 Oper 7F 2 2
980 BBS0 Relative BBS0 Oper 8F 2 2
981 BBS1 Relative BBS1 Oper 9F 2 2
982 BBS2 Relative BBS2 Oper AF 2 2
983 BBS3 Relative BBS3 Oper BF 2 2
984 BBS4 Relative BBS4 Oper CF 2 2
985 BBS5 Relative BBS5 Oper DF 2 2
986 BBS6 Relative BBS6 Oper EF 2 2
987 BBS7 Relative BBS7 Oper FF 2 2
992 static void Op0F(void) // BBR0
994 int16_t m = (int16_t)(int8_t)READ_IMM;
996 if (!(regs.a & 0x01))
1000 static void Op1F(void) // BBR1
1002 int16_t m = (int16_t)(int8_t)READ_IMM;
1004 if (!(regs.a & 0x02))
1008 static void Op2F(void) // BBR2
1010 int16_t m = (int16_t)(int8_t)READ_IMM;
1012 if (!(regs.a & 0x04))
1016 static void Op3F(void) // BBR3
1018 int16_t m = (int16_t)(int8_t)READ_IMM;
1020 if (!(regs.a & 0x08))
1024 static void Op4F(void) // BBR4
1026 int16_t m = (int16_t)(int8_t)READ_IMM;
1028 if (!(regs.a & 0x10))
1032 static void Op5F(void) // BBR5
1034 int16_t m = (int16_t)(int8_t)READ_IMM;
1036 if (!(regs.a & 0x20))
1040 static void Op6F(void) // BBR6
1042 int16_t m = (int16_t)(int8_t)READ_IMM;
1044 if (!(regs.a & 0x40))
1048 static void Op7F(void) // BBR7
1050 int16_t m = (int16_t)(int8_t)READ_IMM;
1052 if (!(regs.a & 0x80))
1056 static void Op8F(void) // BBS0
1058 int16_t m = (int16_t)(int8_t)READ_IMM;
1064 static void Op9F(void) // BBS1
1066 int16_t m = (int16_t)(int8_t)READ_IMM;
1072 static void OpAF(void) // BBS2
1074 int16_t m = (int16_t)(int8_t)READ_IMM;
1080 static void OpBF(void) // BBS3
1082 int16_t m = (int16_t)(int8_t)READ_IMM;
1088 static void OpCF(void) // BBS4
1090 int16_t m = (int16_t)(int8_t)READ_IMM;
1096 static void OpDF(void) // BBS5
1098 int16_t m = (int16_t)(int8_t)READ_IMM;
1104 static void OpEF(void) // BBS6
1106 int16_t m = (int16_t)(int8_t)READ_IMM;
1112 static void OpFF(void) // BBS7
1114 int16_t m = (int16_t)(int8_t)READ_IMM;
1121 BCC Relative BCC Oper 90 2 2
1122 BCS Relative BCS Oper B0 2 2
1123 BEQ Relative BEQ Oper F0 2 2
1126 // Branch taken adds a cycle, crossing page adds one more
1128 #define HANDLE_BRANCH_TAKEN(m) \
1130 uint16_t oldpc = regs.pc; \
1133 if ((oldpc ^ regs.pc) & 0xFF00) \
1139 static void Op90(void) // BCC
1141 int16_t m = (int16_t)(int8_t)READ_IMM;
1143 if (!(regs.cc & FLAG_C))
1144 HANDLE_BRANCH_TAKEN(m)
1147 static void OpB0(void) // BCS
1149 int16_t m = (int16_t)(int8_t)READ_IMM;
1151 if (regs.cc & FLAG_C)
1152 HANDLE_BRANCH_TAKEN(m)
1155 static void OpF0(void) // BEQ
1157 int16_t m = (int16_t)(int8_t)READ_IMM;
1159 if (regs.cc & FLAG_Z)
1160 HANDLE_BRANCH_TAKEN(m)
1164 BIT Immediate BIT #Oper 89 2 2
1165 Zero Page BIT Zpg 24 2 3
1166 Zero Page,X BIT Zpg,X 34 2 4
1167 Absolute BIT Abs 2C 3 4
1168 Absolute,X BIT Abs,X 3C 3 4
1173 /* 1. The BIT instruction copies bit 6 to the V flag, and bit 7 to the N flag (except in immediate
1174 addressing mode where V & N are untouched.) The accumulator and the operand are ANDed and the
1175 Z flag is set appropriately. */
1177 #define OP_BIT_HANDLER(m) \
1178 int8_t result = regs.a & (m); \
1179 regs.cc &= ~(FLAG_N | FLAG_V); \
1180 regs.cc |= ((m) & 0xC0); \
1183 static void Op89(void) // BIT #
1185 int8_t m = READ_IMM;
1186 int8_t result = regs.a & m;
1190 static void Op24(void) // BIT ZP
1196 static void Op34(void) // BIT ZP, X
1198 uint8_t m = READ_ZP_X;
1202 static void Op2C(void) // BIT ABS
1204 uint8_t m = READ_ABS;
1208 static void Op3C(void) // BIT ABS, X
1210 uint8_t m = READ_ABS_X;
1215 BMI Relative BMI Oper 30 2 2
1216 BNE Relative BNE Oper D0 2 2
1217 BPL Relative BPL Oper 10 2 2
1218 BRA Relative BRA Oper 80 2 3
1221 // More branch opcodes
1223 static void Op30(void) // BMI
1225 int16_t m = (int16_t)(int8_t)READ_IMM;
1227 if (regs.cc & FLAG_N)
1228 HANDLE_BRANCH_TAKEN(m)
1232 static void OpD0(void) // BNE
1234 int16_t m = (int16_t)(int8_t)READ_IMM;
1236 if (!(regs.cc & FLAG_Z))
1237 HANDLE_BRANCH_TAKEN(m)
1241 static void Op10(void) // BPL
1243 int16_t m = (int16_t)(int8_t)READ_IMM;
1245 if (!(regs.cc & FLAG_N))
1246 HANDLE_BRANCH_TAKEN(m)
1250 static void Op80(void) // BRA
1252 int16_t m = (int16_t)(int8_t)READ_IMM;
1253 HANDLE_BRANCH_TAKEN(m)
1258 BRK Implied BRK 00 1 7
1261 static void Op00(void) // BRK
1263 regs.cc |= FLAG_B; // Set B
1264 regs.pc++; // RTI comes back to the instruction one byte after the BRK
1265 regs.WrMem(0x0100 + regs.sp--, regs.pc >> 8); // Save PC and CC
1266 regs.WrMem(0x0100 + regs.sp--, regs.pc & 0xFF);
1267 regs.WrMem(0x0100 + regs.sp--, regs.cc);
1268 regs.cc |= FLAG_I; // Set I
1269 regs.cc &= ~FLAG_D; // & clear D
1270 regs.pc = RdMemW(0xFFFE); // Grab the IRQ vector & go...
1274 BVC Relative BVC Oper 50 2 2
1275 BVS Relative BVS Oper 70 2 2
1278 // Even more branch opcodes
1280 static void Op50(void) // BVC
1282 int16_t m = (int16_t)(int8_t)READ_IMM;
1284 if (!(regs.cc & FLAG_V))
1285 HANDLE_BRANCH_TAKEN(m)
1289 static void Op70(void) // BVS
1291 int16_t m = (int16_t)(int8_t)READ_IMM;
1293 if (regs.cc & FLAG_V)
1294 HANDLE_BRANCH_TAKEN(m)
1299 CLC Implied CLC 18 1 2
1302 static void Op18(void) // CLC
1308 CLD Implied CLD D8 1 2
1311 static void OpD8(void) // CLD
1317 CLI Implied CLI 58 1 2
1320 static void Op58(void) // CLI
1326 CLV Implied CLV B8 1 2
1329 static void OpB8(void) // CLV
1335 CMP Immediate CMP #Oper C9 2 2
1336 Zero Page CMP Zpg C5 2 3
1337 Zero Page,X CMP Zpg D5 2 4
1338 Absolute CMP Abs CD 3 4
1339 Absolute,X CMP Abs,X DD 3 4
1340 Absolute,Y CMP Abs,Y D9 3 4
1341 (Zero Page,X) CMP (Zpg,X) C1 2 6
1342 (Zero Page),Y CMP (Zpg),Y D1 2 5
1343 (Zero Page) CMP (Zpg) D2 2 5
1349 Here's the latest: The CMP is NOT generating the Z flag when A=$C0!
1351 FABA: A0 07 LDY #$07 [PC=FABC, SP=01FF, CC=---B-IZ-, A=00, X=00, Y=07]
1352 FABC: C6 01 DEC $01 [PC=FABE, SP=01FF, CC=N--B-I--, A=00, X=00, Y=07]
1353 FABE: A5 01 LDA $01 [PC=FAC0, SP=01FF, CC=N--B-I--, A=C0, X=00, Y=07]
1354 FAC0: C9 C0 CMP #$C0 [PC=FAC2, SP=01FF, CC=N--B-I--, A=C0, X=00, Y=07]
1355 FAC2: F0 D7 BEQ $FA9B [PC=FAC4, SP=01FF, CC=N--B-I--, A=C0, X=00, Y=07]
1356 FAC4: 8D F8 07 STA $07F8 [PC=FAC7, SP=01FF, CC=N--B-I--, A=C0, X=00, Y=07]
1357 FAC7: B1 00 LDA ($00),Y
1358 *** Read at I/O address C007
1359 [PC=FAC9, SP=01FF, CC=---B-IZ-, A=00, X=00, Y=07]
1360 FAC9: D9 01 FB CMP $FB01,Y [PC=FACC, SP=01FF, CC=---B-I--, A=00, X=00, Y=07]
1361 FACC: D0 EC BNE $FABA [PC=FABA, SP=01FF, CC=---B-I--, A=00, X=00, Y=07]
1363 Should be fixed now... (was adding instead of subtracting!)
1365 Small problem here... First two should set the carry while the last one should clear it. !!! FIX !!! [DONE]
1367 FDF0: C9 A0 CMP #$A0 [PC=FDF2, SP=01F1, CC=---B-IZ-, A=A0, X=02, Y=03]
1368 FD7E: C9 E0 CMP #$E0 [PC=FD80, SP=01F4, CC=N--B-I--, A=A0, X=02, Y=03]
1369 FD38: C9 9B CMP #$9B [PC=FD3A, SP=01F2, CC=---B-I-C, A=A0, X=02, Y=03]
1371 Compare sets flags as if a subtraction had been carried out. If the value in the accumulator is equal or greater than the compared value, the Carry will be set. The equal (Z) and sign (S) flags will be set based on equality or lack thereof and the sign (i.e. A>=$80) of the accumulator.
1374 #define OP_CMP_HANDLER(m) \
1375 uint8_t result = regs.a - (m); \
1376 SET_ZNC_CMP(m, regs.a, result)
1378 static void OpC9(void) // CMP #
1380 uint8_t m = READ_IMM;
1384 static void OpC5(void) // CMP ZP
1386 uint8_t m = READ_ZP;
1390 static void OpD5(void) // CMP ZP, X
1392 uint8_t m = READ_ZP_X;
1396 static void OpCD(void) // CMP ABS
1398 uint8_t m = READ_ABS;
1402 static void OpDD(void) // CMP ABS, X
1404 uint8_t m = READ_ABS_X;
1408 static void OpD9(void) // CMP ABS, Y
1410 uint8_t m = READ_ABS_Y;
1414 static void OpC1(void) // CMP (ZP, X)
1416 uint8_t m = READ_IND_ZP_X;
1420 static void OpD1(void) // CMP (ZP), Y
1422 uint8_t m = READ_IND_ZP_Y;
1426 static void OpD2(void) // CMP (ZP)
1428 uint8_t m = READ_IND_ZP;
1433 CPX Immediate CPX #Oper E0 2 2
1434 Zero Page CPX Zpg E4 2 3
1435 Absolute CPX Abs EC 3 4
1440 #define OP_CPX_HANDLER(m) \
1441 uint8_t result = regs.x - (m); \
1442 SET_ZNC_CMP(m, regs.x, result)
1444 static void OpE0(void) // CPX #
1446 uint8_t m = READ_IMM;
1450 static void OpE4(void) // CPX ZP
1452 uint8_t m = READ_ZP;
1456 static void OpEC(void) // CPX ABS
1458 uint8_t m = READ_ABS;
1463 CPY Immediate CPY #Oper C0 2 2
1464 Zero Page CPY Zpg C4 2 3
1465 Absolute CPY Abs CC 3 4
1470 #define OP_CPY_HANDLER(m) \
1471 uint8_t result = regs.y - (m); \
1472 SET_ZNC_CMP(m, regs.y, result)
1474 static void OpC0(void) // CPY #
1476 uint8_t m = READ_IMM;
1480 static void OpC4(void) // CPY ZP
1482 uint8_t m = READ_ZP;
1486 static void OpCC(void) // CPY ABS
1488 uint8_t m = READ_ABS;
1493 DEA Accumulator DEA 3A 1 2
1496 static void Op3A(void) // DEA
1503 DEC Zero Page DEC Zpg C6 2 5
1504 Zero Page,X DEC Zpg,X D6 2 6
1505 Absolute DEC Abs CE 3 6
1506 Absolute,X DEC Abs,X DE 3 7
1511 #define OP_DEC_HANDLER(m) \
1515 static void OpC6(void) // DEC ZP
1523 static void OpD6(void) // DEC ZP, X
1531 static void OpCE(void) // DEC ABS
1539 static void OpDE(void) // DEC ABS, X
1548 Here's one problem: DEX is setting the N flag!
1550 D3EE: A2 09 LDX #$09 [PC=D3F0, SP=01F7, CC=---B-I-C, A=01, X=09, Y=08]
1551 D3F0: 98 TYA [PC=D3F1, SP=01F7, CC=N--B-I-C, A=08, X=09, Y=08]
1552 D3F1: 48 PHA [PC=D3F2, SP=01F6, CC=N--B-I-C, A=08, X=09, Y=08]
1553 D3F2: B5 93 LDA $93,X [PC=D3F4, SP=01F6, CC=---B-IZC, A=00, X=09, Y=08]
1554 D3F4: CA DEX [PC=D3F5, SP=01F6, CC=N--B-I-C, A=00, X=08, Y=08]
1555 D3F5: 10 FA BPL $D3F1 [PC=D3F7, SP=01F6, CC=N--B-I-C, A=00, X=08, Y=08]
1556 D3F7: 20 84 E4 JSR $E484 [PC=E484, SP=01F4, CC=N--B-I-C, A=00, X=08, Y=08]
1558 should be fixed now...
1562 DEX Implied DEX CA 1 2
1565 static void OpCA(void) // DEX
1572 DEY Implied DEY 88 1 2
1575 static void Op88(void) // DEY
1582 EOR Immediate EOR #Oper 49 2 2
1583 Zero Page EOR Zpg 45 2 3
1584 Zero Page,X EOR Zpg,X 55 2 4
1585 Absolute EOR Abs 4D 3 4
1586 Absolute,X EOR Abs,X 5D 3 4
1587 Absolute,Y EOR Abs,Y 59 3 4
1588 (Zero Page,X) EOR (Zpg,X) 41 2 6
1589 (Zero Page),Y EOR (Zpg),Y 51 2 5
1590 (Zero Page) EOR (Zpg) 52 2 5
1595 #define OP_EOR_HANDLER(m) \
1599 static void Op49(void) // EOR #
1601 uint8_t m = READ_IMM;
1605 static void Op45(void) // EOR ZP
1607 uint8_t m = READ_ZP;
1611 static void Op55(void) // EOR ZP, X
1613 uint8_t m = READ_ZP_X;
1617 static void Op4D(void) // EOR ABS
1619 uint8_t m = READ_ABS;
1623 static void Op5D(void) // EOR ABS, X
1625 uint8_t m = READ_ABS_X;
1629 static void Op59(void) // EOR ABS, Y
1631 uint8_t m = READ_ABS_Y;
1635 static void Op41(void) // EOR (ZP, X)
1637 uint8_t m = READ_IND_ZP_X;
1641 static void Op51(void) // EOR (ZP), Y
1643 uint8_t m = READ_IND_ZP_Y;
1647 static void Op52(void) // EOR (ZP)
1649 uint8_t m = READ_IND_ZP;
1654 INA Accumulator INA 1A 1 2
1657 static void Op1A(void) // INA
1664 INC Zero Page INC Zpg E6 2 5
1665 Zero Page,X INC Zpg,X F6 2 6
1666 Absolute INC Abs EE 3 6
1667 Absolute,X INC Abs,X FE 3 7
1672 #define OP_INC_HANDLER(m) \
1676 static void OpE6(void) // INC ZP
1684 static void OpF6(void) // INC ZP, X
1692 static void OpEE(void) // INC ABS
1700 static void OpFE(void) // INC ABS, X
1709 INX Implied INX E8 1 2
1712 static void OpE8(void) // INX
1719 INY Implied INY C8 1 2
1722 static void OpC8(void) // INY
1729 JMP Absolute JMP Abs 4C 3 3
1730 (Absolute) JMP (Abs) 6C 3 5
1731 (Absolute,X) JMP (Abs,X) 7C 3 6
1736 static void Op4C(void) // JMP ABS
1738 regs.pc = RdMemW(regs.pc);
1741 static void Op6C(void) // JMP (ABS)
1743 // uint16_t addr = RdMemW(regs.pc);
1745 //WriteLog("\n[JMP ABS]: addr fetched = %04X, bytes at %04X = %02X %02X (RdMemw=%04X)\n",
1746 // addr, addr, regs.RdMem(addr), regs.RdMem(addr+1), RdMemW(addr));
1748 // addr = RdMemW(addr);
1749 regs.pc = RdMemW(RdMemW(regs.pc));
1752 static void Op7C(void) // JMP (ABS, X)
1754 regs.pc = RdMemW(RdMemW(regs.pc) + regs.x);
1758 JSR Absolute JSR Abs 20 3 6
1761 //This is not jumping to the correct address... !!! FIX !!! [DONE]
1762 static void Op20(void) // JSR
1764 uint16_t addr = RdMemW(regs.pc);
1765 regs.pc++; // Since it pushes return address - 1...
1766 regs.WrMem(0x0100 + regs.sp--, regs.pc >> 8);
1767 regs.WrMem(0x0100 + regs.sp--, regs.pc & 0xFF);
1772 LDA Immediate LDA #Oper A9 2 2
1773 Zero Page LDA Zpg A5 2 3
1774 Zero Page,X LDA Zpg,X B5 2 4
1775 Absolute LDA Abs AD 3 4
1776 Absolute,X LDA Abs,X BD 3 4
1777 Absolute,Y LDA Abs,Y B9 3 4
1778 (Zero Page,X) LDA (Zpg,X) A1 2 6
1779 (Zero Page),Y LDA (Zpg),Y B1 2 5
1780 (Zero Page) LDA (Zpg) B2 2 5
1785 #define OP_LDA_HANDLER(m) \
1789 static void OpA9(void) // LDA #
1791 uint8_t m = READ_IMM;
1795 static void OpA5(void) // LDA ZP
1797 uint8_t m = READ_ZP;
1801 static void OpB5(void) // LDA ZP, X
1803 uint8_t m = READ_ZP_X;
1807 static void OpAD(void) // LDA ABS
1809 uint8_t m = READ_ABS;
1813 static void OpBD(void) // LDA ABS, X
1815 uint8_t m = READ_ABS_X;
1819 static void OpB9(void) // LDA ABS, Y
1821 uint8_t m = READ_ABS_Y;
1825 static void OpA1(void) // LDA (ZP, X)
1827 uint8_t m = READ_IND_ZP_X;
1831 static void OpB1(void) // LDA (ZP), Y
1833 uint8_t m = READ_IND_ZP_Y;
1837 static void OpB2(void) // LDA (ZP)
1839 uint8_t m = READ_IND_ZP;
1844 LDX Immediate LDX #Oper A2 2 2
1845 Zero Page LDX Zpg A6 2 3
1846 Zero Page,Y LDX Zpg,Y B6 2 4
1847 Absolute LDX Abs AE 3 4
1848 Absolute,Y LDX Abs,Y BE 3 4
1853 #define OP_LDX_HANDLER(m) \
1857 static void OpA2(void) // LDX #
1859 uint8_t m = READ_IMM;
1863 static void OpA6(void) // LDX ZP
1865 uint8_t m = READ_ZP;
1869 static void OpB6(void) // LDX ZP, Y
1871 uint8_t m = READ_ZP_Y;
1875 static void OpAE(void) // LDX ABS
1877 uint8_t m = READ_ABS;
1881 static void OpBE(void) // LDX ABS, Y
1883 uint8_t m = READ_ABS_Y;
1888 LDY Immediate LDY #Oper A0 2 2
1889 Zero Page LDY Zpg A4 2 3
1890 Zero Page,Y LDY Zpg,X B4 2 4
1891 Absolute LDY Abs AC 3 4
1892 Absolute,Y LDY Abs,X BC 3 4
1897 #define OP_LDY_HANDLER(m) \
1901 static void OpA0(void) // LDY #
1903 uint8_t m = READ_IMM;
1907 static void OpA4(void) // LDY ZP
1909 uint8_t m = READ_ZP;
1913 static void OpB4(void) // LDY ZP, X
1915 uint8_t m = READ_ZP_X;
1919 static void OpAC(void) // LDY ABS
1921 uint8_t m = READ_ABS;
1925 static void OpBC(void) // LDY ABS, X
1927 uint8_t m = READ_ABS_X;
1932 LSR Accumulator LSR A 4A 1 2
1933 Zero Page LSR Zpg 46 2 5
1934 Zero Page,X LSR Zpg,X 56 2 6
1935 Absolute LSR Abs 4E 3 6
1936 Absolute,X LSR Abs,X 5E 3 7
1941 #define OP_LSR_HANDLER(m) \
1942 regs.cc = ((m) & 0x01 ? regs.cc | FLAG_C : regs.cc & ~FLAG_C); \
1946 static void Op4A(void) // LSR A
1948 OP_LSR_HANDLER(regs.a);
1951 static void Op46(void) // LSR ZP
1959 static void Op56(void) // LSR ZP, X
1967 static void Op4E(void) // LSR ABS
1975 static void Op5E(void) // LSR ABS, X
1984 NOP Implied NOP EA 1 2
1987 static void OpEA(void) // NOP
1992 ORA Immediate ORA #Oper 09 2 2
1993 Zero Page ORA Zpg 05 2 3
1994 Zero Page,X ORA Zpg,X 15 2 4
1995 Absolute ORA Abs 0D 3 4
1996 Absolute,X ORA Abs,X 1D 3 4
1997 Absolute,Y ORA Abs,Y 19 3 4
1998 (Zero Page,X) ORA (Zpg,X) 01 2 6
1999 (Zero Page),Y ORA (Zpg),Y 11 2 5
2000 (Zero Page) ORA (Zpg) 12 2 5
2005 #define OP_ORA_HANDLER(m) \
2009 static void Op09(void) // ORA #
2011 uint8_t m = READ_IMM;
2015 static void Op05(void) // ORA ZP
2017 uint8_t m = READ_ZP;
2021 static void Op15(void) // ORA ZP, X
2023 uint8_t m = READ_ZP_X;
2027 static void Op0D(void) // ORA ABS
2029 uint8_t m = READ_ABS;
2033 static void Op1D(void) // ORA ABS, X
2035 uint8_t m = READ_ABS_X;
2039 static void Op19(void) // ORA ABS, Y
2041 uint8_t m = READ_ABS_Y;
2045 static void Op01(void) // ORA (ZP, X)
2047 uint8_t m = READ_IND_ZP_X;
2051 static void Op11(void) // ORA (ZP), Y
2053 uint8_t m = READ_IND_ZP_Y;
2057 static void Op12(void) // ORA (ZP)
2059 uint8_t m = READ_IND_ZP;
2064 PHA Implied PHA 48 1 3
2067 static void Op48(void) // PHA
2069 regs.WrMem(0x0100 + regs.sp--, regs.a);
2072 static void Op08(void) // PHP
2074 regs.cc |= FLAG_UNK; // Make sure that the unused bit is always set
2075 regs.WrMem(0x0100 + regs.sp--, regs.cc);
2079 PHX Implied PHX DA 1 3
2082 static void OpDA(void) // PHX
2084 regs.WrMem(0x0100 + regs.sp--, regs.x);
2088 PHY Implied PHY 5A 1 3
2091 static void Op5A(void) // PHY
2093 regs.WrMem(0x0100 + regs.sp--, regs.y);
2097 PLA Implied PLA 68 1 4
2100 static void Op68(void) // PLA
2102 regs.a = regs.RdMem(0x0100 + ++regs.sp);
2106 static void Op28(void) // PLP
2108 regs.cc = regs.RdMem(0x0100 + ++regs.sp);
2112 PLX Implied PLX FA 1 4
2115 static void OpFA(void) // PLX
2117 regs.x = regs.RdMem(0x0100 + ++regs.sp);
2122 PLY Implied PLY 7A 1 4
2125 static void Op7A(void) // PLY
2127 regs.y = regs.RdMem(0x0100 + ++regs.sp);
2132 The bit set and clear instructions have the form xyyy0111, where x is 0 to clear a bit or 1 to set it, and yyy is which bit at the memory location to set or clear.
2133 RMB0 RMB1 RMB2 RMB3 RMB4 RMB5 RMB6 RMB7
2134 zp 07 17 27 37 47 57 67 77
2135 SMB0 SMB1 SMB2 SMB3 SMB4 SMB5 SMB6 SMB7
2136 zp 87 97 A7 B7 C7 D7 E7 F7
2141 static void Op07(void) // RMB0 ZP
2149 static void Op17(void) // RMB1 ZP
2157 static void Op27(void) // RMB2 ZP
2165 static void Op37(void) // RMB3 ZP
2173 static void Op47(void) // RMB4 ZP
2181 static void Op57(void) // RMB5 ZP
2189 static void Op67(void) // RMB6 ZP
2197 static void Op77(void) // RMB7 ZP
2206 ROL Accumulator ROL A 2A 1 2
2207 Zero Page ROL Zpg 26 2 5
2208 Zero Page,X ROL Zpg,X 36 2 6
2209 Absolute ROL Abs 2E 3 6
2210 Absolute,X ROL Abs,X 3E 3 7
2215 #define OP_ROL_HANDLER(m) \
2216 uint8_t tmp = regs.cc & 0x01; \
2217 regs.cc = ((m) & 0x80 ? regs.cc | FLAG_C : regs.cc & ~FLAG_C); \
2218 (m) = ((m) << 1) | tmp; \
2221 static void Op2A(void) // ROL A
2223 OP_ROL_HANDLER(regs.a);
2226 static void Op26(void) // ROL ZP
2234 static void Op36(void) // ROL ZP, X
2242 static void Op2E(void) // ROL ABS
2250 static void Op3E(void) // ROL ABS, X
2259 ROR Accumulator ROR A 6A 1 2
2260 Zero Page ROR Zpg 66 2 5
2261 Zero Page,X ROR Zpg,X 76 2 6
2262 Absolute ROR Abs 6E 3 6
2263 Absolute,X ROR Abs,X 7E 3 7
2268 #define OP_ROR_HANDLER(m) \
2269 uint8_t tmp = (regs.cc & 0x01) << 7; \
2270 regs.cc = ((m) & 0x01 ? regs.cc | FLAG_C : regs.cc & ~FLAG_C); \
2271 (m) = ((m) >> 1) | tmp; \
2274 static void Op6A(void) // ROR A
2276 OP_ROR_HANDLER(regs.a);
2279 static void Op66(void) // ROR ZP
2287 static void Op76(void) // ROR ZP, X
2295 static void Op6E(void) // ROR ABS
2303 static void Op7E(void) // ROR ABS, X
2312 RTI Implied RTI 40 1 6
2315 static void Op40(void) // RTI
2317 regs.cc = regs.RdMem(0x0100 + ++regs.sp);
2318 //clear I (seems to be the case, either that or clear it in the IRQ setup...)
2319 //I can't find *any* verification that this is the case.
2320 // regs.cc &= ~FLAG_I;
2321 regs.pc = regs.RdMem(0x0100 + ++regs.sp);
2322 regs.pc |= (uint16_t)(regs.RdMem(0x0100 + ++regs.sp)) << 8;
2326 RTS Implied RTS 60 1 6
2329 static void Op60(void) // RTS
2331 regs.pc = regs.RdMem(0x0100 + ++regs.sp);
2332 regs.pc |= (uint16_t)(regs.RdMem(0x0100 + ++regs.sp)) << 8;
2333 regs.pc++; // Since it pushes return address - 1...
2334 //printf("*** RTS: PC = $%04X, SP= $1%02X\n", regs.pc, regs.sp);
2339 SBC Immediate SBC #Oper E9 2 2
2340 Zero Page SBC Zpg E5 2 3
2341 Zero Page,X SBC Zpg,X F5 2 4
2342 Absolute SBC Abs ED 3 4
2343 Absolute,X SBC Abs,X FD 3 4
2344 Absolute,Y SBC Abs,Y F9 3 4
2345 (Zero Page,X) SBC (Zpg,X) E1 2 6
2346 (Zero Page),Y SBC (Zpg),Y F1 2 5
2347 (Zero Page) SBC (Zpg) F2 2 5
2352 //This is non-optimal, but it works--optimize later. :-)
2353 //This is correct except for the BCD handling... !!! FIX !!! [Possibly DONE]
2354 #define OP_SBC_HANDLER(m) \
2355 uint16_t sum = (uint16_t)regs.a - (m) - (uint16_t)((regs.cc & FLAG_C) ^ 0x01); \
2357 if (regs.cc & FLAG_D) \
2359 if ((sum & 0x0F) > 0x09) \
2362 if ((sum & 0xF0) > 0x90) \
2366 regs.cc = (regs.cc & ~FLAG_C) | (((sum >> 8) ^ 0x01) & FLAG_C); \
2367 regs.cc = ((regs.a ^ (m)) & (regs.a ^ sum) & 0x80 ? regs.cc | FLAG_V : regs.cc & ~FLAG_V); \
2368 regs.a = sum & 0xFF; \
2372 D5AF: 38 SEC [PC=D5B0, SP=01F6, CC=---B-I-C, A=4C, X=00, Y=06]
2374 *** HERE'S where it sets the D flag on a subtract... Arg!
2376 D5B0: F1 9D SBC ($9D),Y [PC=D5B2, SP=01F6, CC=N--BDI--, A=FE, X=00, Y=06]
2381 //OLD V detection: regs.cc = ((regs.a ^ (m) ^ sum ^ (regs.cc << 7)) & 0x80 ? regs.cc | FLAG_V : regs.cc & ~FLAG_V);
2383 static void OpE9(void) // SBC #
2385 uint16_t m = READ_IMM;
2389 static void OpE5(void) // SBC ZP
2391 uint16_t m = READ_ZP;
2395 static void OpF5(void) // SBC ZP, X
2397 uint16_t m = READ_ZP_X;
2401 static void OpED(void) // SBC ABS
2403 uint16_t m = READ_ABS;
2407 static void OpFD(void) // SBC ABS, X
2409 uint16_t m = READ_ABS_X;
2413 static void OpF9(void) // SBC ABS, Y
2415 uint16_t m = READ_ABS_Y;
2419 static void OpE1(void) // SBC (ZP, X)
2421 uint16_t m = READ_IND_ZP_X;
2425 static void OpF1(void) // SBC (ZP), Y
2427 uint16_t m = READ_IND_ZP_Y;
2431 static void OpF2(void) // SBC (ZP)
2433 uint16_t m = READ_IND_ZP;
2438 SEC Implied SEC 38 1 2
2441 static void Op38(void) // SEC
2447 SED Implied SED F8 1 2
2450 static void OpF8(void) // SED
2456 SEI Implied SEI 78 1 2
2459 static void Op78(void) // SEI
2465 The bit set and clear instructions have the form xyyy0111, where x is 0 to clear a bit or 1 to set it, and yyy is which bit at the memory location to set or clear.
2466 RMB0 RMB1 RMB2 RMB3 RMB4 RMB5 RMB6 RMB7
2467 zp 07 17 27 37 47 57 67 77
2468 SMB0 SMB1 SMB2 SMB3 SMB4 SMB5 SMB6 SMB7
2469 zp 87 97 A7 B7 C7 D7 E7 F7
2474 static void Op87(void) // SMB0 ZP
2482 static void Op97(void) // SMB1 ZP
2490 static void OpA7(void) // SMB2 ZP
2498 static void OpB7(void) // SMB3 ZP
2506 static void OpC7(void) // SMB4 ZP
2514 static void OpD7(void) // SMB5 ZP
2522 static void OpE7(void) // SMB6 ZP
2530 static void OpF7(void) // SMB7 ZP
2539 STA Zero Page STA Zpg 85 2 3
2540 Zero Page,X STA Zpg,X 95 2 4
2541 Absolute STA Abs 8D 3 4
2542 Absolute,X STA Abs,X 9D 3 5
2543 Absolute,Y STA Abs,Y 99 3 5
2544 (Zero Page,X) STA (Zpg,X) 81 2 6
2545 (Zero Page),Y STA (Zpg),Y 91 2 6
2546 (Zero Page) STA (Zpg) 92 2 5
2551 static void Op85(void)
2553 regs.WrMem(EA_ZP, regs.a);
2556 static void Op95(void)
2558 regs.WrMem(EA_ZP_X, regs.a);
2561 static void Op8D(void)
2563 regs.WrMem(EA_ABS, regs.a);
2566 static void Op9D(void)
2568 regs.WrMem(EA_ABS_X, regs.a);
2571 static void Op99(void)
2573 regs.WrMem(EA_ABS_Y, regs.a);
2576 static void Op81(void)
2578 regs.WrMem(EA_IND_ZP_X, regs.a);
2581 static void Op91(void)
2583 regs.WrMem(EA_IND_ZP_Y, regs.a);
2586 static void Op92(void)
2588 regs.WrMem(EA_IND_ZP, regs.a);
2592 STX Zero Page STX Zpg 86 2 3
2593 Zero Page,Y STX Zpg,Y 96 2 4
2594 Absolute STX Abs 8E 3 4
2599 static void Op86(void)
2601 regs.WrMem(EA_ZP, regs.x);
2604 static void Op96(void)
2607 //WAS: regs.WrMem(EA_ZP_X, regs.x);
2608 regs.WrMem(EA_ZP_Y, regs.x);
2611 static void Op8E(void)
2613 regs.WrMem(EA_ABS, regs.x);
2617 STY Zero Page STY Zpg 84 2 3
2618 Zero Page,X STY Zpg,X 94 2 4
2619 Absolute STY Abs 8C 3 4
2624 static void Op84(void)
2626 regs.WrMem(EA_ZP, regs.y);
2629 static void Op94(void)
2631 regs.WrMem(EA_ZP_X, regs.y);
2634 static void Op8C(void)
2636 regs.WrMem(EA_ABS, regs.y);
2640 STZ Zero Page STZ Zpg 64 2 3
2641 Zero Page,X STZ Zpg,X 74 2 4
2642 Absolute STZ Abs 9C 3 4
2643 Absolute,X STZ Abs,X 9E 3 5
2648 static void Op64(void)
2650 regs.WrMem(EA_ZP, 0x00);
2653 static void Op74(void)
2655 regs.WrMem(EA_ZP_X, 0x00);
2658 static void Op9C(void)
2660 regs.WrMem(EA_ABS, 0x00);
2663 static void Op9E(void)
2665 regs.WrMem(EA_ABS_X, 0x00);
2669 TAX Implied TAX AA 1 2
2672 static void OpAA(void) // TAX
2679 TAY Implied TAY A8 1 2
2682 static void OpA8(void) // TAY
2689 TRB Zero Page TRB Zpg 14 2 5
2690 Absolute TRB Abs 1C 3 6
2695 #define OP_TRB_HANDLER(m) \
2696 SET_Z(m & regs.a); \
2699 static void Op14(void) // TRB ZP
2707 static void Op1C(void) // TRB ABS
2716 TSB Zero Page TSB Zpg 04 2 5
2717 Absolute TSB Abs 0C 3 6
2722 #define OP_TSB_HANDLER(m) \
2723 SET_Z(m & regs.a); \
2726 static void Op04(void) // TSB ZP
2734 static void Op0C(void) // TSB ABS
2743 TSX Implied TSX BA 1 2
2746 static void OpBA(void) // TSX
2753 TXA Implied TXA 8A 1 2
2756 static void Op8A(void) // TXA
2763 TXS Implied TXS 9A 1 2
2766 static void Op9A(void) // TXS
2772 TYA Implied TYA 98 1 2
2774 static void Op98(void) // TYA
2780 static void Op__(void)
2782 regs.cpuFlags |= V65C02_STATE_ILLEGAL_INST;
2787 // Ok, the exec_op[] array is globally defined here basically to save
2788 // a LOT of unnecessary typing. Sure it's ugly, but hey, it works!
2790 void (* exec_op[256])() = {
2791 Op00, Op01, Op__, Op__, Op04, Op05, Op06, Op07, Op08, Op09, Op0A, Op__, Op0C, Op0D, Op0E, Op0F,
2792 Op10, Op11, Op12, Op__, Op14, Op15, Op16, Op17, Op18, Op19, Op1A, Op__, Op1C, Op1D, Op1E, Op1F,
2793 Op20, Op21, Op__, Op__, Op24, Op25, Op26, Op27, Op28, Op29, Op2A, Op__, Op2C, Op2D, Op2E, Op2F,
2794 Op30, Op31, Op32, Op__, Op34, Op35, Op36, Op37, Op38, Op39, Op3A, Op__, Op3C, Op3D, Op3E, Op3F,
2795 Op40, Op41, Op__, Op__, Op__, Op45, Op46, Op47, Op48, Op49, Op4A, Op__, Op4C, Op4D, Op4E, Op4F,
2796 Op50, Op51, Op52, Op__, Op__, Op55, Op56, Op57, Op58, Op59, Op5A, Op__, Op__, Op5D, Op5E, Op5F,
2797 Op60, Op61, Op__, Op__, Op64, Op65, Op66, Op67, Op68, Op69, Op6A, Op__, Op6C, Op6D, Op6E, Op6F,
2798 Op70, Op71, Op72, Op__, Op74, Op75, Op76, Op77, Op78, Op79, Op7A, Op__, Op7C, Op7D, Op7E, Op7F,
2799 Op80, Op81, Op__, Op__, Op84, Op85, Op86, Op87, Op88, Op89, Op8A, Op__, Op8C, Op8D, Op8E, Op8F,
2800 Op90, Op91, Op92, Op__, Op94, Op95, Op96, Op97, Op98, Op99, Op9A, Op__, Op9C, Op9D, Op9E, Op9F,
2801 OpA0, OpA1, OpA2, Op__, OpA4, OpA5, OpA6, OpA7, OpA8, OpA9, OpAA, Op__, OpAC, OpAD, OpAE, OpAF,
2802 OpB0, OpB1, OpB2, Op__, OpB4, OpB5, OpB6, OpB7, OpB8, OpB9, OpBA, Op__, OpBC, OpBD, OpBE, OpBF,
2803 OpC0, OpC1, Op__, Op__, OpC4, OpC5, OpC6, OpC7, OpC8, OpC9, OpCA, Op__, OpCC, OpCD, OpCE, OpCF,
2804 OpD0, OpD1, OpD2, Op__, Op__, OpD5, OpD6, OpD7, OpD8, OpD9, OpDA, Op__, Op__, OpDD, OpDE, OpDF,
2805 OpE0, OpE1, Op__, Op__, OpE4, OpE5, OpE6, OpE7, OpE8, OpE9, OpEA, Op__, OpEC, OpED, OpEE, OpEF,
2806 OpF0, OpF1, OpF2, Op__, Op__, OpF5, OpF6, OpF7, OpF8, OpF9, OpFA, Op__, Op__, OpFD, OpFE, OpFF
2811 // Internal "memcpy" (so we don't have to link with any external libraries!)
2813 static void myMemcpy(void * dst, void * src, uint32_t size)
2815 uint8_t * d = (uint8_t *)dst, * s = (uint8_t *)src;
2817 for(uint32_t i=0; i<size; i++)
2822 FCA8: 38 698 WAIT SEC
2823 FCA9: 48 699 WAIT2 PHA
2824 FCAA: E9 01 700 WAIT3 SBC #$01
2825 FCAC: D0 FC 701 BNE WAIT3 ;1.0204 USEC
2826 FCAE: 68 702 PLA ;(13+27/2*A+5/2*A*A)
2827 FCAF: E9 01 703 SBC #$01
2828 FCB1: D0 F6 704 BNE WAIT2
2831 FBD9: C9 87 592 BELL1 CMP #$87 ;BELL CHAR? (CNTRL-G)
2832 FBDB: D0 12 593 BNE RTS2B ; NO, RETURN
2833 FBDD: A9 40 594 LDA #$40 ;DELAY .01 SECONDS
2834 FBDF: 20 A8 FC 595 JSR WAIT
2835 FBE2: A0 C0 596 LDY #$C0
2836 FBE4: A9 0C 597 BELL2 LDA #$0C ;TOGGLE SPEAKER AT
2837 FBE6: 20 A8 FC 598 JSR WAIT ; 1 KHZ FOR .1 SEC.
2838 FBE9: AD 30 C0 599 LDA SPKR
2840 FBED: D0 F5 601 BNE BELL2
2841 FBEF: 60 602 RTS2B RTS
2843 //int instCount[256];
2845 bool dumpDis = false;
2846 //bool dumpDis = true;
2850 On //e, $FCAA is the delay routine. (seems to not have changed from ][+)
2854 //Note: could enforce regs.clock to zero on starting the CPU with an Init() function...
2856 //static uint32_t limit = 0;
2857 // Or, we could just say that initializing the CPU struct is the responsibility
2858 // of the caller. :-)
2860 #define DO_BACKTRACE
2862 #define BACKTRACE_SIZE 16384
2863 uint32_t btQueuePtr = 0;
2864 V65C02REGS btQueue[BACKTRACE_SIZE];
2865 uint8_t btQueueInst[BACKTRACE_SIZE][4];
2868 // Function to execute 65C02 for "cycles" cycles
2870 void Execute65C02(V65C02REGS * context, uint32_t cycles)
2872 myMemcpy(®s, context, sizeof(V65C02REGS));
2875 uint64_t endCycles = regs.clock + (uint64_t)cycles - regs.overflow;
2877 while (regs.clock < endCycles)
2880 /*if (regs.pc == 0x4007)
2884 if (regs.pc == 0x444B)
2886 WriteLog("\n*** End of wait...\n\n");
2889 if (regs.pc == 0x444E)
2891 WriteLog("\n*** Start of wait...\n\n");
2895 /*if (regs.pc == 0xBF4C)
2901 /*if (regs.pc == 0x0801)
2903 WriteLog("\n*** DISK BOOT subroutine...\n\n");
2906 if (regs.pc == 0xE000)
2909 WriteLog("\n*** Dump of $E000 routine ***\n\n");
2911 for(uint32_t addr=0xE000; addr<0xF000;)
2913 addr += Decode65C02(addr);
2917 WriteLog("\n*** DISK part II subroutine...\n\n");
2920 if (regs.pc == 0xD000)
2922 WriteLog("\n*** CUSTOM DISK READ subroutine...\n\n");
2925 if (regs.pc == 0xD1BE)
2927 // WriteLog("\n*** DISK part II subroutine...\n\n");
2930 if (regs.pc == 0xD200)
2932 WriteLog("\n*** CUSTOM SCREEN subroutine...\n\n");
2935 if (regs.pc == 0xD269)
2937 // WriteLog("\n*** DISK part II subroutine...\n\n");
2941 //if (regs.pc == 0xE08E)
2942 /*if (regs.pc == 0xAD33)
2944 WriteLog("\n*** After loader ***\n\n");
2947 /*if (regs.pc == 0x0418)
2949 WriteLog("\n*** CUSTOM DISK READ subroutine...\n\n");
2957 //WAIT is commented out here because it's called by BELL1...
2958 if (regs.pc == 0xFCA8)
2960 WriteLog("\n*** WAIT subroutine...\n\n");
2963 if (regs.pc == 0xFBD9)
2965 WriteLog("\n*** BELL1 subroutine...\n\n");
2968 if (regs.pc == 0xFC58)
2970 WriteLog("\n*** HOME subroutine...\n\n");
2973 if (regs.pc == 0xFDED)
2975 WriteLog("\n*** COUT subroutine...\n\n");
2981 if (regs.pc == 0x2000)
2986 static char disbuf[80];
2989 Decode65C02(disbuf, regs.pc);
2990 WriteLog("%s", disbuf);
2993 uint8_t opcode = regs.RdMem(regs.pc++);
2995 //if (!(regs.cpuFlags & V65C02_STATE_ILLEGAL_INST))
2996 //instCount[opcode]++;
2998 exec_op[opcode](); // Execute that opcode...
2999 regs.clock += CPUCycles[opcode];
3002 WriteLog(" [PC=%04X, SP=%04X, CC=%s%s.%s%s%s%s%s, A=%02X, X=%02X, Y=%02X]\n",
3003 regs.pc, 0x0100 + regs.sp,
3004 (regs.cc & FLAG_N ? "N" : "-"), (regs.cc & FLAG_V ? "V" : "-"),
3005 (regs.cc & FLAG_B ? "B" : "-"), (regs.cc & FLAG_D ? "D" : "-"),
3006 (regs.cc & FLAG_I ? "I" : "-"), (regs.cc & FLAG_Z ? "Z" : "-"),
3007 (regs.cc & FLAG_C ? "C" : "-"), regs.a, regs.x, regs.y);
3011 if (regs.pc == 0xFCB3) // WAIT exit point
3015 /*if (regs.pc == 0xFBEF) // BELL1 exit point
3019 /*if (regs.pc == 0xFC22) // HOME exit point
3023 if (regs.pc == 0xFDFF) // COUT exit point
3027 if (regs.pc == 0xFBD8)
3029 WriteLog("\n*** BASCALC set BASL/H = $%04X\n\n", RdMemW(0x0028));
3033 //These should be correct now...
3034 if (regs.cpuFlags & V65C02_ASSERT_LINE_RESET)
3037 WriteLog("\n*** RESET ***\n\n");
3039 // Not sure about this...
3041 regs.cc = FLAG_B | FLAG_I; // Reset the CC register
3042 regs.pc = RdMemW(0xFFFC); // And load PC with the RESET vector
3044 context->cpuFlags &= ~V65C02_ASSERT_LINE_RESET;
3045 regs.cpuFlags &= ~V65C02_ASSERT_LINE_RESET;
3047 else if (regs.cpuFlags & V65C02_ASSERT_LINE_NMI)
3050 WriteLog("\n*** NMI ***\n\n");
3052 regs.WrMem(0x0100 + regs.sp--, regs.pc >> 8); // Save PC and CC
3053 regs.WrMem(0x0100 + regs.sp--, regs.pc & 0xFF);
3054 regs.WrMem(0x0100 + regs.sp--, regs.cc);
3055 regs.cc |= FLAG_I; // Set I
3056 regs.cc &= ~FLAG_D; // & clear D
3057 regs.pc = RdMemW(0xFFFA); // And do it!
3060 context->cpuFlags &= ~V65C02_ASSERT_LINE_NMI;// Reset the asserted line (NMI)...
3061 regs.cpuFlags &= ~V65C02_ASSERT_LINE_NMI; // Reset the asserted line (NMI)...
3063 else if (regs.cpuFlags & V65C02_ASSERT_LINE_IRQ)
3065 if (!(regs.cc & FLAG_I)) // Process an interrupt (I=0)?
3068 WriteLog("\n*** IRQ ***\n\n");
3070 regs.WrMem(0x0100 + regs.sp--, regs.pc >> 8); // Save PC and CC
3071 regs.WrMem(0x0100 + regs.sp--, regs.pc & 0xFF);
3072 regs.WrMem(0x0100 + regs.sp--, regs.cc);
3073 regs.cc |= FLAG_I; // Set I
3074 regs.cc &= ~FLAG_D; // & clear D
3075 regs.pc = RdMemW(0xFFFE); // And do it!
3078 context->cpuFlags &= ~V65C02_ASSERT_LINE_IRQ; // Reset the asserted line (IRQ)...
3079 regs.cpuFlags &= ~V65C02_ASSERT_LINE_IRQ; // Reset the asserted line (IRQ)...
3084 // If we went longer than the passed in cycles, make a note of it so we can
3085 // subtract it out from a subsequent run. It's guaranteed to be positive,
3086 // because the condition that exits the main loop above is written such
3087 // that regs.clock has to be larger than endCycles to exit from it.
3088 regs.overflow = regs.clock - endCycles;
3090 myMemcpy(context, ®s, sizeof(V65C02REGS));
3095 // Get the clock of the currently executing CPU
3097 uint64_t GetCurrentV65C02Clock(void)