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