]> Shamusworld >> Repos - thunder/blob - src/v63701.cpp
Code cleanup, final fix for sprite lag problem.
[thunder] / src / v63701.cpp
1 //
2 // Virtual 63701 Emulator v1.0
3 //
4 // by James Hammons
5 // (C) 2014 Underground Software
6 //
7 // JLH = James Hammons <jlhamm@acm.org>
8 //
9 // WHO  WHEN        WHAT
10 // ---  ----------  -----------------------------------------------------------
11 // JLH  06/15/2006  Added changelog ;-)
12 // JLH  06/15/2006  Scrubbed all BYTE, WORD & DWORD references from the code
13 // JLH  11/13/2006  Converted core to V65C02 macro style :-)
14 // JLH  11/13/2006  Converted flags to unpacked and separate flags
15 // JLH  07/21/2009  Converted clock from 32-bit to 64-bit value, added possible
16 //                  "don't branch" optimization
17 // JLH  09/21/2009  Fixed EA_ABS macros
18 // JLH  04/07/2014  Converted core to HD63701 type
19 // JLH  04/16/2014  Fixed a raft of bugs, added sane timer handling
20 //
21
22 // This is based on V6808, since it's in the same family apparently. The
23 // HD63701 has more opcodes, and apparently some built in timer facility as
24 // well.
25
26 // N.B.: There are some things missing from the emulation, such as the data
27 //       ports, the Input Capture, RAM Control, sleep mode, processor modes,
28 //       and probably some other stuff as well. What is here seems to work, and
29 //       work well. It's a fair sight better than the one that's in MAME,
30 //       that's for sure. :-D
31
32 #define __DEBUG__
33 #define TEST_DONT_BRANCH_OPTIMIZATION
34
35 #include "v63701.h"
36 //#include <stdio.h>            // for printf()
37
38 #ifdef __DEBUG__
39 #include "dis63701.h"
40 //#include "log.h"
41 #include <stdio.h>              // for printf()
42 #define WriteLog printf
43 #endif
44
45 // Various macros
46
47 #define CLR_Z                                   (flagZ = 0)
48 #define CLR_ZN                                  (flagZ = flagN = 0)
49 #define CLR_ZNC                                 (flagZ = flagN = flagC = 0)
50 #define CLR_NVC                                 (flagN = flagV = flagC = 0)
51 #define CLR_VC                                  (flagV = flagC = 0)
52 #define CLR_V                                   (flagV = 0)
53 #define CLR_N                                   (flagN = 0)
54 #define SET_Z(r)                                (flagZ = ((r) == 0 ? 1 : 0))
55 #define SET_N(r)                                (flagN = ((r) & 0x80) >> 7)
56 #define SET_V(a,b,r)                    (flagV = (((b) ^ (a) ^ (r) ^ ((r) >> 1)) & 0x80) >> 7)
57
58 #define SET_C_CMP(a,b)                  (flagC = ((uint8_t)(b) < (uint8_t)(a) ? 1 : 0))
59 #define SET_ZN(r)                               SET_N(r); SET_Z(r)
60 #define SET_ZNC_ADD(a,b,r)              SET_N(r); SET_Z(r); SET_C_ADD(a,b)
61 #define SET_ZNVC_CMP(a,b,r)             SET_N(r); SET_Z(r); SET_C_CMP(a,b); SET_V(a,b,r)
62
63 #define SET_N16(r)                              (flagN = ((r) & 0x8000) >> 15)
64 #define SET_V16(a,b,r)                  (flagV = (((b) ^ (a) ^ (r) ^ ((r) >> 1)) & 0x8000) >> 15)
65 #define SET_C_CMP16(a,b)                (flagC = ((uint16_t)(b) < (uint16_t)(a) ? 1 : 0))
66 #define SET_ZNVC_CMP16(a,b,r)   SET_N16(r); SET_Z(r); SET_C_CMP16(a,b); SET_V16(a,b,r)
67
68 #define EA_IMM                          regs.pc++
69 #define EA_ZP                           regs.RdMem(regs.pc++)
70 #define EA_ZP_X                         (regs.RdMem(regs.pc++) + regs.x)
71 #define EA_ABS                          FetchMemW(regs.pc)
72
73 #define READ_IMM                        regs.RdMem(EA_IMM)
74 #define READ_ZP                         regs.RdMem(EA_ZP)
75 #define READ_ZP_X                       regs.RdMem(EA_ZP_X)
76 #define READ_ABS                        regs.RdMem(EA_ABS)
77
78 #define READ_IMM16                      FetchMemW(regs.pc);
79 #define READ_ZP16                       RdMemW(EA_ZP)
80 #define READ_ZP_X16                     RdMemW(EA_ZP_X)
81 #define READ_ABS16                      RdMemW(EA_ABS)
82
83 #define READ_IMM_WB(v)          uint16_t addr = EA_IMM;         v = regs.RdMem(addr)
84 #define READ_ZP_WB(v)           uint16_t addr = EA_ZP;          v = regs.RdMem(addr)
85 #define READ_ZP_X_WB(v)         uint16_t addr = EA_ZP_X;        v = regs.RdMem(addr)
86 #define READ_ABS_WB(v)          uint16_t addr = EA_ABS;         v = regs.RdMem(addr)
87
88 #define WRITE_BACK(d)           regs.WrMem(addr, (d))
89
90 // This is correct; PUSH writes the location *then* decrements the stack
91 // pointer, and PULL does the opposite. Verified from the data sheet.
92 #define PULL                            regs.RdMem(++regs.s)
93 #define PUSH(r)                         regs.WrMem(regs.s--, (r))
94 #define PULL16                          RdMemW(++regs.s);       ++regs.s;
95 #define PUSH16(r)                       regs.WrMem(regs.s--, (r) & 0xFF); regs.WrMem(regs.s--, (r) >> 8)
96
97 #define PACK_FLAGS                      ((regs.cc & 0xC0) | (flagH << 5) | (flagI << 4) | (flagN << 3) | (flagZ << 2) | (flagV << 1) | flagC)
98 #define UNPACK_FLAGS            flagH = (regs.cc & FLAG_H) >> 5; \
99         flagI = (regs.cc & FLAG_I) >> 4; \
100         flagN = (regs.cc & FLAG_N) >> 3; \
101         flagZ = (regs.cc & FLAG_Z) >> 2; \
102         flagV = (regs.cc & FLAG_V) >> 1; \
103         flagC = (regs.cc & FLAG_C)
104
105 // Private global variables
106
107 static V63701REGS regs;
108 //V63701REGS regs;
109 static V63701REGS * regsPointer;
110 //V63701REGS * regsPointer;
111 static uint8_t flagH, flagI, flagN, flagZ, flagV, flagC;
112
113 static uint8_t CPUCycles[256] = {
114         0,  1,  0,  0,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,
115         1,  1,  0,  0,  0,  0,  1,  1,  2,  2,  4,  1,  0,  0,  0,  0,
116         3,  3,  3,  3,  3,  3,  3,  3,  3,  3,  3,  3,  3,  3,  3,  3,
117         1,  1,  3,  3,  1,  1,  4,  4,  4,  5,  1, 10,  5,  7,  9, 12,
118         1,  0,  0,  1,  1,  0,  1,  1,  1,  1,  1,  0,  1,  1,  0,  1,
119         1,  0,  0,  1,  1,  0,  1,  1,  1,  1,  1,  0,  1,  1,  0,  1,
120         6,  7,  7,  6,  6,  7,  6,  6,  6,  6,  6,  5,  6,  4,  3,  5,
121         6,  6,  6,  6,  6,  6,  6,  6,  6,  6,  6,  4,  6,  4,  3,  5,
122         2,  2,  2,  3,  2,  2,  2,  0,  2,  2,  2,  2,  3,  5,  3,  0,
123         3,  3,  3,  4,  3,  3,  3,  3,  3,  3,  3,  3,  4,  5,  4,  4,
124         4,  4,  4,  5,  4,  4,  4,  4,  4,  4,  4,  4,  5,  5,  5,  5,
125         4,  4,  4,  5,  4,  4,  4,  4,  4,  4,  4,  4,  5,  6,  5,  5,
126         2,  2,  2,  3,  2,  2,  2,  0,  2,  2,  2,  2,  3,  0,  3,  0,
127         3,  3,  3,  4,  3,  3,  3,  3,  3,  3,  3,  3,  4,  4,  4,  4,
128         4,  4,  4,  5,  4,  4,  4,  4,  4,  4,  4,  4,  5,  5,  5,  5,
129         4,  4,  4,  5,  4,  4,  4,  4,  4,  4,  4,  4,  5,  5,  5,  5
130 };
131
132 // Private function prototypes
133
134 static uint16_t RdMemW(uint16_t);
135 static uint16_t FetchMemW(uint16_t);
136 static inline void HandleInterrupt(uint16_t, uint16_t flag = 0);
137
138 //
139 // Read a word out of 63701 memory (little endian format)
140 //
141 static inline uint16_t RdMemW(uint16_t address)
142 {
143         return (uint16_t)(regs.RdMem(address) << 8) | regs.RdMem(address + 1);
144 }
145
146 //
147 // Fetch a word out of 63701 memory (little endian format). Increments PC
148 //
149 static inline uint16_t FetchMemW(uint16_t address)
150 {
151         regs.pc += 2;
152         return (uint16_t)(regs.RdMem(address) << 8) | regs.RdMem(address + 1);
153 }
154
155 //
156 // 63701 OPCODE IMPLEMENTATION
157 //
158 // NOTE: Lots of macros are used here to save a LOT of typing. Also
159 //       helps speed the debugging process. :-) Because of this, combining
160 //       certain lines may look like a good idea but would end in disaster.
161 //       You have been warned! ;-)
162 //
163
164 /*
165 Operation               |Mnem.|Immed.|Direct|Index |Extend|Inher.|Operation |CC Reg|
166                         |     |OP ~ #|OP ~ #|OP ~ #|OP ~ #|OP ~ #|          |HINZVC|
167 Add                     |ADDA |8B 2 2|9B 3 2|AB 5 2|BB 4 3|      |A=A+M     |T TTTT|
168                         |ADDB |CB 2 2|DB 3 2|EB 5 2|FB 4 3|      |B=B+M     |T TTTT|
169 Add Accumulators        |ABA  |      |      |      |      |1B 2 1|A=A+B     |T TTTT|
170 */
171
172 // ADD opcodes
173
174 #define OP_ADD_HANDLER(m, acc) \
175         uint16_t sum = (uint16_t)(acc) + (m); \
176         flagC = sum >> 8; \
177         flagH = (sum >> 4) & 0x01; \
178         SET_V(m, acc, sum); \
179         (acc) = sum & 0xFF; \
180         SET_ZN(acc)
181
182 #define OP_ADD_HANDLER16(m, acc) \
183         uint32_t sum = (uint32_t)(acc) + (m); \
184         flagC = sum >> 16; \
185         SET_V16(m, acc, sum); \
186         (acc) = sum & 0xFFFF; \
187         SET_Z(acc); \
188         SET_N16(acc)
189
190 static void Op8B(void)          // ADDA #
191 {
192         uint16_t m = READ_IMM;
193         OP_ADD_HANDLER(m, regs.d.acc.a);
194 }
195
196 static void Op9B(void)          // ADDA ZP
197 {
198         uint16_t m = READ_ZP;
199         OP_ADD_HANDLER(m, regs.d.acc.a);
200 }
201
202 static void OpAB(void)          // ADDA ZP, X
203 {
204         uint16_t m = READ_ZP_X;
205         OP_ADD_HANDLER(m, regs.d.acc.a);
206 }
207
208 static void OpBB(void)          // ADDA ABS
209 {
210         uint16_t m = READ_ABS;
211         OP_ADD_HANDLER(m, regs.d.acc.a);
212 }
213
214 static void OpCB(void)          // ADDB #
215 {
216         uint16_t m = READ_IMM;
217         OP_ADD_HANDLER(m, regs.d.acc.b);
218 }
219
220 static void OpDB(void)          // ADDB ZP
221 {
222         uint16_t m = READ_ZP;
223         OP_ADD_HANDLER(m, regs.d.acc.b);
224 }
225
226 static void OpEB(void)          // ADDB ZP, X
227 {
228         uint16_t m = READ_ZP_X;
229         OP_ADD_HANDLER(m, regs.d.acc.b);
230 }
231
232 static void OpFB(void)          // ADDB ABS
233 {
234         uint16_t m = READ_ABS;
235         OP_ADD_HANDLER(m, regs.d.acc.b);
236 }
237
238 static void Op1B(void)          // ABA
239 {
240         OP_ADD_HANDLER(regs.d.acc.b, regs.d.acc.a);
241 }
242
243 static void Op3A(void)          // ABX
244 {
245         // Seems this one does *not* affect any flags...
246         regs.x += (uint16_t)regs.d.acc.b;
247 }
248
249 static void OpC3(void)          // ADDD #
250 {
251         uint16_t m = READ_IMM16;
252         OP_ADD_HANDLER16(m, regs.d.word);
253 }
254
255 static void OpD3(void)          // ADDD ZP
256 {
257         uint16_t m = READ_ZP16;
258         OP_ADD_HANDLER16(m, regs.d.word);
259 }
260
261 static void OpE3(void)          // ADDD ZP, X
262 {
263         uint16_t m = READ_ZP_X16;
264         OP_ADD_HANDLER16(m, regs.d.word);
265 }
266
267 static void OpF3(void)          // ADDD ABS
268 {
269         uint16_t m = READ_ABS16;
270         OP_ADD_HANDLER16(m, regs.d.word);
271 }
272
273 /*
274 Operation               |Mnem.|Immed.|Direct|Index |Extend|Inher.|Operation |CC Reg|
275                         |     |OP ~ #|OP ~ #|OP ~ #|OP ~ #|OP ~ #|          |HINZVC|
276 Add with Carry          |ADCA |89 2 2|99 3 2|A9 5 2|B9 4 3|      |A=A+M+C   |T TTTT|
277                         |ADCB |C9 2 2|D9 3 2|E9 5 2|F9 4 3|      |B=B+M+C   |T TTTT|
278 */
279
280 // ADC opcodes
281
282 #define OP_ADC_HANDLER(m, acc) \
283         uint16_t sum = (uint16_t)acc + (m) + (uint16_t)flagC; \
284         flagC = sum >> 8; \
285         flagH = (sum >> 4) & 0x01; \
286         SET_V(m, acc, sum); \
287         acc = sum & 0xFF; \
288         SET_ZN(acc)
289
290 static void Op89(void)                                                  // ADCA #
291 {
292         uint16_t m = READ_IMM;
293         OP_ADC_HANDLER(m, regs.d.acc.a);
294 }
295
296 static void Op99(void)                                                  // ADCA ZP
297 {
298         uint16_t m = READ_ZP;
299         OP_ADC_HANDLER(m, regs.d.acc.a);
300 }
301
302 static void OpA9(void)                                                  // ADCA ZP, X
303 {
304         uint16_t m = READ_ZP_X;
305         OP_ADC_HANDLER(m, regs.d.acc.a);
306 }
307
308 static void OpB9(void)                                                  // ADCA ABS
309 {
310         uint16_t m = READ_ABS;
311         OP_ADC_HANDLER(m, regs.d.acc.a);
312 }
313
314 static void OpC9(void)                                                  // ADCB #
315 {
316         uint16_t m = READ_IMM;
317         OP_ADC_HANDLER(m, regs.d.acc.b);
318 }
319
320 static void OpD9(void)                                                  // ADCB ZP
321 {
322         uint16_t m = READ_ZP;
323         OP_ADC_HANDLER(m, regs.d.acc.b);
324 }
325
326 static void OpE9(void)                                                  // ADCB ZP, X
327 {
328         uint16_t m = READ_ZP_X;
329         OP_ADC_HANDLER(m, regs.d.acc.b);
330 }
331
332 static void OpF9(void)                                                  // ADCB ABS
333 {
334         uint16_t m = READ_ABS;
335         OP_ADC_HANDLER(m, regs.d.acc.b);
336 }
337
338 /*
339 Operation               |Mnem.|Immed.|Direct|Index |Extend|Inher.|Operation |CC Reg|
340                         |     |OP ~ #|OP ~ #|OP ~ #|OP ~ #|OP ~ #|          |HINZVC|
341 And                     |ANDA |84 2 2|94 3 2|A4 5 2|B4 4 3|      |A=A+M     |  TTR |
342                         |ANDB |C4 2 2|D4 3 2|E4 5 2|F4 4 3|      |B=B+M     |  TTR |
343 */
344
345 // AND opcodes
346
347 #define OP_AND_HANDLER(m, acc) \
348         acc &= m; \
349         SET_ZN(acc); \
350         CLR_V
351
352 static void Op84(void)          // ANDA #
353 {
354         uint8_t m = READ_IMM;
355         OP_AND_HANDLER(m, regs.d.acc.a);
356 }
357
358 static void Op94(void)          // ANDA ZP
359 {
360         uint8_t m = READ_ZP;
361         OP_AND_HANDLER(m, regs.d.acc.a);
362 }
363
364 static void OpA4(void)          // ANDA ZP, X
365 {
366         uint16_t m = READ_ZP_X;
367         OP_AND_HANDLER(m, regs.d.acc.a);
368 }
369
370 static void OpB4(void)          // ANDA ABS
371 {
372         uint16_t m = READ_ABS;
373         OP_AND_HANDLER(m, regs.d.acc.a);
374 }
375
376 static void OpC4(void)          // ANDB #
377 {
378         uint8_t m = READ_IMM;
379         OP_AND_HANDLER(m, regs.d.acc.b);
380 }
381
382 static void OpD4(void)          // ANDB ZP
383 {
384         uint8_t m = READ_ZP;
385         OP_AND_HANDLER(m, regs.d.acc.b);
386 }
387
388 static void OpE4(void)          // ANDB ZP, X
389 {
390         uint16_t m = READ_ZP_X;
391         OP_AND_HANDLER(m, regs.d.acc.b);
392 }
393
394 static void OpF4(void)          // ANDB ABS
395 {
396         uint16_t m = READ_ABS;
397         OP_AND_HANDLER(m, regs.d.acc.b);
398 }
399
400 static void Op61(void)          // AIM ZP, X (AND immediate with index)
401 {
402         uint8_t m;
403         uint8_t immValue = READ_IMM;
404         READ_ZP_X_WB(m);
405         OP_AND_HANDLER(immValue, m);
406         WRITE_BACK(m);
407 }
408
409 static void Op71(void)          // AIM ZP (AND immediate with zero page)
410 {
411         uint8_t m;
412         uint8_t immValue = READ_IMM;
413         READ_ZP_WB(m);
414         OP_AND_HANDLER(immValue, m);
415         WRITE_BACK(m);
416 }
417
418 /*
419 Operation               |Mnem.|Immed.|Direct|Index |Extend|Inher.|Operation |CC Reg|
420                         |     |OP ~ #|OP ~ #|OP ~ #|OP ~ #|OP ~ #|          |HINZVC|
421 Bit Test                |BITA |85 2 2|95 3 2|A5 5 2|B5 4 3|      |A+M       |  TTR |
422                         |BITB |C5 2 2|D5 3 2|E5 5 2|F5 4 3|      |B+M       |  TTR |
423 */
424
425 // BIT opcodes
426
427 #define OP_BIT_HANDLER(m, acc) \
428         int8_t result = acc & (m); \
429         SET_ZN(result)
430
431 static void Op85(void)                                                  // BITA #
432 {
433         uint8_t m = READ_IMM;
434         OP_BIT_HANDLER(m, regs.d.acc.a);
435 }
436
437 static void Op95(void)                                                  // BITA ZP
438 {
439         uint8_t m = READ_ZP;
440         OP_BIT_HANDLER(m, regs.d.acc.a);
441 }
442
443 static void OpA5(void)                                                  // BITA ZP, X
444 {
445         uint8_t m = READ_ZP_X;
446         OP_BIT_HANDLER(m, regs.d.acc.a);
447 }
448
449 static void OpB5(void)                                                  // BITA ABS
450 {
451         uint8_t m = READ_ABS;
452         OP_BIT_HANDLER(m, regs.d.acc.a);
453 }
454
455 static void OpC5(void)                                                  // BITB #
456 {
457         uint8_t m = READ_IMM;
458         OP_BIT_HANDLER(m, regs.d.acc.b);
459 }
460
461 static void OpD5(void)                                                  // BITB ZP
462 {
463         uint8_t m = READ_ZP;
464         OP_BIT_HANDLER(m, regs.d.acc.b);
465 }
466
467 static void OpE5(void)                                                  // BITB ZP, X
468 {
469         uint8_t m = READ_ZP_X;
470         OP_BIT_HANDLER(m, regs.d.acc.b);
471 }
472
473 static void OpF5(void)                                                  // BITB ABS
474 {
475         uint8_t m = READ_ABS;
476         OP_BIT_HANDLER(m, regs.d.acc.b);
477 }
478
479 /*
480 Operation               |Mnem.|Immed.|Direct|Index |Extend|Inher.|Operation |CC Reg|
481                         |     |OP ~ #|OP ~ #|OP ~ #|OP ~ #|OP ~ #|          |HINZVC|
482 Clear                   |CLR  |      |      |6F 7 2|7F 6 3|      |M=00      |  RSRR|
483                         |CLRA |      |      |      |      |4F 2 1|A=00      |  RSRR|
484                         |CLRB |      |      |      |      |5F 2 1|B=00      |  RSRR|
485 */
486
487 // CLR opcodes
488
489 static void Op6F(void)                                                  // CLR ZP, X
490 {
491         regs.WrMem(EA_ZP_X, 0);
492         CLR_NVC;
493         SET_Z(0);
494 }
495
496 static void Op7F(void)                                                  // CLR ABS
497 {
498         regs.WrMem(EA_ABS, 0);
499         CLR_NVC;
500         SET_Z(0);
501 }
502
503 static void Op4F(void)                                                  // CLRA
504 {
505         regs.d.acc.a = 0;
506         CLR_NVC;
507         SET_Z(0);
508 }
509
510 static void Op5F(void)                                                  // CLRB
511 {
512         regs.d.acc.b = 0;
513         CLR_NVC;
514         SET_Z(0);
515 }
516
517 /*
518 Operation               |Mnem.|Immed.|Direct|Index |Extend|Inher.|Operation |CC Reg|
519                         |     |OP ~ #|OP ~ #|OP ~ #|OP ~ #|OP ~ #|          |HINZVC|
520 Compare                 |CMPA |81 2 2|91 3 2|A1 5 2|B1 4 3|      |A-M       |  TTTT|
521                         |CMPB |C1 2 2|D1 3 2|E1 5 2|F1 4 3|      |B-M       |  TTTT|
522 Compare Accumulators    |CBA  |      |      |      |      |11 2 1|A-B       |  TTTT|
523 */
524
525 // CMP opcodes
526
527 /*
528 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.
529 */
530
531 #define OP_CMP_HANDLER(m, acc) \
532         uint16_t result = acc - (m); \
533         SET_ZNVC_CMP(m, acc, result)
534
535 static void Op81(void)                                                  // CMPA #
536 {
537         uint8_t m = READ_IMM;
538         OP_CMP_HANDLER(m, regs.d.acc.a);
539 }
540
541 static void Op91(void)                                                  // CMPA ZP
542 {
543         uint8_t m = READ_ZP;
544         OP_CMP_HANDLER(m, regs.d.acc.a);
545 }
546
547 static void OpA1(void)                                                  // CMPA ZP, X
548 {
549         uint8_t m = READ_ZP_X;
550         OP_CMP_HANDLER(m, regs.d.acc.a);
551 }
552
553 static void OpB1(void)                                                  // CMPA ABS
554 {
555         uint8_t m = READ_ABS;
556         OP_CMP_HANDLER(m, regs.d.acc.a);
557 }
558
559 static void OpC1(void)                                                  // CMPB #
560 {
561         uint8_t m = READ_IMM;
562         OP_CMP_HANDLER(m, regs.d.acc.b);
563 }
564
565 static void OpD1(void)                                                  // CMPB ZP
566 {
567         uint8_t m = READ_ZP;
568         OP_CMP_HANDLER(m, regs.d.acc.b);
569 }
570
571 static void OpE1(void)                                                  // CMPB ZP, X
572 {
573         uint8_t m = READ_ZP_X;
574         OP_CMP_HANDLER(m, regs.d.acc.b);
575 }
576
577 static void OpF1(void)                                                  // CMPB ABS
578 {
579         uint8_t m = READ_ABS;
580         OP_CMP_HANDLER(m, regs.d.acc.b);
581 }
582
583 static void Op11(void)                                                  // CBA
584 {
585         OP_CMP_HANDLER(regs.d.acc.b, regs.d.acc.a);
586 }
587
588 /*
589 Operation               |Mnem.|Immed.|Direct|Index |Extend|Inher.|Operation |CC Reg|
590                         |     |OP ~ #|OP ~ #|OP ~ #|OP ~ #|OP ~ #|          |HINZVC|
591 Complement 1's          |COM  |      |      |63 7 2|73 6 3|      |M=-M      |  TTRS|
592                         |COMA |      |      |      |      |43 2 1|A=-A      |  TTRS|
593                         |COMB |      |      |      |      |53 2 1|B=-B      |  TTRS|
594 */
595
596 // COM opcodes
597
598 #define OP_COM_HANDLER(m) \
599         m = m ^ 0xFF; \
600         SET_ZN(m); \
601         CLR_V; \
602         flagC = 1
603
604 static void Op63(void)                                                  // COM ZP, X
605 {
606         uint8_t m;
607         READ_ZP_X_WB(m);
608         OP_COM_HANDLER(m);
609         WRITE_BACK(m);
610 }
611
612 static void Op73(void)                                                  // COM ABS
613 {
614         uint8_t m;
615         READ_ABS_WB(m);
616         OP_COM_HANDLER(m);
617         WRITE_BACK(m);
618 }
619
620 static void Op43(void)                                                  // COMA
621 {
622         OP_COM_HANDLER(regs.d.acc.a);
623 }
624
625 static void Op53(void)                                                  // COMB
626 {
627         OP_COM_HANDLER(regs.d.acc.b);
628 }
629
630 /*
631 Operation               |Mnem.|Immed.|Direct|Index |Extend|Inher.|Operation |CC Reg|
632                         |     |OP ~ #|OP ~ #|OP ~ #|OP ~ #|OP ~ #|          |HINZVC|
633 Complement 2's          |NEG  |      |      |60 7 2|70 6 3|      |M=00-M    |  TT12|
634                         |NEGA |      |      |      |      |40 2 1|A=00-A    |  TT12|
635                         |NEGB |      |      |      |      |50 2 1|B=00-B    |  TT12|
636 */
637
638 // NEG opcodes
639
640 #define OP_NEG_HANDLER(m) \
641         m = -m; \
642         SET_ZN(m); \
643         flagV = (m == 0x80 ? 1 : 0); \
644         flagC = (m == 0x00 ? 1 : 0)
645
646 static void Op60(void)                                                  // NEG ZP, X
647 {
648         uint8_t m;
649         READ_ZP_X_WB(m);
650         OP_NEG_HANDLER(m);
651         WRITE_BACK(m);
652 }
653
654 static void Op70(void)                                                  // NEG ABS
655 {
656         uint8_t m;
657         READ_ABS_WB(m);
658         OP_NEG_HANDLER(m);
659         WRITE_BACK(m);
660 }
661
662 static void Op40(void)                                                  // NEGA
663 {
664         OP_NEG_HANDLER(regs.d.acc.a);
665 }
666
667 static void Op50(void)                                                  // NEGB
668 {
669         OP_NEG_HANDLER(regs.d.acc.b);
670 }
671
672 /*
673 Operation               |Mnem.|Immed.|Direct|Index |Extend|Inher.|Operation |CC Reg|
674                         |     |OP ~ #|OP ~ #|OP ~ #|OP ~ #|OP ~ #|          |HINZVC|
675 Decimal Adjust          |DAA  |      |      |      |      |19 2 1|*         |  TTT3|
676 */
677
678 static void Op19(void)                                                  // DAA
679 {
680         uint16_t result = (uint16_t)regs.d.acc.a;
681
682         if ((regs.d.acc.a & 0x0F) > 0x09 || flagH)
683                 result += 0x06;
684
685         if ((regs.d.acc.a & 0xF0) > 0x90 || flagC || ((regs.d.acc.a & 0xF0) > 0x80 && (regs.d.acc.a & 0x0F) > 0x09))
686                 result += 0x60;
687
688         regs.d.acc.a = (uint8_t)result;
689         SET_ZN(result);
690         CLR_V;                                                                          // Not sure this is correct...
691         flagC |= (result & 0x100) >> 8;                         // Overwrite carry if it was 0, otherwise, ignore
692 }
693
694 /*
695 Operation               |Mnem.|Immed.|Direct|Index |Extend|Inher.|Operation |CC Reg|
696                         |     |OP ~ #|OP ~ #|OP ~ #|OP ~ #|OP ~ #|          |HINZVC|
697 Decrement               |DEC  |      |      |6A 7 2|7A 6 3|      |M=M-1     |  TT4 |
698                         |DECA |      |      |      |      |4A 2 1|A=A-1     |  TT4 |
699                         |DECB |      |      |      |      |5A 2 1|B=B-1     |  TT4 |
700 */
701
702 // DEC opcodes
703
704 #define OP_DEC_HANDLER(m) \
705         m--; \
706         SET_ZN(m); \
707         flagV = (m == 0x7F ? 1 : 0)
708
709 static void Op6A(void)                                                  // DEC ZP, X
710 {
711         uint8_t m;
712         READ_ZP_X_WB(m);
713         OP_DEC_HANDLER(m);
714         WRITE_BACK(m);
715 }
716
717 static void Op7A(void)                                                  // DEC ABS
718 {
719         uint8_t m;
720         READ_ABS_WB(m);
721         OP_DEC_HANDLER(m);
722         WRITE_BACK(m);
723 }
724
725 static void Op4A(void)                                                  // DECA
726 {
727         OP_DEC_HANDLER(regs.d.acc.a);
728 }
729
730 static void Op5A(void)                                                  // DECB
731 {
732         OP_DEC_HANDLER(regs.d.acc.b);
733 }
734
735 /*
736 Operation               |Mnem.|Immed.|Direct|Index |Extend|Inher.|Operation |CC Reg|
737                         |     |OP ~ #|OP ~ #|OP ~ #|OP ~ #|OP ~ #|          |HINZVC|
738 Exclusive OR            |EORA |88 2 2|98 3 2|A8 5 2|B8 4 3|      |A=A(+)M   |  TTR |
739                         |EORB |C8 2 2|D8 3 2|E8 5 2|F8 4 3|      |B=B(+)M   |  TTR |
740 */
741
742 // EOR opcodes
743
744 #define OP_EOR_HANDLER(m, acc) \
745         acc ^= m; \
746         SET_ZN(acc); \
747         CLR_V
748
749 static void Op88(void)          // EORA #
750 {
751         uint8_t m = READ_IMM;
752         OP_EOR_HANDLER(m, regs.d.acc.a);
753 }
754
755 static void Op98(void)          // EORA ZP
756 {
757         uint8_t m = READ_ZP;
758         OP_EOR_HANDLER(m, regs.d.acc.a);
759 }
760
761 static void OpA8(void)          // EORA ZP, X
762 {
763         uint8_t m = READ_ZP_X;
764         OP_EOR_HANDLER(m, regs.d.acc.a);
765 }
766
767 static void OpB8(void)          // EORA ABS
768 {
769         uint8_t m = READ_ABS;
770         OP_EOR_HANDLER(m, regs.d.acc.a);
771 }
772
773 static void OpC8(void)          // EORB #
774 {
775         uint8_t m = READ_IMM;
776         OP_EOR_HANDLER(m, regs.d.acc.b);
777 }
778
779 static void OpD8(void)          // EORB ZP
780 {
781         uint8_t m = READ_ZP;
782         OP_EOR_HANDLER(m, regs.d.acc.b);
783 }
784
785 static void OpE8(void)          // EORB ZP, X
786 {
787         uint8_t m = READ_ZP_X;
788         OP_EOR_HANDLER(m, regs.d.acc.b);
789 }
790
791 static void OpF8(void)          // EORB ABS
792 {
793         uint8_t m = READ_ABS;
794         OP_EOR_HANDLER(m, regs.d.acc.b);
795 }
796
797 static void Op65(void)          // EIM ZP, X (EOR immediate with index)
798 {
799         uint8_t m;
800         uint8_t immValue = READ_IMM;
801         READ_ZP_X_WB(m);
802         OP_EOR_HANDLER(immValue, m);
803         WRITE_BACK(m);
804 }
805
806 static void Op75(void)          // EIM ZP (EOR immediate with zero page)
807 {
808         uint8_t m;
809         uint8_t immValue = READ_IMM;
810         READ_ZP_WB(m);
811         OP_EOR_HANDLER(immValue, m);
812         WRITE_BACK(m);
813 }
814
815 /*
816 Operation               |Mnem.|Immed.|Direct|Index |Extend|Inher.|Operation |CC Reg|
817                         |     |OP ~ #|OP ~ #|OP ~ #|OP ~ #|OP ~ #|          |HINZVC|
818 Increment               |INC  |      |      |6C 7 2|7C 6 3|      |M=M+1     |  TT5 |
819                         |INCA |      |      |      |      |4C 2 1|A=A+1     |  TT5 |
820                         |INCB |      |      |      |      |5C 2 1|B=B+1     |  TT5 |
821 */
822
823 // INC opcodes
824
825 #define OP_INC_HANDLER(m) \
826         m++; \
827         SET_ZN(m); \
828         flagV = (m == 0x80 ? 1 : 0)
829
830 static void Op6C(void)                                                  // INC ZP, X
831 {
832         uint8_t m;
833         READ_ZP_X_WB(m);
834         OP_INC_HANDLER(m);
835         WRITE_BACK(m);
836 }
837
838 static void Op7C(void)                                                  // INC ABS
839 {
840         uint8_t m;
841         READ_ABS_WB(m);
842         OP_INC_HANDLER(m);
843         WRITE_BACK(m);
844 }
845
846 static void Op4C(void)                                                  // INCA
847 {
848         OP_INC_HANDLER(regs.d.acc.a);
849 }
850
851 static void Op5C(void)                                                  // INCB
852 {
853         OP_INC_HANDLER(regs.d.acc.b);
854 }
855
856 /*
857 Operation               |Mnem.|Immed.|Direct|Index |Extend|Inher.|Operation |CC Reg|
858                         |     |OP ~ #|OP ~ #|OP ~ #|OP ~ #|OP ~ #|          |HINZVC|
859 Load Accumulator        |LDAA |86 2 2|96 3 2|A6 5 2|B6 4 3|      |A=M       |  TTR |
860                         |LDAB |C6 2 2|D6 3 2|E6 5 2|F6 4 3|      |B=M       |  TTR |
861 */
862
863 // LDA opcodes
864
865 #define OP_LDA_HANDLER(m, acc) \
866         acc = m; \
867         SET_ZN(acc); \
868         CLR_V
869
870 static void Op86(void)                                                  // LDAA #
871 {
872         uint8_t m = READ_IMM;
873         OP_LDA_HANDLER(m, regs.d.acc.a);
874 }
875
876 static void Op96(void)                                                  // LDAA ZP
877 {
878         uint8_t m = READ_ZP;
879         OP_LDA_HANDLER(m, regs.d.acc.a);
880 }
881
882 static void OpA6(void)                                                  // LDAA ZP, X
883 {
884         uint8_t m = READ_ZP_X;
885         OP_LDA_HANDLER(m, regs.d.acc.a);
886 }
887
888 static void OpB6(void)                                                  // LDAA ABS
889 {
890         uint8_t m = READ_ABS;
891         OP_LDA_HANDLER(m, regs.d.acc.a);
892 }
893
894 static void OpC6(void)                                                  // LDAB #
895 {
896         uint8_t m = READ_IMM;
897         OP_LDA_HANDLER(m, regs.d.acc.b);
898 }
899
900 static void OpD6(void)                                                  // LDAB ZP
901 {
902         uint8_t m = READ_ZP;
903         OP_LDA_HANDLER(m, regs.d.acc.b);
904 }
905
906 static void OpE6(void)                                                  // LDAB ZP, X
907 {
908         uint8_t m = READ_ZP_X;
909         OP_LDA_HANDLER(m, regs.d.acc.b);
910 }
911
912 static void OpF6(void)                                                  // LDAB ABS
913 {
914         uint8_t m = READ_ABS;
915         OP_LDA_HANDLER(m, regs.d.acc.b);
916 }
917
918 /*
919 Operation               |Mnem.|Immed.|Direct|Index |Extend|Inher.|Operation |CC Reg|
920                         |     |OP ~ #|OP ~ #|OP ~ #|OP ~ #|OP ~ #|          |HINZVC|
921 OR, Inclusive           |ORAA |8A 2 2|9A 3 2|AA 5 2|BA 4 3|      |A=A+M     |  TTR |
922                         |ORAB |CA 2 2|DA 3 2|EA 5 2|FA 4 3|      |B=B+M     |  TTR |
923 */
924
925 // ORA opcodes
926
927 #define OP_ORA_HANDLER(m, acc) \
928         acc |= m; \
929         SET_ZN(acc); \
930         CLR_V
931
932 static void Op8A(void)          // ORAA #
933 {
934         uint8_t m = READ_IMM;
935         OP_ORA_HANDLER(m, regs.d.acc.a);
936 }
937
938 static void Op9A(void)          // ORAA ZP
939 {
940         uint8_t m = READ_ZP;
941         OP_ORA_HANDLER(m, regs.d.acc.a);
942 }
943
944 static void OpAA(void)          // ORAA ZP, X
945 {
946         uint8_t m = READ_ZP_X;
947         OP_ORA_HANDLER(m, regs.d.acc.a);
948 }
949
950 static void OpBA(void)          // ORAA ABS
951 {
952         uint8_t m = READ_ABS;
953         OP_ORA_HANDLER(m, regs.d.acc.a);
954 }
955
956 static void OpCA(void)          // ORAB #
957 {
958         uint8_t m = READ_IMM;
959         OP_ORA_HANDLER(m, regs.d.acc.b);
960 }
961
962 static void OpDA(void)          // ORAB ZP
963 {
964         uint8_t m = READ_ZP;
965         OP_ORA_HANDLER(m, regs.d.acc.b);
966 }
967
968 static void OpEA(void)          // ORAB ZP, X
969 {
970         uint8_t m = READ_ZP_X;
971         OP_ORA_HANDLER(m, regs.d.acc.b);
972 }
973
974 static void OpFA(void)          // ORAB ABS
975 {
976         uint8_t m = READ_ABS;
977         OP_ORA_HANDLER(m, regs.d.acc.b);
978 }
979
980 static void Op62(void)          // OIM ZP, X (ORA immediate with index)
981 {
982         uint8_t m;
983         uint8_t immValue = READ_IMM;
984         READ_ZP_X_WB(m);
985         OP_ORA_HANDLER(immValue, m);
986         WRITE_BACK(m);
987 }
988
989 static void Op72(void)          // OIM ZP (ORA immediate with zero page)
990 {
991         uint8_t m;
992         uint8_t immValue = READ_IMM;
993         READ_ZP_WB(m);
994         OP_ORA_HANDLER(immValue, m);
995         WRITE_BACK(m);
996 }
997
998 /*
999 Operation               |Mnem.|Immed.|Direct|Index |Extend|Inher.|Operation |CC Reg|
1000                         |     |OP ~ #|OP ~ #|OP ~ #|OP ~ #|OP ~ #|          |HINZVC|
1001 Push Data               |PSHA |      |      |      |      |36 4 1|Msp=A, *- |      |
1002                         |PSHB |      |      |      |      |37 4 1|Msp=B, *- |      |
1003 Pull Data               |PULA |      |      |      |      |32 4 1|A=Msp, *+ |      |
1004                         |PULB |      |      |      |      |33 4 1|B=Msp, *+ |      |
1005 */
1006
1007 static void Op36(void)                                                  // PSHA
1008 {
1009         PUSH(regs.d.acc.a);
1010 }
1011
1012 static void Op37(void)                                                  // PSHB
1013 {
1014         PUSH(regs.d.acc.b);
1015 }
1016
1017 static void Op32(void)                                                  // PULA
1018 {
1019         regs.d.acc.a = PULL;
1020 }
1021
1022 static void Op33(void)                                                  // PULB
1023 {
1024         regs.d.acc.b = PULL;
1025 }
1026
1027 static void Op38(void)                                                  // PULX
1028 {
1029         regs.x = PULL16;
1030 }
1031
1032 static void Op3C(void)                                                  // PSHX
1033 {
1034         PUSH16(regs.x);
1035 }
1036
1037 /*
1038 Operation               |Mnem.|Immed.|Direct|Index |Extend|Inher.|Operation |CC Reg|
1039                         |     |OP ~ #|OP ~ #|OP ~ #|OP ~ #|OP ~ #|          |HINZVC|
1040 Rotate Left             |ROL  |      |      |69 7 2|79 6 3|      |Memory  *1|  TT6T|
1041                         |ROLA |      |      |      |      |49 2 1|Accum A *1|  TT6T|
1042                         |ROLB |      |      |      |      |59 2 1|Accum B *1|  TT6T|
1043 */
1044
1045 // ROL opcodes
1046
1047 #define OP_ROL_HANDLER(m) \
1048         uint8_t newCarry = (m & 0x80) >> 7; \
1049         m = (m << 1) | flagC; \
1050         SET_ZN(m); \
1051         flagC = newCarry; \
1052         flagV = flagN ^ flagC
1053
1054 static void Op69(void)                                                  // ROL ZP, X
1055 {
1056         uint8_t m;
1057         READ_ZP_X_WB(m);
1058         OP_ROL_HANDLER(m);
1059         WRITE_BACK(m);
1060 }
1061
1062 static void Op79(void)                                                  // ROL ABS
1063 {
1064         uint8_t m;
1065         READ_ABS_WB(m);
1066         OP_ROL_HANDLER(m);
1067         WRITE_BACK(m);
1068 }
1069
1070 static void Op49(void)                                                  // ROLA
1071 {
1072         OP_ROL_HANDLER(regs.d.acc.a);
1073 }
1074
1075 static void Op59(void)                                                  // ROLB
1076 {
1077         OP_ROL_HANDLER(regs.d.acc.b);
1078 }
1079
1080 /*
1081 Operation               |Mnem.|Immed.|Direct|Index |Extend|Inher.|Operation |CC Reg|
1082                         |     |OP ~ #|OP ~ #|OP ~ #|OP ~ #|OP ~ #|          |HINZVC|
1083 Rotate Right            |ROR  |      |      |66 7 2|76 6 3|      |Memory  *2|  TT6T|
1084                         |RORA |      |      |      |      |46 2 1|Accum A *2|  TT6T|
1085                         |RORB |      |      |      |      |56 2 1|Accum B *2|  TT6T|
1086 */
1087
1088 // ROR opcodes
1089
1090 #define OP_ROR_HANDLER(m) \
1091         uint8_t newCarry = m & 0x01; \
1092         m = (m >> 1) | (flagC << 7); \
1093         SET_ZN(m); \
1094         flagC = newCarry; \
1095         flagV = flagN ^ flagC
1096
1097 static void Op66(void)                                                  // ROR ZP, X
1098 {
1099         uint8_t m;
1100         READ_ZP_X_WB(m);
1101         OP_ROR_HANDLER(m);
1102         WRITE_BACK(m);
1103 }
1104
1105 static void Op76(void)                                                  // ROR ABS
1106 {
1107         uint8_t m;
1108         READ_ABS_WB(m);
1109         OP_ROR_HANDLER(m);
1110         WRITE_BACK(m);
1111 }
1112
1113 static void Op46(void)                                                  // RORA
1114 {
1115         OP_ROR_HANDLER(regs.d.acc.a);
1116 }
1117
1118 static void Op56(void)                                                  // RORB
1119 {
1120         OP_ROR_HANDLER(regs.d.acc.b);
1121 }
1122
1123 /*
1124 Operation               |Mnem.|Immed.|Direct|Index |Extend|Inher.|Operation |CC Reg|
1125                         |     |OP ~ #|OP ~ #|OP ~ #|OP ~ #|OP ~ #|          |HINZVC|
1126 Arithmetic Shift Left   |ASL  |      |      |68 7 2|78 6 3|      |Memory  *3|  TT6T|
1127                         |ASLA |      |      |      |      |48 2 1|Accum A *3|  TT6T|
1128                         |ASLB |      |      |      |      |58 2 1|Accum B *3|  TT6T|
1129 */
1130
1131 // ASL opcodes
1132
1133 #define OP_ASL_HANDLER(m) \
1134         uint8_t newCarry = (m & 0x80) >> 7; \
1135         m <<= 1; \
1136         SET_ZN(m); \
1137         flagC = newCarry; \
1138         flagV = flagN ^ flagC
1139
1140 static void Op68(void)          // ASL ZP, X
1141 {
1142         uint8_t m;
1143         READ_ZP_X_WB(m);
1144         OP_ASL_HANDLER(m);
1145         WRITE_BACK(m);
1146 }
1147
1148 static void Op78(void)          // ASL ABS
1149 {
1150         uint8_t m;
1151         READ_ABS_WB(m);
1152         OP_ASL_HANDLER(m);
1153         WRITE_BACK(m);
1154 }
1155
1156 static void Op48(void)          // ASLA
1157 {
1158         OP_ASL_HANDLER(regs.d.acc.a);
1159 }
1160
1161 static void Op58(void)          // ASLB
1162 {
1163         OP_ASL_HANDLER(regs.d.acc.b);
1164 }
1165
1166 static void Op05(void)          // ASLD
1167 {
1168         uint8_t newCarry = (regs.d.word & 0x8000) >> 15;
1169         regs.d.word <<= 1;
1170         SET_Z(regs.d.word);
1171         SET_N16(regs.d.word);
1172         flagC = newCarry;
1173         flagV = flagN ^ flagC;
1174 }
1175
1176 /*
1177 Operation               |Mnem.|Immed.|Direct|Index |Extend|Inher.|Operation |CC Reg|
1178                         |     |OP ~ #|OP ~ #|OP ~ #|OP ~ #|OP ~ #|          |HINZVC|
1179 Arithmetic Shift Right  |ASR  |      |      |67 7 2|77 6 3|      |Memory  *4|  TT6T|
1180                         |ASRA |      |      |      |      |47 2 1|Accum A *4|  TT6T|
1181                         |ASRB |      |      |      |      |57 2 1|Accum B *4|  TT6T|
1182 */
1183
1184 // ASR opcodes
1185
1186 #define OP_ASR_HANDLER(m) \
1187         uint8_t newCarry = m & 0x01; \
1188         m = (m >> 1) | (m & 0x80); \
1189         SET_ZN(m); \
1190         flagC = newCarry; \
1191         flagV = flagN ^ flagC
1192
1193 static void Op67(void)          // ASR ZP, X
1194 {
1195         uint8_t m;
1196         READ_ZP_X_WB(m);
1197         OP_ASR_HANDLER(m);
1198         WRITE_BACK(m);
1199 }
1200
1201 static void Op77(void)          // ASR ABS
1202 {
1203         uint8_t m;
1204         READ_ABS_WB(m);
1205         OP_ASR_HANDLER(m);
1206         WRITE_BACK(m);
1207 }
1208
1209 static void Op47(void)          // ASRA
1210 {
1211         OP_ASR_HANDLER(regs.d.acc.a);
1212 }
1213
1214 static void Op57(void)          // ASRB
1215 {
1216         OP_ASR_HANDLER(regs.d.acc.b);
1217 }
1218
1219 /*
1220 Operation               |Mnem.|Immed.|Direct|Index |Extend|Inher.|Operation |CC Reg|
1221                         |     |OP ~ #|OP ~ #|OP ~ #|OP ~ #|OP ~ #|          |HINZVC|
1222 Logic Shift Right       |LSR  |      |      |64 7 2|74 6 3|      |Memory  *5|  TT6T|
1223                         |LSRA |      |      |      |      |44 2 1|Accum A *5|  TT6T|
1224                         |LSRB |      |      |      |      |54 2 1|Accum B *5|  TT6T|
1225 */
1226
1227 // LSR opcodes
1228
1229 #define OP_LSR_HANDLER(m) \
1230         uint8_t newCarry = m & 0x01; \
1231         m >>= 1; \
1232         SET_ZN(m); \
1233         flagC = newCarry; \
1234         flagV = flagN ^ flagC
1235
1236 static void Op64(void)          // LSR ZP, X
1237 {
1238         uint8_t m;
1239         READ_ZP_X_WB(m);
1240         OP_LSR_HANDLER(m);
1241         WRITE_BACK(m);
1242 }
1243
1244 static void Op74(void)          // LSR ABS
1245 {
1246         uint8_t m;
1247         READ_ABS_WB(m);
1248         OP_LSR_HANDLER(m);
1249         WRITE_BACK(m);
1250 }
1251
1252 static void Op44(void)          // LSRA
1253 {
1254         OP_LSR_HANDLER(regs.d.acc.a);
1255 }
1256
1257 static void Op54(void)          // LSRB
1258 {
1259         OP_LSR_HANDLER(regs.d.acc.b);
1260 }
1261
1262 static void Op04(void)          // LSRD
1263 {
1264         uint8_t newCarry = regs.d.word & 0x01;
1265         regs.d.word >>= 1;
1266         SET_Z(regs.d.word);
1267         flagN = 0;
1268         flagC = newCarry;
1269         flagV = flagN ^ flagC;
1270 }
1271
1272 /*
1273 Operation               |Mnem.|Immed.|Direct|Index |Extend|Inher.|Operation |CC Reg|
1274                         |     |OP ~ #|OP ~ #|OP ~ #|OP ~ #|OP ~ #|          |HINZVC|
1275 Store Accumulator       |STAA |      |97 4 2|A7 6 2|B7 5 3|      |M=A       |  TTR |
1276                         |STAB |      |D7 4 2|E7 6 2|F7 5 3|      |M=B       |  TTR |
1277 */
1278
1279 static void Op97(void)          // STAA ZP
1280 {
1281         regs.WrMem(EA_ZP, regs.d.acc.a);
1282 }
1283
1284 static void OpA7(void)          // STAA ZP, X
1285 {
1286         regs.WrMem(EA_ZP_X, regs.d.acc.a);
1287 }
1288
1289 static void OpB7(void)          // STAA ABS
1290 {
1291         regs.WrMem(EA_ABS, regs.d.acc.a);
1292 }
1293
1294 static void OpD7(void)          // STAB ZP
1295 {
1296         regs.WrMem(EA_ZP, regs.d.acc.b);
1297 }
1298
1299 static void OpE7(void)          // STAB ZP, X
1300 {
1301         regs.WrMem(EA_ZP_X, regs.d.acc.b);
1302 }
1303
1304 static void OpF7(void)          // STAB ABS
1305 {
1306         regs.WrMem(EA_ABS, regs.d.acc.b);
1307 }
1308
1309 // These are illegal instructions!
1310 #if 0
1311 static void Op87(void)          // STA #
1312 {
1313         // What does this even mean? Seems the M.A.M.E. guys think it's something
1314         // like so:
1315         uint16_t effectiveAddress = regs.pc;
1316         regs.pc++;
1317         regs.WrMem(effectiveAddress, regs.d.acc.a);
1318         SET_ZN(regs.d.acc.a);
1319         flagV = 0;
1320         // So, basically, what this does is change the immediate value in the
1321         // STA #. Seems like a completely useless thing to me.
1322 }
1323
1324
1325 static void OpC7(void)          // STB #
1326 {
1327         uint16_t effectiveAddress = regs.pc;
1328         regs.pc++;
1329         regs.WrMem(effectiveAddress, regs.d.acc.b);
1330         SET_ZN(regs.d.acc.b);
1331         flagV = 0;
1332 }
1333 #endif
1334
1335 /*
1336 Operation               |Mnem.|Immed.|Direct|Index |Extend|Inher.|Operation |CC Reg|
1337                         |     |OP ~ #|OP ~ #|OP ~ #|OP ~ #|OP ~ #|          |HINZVC|
1338 Subtract                |SUBA |80 2 2|90 3 2|A0 5 2|B0 4 3|      |A=A-M     |  TTTT|
1339                         |SUBB |C0 2 2|D0 3 2|E0 5 2|F0 4 3|      |B=B-M     |  TTTT|
1340 Subtract Accumulators   |SBA  |      |      |      |      |10 2 1|A=A-B     |  TTTT|
1341 */
1342
1343 // SUB opcodes
1344
1345 #define OP_SUB_HANDLER(m, acc) \
1346         uint16_t sum = (uint16_t)acc - (m); \
1347         flagC = sum >> 15; \
1348         SET_V(m, acc, sum); \
1349         acc = (uint8_t)sum; \
1350         SET_ZN(acc)
1351
1352 #define OP_SUB_HANDLER16(m, acc) \
1353         uint32_t sum = (uint32_t)acc - (m); \
1354         flagC = sum >> 31; \
1355         SET_V16(m, acc, sum); \
1356         acc = (uint16_t)sum; \
1357         SET_Z(acc); \
1358         SET_N16(acc)
1359
1360 static void Op80(void)          // SUBA #
1361 {
1362         uint16_t m = READ_IMM;
1363         OP_SUB_HANDLER(m, regs.d.acc.a);
1364 }
1365
1366 static void Op90(void)          // SUBA ZP
1367 {
1368         uint16_t m = READ_ZP;
1369         OP_SUB_HANDLER(m, regs.d.acc.a);
1370 }
1371
1372 static void OpA0(void)          // SUBA ZP, X
1373 {
1374         uint16_t m = READ_ZP_X;
1375         OP_SUB_HANDLER(m, regs.d.acc.a);
1376 }
1377
1378 static void OpB0(void)          // SUBA ABS
1379 {
1380         uint16_t m = READ_ABS;
1381         OP_SUB_HANDLER(m, regs.d.acc.a);
1382 }
1383
1384 static void OpC0(void)          // SUBB #
1385 {
1386         uint16_t m = READ_IMM;
1387         OP_SUB_HANDLER(m, regs.d.acc.b);
1388 }
1389
1390 static void OpD0(void)          // SUBB ZP
1391 {
1392         uint16_t m = READ_ZP;
1393         OP_SUB_HANDLER(m, regs.d.acc.b);
1394 }
1395
1396 static void OpE0(void)          // SUBB ZP, X
1397 {
1398         uint16_t m = READ_ZP_X;
1399         OP_SUB_HANDLER(m, regs.d.acc.b);
1400 }
1401
1402 static void OpF0(void)          // SUBB ABS
1403 {
1404         uint16_t m = READ_ABS;
1405         OP_SUB_HANDLER(m, regs.d.acc.b);
1406 }
1407
1408 static void Op10(void)          // SBA
1409 {
1410         OP_SUB_HANDLER(regs.d.acc.b, regs.d.acc.a);
1411 }
1412
1413 static void Op83(void)          // SUBD #
1414 {
1415         uint16_t m = READ_IMM16;
1416         OP_SUB_HANDLER16(m, regs.d.word);
1417 }
1418
1419 static void Op93(void)          // SUBD ZP
1420 {
1421         uint16_t m = READ_ZP16;
1422         OP_SUB_HANDLER16(m, regs.d.word);
1423 }
1424
1425 static void OpA3(void)          // SUBD ZP, X
1426 {
1427         uint16_t m = READ_ZP_X16;
1428         OP_SUB_HANDLER16(m, regs.d.word);
1429 }
1430
1431 static void OpB3(void)          // SUBD ABS
1432 {
1433         uint16_t m = READ_ABS16;
1434         OP_SUB_HANDLER16(m, regs.d.word);
1435 }
1436
1437 /*
1438 Operation               |Mnem.|Immed.|Direct|Index |Extend|Inher.|Operation |CC Reg|
1439                         |     |OP ~ #|OP ~ #|OP ~ #|OP ~ #|OP ~ #|          |HINZVC|
1440 Subtract with Carry     |SBCA |82 2 2|92 3 2|A2 5 2|B2 4 3|      |A=A-M-C   |  TTTT|
1441                         |SBCB |C2 2 2|D2 3 2|E2 5 2|F2 4 3|      |B=B-M-C   |  TTTT|
1442 */
1443
1444 // SBC opcodes
1445
1446 #define OP_SBC_HANDLER(m, acc) \
1447         uint16_t sum = (uint16_t)acc - (m) - (uint16_t)flagC; \
1448         flagC = sum >> 15; \
1449         SET_V(m, acc, sum); \
1450         acc = (uint8_t)sum; \
1451         SET_ZN(acc)
1452
1453 static void Op82(void)                                                  // SBCA #
1454 {
1455         uint16_t m = READ_IMM;
1456         OP_SBC_HANDLER(m, regs.d.acc.a);
1457 }
1458
1459 static void Op92(void)                                                  // SBCA ZP
1460 {
1461         uint16_t m = READ_ZP;
1462         OP_SBC_HANDLER(m, regs.d.acc.a);
1463 }
1464
1465 static void OpA2(void)                                                  // SBCA ZP, X
1466 {
1467         uint16_t m = READ_ZP_X;
1468         OP_SBC_HANDLER(m, regs.d.acc.a);
1469 }
1470
1471 static void OpB2(void)                                                  // SBCA ABS
1472 {
1473         uint16_t m = READ_ABS;
1474         OP_SBC_HANDLER(m, regs.d.acc.a);
1475 }
1476
1477 static void OpC2(void)                                                  // SBCB #
1478 {
1479         uint16_t m = READ_IMM;
1480         OP_SBC_HANDLER(m, regs.d.acc.b);
1481 }
1482
1483 static void OpD2(void)                                                  // SBCB ZP
1484 {
1485         uint16_t m = READ_ZP;
1486         OP_SBC_HANDLER(m, regs.d.acc.b);
1487 }
1488
1489 static void OpE2(void)                                                  // SBCB ZP, X
1490 {
1491         uint16_t m = READ_ZP_X;
1492         OP_SBC_HANDLER(m, regs.d.acc.b);
1493 }
1494
1495 static void OpF2(void)                                                  // SBCB ABS
1496 {
1497         uint16_t m = READ_ABS;
1498         OP_SBC_HANDLER(m, regs.d.acc.b);
1499 }
1500
1501 /*
1502 Operation               |Mnem.|Immed.|Direct|Index |Extend|Inher.|Operation |CC Reg|
1503                         |     |OP ~ #|OP ~ #|OP ~ #|OP ~ #|OP ~ #|          |HINZVC|
1504 Transfer Accumulators   |TAB  |      |      |      |      |16 2 1|B=A       |  TTR |
1505                         |TBA  |      |      |      |      |17 2 1|A=B       |  TTR |
1506 */
1507
1508 static void Op16(void)                                                  // TAB
1509 {
1510         regs.d.acc.b = regs.d.acc.a;
1511         SET_ZN(regs.d.acc.b);
1512         CLR_V;
1513 }
1514
1515 static void Op17(void)                                                  // TBA
1516 {
1517         regs.d.acc.a = regs.d.acc.b;
1518         SET_ZN(regs.d.acc.a);
1519         CLR_V;
1520 }
1521
1522 /*
1523 Operation               |Mnem.|Immed.|Direct|Index |Extend|Inher.|Operation |CC Reg|
1524                         |     |OP ~ #|OP ~ #|OP ~ #|OP ~ #|OP ~ #|          |HINZVC|
1525 Test, Zero/Minus        |TST  |      |      |6D 7 2|7D 6 3|      |M-00      |  TTRR|
1526                         |TSTA |      |      |      |      |4D 2 1|A-00      |  TTRR|
1527                         |TSTB |      |      |      |      |5D 2 1|B-00      |  TTRR|
1528 */
1529
1530 // TST opcodes
1531
1532 #define OP_TST_HANDLER(m) \
1533         uint8_t result = m; \
1534         SET_ZN(result); \
1535         CLR_VC
1536
1537 #define OP_TST_IMM_HANDLER(m, acc) \
1538         uint8_t result = m & acc; \
1539         SET_ZN(result); \
1540         CLR_VC
1541
1542 static void Op6D(void)                                                  // TST ZP, X
1543 {
1544 #if 0
1545         uint8_t m;
1546         READ_ZP_X_WB(m);
1547         OP_TST_HANDLER(m);
1548         WRITE_BACK(m);
1549 #else
1550         OP_TST_HANDLER(READ_ZP_X);
1551 #endif
1552 }
1553
1554 static void Op7D(void)                                                  // TST ABS
1555 {
1556 #if 0
1557         uint8_t m;
1558         READ_ABS_WB(m);
1559         OP_TST_HANDLER(m);
1560         WRITE_BACK(m);
1561 #else
1562         OP_TST_HANDLER(READ_ABS);
1563 #endif
1564 }
1565
1566 static void Op4D(void)                                                  // TSTA
1567 {
1568         OP_TST_HANDLER(regs.d.acc.a);
1569 }
1570
1571 static void Op5D(void)                                                  // TSTB
1572 {
1573         OP_TST_HANDLER(regs.d.acc.b);
1574 }
1575
1576 static void Op6B(void)          // TIM ZP, X (TST immediate with index)
1577 {
1578 //      uint8_t m;
1579         uint8_t immValue = READ_IMM;
1580 //      READ_ZP_X_WB(m);
1581         OP_TST_IMM_HANDLER(immValue, READ_ZP_X);
1582 //      WRITE_BACK(m);
1583 }
1584
1585 static void Op7B(void)          // TIM ZP (TST immediate with zero page)
1586 {
1587 //      uint8_t m;
1588         uint8_t immValue = READ_IMM;
1589 //      READ_ZP_WB(m);
1590         OP_TST_IMM_HANDLER(immValue, READ_ZP);
1591 //      WRITE_BACK(m);
1592 }
1593
1594 /*
1595 Operation               |Mnem.|Immed.|Direct|Index |Extend|Inher.|Operation |CC Reg|
1596                         |     |OP ~ #|OP ~ #|OP ~ #|OP ~ #|OP ~ #|          |HINZVC|
1597 Compare Index Register  |CPX  |8C 3 3|9C 4 2|AC 6 2|BC 5 3|      |Formula 1 |  7T8 |
1598 */
1599
1600 // CPX opcodes
1601
1602 /*
1603 Compare sets flags as if a subtraction had been carried out. If the value in the X register 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. X>=$8000) of the X register.
1604 */
1605
1606 #define OP_CPX_HANDLER(m) \
1607         uint32_t result = regs.x - (m); \
1608         SET_ZNVC_CMP16(m, regs.x, result)
1609
1610 static void Op8C(void)                                                  // CPX #
1611 {
1612         uint16_t m = READ_IMM16;
1613         OP_CPX_HANDLER(m);
1614 }
1615
1616 static void Op9C(void)                                                  // CPX ZP
1617 {
1618         uint16_t m = READ_ZP16;
1619         OP_CPX_HANDLER(m);
1620 }
1621
1622 static void OpAC(void)                                                  // CPX ZP, X
1623 {
1624         uint16_t m = READ_ZP_X16;
1625         OP_CPX_HANDLER(m);
1626 }
1627
1628 static void OpBC(void)                                                  // CPX ABS
1629 {
1630         uint16_t m = READ_ABS16;
1631         OP_CPX_HANDLER(m);
1632 }
1633
1634 /*
1635 Operation               |Mnem.|Immed.|Direct|Index |Extend|Inher.|Operation |CC Reg|
1636                         |     |OP ~ #|OP ~ #|OP ~ #|OP ~ #|OP ~ #|          |HINZVC|
1637 Decrement Index Register|DEX  |      |      |      |      |09 4 1|X=X-1     |   T  |
1638 Dec Stack Pointer       |DES  |      |      |      |      |34 4 1|SP=SP-1   |      |
1639 Inc Index Regster       |INX  |      |      |      |      |08 4 1|X=X+1     |   T  |
1640 Inc Stack Pointer       |INS  |      |      |      |      |31 4 1|SP=SP+1   |      |
1641 */
1642
1643 static void Op09(void)                                                  // DEX
1644 {
1645         regs.x--;
1646         SET_Z(regs.x);
1647 }
1648
1649 static void Op34(void)                                                  // DES
1650 {
1651         regs.s--;
1652 }
1653
1654 static void Op08(void)                                                  // INX
1655 {
1656         regs.x++;
1657         SET_Z(regs.x);
1658 }
1659
1660 static void Op31(void)                                                  // INS
1661 {
1662         regs.s++;
1663 }
1664
1665 /*
1666 Operation               |Mnem.|Immed.|Direct|Index |Extend|Inher.|Operation |CC Reg|
1667                         |     |OP ~ #|OP ~ #|OP ~ #|OP ~ #|OP ~ #|          |HINZVC|
1668 Load Index Register     |LDX  |CE 3 3|DE 4 2|EE 6 2|FE 5 3|      |Formula 2 |  9TR |
1669 Load Stack Pointer      |LDS  |8E 3 3|9E 4 2|AE 6 2|BE 5 3|      |Formula 3 |  9TR |
1670 */
1671
1672 // LD* opcode handler
1673
1674 #define OP_LD_HANDLER(acc) \
1675         SET_N16(acc); \
1676         SET_Z(acc); \
1677         CLR_V
1678
1679 static void OpCE(void)          // LDX #
1680 {
1681         regs.x = READ_IMM16;
1682         OP_LD_HANDLER(regs.x);
1683 }
1684
1685 static void OpDE(void)          // LDX ZP
1686 {
1687         regs.x = READ_ZP16;
1688         OP_LD_HANDLER(regs.x);
1689 }
1690
1691 static void OpEE(void)          // LDX ZP, X
1692 {
1693         regs.x = READ_ZP_X16;
1694         OP_LD_HANDLER(regs.x);
1695 }
1696
1697 static void OpFE(void)          // LDX ABS
1698 {
1699         regs.x = READ_ABS16;
1700         OP_LD_HANDLER(regs.x);
1701 }
1702
1703 static void Op8E(void)          // LDS #
1704 {
1705         regs.s = READ_IMM16;
1706         OP_LD_HANDLER(regs.s);
1707 }
1708
1709 static void Op9E(void)          // LDS ZP
1710 {
1711         regs.s = READ_ZP16;
1712         OP_LD_HANDLER(regs.s);
1713 }
1714
1715 static void OpAE(void)          // LDS ZP, X
1716 {
1717         regs.s = READ_ZP_X16;
1718         OP_LD_HANDLER(regs.s);
1719 }
1720
1721 static void OpBE(void)          // LDS ABS
1722 {
1723         regs.s = READ_ABS16;
1724         OP_LD_HANDLER(regs.s);
1725 }
1726
1727 static void OpCC(void)          // LDD #
1728 {
1729         regs.d.word = READ_IMM16;
1730         OP_LD_HANDLER(regs.d.word);
1731 }
1732
1733 static void OpDC(void)          // LDD ZP
1734 {
1735         regs.d.word = READ_ZP16;
1736         OP_LD_HANDLER(regs.d.word);
1737 }
1738
1739 static void OpEC(void)          // LDD ZP, X
1740 {
1741         regs.d.word = READ_ZP_X16;
1742         OP_LD_HANDLER(regs.d.word);
1743 }
1744
1745 static void OpFC(void)          // LDD ABS
1746 {
1747         regs.d.word = READ_ABS16;
1748         OP_LD_HANDLER(regs.d.word);
1749 }
1750
1751 /*
1752 Operation               |Mnem.|Immed.|Direct|Index |Extend|Inher.|Operation |CC Reg|
1753                         |     |OP ~ #|OP ~ #|OP ~ #|OP ~ #|OP ~ #|          |HINZVC|
1754 Store Index Register    |STX  |      |DF 5 2|EF 7 2|FF 6 3|      |Formula 4 |  9TR |
1755 Store Stack Pointer     |STS  |      |9F 5 2|AF 7 2|BF 6 3|      |Formula 5 |  9TR |
1756 */
1757
1758 // ST* opcode handler
1759
1760 #define OP_ST_HANDLER(m, acc) \
1761         regs.WrMem(m + 0, acc >> 8); \
1762         regs.WrMem(m + 1, acc & 0xFF); \
1763         SET_N16(acc); \
1764         SET_Z(acc); \
1765         CLR_V
1766
1767 static void OpDF(void)          // STX ZP
1768 {
1769         uint16_t m = EA_ZP;
1770         OP_ST_HANDLER(m, regs.x);
1771 }
1772
1773 static void OpEF(void)          // STX ZP, X
1774 {
1775         uint16_t m = EA_ZP_X;
1776         OP_ST_HANDLER(m, regs.x);
1777 }
1778
1779 static void OpFF(void)          // STX ABS
1780 {
1781         uint16_t m = EA_ABS;
1782         OP_ST_HANDLER(m, regs.x);
1783 }
1784
1785 static void Op9F(void)          // STS ZP
1786 {
1787         uint16_t m = EA_ZP;
1788         OP_ST_HANDLER(m, regs.s);
1789 }
1790
1791 static void OpAF(void)          // STS ZP, X
1792 {
1793         uint16_t m = EA_ZP_X;
1794         OP_ST_HANDLER(m, regs.s);
1795 }
1796
1797 static void OpBF(void)          // STS ABS
1798 {
1799         uint16_t m = EA_ABS;
1800         OP_ST_HANDLER(m, regs.s);
1801 }
1802
1803 // These are illegal instructions!
1804 #if 0
1805 // Store immediate--nonsensical opcodes :-P
1806 static void Op8F(void)          // STS #
1807 {
1808         uint16_t effectiveAddress = regs.pc;
1809         regs.pc += 2;
1810         OP_ST_HANDLER(effectiveAddress, regs.s);
1811 }
1812
1813 static void OpCF(void)          // STX #
1814 {
1815         uint16_t effectiveAddress = regs.pc;
1816         regs.pc += 2;
1817         OP_ST_HANDLER(effectiveAddress, regs.x);
1818 }
1819
1820 static void OpCD(void)          // STD #
1821 {
1822         uint16_t effectiveAddress = regs.pc;
1823         regs.pc += 2;
1824         OP_ST_HANDLER(effectiveAddress, regs.d.word);
1825 }
1826 #endif
1827
1828 static void OpDD(void)          // STD ZP
1829 {
1830         uint16_t m = EA_ZP;
1831         OP_ST_HANDLER(m, regs.d.word);
1832 }
1833
1834 static void OpED(void)          // STD ZP, X
1835 {
1836         uint16_t m = EA_ZP_X;
1837         OP_ST_HANDLER(m, regs.d.word);
1838 }
1839
1840 static void OpFD(void)          // STD ABS
1841 {
1842         uint16_t m = EA_ABS;
1843         OP_ST_HANDLER(m, regs.d.word);
1844 }
1845
1846 /*
1847 Operation               |Mnem.|Immed.|Direct|Index |Extend|Inher.|Operation |CC Reg|
1848                         |     |OP ~ #|OP ~ #|OP ~ #|OP ~ #|OP ~ #|          |HINZVC|
1849 Index Reg > Stack Pnter |TXS  |      |      |      |      |35 4 1|SP=X-1    |      |
1850 Stack Ptr > Index Regtr |TSX  |      |      |      |      |30 4 1|X=SP+1    |      |
1851 */
1852
1853 static void Op35(void)                                                  // TXS
1854 {
1855         regs.s = regs.x - 1;
1856 }
1857
1858 static void Op30(void)                                                  // TSX
1859 {
1860         regs.x = regs.s + 1;
1861 }
1862
1863 /*
1864 Operation               |Mnem.|Immed.|Direct|Index |Extend|Inher.|Operation |CC Reg|
1865                         |     |OP ~ #|OP ~ #|OP ~ #|OP ~ #|OP ~ #|          |HINZVC|
1866 Always                  |BRA  |      |20 4 2|      |      |      |none      |      |
1867 Carry is Clear          |BCC  |      |24 4 2|      |      |      |C=0       |      |
1868 Carry is Set            |BCS  |      |25 4 2|      |      |      |C=1       |      |
1869 Equals Zero             |BEQ  |      |27 4 2|      |      |      |Z=1       |      |
1870 Greater or Equal to Zero|BGE  |      |2C 4 2|      |      |      |N(+)V=0   |      |
1871 Greater than Zero       |BGT  |      |2E 4 2|      |      |      |Z+N(+)V=0 |      |
1872 Higher                  |BHI  |      |22 4 2|      |      |      |C+Z=0     |      |
1873 Less or Equal than Zero |BLE  |      |2F 4 2|      |      |      |Z+N(+)V=1 |      |
1874 Lower or Same           |BLS  |      |23 4 2|      |      |      |C+Z=1     |      |
1875 Less Than Zero          |BLT  |      |2D 4 2|      |      |      |N(+)V=1   |      |
1876 Minus                   |BMI  |      |2B 4 2|      |      |      |N=1       |      |
1877 Not Zero                |BNE  |      |26 4 2|      |      |      |Z=0       |      |
1878 Overflow Clear          |BVC  |      |28 4 2|      |      |      |V=0       |      |
1879 Overflow Set            |BVS  |      |29 4 2|      |      |      |V=1       |      |
1880 Plus                    |BPL  |      |2A 4 2|      |      |      |N=0       |      |
1881 */
1882
1883 static void Op20(void)          // BRA
1884 {
1885         int16_t m = (int16_t)(int8_t)READ_IMM;
1886         regs.pc += m;
1887 }
1888
1889 static void Op21(void)          // BRN
1890 {
1891         int16_t m = (int16_t)(int8_t)READ_IMM;
1892 //      regs.pc += m;
1893 }
1894
1895 static void Op24(void)          // BCC
1896 {
1897 // NOTE: We can optimize this by following the maxim: "Don't branch!" by
1898 //       converting the boolean result into a multiplication. The only way to
1899 //       know if this is a win is to do some profiling both with and without
1900 //       the optimization.
1901         int16_t m = (int16_t)(int8_t)READ_IMM;
1902
1903 #ifdef TEST_DONT_BRANCH_OPTIMIZATION
1904 //Note sure if the ! operator will do what we want, so we use ^ 1
1905         regs.pc += m * (flagC ^ 0x01);
1906 #else
1907         if (!flagC)
1908                 regs.pc += m;
1909 #endif
1910 }
1911
1912 static void Op25(void)          // BCS
1913 {
1914         int16_t m = (int16_t)(int8_t)READ_IMM;
1915
1916 #ifdef TEST_DONT_BRANCH_OPTIMIZATION
1917         regs.pc += m * (flagC);
1918 #else
1919         if (flagC)
1920                 regs.pc += m;
1921 #endif
1922 }
1923
1924 static void Op27(void)          // BEQ
1925 {
1926         int16_t m = (int16_t)(int8_t)READ_IMM;
1927
1928 #ifdef TEST_DONT_BRANCH_OPTIMIZATION
1929         regs.pc += m * (flagZ);
1930 #else
1931         if (flagZ)
1932                 regs.pc += m;
1933 #endif
1934 }
1935
1936 static void Op2C(void)          // BGE
1937 {
1938         int16_t m = (int16_t)(int8_t)READ_IMM;
1939
1940 #ifdef TEST_DONT_BRANCH_OPTIMIZATION
1941         regs.pc += m * ((flagN ^ flagV) ^ 0x01);
1942 #else
1943         if (!(flagN ^ flagV))
1944                 regs.pc += m;
1945 #endif
1946 }
1947
1948 static void Op2E(void)          // BGT
1949 {
1950         int16_t m = (int16_t)(int8_t)READ_IMM;
1951
1952 #ifdef TEST_DONT_BRANCH_OPTIMIZATION
1953         regs.pc += m * ((flagZ | (flagN ^ flagV)) ^ 0x01);
1954 #else
1955         if (!(flagZ | (flagN ^ flagV)))
1956                 regs.pc += m;
1957 #endif
1958 }
1959
1960 static void Op22(void)          // BHI
1961 {
1962         int16_t m = (int16_t)(int8_t)READ_IMM;
1963
1964 #ifdef TEST_DONT_BRANCH_OPTIMIZATION
1965         regs.pc += m * ((flagZ | flagC) ^ 0x01);
1966 #else
1967         if (!(flagZ | flagC))
1968                 regs.pc += m;
1969 #endif
1970 }
1971
1972 static void Op2F(void)          // BLE
1973 {
1974         int16_t m = (int16_t)(int8_t)READ_IMM;
1975
1976 #ifdef TEST_DONT_BRANCH_OPTIMIZATION
1977         regs.pc += m * (flagZ | (flagN ^ flagV));
1978 #else
1979         if (flagZ | (flagN ^ flagV))
1980                 regs.pc += m;
1981 #endif
1982 }
1983
1984 static void Op23(void)          // BLS
1985 {
1986         int16_t m = (int16_t)(int8_t)READ_IMM;
1987
1988 #ifdef TEST_DONT_BRANCH_OPTIMIZATION
1989         regs.pc += m * (flagZ | flagC);
1990 #else
1991         if (flagZ | flagC)
1992                 regs.pc += m;
1993 #endif
1994 }
1995
1996 static void Op2D(void)          // BLT
1997 {
1998         int16_t m = (int16_t)(int8_t)READ_IMM;
1999
2000 #ifdef TEST_DONT_BRANCH_OPTIMIZATION
2001         regs.pc += m * (flagN ^ flagV);
2002 #else
2003         if (flagN ^ flagV)
2004                 regs.pc += m;
2005 #endif
2006 }
2007
2008 static void Op2B(void)          // BMI
2009 {
2010         int16_t m = (int16_t)(int8_t)READ_IMM;
2011
2012 #ifdef TEST_DONT_BRANCH_OPTIMIZATION
2013         regs.pc += m * (flagN);
2014 #else
2015         if (flagN)
2016                 regs.pc += m;
2017 #endif
2018 }
2019
2020 static void Op26(void)          // BNE
2021 {
2022         int16_t m = (int16_t)(int8_t)READ_IMM;
2023
2024 #ifdef TEST_DONT_BRANCH_OPTIMIZATION
2025         regs.pc += m * (flagZ ^ 0x01);
2026 #else
2027         if (!flagZ)
2028                 regs.pc += m;
2029 #endif
2030 }
2031
2032 static void Op28(void)          // BVC
2033 {
2034         int16_t m = (int16_t)(int8_t)READ_IMM;
2035
2036 #ifdef TEST_DONT_BRANCH_OPTIMIZATION
2037         regs.pc += m * (flagV ^ 0x01);
2038 #else
2039         if (!flagV)
2040                 regs.pc += m;
2041 #endif
2042 }
2043
2044 static void Op29(void)          // BVS
2045 {
2046         int16_t m = (int16_t)(int8_t)READ_IMM;
2047
2048 #ifdef TEST_DONT_BRANCH_OPTIMIZATION
2049         regs.pc += m * (flagV);
2050 #else
2051         if (flagV)
2052                 regs.pc += m;
2053 #endif
2054 }
2055
2056 static void Op2A(void)          // BPL
2057 {
2058         int16_t m = (int16_t)(int8_t)READ_IMM;
2059
2060 #ifdef TEST_DONT_BRANCH_OPTIMIZATION
2061         regs.pc += m * (flagN ^ 0x01);
2062 #else
2063         if (!flagN)
2064                 regs.pc += m;
2065 #endif
2066 }
2067
2068 /*
2069 Operation               |Mnem.|Immed.|Direct|Index |Extend|Inher.|Operation |CC Reg|
2070                         |     |OP ~ #|OP ~ #|OP ~ #|OP ~ #|OP ~ #|          |HINZVC|
2071 Branch to Subroutine    |BSR  |      |8D 8 2|      |      |      |          |      |
2072 Jump                    |JMP  |      |      |6E 4 2|7E 3 3|      |          |      |
2073 Jump to Subroutine      |JSR  |      |      |AD 8 2|BD 9 3|      |          |      |
2074 */
2075
2076 static void Op8D(void)          // BSR
2077 {
2078         int16_t m = (int16_t)(int8_t)READ_IMM;
2079         PUSH16(regs.pc);
2080         regs.pc += m;
2081 }
2082
2083 static void Op6E(void)          // JMP ZP, X
2084 {
2085         uint16_t m = EA_ZP_X;
2086         regs.pc = m;
2087 }
2088
2089 static void Op7E(void)          // JMP ABS
2090 {
2091         regs.pc = EA_ABS;
2092 }
2093
2094 static void Op9D(void)          // JSR ZP
2095 {
2096         uint16_t m = (uint16_t)EA_ZP;
2097         PUSH16(regs.pc);
2098         regs.pc = m;
2099 }
2100
2101 static void OpAD(void)          // JSR ZP, X
2102 {
2103         uint16_t m = EA_ZP_X;
2104         PUSH16(regs.pc);
2105         regs.pc = m;
2106 }
2107
2108 static void OpBD(void)          // JSR ABS
2109 {
2110         uint16_t m = EA_ABS;
2111         PUSH16(regs.pc);
2112         regs.pc = m;
2113 }
2114
2115 /*
2116 Operation               |Mnem.|Immed.|Direct|Index |Extend|Inher.|Operation |CC Reg|
2117                         |     |OP ~ #|OP ~ #|OP ~ #|OP ~ #|OP ~ #|          |HINZVC|
2118 No Operation            |NOP  |      |      |      |      |01 2 1|          |      |
2119 Return from Interrupt   |RTI  |      |      |      |      |3B A 1|          |AAAAAA|
2120 Return from Subroutine  |RTS  |      |      |      |      |39 5 1|          |      |
2121 Software Interrupt      |SWI  |      |      |      |      |3F C 1|          | S    |
2122 Wait For Interrupt      |WAI  |      |      |      |      |3E 9 1|          | B    |
2123 */
2124
2125 static void Op01(void)          // NOP
2126 {
2127 }
2128
2129 static void Op3B(void)          // RTI
2130 {
2131         regs.cc = PULL;
2132         regs.d.acc.b  = PULL;
2133         regs.d.acc.a  = PULL;
2134         regs.x  = PULL16;
2135         regs.pc = PULL16;
2136         UNPACK_FLAGS;
2137 }
2138
2139 static void Op39(void)          // RTS
2140 {
2141         regs.pc = PULL16;
2142 }
2143
2144 static void Op3F(void)          // SWI
2145 {
2146         // It seems that the SWI is non-maskable, unlike the IRQ...
2147 #if 0
2148         regs.cc = PACK_FLAGS;                   // Mash flags back into the CC register
2149         PUSH16(regs.pc);                                // Save all regs...
2150         PUSH16(regs.x);
2151         PUSH(regs.d.acc.b);
2152         PUSH(regs.d.acc.a);
2153         PUSH(regs.cc);
2154         regs.pc = RdMemW(0xFFFA);               // And do it!
2155         flagI = 1;                                              // Also, set IRQ inhibit
2156 #endif
2157         HandleInterrupt(0xFFFA);
2158 }
2159
2160 static void Op3E(void)          // WAI
2161 {
2162 #ifdef __DEBUG__
2163 WriteLog("*** WAI STATE ASSERTED ***\n");
2164 #endif
2165         regs.cc = PACK_FLAGS;                   // Mash flags back into the CC register
2166         PUSH16(regs.pc);                                // Save all regs...
2167         PUSH16(regs.x);
2168         PUSH(regs.d.acc.b);
2169         PUSH(regs.d.acc.a);
2170         PUSH(regs.cc);
2171         regs.cpuFlags |= V63701_STATE_WAI;      // And signal that we're in WAI mode
2172 }
2173
2174 // Multiply opcode
2175
2176 static void Op3D(void)          // MUL
2177 {
2178         regs.d.word = (uint16_t)regs.d.acc.a * (uint16_t)regs.d.acc.b;
2179         flagC = regs.d.acc.b >> 7;      // bug?  No, this is how it really does it
2180 }
2181
2182 // Exchange X and D opcode
2183
2184 static void Op18(void)          // XGDX
2185 {
2186         // This doesn't affect flags apparently
2187         uint16_t temp = regs.x;
2188         regs.x = regs.d.word;
2189         regs.d.word = temp;
2190 }
2191
2192 // Sleep opcode (similar to WAI)
2193
2194 static void Op1A(void)          // SLP
2195 {
2196         // Apparently doesn't stack the state, so no need for RTI
2197         // It would seem that this opcode is intended for use in interrupt
2198         // routines, as it prevents stacking the state when one happens.
2199         // (Actually, this is used to put the MCU into a low power "sleep" mode,
2200         // where it stays until an interrupt or RESET occurs.)
2201         regs.cpuFlags |= V63701_STATE_WAI;
2202 }
2203
2204 // Undocumented opcode ($12 & $13)
2205
2206 static void OpUN(void)          // Undocumented
2207 {
2208         regs.x += regs.RdMem(regs.s + 1);
2209 }
2210
2211 /*
2212 Operation               |Mnem.|Immed.|Direct|Index |Extend|Inher.|Operation |CC Reg|
2213                         |     |OP ~ #|OP ~ #|OP ~ #|OP ~ #|OP ~ #|          |HINZVC|
2214 Clear Carry             |CLC  |      |      |      |      |0C 2 1|C=0       |     R|
2215 Clear Interrupt         |CLI  |      |      |      |      |0E 2 1|I=0       | R    |
2216 Clear Overflow          |CLV  |      |      |      |      |0A 2 1|V=0       |    R |
2217 Set Carry               |SEC  |      |      |      |      |0D 2 1|C=1       |     S|
2218 Set Interrupt           |SEI  |      |      |      |      |0F 2 1|I=1       | S    |
2219 Set Overflow            |SEV  |      |      |      |      |0B 2 1|V=1       |    S |
2220 CCR=Accumulator A       |TAP  |      |      |      |      |06 2 1|CCR=A     |CCCCCC|
2221 Accumlator A=CCR        |TPA  |      |      |      |      |07 2 1|A=CCR     |      |
2222 */
2223
2224 static void Op0C(void)                                                  // CLC
2225 {
2226         flagC = 0;
2227 }
2228
2229 static void Op0E(void)                                                  // CLI
2230 {
2231         flagI = 0;
2232 }
2233
2234 static void Op0A(void)                                                  // CLV
2235 {
2236         flagV = 0;
2237 }
2238
2239 static void Op0D(void)                                                  // SEC
2240 {
2241         flagC = 1;
2242 }
2243
2244 static void Op0F(void)                                                  // SEI
2245 {
2246         flagI = 1;
2247 }
2248
2249 static void Op0B(void)                                                  // SEV
2250 {
2251         flagV = 1;
2252 }
2253
2254 static void Op06(void)                                                  // TAP
2255 {
2256         regs.cc = regs.d.acc.a;
2257         UNPACK_FLAGS;
2258 }
2259
2260 static void Op07(void)                                                  // TPA
2261 {
2262         regs.d.acc.a = PACK_FLAGS;
2263 }
2264
2265 /*
2266   OP  Operation Code, in Hexadecimal
2267   ~   Number of MPU cycles required
2268   #   Number of program bytes required
2269   +   Arithmetic Plus
2270   -   Arithmetic Minus
2271   +   Boolean AND
2272   Msp Contents of Memory pointed to be Stack Pointer
2273   +   Boolean Inclusive OR
2274   (+) Boolean Exclusive OR (XOR)
2275   *   Converts Binary Addition of BCD Characters into BCD Format
2276   *-  SP=SP-1
2277   *+  SP=SP+1
2278
2279   Condition Code Register Legend
2280      Not Affected
2281    R Reset (0, Low)
2282    S Set   (1, High)
2283    T Tests and sets if True, cleared otherise
2284    1 Test: Result=10000000?
2285    2 Test: Result=00000000?
2286    3 Test: Decimal value of most significant BCD character greater than nine?
2287            (Not cleared if previously set)
2288    4 Test: Operand=10000000 prior to execution?
2289    5 Test: Operand=01111111 prior to execution?
2290    6 Test: Set equal to result or N(+)C after shift has occurred.
2291    7 Test: Sign bit of most significant byte or result=1?
2292    8 Test: 2's compliment overflow from subtraction of least
2293            significant bytes?
2294    9 Test: Result less than zero? (Bit 15=1)
2295    A Load Condition Code Register from Stack.
2296    B Set when interrupt occurs.  If previously set, a NMI is
2297         required to exit the wait state.
2298    C Set according to the contents of Accumulator A.
2299
2300   *x SHIFT AND ROTATION DIAGRAMS
2301    *1     +-----------------+       C to LSB
2302           - C <- 76543210 <-+
2303
2304    *2    +-----------------+
2305          +> C -> 76543210 -+
2306
2307    *3       C <- 76543210 <- 0(Data)
2308                +-+
2309
2310    *4          ï¿½>76543210 -> C
2311
2312    *5 (Data)0 -> 76543210 -> C
2313
2314   FORMULAS
2315    1: (Xh/Xl)-(M/M+1)
2316    2: Xh=M, Xl=M+1
2317    3: SPh=M, SPl=M+1
2318    4: M=Xh, M+1=Xl
2319 */
2320
2321 static void Op__(void)
2322 {
2323         // TRAP is non-maskable, unlike the IRQ... Also, highest priority after
2324         // RESET
2325         HandleInterrupt(0xFFEE);
2326 //      regs.cpuFlags |= V63701_STATE_ILLEGAL_INST;
2327 }
2328
2329 //
2330 // Ok, the exec_op[] array is globally defined here basically to save
2331 // a LOT of unnecessary typing.  Sure it's ugly, but hey, it works!
2332 //
2333 static void (* exec_op[256])() = {
2334         Op__, Op01, Op__, Op__, Op04, Op05, Op06, Op07, Op08, Op09, Op0A, Op0B, Op0C, Op0D, Op0E, Op0F,
2335         Op10, Op11, OpUN, OpUN, Op__, Op__, Op16, Op17, Op18, Op19, Op1A, Op1B, Op__, Op__, Op__, Op__,
2336         Op20, Op21, Op22, Op23, Op24, Op25, Op26, Op27, Op28, Op29, Op2A, Op2B, Op2C, Op2D, Op2E, Op2F,
2337         Op30, Op31, Op32, Op33, Op34, Op35, Op36, Op37, Op38, Op39, Op3A, Op3B, Op3C, Op3D, Op3E, Op3F,
2338         Op40, Op__, Op__, Op43, Op44, Op__, Op46, Op47, Op48, Op49, Op4A, Op__, Op4C, Op4D, Op__, Op4F,
2339         Op50, Op__, Op__, Op53, Op54, Op__, Op56, Op57, Op58, Op59, Op5A, Op__, Op5C, Op5D, Op__, Op5F,
2340         Op60, Op61, Op62, Op63, Op64, Op65, Op66, Op67, Op68, Op69, Op6A, Op6B, Op6C, Op6D, Op6E, Op6F,
2341         Op70, Op71, Op72, Op73, Op74, Op75, Op76, Op77, Op78, Op79, Op7A, Op7B, Op7C, Op7D, Op7E, Op7F,
2342         Op80, Op81, Op82, Op83, Op84, Op85, Op86, Op__, Op88, Op89, Op8A, Op8B, Op8C, Op8D, Op8E, Op__,
2343         Op90, Op91, Op92, Op93, Op94, Op95, Op96, Op97, Op98, Op99, Op9A, Op9B, Op9C, Op9D, Op9E, Op9F,
2344         OpA0, OpA1, OpA2, OpA3, OpA4, OpA5, OpA6, OpA7, OpA8, OpA9, OpAA, OpAB, OpAC, OpAD, OpAE, OpAF,
2345         OpB0, OpB1, OpB2, OpB3, OpB4, OpB5, OpB6, OpB7, OpB8, OpB9, OpBA, OpBB, OpBC, OpBD, OpBE, OpBF,
2346         OpC0, OpC1, OpC2, OpC3, OpC4, OpC5, OpC6, Op__, OpC8, OpC9, OpCA, OpCB, OpCC, Op__, OpCE, Op__,
2347         OpD0, OpD1, OpD2, OpD3, OpD4, OpD5, OpD6, OpD7, OpD8, OpD9, OpDA, OpDB, OpDC, OpDD, OpDE, OpDF,
2348         OpE0, OpE1, OpE2, OpE3, OpE4, OpE5, OpE6, OpE7, OpE8, OpE9, OpEA, OpEB, OpEC, OpED, OpEE, OpEF,
2349         OpF0, OpF1, OpF2, OpF3, OpF4, OpF5, OpF6, OpF7, OpF8, OpF9, OpFA, OpFB, OpFC, OpFD, OpFE, OpFF
2350 };
2351
2352 //
2353 // Internal "memcpy" (so we don't have to link with any external libraries!)
2354 //
2355 static void myMemcpy(void * dst, void * src, uint32_t size)
2356 {
2357         uint8_t * d = (uint8_t *)dst, * s = (uint8_t *)src;
2358
2359         for(uint32_t i=0; i<size; i++)
2360                 d[i] = s[i];
2361 }
2362
2363 #ifdef __DEBUG__
2364 //int instCount[256];
2365 bool V63701LogGo = false;
2366 //static bool V63701LogGo = true;
2367 char instBuf[256];
2368 extern uint8_t mcuMem[];
2369 uint8_t * memory = mcuMem;
2370 #endif
2371 //
2372 // Function to execute 63701 for "cycles" cycles
2373 //
2374 void Execute63701(V63701REGS * context, uint32_t cycles)
2375 {
2376 //#warning "V63701_STATE_WAI is not properly handled yet! !!! FIX !!!"
2377 //#warning "Need to convert from destructive clock to non-destructive. !!! FIX !!!"
2378         regsPointer = context;
2379         myMemcpy(&regs, context, sizeof(V63701REGS));
2380         // Explode flags register into individual uint8_ts
2381         UNPACK_FLAGS;
2382
2383 #if 0
2384         // Execute here...
2385         while (regs.clock < cycles)
2386 #else
2387         // Execute here...
2388         uint64_t endCycles = regs.clock + (uint64_t)cycles - regs.clockOverrun;
2389
2390         while (regs.clock < endCycles)
2391 #endif
2392         {
2393 #if 0
2394 if (regs.pc == 0x8236)
2395 {
2396         printf("V63701: $8236 called by $%04X...\n", RdMemW(regs.s));
2397 }
2398 #endif
2399 #ifdef __DEBUG__
2400 if (V63701LogGo)
2401 {
2402         Decode63701(memory, regs.pc, instBuf);
2403         WriteLog("%s\n", instBuf);
2404 }
2405 #endif
2406                 if (regs.cpuFlags & V63701_STATE_WAI)
2407                 {
2408                         // Only bail out if no interrupts/resets are pending
2409                         if (!(regs.cpuFlags & (V63701_LINE_IRQ | V63701_LINE_NMI | V63701_LINE_RESET | V63701_TIMER_OVERFLOW | V63701_OUTPUT_COMPARE | V63701_INPUT_CAPTURE)))
2410                                 // Burn any remaining cycles...
2411                                 regs.clock = endCycles;
2412                 }
2413                 else
2414                 {
2415                         uint8_t opcode = regs.RdMem(regs.pc++);
2416                         exec_op[opcode]();                                              // Execute that opcode...
2417                         regs.clock += CPUCycles[opcode];
2418                         uint16_t oldCounter = regs.counter.word;
2419                         regs.counter.word += CPUCycles[opcode];
2420
2421                         // We fake the free running counter above, by adding cycle counts
2422                         // to it; this means we can never be sure that the counter will
2423                         // be equal to the output compare register. So we have to check
2424                         // for two cases: 1st, look for the previous counter value and see
2425                         // if we went past it, and 2nd, do the same but check to see if we
2426                         // overflowed in the meantime.
2427                         if (((oldCounter < regs.outputCompare.word)
2428                                 && (regs.counter.word >= regs.outputCompare.word))
2429                                 || ((oldCounter > regs.counter.word)
2430                                 && (regs.counter.word >= regs.outputCompare.word)))
2431                         {
2432                                 // Set the output compare flag bit
2433                                 regs.tcsr.bit.ocf = 1;
2434
2435                                 if (regs.tcsr.bit.eoci)
2436                                 {
2437                                         regs.cpuFlags |= V63701_OUTPUT_COMPARE;
2438                                         regsPointer->cpuFlags |= V63701_OUTPUT_COMPARE;
2439                                 }
2440                         }
2441
2442                         // Check for counter overflow
2443                         if (regs.counter.word < oldCounter)
2444                         {
2445                                 // Set the timer overflow flag bit
2446                                 regs.tcsr.bit.tof = 1;
2447
2448                                 if (regs.tcsr.bit.etoi)
2449                                 {
2450                                         regs.cpuFlags |= V63701_TIMER_OVERFLOW;
2451                                         regsPointer->cpuFlags |= V63701_TIMER_OVERFLOW;
2452                                 }
2453                         }
2454 #ifdef __DEBUG__
2455 if (V63701LogGo)
2456 //      WriteLog(" [PC=%04X, S=%04X, X=%04X, A=%02X, B=%02X, CC=%s%s%s%s%s%s%s%s]\n", regs.pc, regs.s, regs.x, regs.d.acc.a, regs.d.acc.b, (regs.cc & FLAG_E ? "E" : " "), (regs.cc & FLAG_F ? "F" : " "), (regs.cc & FLAG_H ? "H" : " "), (regs.cc & FLAG_I ? "I" : " "), (regs.cc & FLAG_N ? "N" : " "), (regs.cc & FLAG_Z ? "Z" : " "), (regs.cc & FLAG_V ? "V" : " "), (regs.cc & FLAG_C ? "C" : " "));
2457         WriteLog(" [PC=%04X S=%04X X=%04X A=%02X B=%02X CC=%s%s%s%s%s%s TCSR=%s%s%s%s%s%s%s%s CT=%04X OC=%04X]\n", regs.pc, regs.s, regs.x, regs.d.acc.a, regs.d.acc.b, (flagH ? "H" : "."), (flagI ? "I" : "."), (flagN ? "N" : "."), (flagZ ? "Z" : "."), (flagV ? "V" : "."), (flagC ? "C" : "."), (regs.tcsr.bit.icf ? "I" :"."), (regs.tcsr.bit.ocf ? "O" :"."), (regs.tcsr.bit.tof ? "T" :"."), (regs.tcsr.bit.eici ? "i" :"."), (regs.tcsr.bit.eoci ? "o" :"."), (regs.tcsr.bit.etoi ? "t" :"."), (regs.tcsr.bit.iedg ? "E" :"."), (regs.tcsr.bit.olvl ? "O" :"."), regs.counter.word, regs.outputCompare.word);
2458 #endif
2459                 }
2460
2461                 if (regs.cpuFlags & V63701_LINE_RESET)
2462                 {
2463 #ifdef __DEBUG__
2464 if (V63701LogGo)
2465         WriteLog("*** RESET LINE ASSERTED ***\n");
2466 #endif
2467                         regs.tcsr.byte = 0;
2468                         regs.tcsrWasRead = false;
2469                         regs.counter.word = 0;
2470                         regs.outputCompare.word = 0xFFFF;
2471                         flagI = 1;                                      // Set I
2472                         regs.pc = RdMemW(0xFFFE);       // And load PC with the RESET vector
2473                         context->cpuFlags = 0;          // Clear all lingering flags...
2474                         regs.cpuFlags = 0;
2475                 }
2476                 else if (regs.cpuFlags & V63701_LINE_NMI)
2477                 {
2478 #ifdef __DEBUG__
2479 if (V63701LogGo)
2480         WriteLog("*** NMI LINE ASSERTED ***\n");
2481 #endif
2482                         HandleInterrupt(0xFFFC, V63701_LINE_NMI);
2483                 }
2484                 else if (regs.cpuFlags & V63701_LINE_IRQ)
2485                 {
2486 #ifdef __DEBUG__
2487 if (V63701LogGo)
2488         WriteLog("*** IRQ LINE ASSERTED ***\n");
2489 #endif
2490 //                      if (!(regs.cc & FLAG_I))                        // Process an interrupt (I=0)?
2491                         if (!flagI)                                                     // Process an interrupt (I=0)?
2492                         {
2493 #ifdef __DEBUG__
2494 if (V63701LogGo)
2495         WriteLog("    IRQ TAKEN!\n");
2496 //V63701LogGo = true;
2497 #endif
2498                                 HandleInterrupt(0xFFF8, V63701_LINE_IRQ);
2499                         }
2500                 }
2501                 else if (regs.cpuFlags & V63701_INPUT_CAPTURE)
2502                 {
2503 #ifdef __DEBUG__
2504 if (V63701LogGo)
2505         WriteLog("*** INPUT CAPTURE ASSERTED ***\n");
2506 #endif
2507                         // Process interrupt if no I inhibit set, & enable in TCSR is set
2508                         if (!flagI && regs.tcsr.bit.eici)
2509                         {
2510 #ifdef __DEBUG__
2511 if (V63701LogGo)
2512         WriteLog("    IC TAKEN!\n");
2513 //V63701LogGo = true;
2514 #endif
2515                                 HandleInterrupt(0xFFF6, V63701_INPUT_CAPTURE);
2516                         }
2517                 }
2518                 else if (regs.cpuFlags & V63701_OUTPUT_COMPARE)
2519                 {
2520 #ifdef __DEBUG__
2521 if (V63701LogGo)
2522         WriteLog("*** OUTPUT COMPARE ASSERTED ***\n");
2523 #endif
2524                         // Process interrupt if no I inhibit set, & enable in TCSR is set
2525                         if (!flagI && regs.tcsr.bit.eoci)
2526                         {
2527 #ifdef __DEBUG__
2528 if (V63701LogGo)
2529         WriteLog("    OC TAKEN!\n");
2530 //V63701LogGo = true;
2531 #endif
2532                                 HandleInterrupt(0xFFF4, V63701_OUTPUT_COMPARE);
2533                         }
2534                 }
2535                 else if (regs.cpuFlags & V63701_TIMER_OVERFLOW)
2536                 {
2537 #ifdef __DEBUG__
2538 if (V63701LogGo)
2539         WriteLog("*** TIMER OVER ASSERTED ***\n");
2540 #endif
2541                         // Process interrupt if no I inhibit set, & enable in TCSR is set
2542                         if (!flagI && regs.tcsr.bit.etoi)
2543                         {
2544 #ifdef __DEBUG__
2545 if (V63701LogGo)
2546         WriteLog("    TO TAKEN!\n");
2547 //V63701LogGo = true;
2548 #endif
2549                                 HandleInterrupt(0xFFF2, V63701_TIMER_OVERFLOW);
2550                         }
2551                 }
2552         }
2553
2554         // If we went longer than the passed in cycles, make a note of it so we can
2555         // subtract it out from a subsequent run. It's guaranteed to be positive,
2556         // because the condition that exits the main loop above is written such
2557         // that regs.clock has to be larger than endCycles to exit from it.
2558         regs.clockOverrun = regs.clock - endCycles;
2559
2560         regs.cc = PACK_FLAGS;                                           // Mash flags back into the CC register
2561         myMemcpy(context, &regs, sizeof(V63701REGS));
2562 }
2563
2564 //
2565 // Get the clock of the currently executing CPU
2566 //
2567 uint64_t GetCurrentV63701Clock(void)
2568 {
2569         return regs.clock;
2570 }
2571
2572 static inline void HandleInterrupt(uint16_t vector, uint16_t flag/*= 0*/)
2573 {
2574         if (regs.cpuFlags & V63701_STATE_WAI)
2575                 regs.clock += 4;
2576         else
2577         {
2578                 regs.cc = PACK_FLAGS;   // Mash flags back into the CC register
2579                 PUSH16(regs.pc);                // Save all regs...
2580                 PUSH16(regs.x);
2581                 PUSH(regs.d.acc.a);
2582                 PUSH(regs.d.acc.b);
2583                 PUSH(regs.cc);
2584                 regs.clock += 12;
2585         }
2586
2587         regs.pc = RdMemW(vector);       // And do it!
2588         flagI = 1;
2589
2590         // Clear the passed in flag + WAI state
2591         regs.cpuFlags &= ~(flag | V63701_STATE_WAI);
2592         regsPointer->cpuFlags &= ~(flag | V63701_STATE_WAI);
2593 }
2594
2595 uint8_t InternalRegisterRead(uint16_t address)
2596 {
2597         switch (address & 0x1F)
2598         {
2599         case 0x00:
2600                 return regs.ddr1;
2601         case 0x01:
2602                 return regs.ddr2;
2603         case 0x02:
2604                 return (V63701ReadPort1() & ~regs.ddr1) | (regs.port1data & regs.ddr1);
2605 //              return /*(regs.port1read & ~regs.ddr1) |*/ (regs.port1r & ~regs.ddr1);
2606         case 0x03:
2607                 // Top 3 bits are MCU mode bits.
2608                 return (V63701ReadPort2() & ~regs.ddr2) | (regs.port2data & regs.ddr2);
2609 //              return /*(regs.port1read & ~regs.ddr1) |*/ (regs.port2r & ~regs.ddr2 & 0x1F);
2610         // Timer Control and Status Register
2611         case 0x08:
2612                 regs.tcsrWasRead = true;
2613                 return regs.tcsr.byte;
2614         // Counter high byte
2615         case 0x09:
2616                 if (regs.tcsrWasRead)
2617                 {
2618                         regs.tcsr.bit.tof = 0;
2619                         regs.tcsrWasRead = false;
2620                 }
2621
2622                 regs.cReadLatch = regs.counter.byte.lo;
2623                 return regs.counter.byte.hi;
2624         // Counter low byte
2625         case 0x0A:
2626                 return regs.cReadLatch;
2627         // Output compare high byte
2628         case 0x0B:
2629                 return regs.outputCompare.byte.hi;
2630         // Output compare low byte
2631         case 0x0C:
2632                 return regs.outputCompare.byte.lo;
2633         // RAM Control register (only bits 6 & 7 are valid)
2634         case 0x14:
2635                 return (regs.ramCtrl & 0xC0) | 0x3F;
2636         default:
2637 #ifdef __DEBUG__
2638                 printf("V63701: Unhandled register read @ $%02X...\n", address);
2639 #else
2640                 ;
2641 #endif
2642         }
2643
2644         return 0x00;
2645 }
2646
2647 void InternalRegisterWrite(uint16_t address, uint8_t data)
2648 {
2649         uint8_t writeData;
2650
2651         switch (address & 0x1F)
2652         {
2653         case 0x00:
2654                 regs.ddr1 = data;
2655                 break;
2656         case 0x01:
2657                 regs.ddr2 = data;
2658                 break;
2659         case 0x02:
2660                 regs.port1data = data;
2661                 writeData = (V63701ReadPort1() & ~regs.ddr1) | (data & regs.ddr1);
2662                 V63701WritePort1(writeData);
2663                 break;
2664         case 0x03:
2665                 // Port 2 only has 5 bits of output, top 3 are the MCU mode bits
2666                 regs.port2data = ((regs.port2data & ~regs.ddr2) | (data & regs.ddr2)) & 0x1F;
2667                 break;
2668 //      case 0x05:
2669         // Timer Control and Status Register
2670         case 0x08:
2671                 // Top 3 bits are RO, so protect them
2672                 regs.tcsr.byte = (data & 0x1F) | (regs.tcsr.byte & 0xE0);
2673                 break;
2674         // Counter (High Byte)
2675         case 0x09:
2676                 regs.cWriteLatch = data;
2677                 regs.counter.word = 0xFFF8;
2678                 break;
2679         // Counter (Low Byte)
2680         case 0x0A:
2681                 regs.counter.word = (regs.cWriteLatch << 8) | data;
2682                 break;
2683         // Output Compare Register (High Byte)
2684         case 0x0B:
2685                 regs.outputCompare.byte.hi = data;
2686
2687                 if (regs.tcsrWasRead)
2688                 {
2689                         regs.tcsr.bit.ocf = 0;
2690                         regs.tcsrWasRead = false;
2691                 }
2692
2693                 break;
2694         // Output Compare Register (Low Byte)
2695         case 0x0C:
2696                 regs.outputCompare.byte.lo = data;
2697
2698                 if (regs.tcsrWasRead)
2699                 {
2700                         regs.tcsr.bit.ocf = 0;
2701                         regs.tcsrWasRead = false;
2702                 }
2703
2704                 break;
2705         // RAM Control register
2706         case 0x14:
2707                 regs.ramCtrl = data;
2708                 break;
2709         default:
2710 #ifdef __DEBUG__
2711                 WriteLog("V63701: Unhandled register write @ $%02X...\n", address);
2712 #else
2713                 ;
2714 #endif
2715         }
2716 }