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