]> Shamusworld >> Repos - thunder/blob - src/v63701.cpp
b76063fccc168a931ee92d83e1d8c63b620a0cf9
[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         uint16_t m = EA_ZP_X;
2289         regs.pc = m;
2290 }
2291
2292
2293 static void Op7E(void)          // JMP ABS
2294 {
2295         regs.pc = EA_ABS;
2296 }
2297
2298
2299 static void Op9D(void)          // JSR ZP
2300 {
2301         uint16_t m = (uint16_t)EA_ZP;
2302         PUSH16(regs.pc);
2303         regs.pc = m;
2304 }
2305
2306
2307 static void OpAD(void)          // JSR ZP, X
2308 {
2309         uint16_t m = EA_ZP_X;
2310         PUSH16(regs.pc);
2311         regs.pc = m;
2312 }
2313
2314
2315 static void OpBD(void)          // JSR ABS
2316 {
2317         uint16_t m = EA_ABS;
2318         PUSH16(regs.pc);
2319         regs.pc = m;
2320 }
2321
2322
2323 /*
2324 Operation               |Mnem.|Immed.|Direct|Index |Extend|Inher.|Operation |CC Reg|
2325                         |     |OP ~ #|OP ~ #|OP ~ #|OP ~ #|OP ~ #|          |HINZVC|
2326 No Operation            |NOP  |      |      |      |      |01 2 1|          |      |
2327 Return from Interrupt   |RTI  |      |      |      |      |3B A 1|          |AAAAAA|
2328 Return from Subroutine  |RTS  |      |      |      |      |39 5 1|          |      |
2329 Software Interrupt      |SWI  |      |      |      |      |3F C 1|          | S    |
2330 Wait For Interrupt      |WAI  |      |      |      |      |3E 9 1|          | B    |
2331 */
2332
2333 static void Op01(void)          // NOP
2334 {
2335 }
2336
2337
2338 static void Op3B(void)          // RTI
2339 {
2340         regs.cc = PULL;
2341         regs.d.acc.b  = PULL;
2342         regs.d.acc.a  = PULL;
2343         regs.x  = PULL16;
2344         regs.pc = PULL16;
2345         UNPACK_FLAGS;
2346 }
2347
2348
2349 static void Op39(void)          // RTS
2350 {
2351         regs.pc = PULL16;
2352 }
2353
2354
2355 static void Op3F(void)          // SWI
2356 {
2357         // It seems that the SWI is non-maskable, unlike the IRQ...
2358 #if 0
2359         regs.cc = PACK_FLAGS;                   // Mash flags back into the CC register
2360         PUSH16(regs.pc);                                // Save all regs...
2361         PUSH16(regs.x);
2362         PUSH(regs.d.acc.b);
2363         PUSH(regs.d.acc.a);
2364         PUSH(regs.cc);
2365         regs.pc = RdMemW(0xFFFA);               // And do it!
2366         flagI = 1;                                              // Also, set IRQ inhibit
2367 #endif
2368         HandleInterrupt(0xFFFA);
2369 }
2370
2371
2372 static void Op3E(void)          // WAI
2373 {
2374 #ifdef __DEBUG__
2375 WriteLog("*** WAI STATE ASSERTED ***\n");
2376 #endif
2377         regs.cc = PACK_FLAGS;                   // Mash flags back into the CC register
2378         PUSH16(regs.pc);                                // Save all regs...
2379         PUSH16(regs.x);
2380         PUSH(regs.d.acc.b);
2381         PUSH(regs.d.acc.a);
2382         PUSH(regs.cc);
2383         regs.cpuFlags |= V63701_STATE_WAI;      // And signal that we're in WAI mode
2384 }
2385
2386
2387 // Multiply opcode
2388
2389 static void Op3D(void)          // MUL
2390 {
2391         regs.d.word = (uint16_t)regs.d.acc.a * (uint16_t)regs.d.acc.b;
2392         flagC = regs.d.acc.b >> 7;      // bug?  No, this is how it really does it
2393 }
2394
2395
2396 // Exchange X and D opcode
2397
2398 static void Op18(void)          // XGDX
2399 {
2400         // This doesn't affect flags apparently
2401         uint16_t temp = regs.x;
2402         regs.x = regs.d.word;
2403         regs.d.word = temp;
2404 }
2405
2406
2407 // Sleep opcode (similar to WAI)
2408
2409 static void Op1A(void)          // SLP
2410 {
2411         // Apparently doesn't stack the state, so no need for RTI
2412         // It would seem that this opcode is intended for use in interrupt
2413         // routines, as it prevents stacking the state when one happens.
2414         // (Actually, this is used to put the MCU into a low power "sleep" mode,
2415         // where it stays until an interrupt or RESET occurs.)
2416         regs.cpuFlags |= V63701_STATE_WAI;
2417 }
2418
2419
2420 // Undocumented opcode ($12 & $13)
2421
2422 static void OpUN(void)          // Undocumented
2423 {
2424         regs.x += regs.RdMem(regs.s + 1);
2425 }
2426
2427
2428 /*
2429 Operation               |Mnem.|Immed.|Direct|Index |Extend|Inher.|Operation |CC Reg|
2430                         |     |OP ~ #|OP ~ #|OP ~ #|OP ~ #|OP ~ #|          |HINZVC|
2431 Clear Carry             |CLC  |      |      |      |      |0C 2 1|C=0       |     R|
2432 Clear Interrupt         |CLI  |      |      |      |      |0E 2 1|I=0       | R    |
2433 Clear Overflow          |CLV  |      |      |      |      |0A 2 1|V=0       |    R |
2434 Set Carry               |SEC  |      |      |      |      |0D 2 1|C=1       |     S|
2435 Set Interrupt           |SEI  |      |      |      |      |0F 2 1|I=1       | S    |
2436 Set Overflow            |SEV  |      |      |      |      |0B 2 1|V=1       |    S |
2437 CCR=Accumulator A       |TAP  |      |      |      |      |06 2 1|CCR=A     |CCCCCC|
2438 Accumlator A=CCR        |TPA  |      |      |      |      |07 2 1|A=CCR     |      |
2439 */
2440
2441 static void Op0C(void)                                                  // CLC
2442 {
2443         flagC = 0;
2444 }
2445
2446
2447 static void Op0E(void)                                                  // CLI
2448 {
2449         flagI = 0;
2450 }
2451
2452
2453 static void Op0A(void)                                                  // CLV
2454 {
2455         flagV = 0;
2456 }
2457
2458
2459 static void Op0D(void)                                                  // SEC
2460 {
2461         flagC = 1;
2462 }
2463
2464
2465 static void Op0F(void)                                                  // SEI
2466 {
2467         flagI = 1;
2468 }
2469
2470
2471 static void Op0B(void)                                                  // SEV
2472 {
2473         flagV = 1;
2474 }
2475
2476
2477 static void Op06(void)                                                  // TAP
2478 {
2479         regs.cc = regs.d.acc.a;
2480         UNPACK_FLAGS;
2481 }
2482
2483
2484 static void Op07(void)                                                  // TPA
2485 {
2486         regs.d.acc.a = PACK_FLAGS;
2487 }
2488
2489
2490 /*
2491   OP  Operation Code, in Hexadecimal
2492   ~   Number of MPU cycles required
2493   #   Number of program bytes required
2494   +   Arithmetic Plus
2495   -   Arithmetic Minus
2496   +   Boolean AND
2497   Msp Contents of Memory pointed to be Stack Pointer
2498   +   Boolean Inclusive OR
2499   (+) Boolean Exclusive OR (XOR)
2500   *   Converts Binary Addition of BCD Characters into BCD Format
2501   *-  SP=SP-1
2502   *+  SP=SP+1
2503
2504   Condition Code Register Legend
2505      Not Affected
2506    R Reset (0, Low)
2507    S Set   (1, High)
2508    T Tests and sets if True, cleared otherise
2509    1 Test: Result=10000000?
2510    2 Test: Result=00000000?
2511    3 Test: Decimal value of most significant BCD character greater than nine?
2512            (Not cleared if previously set)
2513    4 Test: Operand=10000000 prior to execution?
2514    5 Test: Operand=01111111 prior to execution?
2515    6 Test: Set equal to result or N(+)C after shift has occurred.
2516    7 Test: Sign bit of most significant byte or result=1?
2517    8 Test: 2's compliment overflow from subtraction of least
2518            significant bytes?
2519    9 Test: Result less than zero? (Bit 15=1)
2520    A Load Condition Code Register from Stack.
2521    B Set when interrupt occurs.  If previously set, a NMI is
2522         required to exit the wait state.
2523    C Set according to the contents of Accumulator A.
2524
2525   *x SHIFT AND ROTATION DIAGRAMS
2526    *1     +-----------------+       C to LSB
2527           - C <- 76543210 <-+
2528
2529    *2    +-----------------+
2530          +> C -> 76543210 -+
2531
2532    *3       C <- 76543210 <- 0(Data)
2533                +-+
2534
2535    *4          ï¿½>76543210 -> C
2536
2537    *5 (Data)0 -> 76543210 -> C
2538
2539   FORMULAS
2540    1: (Xh/Xl)-(M/M+1)
2541    2: Xh=M, Xl=M+1
2542    3: SPh=M, SPl=M+1
2543    4: M=Xh, M+1=Xl
2544 */
2545
2546
2547 static void Op__(void)
2548 {
2549         // TRAP is non-maskable, unlike the IRQ... Also, highest priority after
2550         // RESET
2551         HandleInterrupt(0xFFEE);
2552 //      regs.cpuFlags |= V63701_STATE_ILLEGAL_INST;
2553 }
2554
2555
2556 //
2557 // Ok, the exec_op[] array is globally defined here basically to save
2558 // a LOT of unnecessary typing.  Sure it's ugly, but hey, it works!
2559 //
2560 static void (* exec_op[256])() = {
2561         Op__, Op01, Op__, Op__, Op04, Op05, Op06, Op07, Op08, Op09, Op0A, Op0B, Op0C, Op0D, Op0E, Op0F,
2562         Op10, Op11, OpUN, OpUN, Op__, Op__, Op16, Op17, Op18, Op19, Op1A, Op1B, Op__, Op__, Op__, Op__,
2563         Op20, Op21, Op22, Op23, Op24, Op25, Op26, Op27, Op28, Op29, Op2A, Op2B, Op2C, Op2D, Op2E, Op2F,
2564         Op30, Op31, Op32, Op33, Op34, Op35, Op36, Op37, Op38, Op39, Op3A, Op3B, Op3C, Op3D, Op3E, Op3F,
2565         Op40, Op__, Op__, Op43, Op44, Op__, Op46, Op47, Op48, Op49, Op4A, Op__, Op4C, Op4D, Op__, Op4F,
2566         Op50, Op__, Op__, Op53, Op54, Op__, Op56, Op57, Op58, Op59, Op5A, Op__, Op5C, Op5D, Op__, Op5F,
2567         Op60, Op61, Op62, Op63, Op64, Op65, Op66, Op67, Op68, Op69, Op6A, Op6B, Op6C, Op6D, Op6E, Op6F,
2568         Op70, Op71, Op72, Op73, Op74, Op75, Op76, Op77, Op78, Op79, Op7A, Op7B, Op7C, Op7D, Op7E, Op7F,
2569         Op80, Op81, Op82, Op83, Op84, Op85, Op86, Op__, Op88, Op89, Op8A, Op8B, Op8C, Op8D, Op8E, Op__,
2570         Op90, Op91, Op92, Op93, Op94, Op95, Op96, Op97, Op98, Op99, Op9A, Op9B, Op9C, Op9D, Op9E, Op9F,
2571         OpA0, OpA1, OpA2, OpA3, OpA4, OpA5, OpA6, OpA7, OpA8, OpA9, OpAA, OpAB, OpAC, OpAD, OpAE, OpAF,
2572         OpB0, OpB1, OpB2, OpB3, OpB4, OpB5, OpB6, OpB7, OpB8, OpB9, OpBA, OpBB, OpBC, OpBD, OpBE, OpBF,
2573         OpC0, OpC1, OpC2, OpC3, OpC4, OpC5, OpC6, Op__, OpC8, OpC9, OpCA, OpCB, OpCC, Op__, OpCE, Op__,
2574         OpD0, OpD1, OpD2, OpD3, OpD4, OpD5, OpD6, OpD7, OpD8, OpD9, OpDA, OpDB, OpDC, OpDD, OpDE, OpDF,
2575         OpE0, OpE1, OpE2, OpE3, OpE4, OpE5, OpE6, OpE7, OpE8, OpE9, OpEA, OpEB, OpEC, OpED, OpEE, OpEF,
2576         OpF0, OpF1, OpF2, OpF3, OpF4, OpF5, OpF6, OpF7, OpF8, OpF9, OpFA, OpFB, OpFC, OpFD, OpFE, OpFF
2577 };
2578
2579
2580 //
2581 // Internal "memcpy" (so we don't have to link with any external libraries!)
2582 //
2583 static void myMemcpy(void * dst, void * src, uint32_t size)
2584 {
2585         uint8_t * d = (uint8_t *)dst, * s = (uint8_t *)src;
2586
2587         for(uint32_t i=0; i<size; i++)
2588                 d[i] = s[i];
2589 }
2590
2591
2592 #ifdef __DEBUG__
2593 //int instCount[256];
2594 //static bool logGo = false;
2595 static bool logGo = true;
2596 char instBuf[256];
2597 extern uint8_t memory[];
2598 #endif
2599 //
2600 // Function to execute 63701 for "cycles" cycles
2601 //
2602 void Execute63701(V63701REGS * context, uint32_t cycles)
2603 {
2604 //#warning "V63701_STATE_WAI is not properly handled yet! !!! FIX !!!"
2605 //#warning "Need to convert from destructive clock to non-destructive. !!! FIX !!!"
2606         regsPointer = context;
2607         myMemcpy(&regs, context, sizeof(V63701REGS));
2608         // Explode flags register into individual uint8_ts
2609         UNPACK_FLAGS;
2610
2611 #if 0
2612         // Execute here...
2613         while (regs.clock < cycles)
2614 #else
2615         // Execute here...
2616         uint64_t endCycles = regs.clock + (uint64_t)cycles - regs.clockOverrun;
2617
2618         while (regs.clock < endCycles)
2619 #endif
2620         {
2621 #ifdef __DEBUG__
2622 if (logGo)
2623 {
2624         Decode63701(memory, regs.pc, instBuf);
2625         WriteLog("%s\n", instBuf);
2626 }
2627 #endif
2628                 if (regs.cpuFlags & V63701_STATE_WAI)
2629                 {
2630                         // Only bail out if no interrupts/resets are pending
2631                         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)))
2632                                 // Burn any remaining cycles...
2633                                 regs.clock = endCycles;
2634                 }
2635                 else
2636                 {
2637                         uint8_t opcode = regs.RdMem(regs.pc++);
2638                         exec_op[opcode]();                                              // Execute that opcode...
2639                         regs.clock += CPUCycles[opcode];
2640                         uint16_t oldCounter = regs.counter.word;
2641                         regs.counter.word += CPUCycles[opcode];
2642
2643                         // We fake the free running counter above, by adding cycle counts
2644                         // to it; this means we can never be sure that the counter will
2645                         // be equal to the output compare register. So we have to check
2646                         // for two cases: 1st, look for the previous counter value and see
2647                         // if we went past it, and 2nd, do the same but check to see if we
2648                         // overflowed in the meantime.
2649                         if (((oldCounter < regs.outputCompare.word)
2650                                 && (regs.counter.word >= regs.outputCompare.word))
2651                                 || ((oldCounter > regs.counter.word)
2652                                 && (regs.counter.word >= regs.outputCompare.word)))
2653                         {
2654                                 // Set the output compare flag bit
2655                                 regs.tcsr.bit.ocf = 1;
2656
2657                                 if (regs.tcsr.bit.eoci)
2658                                 {
2659                                         regs.cpuFlags |= V63701_ASSERT_OUTPUT_COMPARE;
2660                                         regsPointer->cpuFlags |= V63701_ASSERT_OUTPUT_COMPARE;
2661                                 }
2662                         }
2663
2664                         // Check for counter overflow
2665                         if (regs.counter.word < oldCounter)
2666                         {
2667                                 // Set the timer overflow flag bit
2668                                 regs.tcsr.bit.tof = 1;
2669
2670                                 if (regs.tcsr.bit.etoi)
2671                                 {
2672                                         regs.cpuFlags |= V63701_ASSERT_TIMER_OVERFLOW;
2673                                         regsPointer->cpuFlags |= V63701_ASSERT_TIMER_OVERFLOW;
2674                                 }
2675                         }
2676 #ifdef __DEBUG__
2677 if (logGo)
2678 //      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" : " "));
2679         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);
2680 #endif
2681                 }
2682
2683                 if (regs.cpuFlags & V63701_ASSERT_LINE_RESET)
2684                 {
2685 #ifdef __DEBUG__
2686 WriteLog("*** RESET LINE ASSERTED ***\n");
2687 #endif
2688                         regs.tcsr.byte = 0;
2689                         regs.tcsrWasRead = false;
2690                         regs.counter.word = 0;
2691                         regs.outputCompare.word = 0xFFFF;
2692                         flagI = 1;                                      // Set I
2693                         regs.pc = RdMemW(0xFFFE);       // And load PC with the RESET vector
2694                         context->cpuFlags = 0;          // Clear all lingering flags...
2695                         regs.cpuFlags = 0;
2696                 }
2697                 else if (regs.cpuFlags & V63701_ASSERT_LINE_NMI)
2698                 {
2699 #ifdef __DEBUG__
2700 WriteLog("*** NMI LINE ASSERTED ***\n");
2701 #endif
2702                         HandleInterrupt(0xFFFC, V63701_ASSERT_LINE_NMI);
2703                 }
2704                 else if (regs.cpuFlags & V63701_ASSERT_LINE_IRQ)
2705                 {
2706 #ifdef __DEBUG__
2707 WriteLog("*** IRQ LINE ASSERTED ***\n");
2708 #endif
2709 //                      if (!(regs.cc & FLAG_I))                        // Process an interrupt (I=0)?
2710                         if (!flagI)                                                     // Process an interrupt (I=0)?
2711                         {
2712 #ifdef __DEBUG__
2713 WriteLog("    IRQ TAKEN!\n");
2714 logGo = true;
2715 #endif
2716                                 HandleInterrupt(0xFFF8, V63701_ASSERT_LINE_IRQ);
2717                         }
2718                 }
2719                 else if (regs.cpuFlags & V63701_ASSERT_INPUT_CAPTURE)
2720                 {
2721 #ifdef __DEBUG__
2722 WriteLog("*** INPUT CAPTURE ASSERTED ***\n");
2723 #endif
2724                         // Process interrupt if no I inhibit set, & enable in TCSR is set
2725                         if (!flagI && regs.tcsr.bit.eici)
2726                         {
2727 #ifdef __DEBUG__
2728 WriteLog("    IC TAKEN!\n");
2729 logGo = true;
2730 #endif
2731                                 HandleInterrupt(0xFFF6, V63701_ASSERT_INPUT_CAPTURE);
2732                         }
2733                 }
2734                 else if (regs.cpuFlags & V63701_ASSERT_OUTPUT_COMPARE)
2735                 {
2736 #ifdef __DEBUG__
2737 WriteLog("*** OUTPUT COMPARE ASSERTED ***\n");
2738 #endif
2739                         // Process interrupt if no I inhibit set, & enable in TCSR is set
2740                         if (!flagI && regs.tcsr.bit.eoci)
2741                         {
2742 #ifdef __DEBUG__
2743 WriteLog("    OC TAKEN!\n");
2744 logGo = true;
2745 #endif
2746                                 HandleInterrupt(0xFFF4, V63701_ASSERT_OUTPUT_COMPARE);
2747                         }
2748                 }
2749                 else if (regs.cpuFlags & V63701_ASSERT_TIMER_OVERFLOW)
2750                 {
2751 #ifdef __DEBUG__
2752 WriteLog("*** TIMER OVER ASSERTED ***\n");
2753 #endif
2754                         // Process interrupt if no I inhibit set, & enable in TCSR is set
2755                         if (!flagI && regs.tcsr.bit.etoi)
2756                         {
2757 #ifdef __DEBUG__
2758 WriteLog("    TO TAKEN!\n");
2759 logGo = true;
2760 #endif
2761                                 HandleInterrupt(0xFFF2, V63701_ASSERT_TIMER_OVERFLOW);
2762                         }
2763                 }
2764         }
2765
2766         // If we went longer than the passed in cycles, make a note of it so we can
2767         // subtract it out from a subsequent run. It's guaranteed to be positive,
2768         // because the condition that exits the main loop above is written such
2769         // that regs.clock has to be larger than endCycles to exit from it.
2770         regs.clockOverrun = regs.clock - endCycles;
2771
2772         regs.cc = PACK_FLAGS;                                           // Mash flags back into the CC register
2773         myMemcpy(context, &regs, sizeof(V63701REGS));
2774 }
2775
2776
2777 //
2778 // Get the clock of the currently executing CPU
2779 //
2780 uint64_t GetCurrentV63701Clock(void)
2781 {
2782         return regs.clock;
2783 }
2784
2785
2786 static inline void HandleInterrupt(uint16_t vector, uint16_t flag/*= 0*/)
2787 {
2788         if (regs.cpuFlags & V63701_STATE_WAI)
2789                 regs.clock += 4;
2790         else
2791         {
2792                 regs.cc = PACK_FLAGS;   // Mash flags back into the CC register
2793                 PUSH16(regs.pc);                // Save all regs...
2794                 PUSH16(regs.x);
2795                 PUSH(regs.d.acc.a);
2796                 PUSH(regs.d.acc.b);
2797                 PUSH(regs.cc);
2798                 regs.clock += 12;
2799         }
2800
2801         regs.pc = RdMemW(vector);       // And do it!
2802         flagI = 1;
2803
2804         // Clear the passed in flag + WAI state
2805         regs.cpuFlags &= ~(flag | V63701_STATE_WAI);
2806         regsPointer->cpuFlags &= ~(flag | V63701_STATE_WAI);
2807 }
2808
2809
2810 uint8_t InternalRegisterRead(uint16_t address)
2811 {
2812         switch (address & 0x1F)
2813         {
2814         case 0x00:
2815                 return regs.ddr1;
2816         case 0x02:
2817                 return /*(regs.port1read & ~regs.ddr1) |*/ (regs.port1 & regs.ddr1);
2818         // Timer Control and Status Register
2819         case 0x08:
2820                 regs.tcsrWasRead = true;
2821                 return regs.tcsr.byte;
2822         // Counter high byte
2823         case 0x09:
2824                 if (regs.tcsrWasRead)
2825                 {
2826                         regs.tcsr.bit.tof = 0;
2827                         regs.tcsrWasRead = false;
2828                 }
2829
2830                 regs.cReadLatch = regs.counter.byte.lo;
2831                 return regs.counter.byte.hi;
2832         // Counter low byte
2833         case 0x0A:
2834                 return regs.cReadLatch;
2835         // Output compare high byte
2836         case 0x0B:
2837                 return regs.outputCompare.byte.hi;
2838         // Output compare low byte
2839         case 0x0C:
2840                 return regs.outputCompare.byte.lo;
2841         // RAM Control register (only bits 6 & 7 are valid)
2842         case 0x14:
2843                 return (regs.ramCtrl & 0xC0) | 0x3F;
2844         default:
2845 #ifdef __DEBUG__
2846                 printf("V63701: Unhandled register read @ $%02X...\n", address);
2847 #else
2848                 ;
2849 #endif
2850         }
2851
2852         return 0x00;
2853 }
2854
2855
2856 void InternalRegisterWrite(uint16_t address, uint8_t data)
2857 {
2858         switch (address & 0x1F)
2859         {
2860         case 0x00:
2861                 regs.ddr1 = data;
2862                 break;
2863         case 0x01:
2864                 regs.ddr2 = data;
2865                 break;
2866         case 0x02:
2867                 regs.port1 = data;
2868                 break;
2869         case 0x03:
2870                 regs.port2 = data;
2871                 break;
2872 //      case 0x05:
2873         // Timer Control and Status Register
2874         case 0x08:
2875                 // Top 3 bits are RO, so protect them
2876                 regs.tcsr.byte = (data & 0x1F) | (regs.tcsr.byte & 0xE0);
2877                 break;
2878         // Counter (High Byte)
2879         case 0x09:
2880                 regs.cWriteLatch = data;
2881                 regs.counter.word = 0xFFF8;
2882                 break;
2883         // Counter (Low Byte)
2884         case 0x0A:
2885                 regs.counter.word = (regs.cWriteLatch << 8) | data;
2886                 break;
2887         // Output Compare Register (High Byte)
2888         case 0x0B:
2889                 regs.outputCompare.byte.hi = data;
2890
2891                 if (regs.tcsrWasRead)
2892                 {
2893                         regs.tcsr.bit.ocf = 0;
2894                         regs.tcsrWasRead = false;
2895                 }
2896
2897                 break;
2898         // Output Compare Register (Low Byte)
2899         case 0x0C:
2900                 regs.outputCompare.byte.lo = data;
2901
2902                 if (regs.tcsrWasRead)
2903                 {
2904                         regs.tcsr.bit.ocf = 0;
2905                         regs.tcsrWasRead = false;
2906                 }
2907
2908                 break;
2909         // RAM Control register
2910         case 0x14:
2911                 regs.ramCtrl = data;
2912                 break;
2913         default:
2914 #ifdef __DEBUG__
2915                 WriteLog("V63701: Unhandled register write @ $%02X...\n", address);
2916 #else
2917                 ;
2918 #endif
2919         }
2920 }
2921