]> Shamusworld >> Repos - stargem2/blob - src/v6808.cpp
Finally fixed problems with demo mode.
[stargem2] / src / v6808.cpp
1 //
2 // Virtual 6808 Emulator v2.1
3 //
4 // by James Hammons
5 // (C) 2006 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 //
19
20 // NOTE: V6808_STATE_WAI is not handled in the main loop correctly. !!! FIX !!!
21
22 #define TEST_DONT_BRANCH_OPTIMIZATION
23
24 #include "v6808.h"
25
26 #ifdef __DEBUG__
27 #include "dis6808.h"
28 #include "log.h"
29 #endif
30
31 // Various macros
32
33 #define CLR_Z                                   (flagZ = 0)
34 #define CLR_ZN                                  (flagZ = flagN = 0)
35 #define CLR_ZNC                                 (flagZ = flagN = flagC = 0)
36 #define CLR_NVC                                 (flagN = flagV = flagC = 0)
37 #define CLR_VC                                  (flagV = flagC = 0)
38 #define CLR_V                                   (flagV = 0)
39 #define CLR_N                                   (flagN = 0)
40 #define SET_Z(r)                                (flagZ = ((r) == 0 ? 1 : 0))
41 #define SET_N(r)                                (flagN = ((r) & 0x80) >> 7)
42 #define SET_V(a,b,r)                    (flagV = (((b) ^ (a) ^ (r) ^ ((r) >> 1)) & 0x80) >> 7)
43
44 #define SET_C_CMP(a,b)                  (flagC = ((uint8_t)(b) < (uint8_t)(a) ? 1 : 0))
45 #define SET_ZN(r)                               SET_N(r); SET_Z(r)
46 #define SET_ZNC_ADD(a,b,r)              SET_N(r); SET_Z(r); SET_C_ADD(a,b)
47 #define SET_ZNVC_CMP(a,b,r)             SET_N(r); SET_Z(r); SET_C_CMP(a,b); SET_V(a,b,r)
48
49 #define SET_N16(r)                              (flagN = ((r) & 0x8000) >> 15)
50 #define SET_V16(a,b,r)                  (flagV = (((b) ^ (a) ^ (r) ^ ((r) >> 1)) & 0x8000) >> 15)
51 #define SET_C_CMP16(a,b)                (flagC = ((uint16_t)(b) < (uint16_t)(a) ? 1 : 0))
52 #define SET_ZNVC_CMP16(a,b,r)   SET_N16(r); SET_Z(r); SET_C_CMP16(a,b); SET_V16(a,b,r)
53
54 #define EA_IMM                          regs.pc++
55 #define EA_ZP                           regs.RdMem(regs.pc++)
56 #define EA_ZP_X                         (regs.RdMem(regs.pc++) + regs.x)
57 #define EA_ABS                          FetchMemW(regs.pc)
58
59 #define READ_IMM                        regs.RdMem(EA_IMM)
60 #define READ_ZP                         regs.RdMem(EA_ZP)
61 #define READ_ZP_X                       regs.RdMem(EA_ZP_X)
62 #define READ_ABS                        regs.RdMem(EA_ABS)
63
64 #define READ_IMM16                      FetchMemW(regs.pc);
65 #define READ_ZP16                       RdMemW(EA_ZP)
66 #define READ_ZP_X16                     RdMemW(EA_ZP_X)
67 #define READ_ABS16                      RdMemW(EA_ABS)
68
69 #define READ_IMM_WB(v)          uint16_t addr = EA_IMM;         v = regs.RdMem(addr)
70 #define READ_ZP_WB(v)           uint16_t addr = EA_ZP;          v = regs.RdMem(addr)
71 #define READ_ZP_X_WB(v)         uint16_t addr = EA_ZP_X;                v = regs.RdMem(addr)
72 #define READ_ABS_WB(v)          uint16_t addr = EA_ABS;         v = regs.RdMem(addr)
73
74 #define WRITE_BACK(d)           regs.WrMem(addr, (d))
75
76 #define PULL                            regs.RdMem(regs.s++)
77 #define PUSH(r)                         regs.WrMem(--regs.s, (r))
78 #define PULL16                          RdMemW(regs.s);                         regs.s += 2
79 #define PUSH16(r)                       regs.WrMem(--regs.s, (r) & 0xFF); regs.WrMem(--regs.s, (r) >> 8)
80
81 #define PACK_FLAGS                      ((regs.cc & 0xC0) | (flagH << 5) | (flagI << 4) | (flagN << 3) | (flagZ << 2) | (flagV << 1) | flagC)
82 #define UNPACK_FLAGS            flagH = (regs.cc & FLAG_H) >> 5; \
83         flagI = (regs.cc & FLAG_I) >> 4; \
84         flagN = (regs.cc & FLAG_N) >> 3; \
85         flagZ = (regs.cc & FLAG_Z) >> 2; \
86         flagV = (regs.cc & FLAG_V) >> 1; \
87         flagC = (regs.cc & FLAG_C)
88
89 // Private global variables
90
91 static V6808REGS regs;
92 static uint8_t flagH, flagI, flagN, flagZ, flagV, flagC;
93
94 static uint8_t CPUCycles[256] = {
95         1,  2,  1,  1,  1,  1,  2,  2,  4,  4,  2,  2,  2,  2,  2,  2,
96         2,  2,  1,  1,  1,  1,  2,  2,  1,  2,  1,  2,  1,  1,  1,  1,
97         4,  1,  4,  4,  4,  4,  4,  4,  4,  4,  4,  4,  4,  4,  4,  4,
98         4,  4,  4,  4,  4,  4,  4,  4,  1,  5,  1, 10,  1,  1,  9, 12,
99         2,  1,  1,  2,  2,  1,  2,  2,  2,  2,  2,  1,  2,  2,  1,  2,
100         2,  1,  1,  2,  2,  1,  2,  2,  2,  2,  2,  1,  2,  2,  1,  2,
101         7,  1,  1,  8,  7,  1,  7,  7,  7,  7,  7,  1,  7,  7,  4,  7,
102         6,  1,  1,  7,  6,  1,  6,  6,  6,  6,  6,  1,  6,  6,  3,  6,
103         2,  2,  2,  1,  2,  2,  2,  1,  2,  2,  2,  2,  3,  8,  3,  1,
104         3,  3,  3,  1,  3,  3,  3,  4,  3,  3,  3,  3,  4,  1,  4,  5,
105         5,  5,  5,  1,  5,  5,  5,  6,  5,  5,  5,  5,  6,  8,  6,  7,
106         4,  4,  4,  1,  4,  4,  4,  5,  4,  4,  4,  4,  5,  9,  5,  6,
107         2,  2,  2,  1,  2,  2,  2,  1,  2,  2,  2,  2,  1,  1,  3,  1,
108         3,  3,  3,  1,  3,  3,  3,  4,  3,  3,  3,  3,  1,  1,  4,  5,
109         5,  5,  5,  1,  5,  5,  5,  6,  5,  5,  5,  5,  1,  1,  6,  7,
110         4,  4,  4,  1,  4,  4,  4,  5,  4,  4,  4,  4,  1,  1,  5,  6
111 };
112
113 // Private function prototypes
114
115 static uint16_t RdMemW(uint16_t);
116 static uint16_t FetchMemW(uint16_t);
117
118 //
119 // Read a word out of 6808 memory (little endian format)
120 //
121 static inline uint16_t RdMemW(uint16_t address)
122 {
123         return (uint16_t)(regs.RdMem(address) << 8) | regs.RdMem(address + 1);
124 }
125
126 //
127 // Fetch a word out of 6808 memory (little endian format). Increments PC
128 //
129 static inline uint16_t FetchMemW(uint16_t address)
130 {
131         regs.pc += 2;
132         return (uint16_t)(regs.RdMem(address) << 8) | regs.RdMem(address + 1);
133 }
134
135 //
136 // 6808 OPCODE IMPLEMENTATION
137 //
138 // NOTE: Lots of macros are used here to save a LOT of typing. Also
139 //       helps speed the debugging process. :-) Because of this, combining
140 //       certain lines may look like a good idea but would end in disaster.
141 //       You have been warned! ;-)
142 //
143
144 /*
145 Operation           |Mnem.|Immed.|Direct|Index |Extend|Inher.|Operation |CC Reg|
146                     |     |OP ~ #|OP ~ #|OP ~ #|OP ~ #|OP ~ #|          |HINZVC|
147 Add                 |ADDA |8B 2 2|9B 3 2|AB 5 2|BB 4 3|      |A=A+M     |T TTTT|
148                     |ADDB |CB 2 2|DB 3 2|EB 5 2|FB 4 3|      |B=B+M     |T TTTT|
149 Add Accumulators    |ABA  |      |      |      |      |1B 2 1|A=A+B     |T TTTT|
150 */
151
152 // ADD opcodes
153
154 #define OP_ADD_HANDLER(m, acc) \
155         uint16_t sum = (uint16_t)(acc) + (m); \
156         flagC = sum >> 8; \
157         flagH = (sum >> 4) & 0x01; \
158         SET_V(m, acc, sum); \
159         (acc) = sum & 0xFF; \
160         SET_ZN(acc)
161
162 static void Op8B(void)                                                  // ADDA #
163 {
164         uint16_t m = READ_IMM;
165         OP_ADD_HANDLER(m, regs.a);
166 }
167
168 static void Op9B(void)                                                  // ADDA ZP
169 {
170         uint16_t m = READ_ZP;
171         OP_ADD_HANDLER(m, regs.a);
172 }
173
174 static void OpAB(void)                                                  // ADDA ZP, X
175 {
176         uint16_t m = READ_ZP_X;
177         OP_ADD_HANDLER(m, regs.a);
178 }
179
180 static void OpBB(void)                                                  // ADDA ABS
181 {
182         uint16_t m = READ_ABS;
183         OP_ADD_HANDLER(m, regs.a);
184 }
185
186 static void OpCB(void)                                                  // ADDB #
187 {
188         uint16_t m = READ_IMM;
189         OP_ADD_HANDLER(m, regs.b);
190 }
191
192 static void OpDB(void)                                                  // ADDB ZP
193 {
194         uint16_t m = READ_ZP;
195         OP_ADD_HANDLER(m, regs.b);
196 }
197
198 static void OpEB(void)                                                  // ADDB ZP, X
199 {
200         uint16_t m = READ_ZP_X;
201         OP_ADD_HANDLER(m, regs.b);
202 }
203
204 static void OpFB(void)                                                  // ADDB ABS
205 {
206         uint16_t m = READ_ABS;
207         OP_ADD_HANDLER(m, regs.b);
208 }
209
210 static void Op1B(void)                                                  // ABA
211 {
212         OP_ADD_HANDLER(regs.b, regs.a);
213 }
214
215 /*
216 Operation           |Mnem.|Immed.|Direct|Index |Extend|Inher.|Operation |CC Reg|
217                     |     |OP ~ #|OP ~ #|OP ~ #|OP ~ #|OP ~ #|          |HINZVC|
218 Add with Carry      |ADCA |89 2 2|99 3 2|A9 5 2|B9 4 3|      |A=A+M+C   |T TTTT|
219                     |ADCB |C9 2 2|D9 3 2|E9 5 2|F9 4 3|      |B=B+M+C   |T TTTT|
220 */
221
222 // ADC opcodes
223
224 #define OP_ADC_HANDLER(m, acc) \
225         uint16_t sum = (uint16_t)acc + (m) + (uint16_t)flagC; \
226         flagC = sum >> 8; \
227         flagH = (sum >> 4) & 0x01; \
228         SET_V(m, acc, sum); \
229         acc = sum & 0xFF; \
230         SET_ZN(acc)
231
232 static void Op89(void)                                                  // ADCA #
233 {
234         uint16_t m = READ_IMM;
235         OP_ADC_HANDLER(m, regs.a);
236 }
237
238 static void Op99(void)                                                  // ADCA ZP
239 {
240         uint16_t m = READ_ZP;
241         OP_ADC_HANDLER(m, regs.a);
242 }
243
244 static void OpA9(void)                                                  // ADCA ZP, X
245 {
246         uint16_t m = READ_ZP_X;
247         OP_ADC_HANDLER(m, regs.a);
248 }
249
250 static void OpB9(void)                                                  // ADCA ABS
251 {
252         uint16_t m = READ_ABS;
253         OP_ADC_HANDLER(m, regs.a);
254 }
255
256 static void OpC9(void)                                                  // ADCB #
257 {
258         uint16_t m = READ_IMM;
259         OP_ADC_HANDLER(m, regs.b);
260 }
261
262 static void OpD9(void)                                                  // ADCB ZP
263 {
264         uint16_t m = READ_ZP;
265         OP_ADC_HANDLER(m, regs.b);
266 }
267
268 static void OpE9(void)                                                  // ADCB ZP, X
269 {
270         uint16_t m = READ_ZP_X;
271         OP_ADC_HANDLER(m, regs.b);
272 }
273
274 static void OpF9(void)                                                  // ADCB ABS
275 {
276         uint16_t m = READ_ABS;
277         OP_ADC_HANDLER(m, regs.b);
278 }
279
280 /*
281 Operation           |Mnem.|Immed.|Direct|Index |Extend|Inher.|Operation |CC Reg|
282                     |     |OP ~ #|OP ~ #|OP ~ #|OP ~ #|OP ~ #|          |HINZVC|
283 And                 |ANDA |84 2 2|94 3 2|A4 5 2|B4 4 3|      |A=A+M     |  TTR |
284                     |ANDB |C4 2 2|D4 3 2|E4 5 2|F4 4 3|      |B=B+M     |  TTR |
285 */
286
287 // AND opcodes
288
289 #define OP_AND_HANDLER(m, acc) \
290         acc &= m; \
291         SET_ZN(acc); \
292         CLR_V
293
294 static void Op84(void)                                                  // ANDA #
295 {
296         uint8_t m = READ_IMM;
297         OP_AND_HANDLER(m, regs.a);
298 }
299
300 static void Op94(void)                                                  // ANDA ZP
301 {
302         uint8_t m = READ_ZP;
303         OP_AND_HANDLER(m, regs.a);
304 }
305
306 static void OpA4(void)                                                  // ANDA ZP, X
307 {
308         uint16_t m = READ_ZP_X;
309         OP_AND_HANDLER(m, regs.a);
310 }
311
312 static void OpB4(void)                                                  // ANDA ABS
313 {
314         uint16_t m = READ_ABS;
315         OP_AND_HANDLER(m, regs.a);
316 }
317
318 static void OpC4(void)                                                  // ANDB #
319 {
320         uint8_t m = READ_IMM;
321         OP_AND_HANDLER(m, regs.b);
322 }
323
324 static void OpD4(void)                                                  // ANDB ZP
325 {
326         uint8_t m = READ_ZP;
327         OP_AND_HANDLER(m, regs.b);
328 }
329
330 static void OpE4(void)                                                  // ANDB ZP, X
331 {
332         uint16_t m = READ_ZP_X;
333         OP_AND_HANDLER(m, regs.b);
334 }
335
336 static void OpF4(void)                                                  // ANDB ABS
337 {
338         uint16_t m = READ_ABS;
339         OP_AND_HANDLER(m, regs.b);
340 }
341
342 /*
343 Operation           |Mnem.|Immed.|Direct|Index |Extend|Inher.|Operation |CC Reg|
344                     |     |OP ~ #|OP ~ #|OP ~ #|OP ~ #|OP ~ #|          |HINZVC|
345 Bit Test            |BITA |85 2 2|95 3 2|A5 5 2|B5 4 3|      |A+M       |  TTR |
346                     |BITB |C5 2 2|D5 3 2|E5 5 2|F5 4 3|      |B+M       |  TTR |
347 */
348
349 // BIT opcodes
350
351 #define OP_BIT_HANDLER(m, acc) \
352         int8_t result = acc & (m); \
353         SET_ZN(result)
354
355 static void Op85(void)                                                  // BITA #
356 {
357         uint8_t m = READ_IMM;
358         OP_BIT_HANDLER(m, regs.a);
359 }
360
361 static void Op95(void)                                                  // BITA ZP
362 {
363         uint8_t m = READ_ZP;
364         OP_BIT_HANDLER(m, regs.a);
365 }
366
367 static void OpA5(void)                                                  // BITA ZP, X
368 {
369         uint8_t m = READ_ZP_X;
370         OP_BIT_HANDLER(m, regs.a);
371 }
372
373 static void OpB5(void)                                                  // BITA ABS
374 {
375         uint8_t m = READ_ABS;
376         OP_BIT_HANDLER(m, regs.a);
377 }
378
379 static void OpC5(void)                                                  // BITB #
380 {
381         uint8_t m = READ_IMM;
382         OP_BIT_HANDLER(m, regs.b);
383 }
384
385 static void OpD5(void)                                                  // BITB ZP
386 {
387         uint8_t m = READ_ZP;
388         OP_BIT_HANDLER(m, regs.b);
389 }
390
391 static void OpE5(void)                                                  // BITB ZP, X
392 {
393         uint8_t m = READ_ZP_X;
394         OP_BIT_HANDLER(m, regs.b);
395 }
396
397 static void OpF5(void)                                                  // BITB ABS
398 {
399         uint8_t m = READ_ABS;
400         OP_BIT_HANDLER(m, regs.b);
401 }
402
403 /*
404 Operation           |Mnem.|Immed.|Direct|Index |Extend|Inher.|Operation |CC Reg|
405                     |     |OP ~ #|OP ~ #|OP ~ #|OP ~ #|OP ~ #|          |HINZVC|
406 Clear               |CLR  |      |      |6F 7 2|7F 6 3|      |M=00      |  RSRR|
407                     |CLRA |      |      |      |      |4F 2 1|A=00      |  RSRR|
408                     |CLRB |      |      |      |      |5F 2 1|B=00      |  RSRR|
409 */
410
411 // CLR opcodes
412
413 static void Op6F(void)                                                  // CLR ZP, X
414 {
415         regs.WrMem(EA_ZP_X, 0);
416         CLR_NVC;
417         SET_Z(0);
418 }
419
420 static void Op7F(void)                                                  // CLR ABS
421 {
422         regs.WrMem(EA_ABS, 0);
423         CLR_NVC;
424         SET_Z(0);
425 }
426
427 static void Op4F(void)                                                  // CLRA
428 {
429         regs.a = 0;
430         CLR_NVC;
431         SET_Z(0);
432 }
433
434 static void Op5F(void)                                                  // CLRB
435 {
436         regs.b = 0;
437         CLR_NVC;
438         SET_Z(0);
439 }
440
441 /*
442 Operation           |Mnem.|Immed.|Direct|Index |Extend|Inher.|Operation |CC Reg|
443                     |     |OP ~ #|OP ~ #|OP ~ #|OP ~ #|OP ~ #|          |HINZVC|
444 Compare             |CMPA |81 2 2|91 3 2|A1 5 2|B1 4 3|      |A-M       |  TTTT|
445                     |CMPB |C1 2 2|D1 3 2|E1 5 2|F1 4 3|      |B-M       |  TTTT|
446 Compare Accumulators|CBA  |      |      |      |      |11 2 1|A-B       |  TTTT|
447 */
448
449 // CMP opcodes
450
451 /*
452 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.
453 */
454
455 #define OP_CMP_HANDLER(m, acc) \
456         uint16_t result = acc - (m); \
457         SET_ZNVC_CMP(m, acc, result)
458
459 static void Op81(void)                                                  // CMPA #
460 {
461         uint8_t m = READ_IMM;
462         OP_CMP_HANDLER(m, regs.a);
463 }
464
465 static void Op91(void)                                                  // CMPA ZP
466 {
467         uint8_t m = READ_ZP;
468         OP_CMP_HANDLER(m, regs.a);
469 }
470
471 static void OpA1(void)                                                  // CMPA ZP, X
472 {
473         uint8_t m = READ_ZP_X;
474         OP_CMP_HANDLER(m, regs.a);
475 }
476
477 static void OpB1(void)                                                  // CMPA ABS
478 {
479         uint8_t m = READ_ABS;
480         OP_CMP_HANDLER(m, regs.a);
481 }
482
483 static void OpC1(void)                                                  // CMPB #
484 {
485         uint8_t m = READ_IMM;
486         OP_CMP_HANDLER(m, regs.b);
487 }
488
489 static void OpD1(void)                                                  // CMPB ZP
490 {
491         uint8_t m = READ_ZP;
492         OP_CMP_HANDLER(m, regs.b);
493 }
494
495 static void OpE1(void)                                                  // CMPB ZP, X
496 {
497         uint8_t m = READ_ZP_X;
498         OP_CMP_HANDLER(m, regs.b);
499 }
500
501 static void OpF1(void)                                                  // CMPB ABS
502 {
503         uint8_t m = READ_ABS;
504         OP_CMP_HANDLER(m, regs.b);
505 }
506
507 static void Op11(void)                                                  // CBA
508 {
509         OP_CMP_HANDLER(regs.b, regs.a);
510 }
511
512 /*
513 Operation           |Mnem.|Immed.|Direct|Index |Extend|Inher.|Operation |CC Reg|
514                     |     |OP ~ #|OP ~ #|OP ~ #|OP ~ #|OP ~ #|          |HINZVC|
515 Complement 1's      |COM  |      |      |63 7 2|73 6 3|      |M=-M      |  TTRS|
516                     |COMA |      |      |      |      |43 2 1|A=-A      |  TTRS|
517                     |COMB |      |      |      |      |53 2 1|B=-B      |  TTRS|
518 */
519
520 // COM opcodes
521
522 #define OP_COM_HANDLER(m) \
523         m = m ^ 0xFF; \
524         SET_ZN(m); \
525         CLR_V; \
526         flagC = 1
527
528 static void Op63(void)                                                  // COM ZP, X
529 {
530         uint8_t m;
531         READ_ZP_X_WB(m);
532         OP_COM_HANDLER(m);
533         WRITE_BACK(m);
534 }
535
536 static void Op73(void)                                                  // COM ABS
537 {
538         uint8_t m;
539         READ_ABS_WB(m);
540         OP_COM_HANDLER(m);
541         WRITE_BACK(m);
542 }
543
544 static void Op43(void)                                                  // COMA
545 {
546         OP_COM_HANDLER(regs.a);
547 }
548
549 static void Op53(void)                                                  // COMB
550 {
551         OP_COM_HANDLER(regs.b);
552 }
553
554 /*
555 Operation           |Mnem.|Immed.|Direct|Index |Extend|Inher.|Operation |CC Reg|
556                     |     |OP ~ #|OP ~ #|OP ~ #|OP ~ #|OP ~ #|          |HINZVC|
557 Complement 2's      |NEG  |      |      |60 7 2|70 6 3|      |M=00-M    |  TT12|
558                     |NEGA |      |      |      |      |40 2 1|A=00-A    |  TT12|
559                     |NEGB |      |      |      |      |50 2 1|B=00-B    |  TT12|
560 */
561
562 // NEG opcodes
563
564 #define OP_NEG_HANDLER(m) \
565         m = -m; \
566         SET_ZN(m); \
567         flagV = (m == 0x80 ? 1 : 0); \
568         flagC = (m == 0x00 ? 1 : 0)
569
570 static void Op60(void)                                                  // NEG ZP, X
571 {
572         uint8_t m;
573         READ_ZP_X_WB(m);
574         OP_NEG_HANDLER(m);
575         WRITE_BACK(m);
576 }
577
578 static void Op70(void)                                                  // NEG ABS
579 {
580         uint8_t m;
581         READ_ABS_WB(m);
582         OP_NEG_HANDLER(m);
583         WRITE_BACK(m);
584 }
585
586 static void Op40(void)                                                  // NEGA
587 {
588         OP_NEG_HANDLER(regs.a);
589 }
590
591 static void Op50(void)                                                  // NEGB
592 {
593         OP_NEG_HANDLER(regs.b);
594 }
595
596 /*
597 Operation           |Mnem.|Immed.|Direct|Index |Extend|Inher.|Operation |CC Reg|
598                     |     |OP ~ #|OP ~ #|OP ~ #|OP ~ #|OP ~ #|          |HINZVC|
599 Decimal Adjust      |DAA  |      |      |      |      |19 2 1|*         |  TTT3|
600 */
601
602 static void Op19(void)                                                  // DAA
603 {
604         uint16_t result = (uint16_t)regs.a;
605
606         if ((regs.a & 0x0F) > 0x09 || flagH)
607                 result += 0x06;
608
609         if ((regs.a & 0xF0) > 0x90 || flagC || ((regs.a & 0xF0) > 0x80 && (regs.a & 0x0F) > 0x09))
610                 result += 0x60;
611
612         regs.a = (uint8_t)result;
613         SET_ZN(result);
614         CLR_V;                                                                          // Not sure this is correct...
615         flagC |= (result & 0x100) >> 8;                         // Overwrite carry if it was 0, otherwise, ignore
616 }
617
618 /*
619 Operation           |Mnem.|Immed.|Direct|Index |Extend|Inher.|Operation |CC Reg|
620                     |     |OP ~ #|OP ~ #|OP ~ #|OP ~ #|OP ~ #|          |HINZVC|
621 Decrement           |DEC  |      |      |6A 7 2|7A 6 3|      |M=M-1     |  TT4 |
622                     |DECA |      |      |      |      |4A 2 1|A=A-1     |  TT4 |
623                     |DECB |      |      |      |      |5A 2 1|B=B-1     |  TT4 |
624 */
625
626 // DEC opcodes
627
628 #define OP_DEC_HANDLER(m) \
629         m--; \
630         SET_ZN(m); \
631         flagV = (m == 0x7F ? 1 : 0)
632
633 static void Op6A(void)                                                  // DEC ZP, X
634 {
635         uint8_t m;
636         READ_ZP_X_WB(m);
637         OP_DEC_HANDLER(m);
638         WRITE_BACK(m);
639 }
640
641 static void Op7A(void)                                                  // DEC ABS
642 {
643         uint8_t m;
644         READ_ABS_WB(m);
645         OP_DEC_HANDLER(m);
646         WRITE_BACK(m);
647 }
648
649 static void Op4A(void)                                                  // DECA
650 {
651         OP_DEC_HANDLER(regs.a);
652 }
653
654 static void Op5A(void)                                                  // DECB
655 {
656         OP_DEC_HANDLER(regs.b);
657 }
658
659 /*
660 Operation           |Mnem.|Immed.|Direct|Index |Extend|Inher.|Operation |CC Reg|
661                     |     |OP ~ #|OP ~ #|OP ~ #|OP ~ #|OP ~ #|          |HINZVC|
662 Exclusive OR        |EORA |88 2 2|98 3 2|A8 5 2|B8 4 3|      |A=A(+)M   |  TTR |
663                     |EORB |C8 2 2|D8 3 2|E8 5 2|F8 4 3|      |B=B(+)M   |  TTR |
664 */
665
666 // EOR opcodes
667
668 #define OP_EOR_HANDLER(m, acc) \
669         acc ^= m; \
670         SET_ZN(acc); \
671         CLR_V
672
673 static void Op88(void)                                                  // EORA #
674 {
675         uint8_t m = READ_IMM;
676         OP_EOR_HANDLER(m, regs.a);
677 }
678
679 static void Op98(void)                                                  // EORA ZP
680 {
681         uint8_t m = READ_ZP;
682         OP_EOR_HANDLER(m, regs.a);
683 }
684
685 static void OpA8(void)                                                  // EORA ZP, X
686 {
687         uint8_t m = READ_ZP_X;
688         OP_EOR_HANDLER(m, regs.a);
689 }
690
691 static void OpB8(void)                                                  // EORA ABS
692 {
693         uint8_t m = READ_ABS;
694         OP_EOR_HANDLER(m, regs.a);
695 }
696
697 static void OpC8(void)                                                  // EORB #
698 {
699         uint8_t m = READ_IMM;
700         OP_EOR_HANDLER(m, regs.b);
701 }
702
703 static void OpD8(void)                                                  // EORB ZP
704 {
705         uint8_t m = READ_ZP;
706         OP_EOR_HANDLER(m, regs.b);
707 }
708
709 static void OpE8(void)                                                  // EORB ZP, X
710 {
711         uint8_t m = READ_ZP_X;
712         OP_EOR_HANDLER(m, regs.b);
713 }
714
715 static void OpF8(void)                                                  // EORB ABS
716 {
717         uint8_t m = READ_ABS;
718         OP_EOR_HANDLER(m, regs.b);
719 }
720
721 /*
722 Operation           |Mnem.|Immed.|Direct|Index |Extend|Inher.|Operation |CC Reg|
723                     |     |OP ~ #|OP ~ #|OP ~ #|OP ~ #|OP ~ #|          |HINZVC|
724 Increment           |INC  |      |      |6C 7 2|7C 6 3|      |M=M+1     |  TT5 |
725                     |INCA |      |      |      |      |4C 2 1|A=A+1     |  TT5 |
726                     |INCB |      |      |      |      |5C 2 1|B=B+1     |  TT5 |
727 */
728
729 // INC opcodes
730
731 #define OP_INC_HANDLER(m) \
732         m++; \
733         SET_ZN(m); \
734         flagV = (m == 0x80 ? 1 : 0)
735
736 static void Op6C(void)                                                  // INC ZP, X
737 {
738         uint8_t m;
739         READ_ZP_X_WB(m);
740         OP_INC_HANDLER(m);
741         WRITE_BACK(m);
742 }
743
744 static void Op7C(void)                                                  // INC ABS
745 {
746         uint8_t m;
747         READ_ABS_WB(m);
748         OP_INC_HANDLER(m);
749         WRITE_BACK(m);
750 }
751
752 static void Op4C(void)                                                  // INCA
753 {
754         OP_INC_HANDLER(regs.a);
755 }
756
757 static void Op5C(void)                                                  // INCB
758 {
759         OP_INC_HANDLER(regs.b);
760 }
761
762 /*
763 Operation           |Mnem.|Immed.|Direct|Index |Extend|Inher.|Operation |CC Reg|
764                     |     |OP ~ #|OP ~ #|OP ~ #|OP ~ #|OP ~ #|          |HINZVC|
765 Load Accumulator    |LDAA |86 2 2|96 3 2|A6 5 2|B6 4 3|      |A=M       |  TTR |
766                     |LDAB |C6 2 2|D6 3 2|E6 5 2|F6 4 3|      |B=M       |  TTR |
767 */
768
769 // LDA opcodes
770
771 #define OP_LDA_HANDLER(m, acc) \
772         acc = m; \
773         SET_ZN(acc); \
774         CLR_V
775
776 static void Op86(void)                                                  // LDAA #
777 {
778         uint8_t m = READ_IMM;
779         OP_LDA_HANDLER(m, regs.a);
780 }
781
782 static void Op96(void)                                                  // LDAA ZP
783 {
784         uint8_t m = READ_ZP;
785         OP_LDA_HANDLER(m, regs.a);
786 }
787
788 static void OpA6(void)                                                  // LDAA ZP, X
789 {
790         uint8_t m = READ_ZP_X;
791         OP_LDA_HANDLER(m, regs.a);
792 }
793
794 static void OpB6(void)                                                  // LDAA ABS
795 {
796         uint8_t m = READ_ABS;
797         OP_LDA_HANDLER(m, regs.a);
798 }
799
800 static void OpC6(void)                                                  // LDAB #
801 {
802         uint8_t m = READ_IMM;
803         OP_LDA_HANDLER(m, regs.b);
804 }
805
806 static void OpD6(void)                                                  // LDAB ZP
807 {
808         uint8_t m = READ_ZP;
809         OP_LDA_HANDLER(m, regs.b);
810 }
811
812 static void OpE6(void)                                                  // LDAB ZP, X
813 {
814         uint8_t m = READ_ZP_X;
815         OP_LDA_HANDLER(m, regs.b);
816 }
817
818 static void OpF6(void)                                                  // LDAB ABS
819 {
820         uint8_t m = READ_ABS;
821         OP_LDA_HANDLER(m, regs.b);
822 }
823
824 /*
825 Operation           |Mnem.|Immed.|Direct|Index |Extend|Inher.|Operation |CC Reg|
826                     |     |OP ~ #|OP ~ #|OP ~ #|OP ~ #|OP ~ #|          |HINZVC|
827 OR, Inclusive       |ORAA |8A 2 2|9A 3 2|AA 5 2|BA 4 3|      |A=A+M     |  TTR |
828                     |ORAB |CA 2 2|DA 3 2|EA 5 2|FA 4 3|      |B=B+M     |  TTR |
829 */
830
831 // ORA opcodes
832
833 #define OP_ORA_HANDLER(m, acc) \
834         acc |= m; \
835         SET_ZN(acc); \
836         CLR_V
837
838 static void Op8A(void)                                                  // ORAA #
839 {
840         uint8_t m = READ_IMM;
841         OP_ORA_HANDLER(m, regs.a);
842 }
843
844 static void Op9A(void)                                                  // ORAA ZP
845 {
846         uint8_t m = READ_ZP;
847         OP_ORA_HANDLER(m, regs.a);
848 }
849
850 static void OpAA(void)                                                  // ORAA ZP, X
851 {
852         uint8_t m = READ_ZP_X;
853         OP_ORA_HANDLER(m, regs.a);
854 }
855
856 static void OpBA(void)                                                  // ORAA ABS
857 {
858         uint8_t m = READ_ABS;
859         OP_ORA_HANDLER(m, regs.a);
860 }
861
862 static void OpCA(void)                                                  // ORAB #
863 {
864         uint8_t m = READ_IMM;
865         OP_ORA_HANDLER(m, regs.b);
866 }
867
868 static void OpDA(void)                                                  // ORAB ZP
869 {
870         uint8_t m = READ_ZP;
871         OP_ORA_HANDLER(m, regs.b);
872 }
873
874 static void OpEA(void)                                                  // ORAB ZP, X
875 {
876         uint8_t m = READ_ZP_X;
877         OP_ORA_HANDLER(m, regs.b);
878 }
879
880 static void OpFA(void)                                                  // ORAB ABS
881 {
882         uint8_t m = READ_ABS;
883         OP_ORA_HANDLER(m, regs.b);
884 }
885
886 /*
887 Operation           |Mnem.|Immed.|Direct|Index |Extend|Inher.|Operation |CC Reg|
888                     |     |OP ~ #|OP ~ #|OP ~ #|OP ~ #|OP ~ #|          |HINZVC|
889 Push Data           |PSHA |      |      |      |      |36 4 1|Msp=A, *- |      |
890                     |PSHB |      |      |      |      |37 4 1|Msp=B, *- |      |
891 Pull Data           |PULA |      |      |      |      |32 4 1|A=Msp, *+ |      |
892                     |PULB |      |      |      |      |33 4 1|B=Msp, *+ |      |
893 */
894
895 static void Op36(void)                                                  // PSHA
896 {
897         PUSH(regs.a);
898 }
899
900 static void Op37(void)                                                  // PSHB
901 {
902         PUSH(regs.b);
903 }
904
905 static void Op32(void)                                                  // PULA
906 {
907         regs.a = PULL;
908 }
909
910 static void Op33(void)                                                  // PULB
911 {
912         regs.b = PULL;
913 }
914
915 /*
916 Operation           |Mnem.|Immed.|Direct|Index |Extend|Inher.|Operation |CC Reg|
917                     |     |OP ~ #|OP ~ #|OP ~ #|OP ~ #|OP ~ #|          |HINZVC|
918 Rotate Left         |ROL  |      |      |69 7 2|79 6 3|      |Memory  *1|  TT6T|
919                     |ROLA |      |      |      |      |49 2 1|Accum A *1|  TT6T|
920                     |ROLB |      |      |      |      |59 2 1|Accum B *1|  TT6T|
921 */
922
923 // ROL opcodes
924
925 #define OP_ROL_HANDLER(m) \
926         uint8_t newCarry = (m & 0x80) >> 7; \
927         m = (m << 1) | flagC; \
928         SET_ZN(m); \
929         flagC = newCarry; \
930         flagV = flagN ^ flagC
931
932 static void Op69(void)                                                  // ROL ZP, X
933 {
934         uint8_t m;
935         READ_ZP_X_WB(m);
936         OP_ROL_HANDLER(m);
937         WRITE_BACK(m);
938 }
939
940 static void Op79(void)                                                  // ROL ABS
941 {
942         uint8_t m;
943         READ_ABS_WB(m);
944         OP_ROL_HANDLER(m);
945         WRITE_BACK(m);
946 }
947
948 static void Op49(void)                                                  // ROLA
949 {
950         OP_ROL_HANDLER(regs.a);
951 }
952
953 static void Op59(void)                                                  // ROLB
954 {
955         OP_ROL_HANDLER(regs.b);
956 }
957
958 /*
959 Operation           |Mnem.|Immed.|Direct|Index |Extend|Inher.|Operation |CC Reg|
960                     |     |OP ~ #|OP ~ #|OP ~ #|OP ~ #|OP ~ #|          |HINZVC|
961 Rotate Right        |ROR  |      |      |66 7 2|76 6 3|      |Memory  *2|  TT6T|
962                     |RORA |      |      |      |      |46 2 1|Accum A *2|  TT6T|
963                     |RORB |      |      |      |      |56 2 1|Accum B *2|  TT6T|
964 */
965
966 // ROR opcodes
967
968 #define OP_ROR_HANDLER(m) \
969         uint8_t newCarry = m & 0x01; \
970         m = (m >> 1) | (flagC << 7); \
971         SET_ZN(m); \
972         flagC = newCarry; \
973         flagV = flagN ^ flagC
974
975 static void Op66(void)                                                  // ROR ZP, X
976 {
977         uint8_t m;
978         READ_ZP_X_WB(m);
979         OP_ROR_HANDLER(m);
980         WRITE_BACK(m);
981 }
982
983 static void Op76(void)                                                  // ROR ABS
984 {
985         uint8_t m;
986         READ_ABS_WB(m);
987         OP_ROR_HANDLER(m);
988         WRITE_BACK(m);
989 }
990
991 static void Op46(void)                                                  // RORA
992 {
993         OP_ROR_HANDLER(regs.a);
994 }
995
996 static void Op56(void)                                                  // RORB
997 {
998         OP_ROR_HANDLER(regs.b);
999 }
1000
1001 /*
1002 Operation           |Mnem.|Immed.|Direct|Index |Extend|Inher.|Operation |CC Reg|
1003                     |     |OP ~ #|OP ~ #|OP ~ #|OP ~ #|OP ~ #|          |HINZVC|
1004 Arithmetic Shft Left|ASL  |      |      |68 7 2|78 6 3|      |Memory  *3|  TT6T|
1005                     |ASLA |      |      |      |      |48 2 1|Accum A *3|  TT6T|
1006                     |ASLB |      |      |      |      |58 2 1|Accum B *3|  TT6T|
1007 */
1008
1009 // ASL opcodes
1010
1011 #define OP_ASL_HANDLER(m) \
1012         uint8_t newCarry = (m & 0x80) >> 7; \
1013         m <<= 1; \
1014         SET_ZN(m); \
1015         flagC = newCarry; \
1016         flagV = flagN ^ flagC
1017
1018 static void Op68(void)                                                  // ASL ZP, X
1019 {
1020         uint8_t m;
1021         READ_ZP_X_WB(m);
1022         OP_ASL_HANDLER(m);
1023         WRITE_BACK(m);
1024 }
1025
1026 static void Op78(void)                                                  // ASL ABS
1027 {
1028         uint8_t m;
1029         READ_ABS_WB(m);
1030         OP_ASL_HANDLER(m);
1031         WRITE_BACK(m);
1032 }
1033
1034 static void Op48(void)                                                  // ASLA
1035 {
1036         OP_ASL_HANDLER(regs.a);
1037 }
1038
1039 static void Op58(void)                                                  // ASLB
1040 {
1041         OP_ASL_HANDLER(regs.b);
1042 }
1043
1044 /*
1045 Operation           |Mnem.|Immed.|Direct|Index |Extend|Inher.|Operation |CC Reg|
1046                     |     |OP ~ #|OP ~ #|OP ~ #|OP ~ #|OP ~ #|          |HINZVC|
1047 Arithmetic Shft Rght|ASR  |      |      |67 7 2|77 6 3|      |Memory  *4|  TT6T|
1048                     |ASRA |      |      |      |      |47 2 1|Accum A *4|  TT6T|
1049                     |ASRB |      |      |      |      |57 2 1|Accum B *4|  TT6T|
1050 */
1051
1052 // ASR opcodes
1053
1054 #define OP_ASR_HANDLER(m) \
1055         uint8_t newCarry = m & 0x01; \
1056         m = (m >> 1) | (m & 0x80); \
1057         SET_ZN(m); \
1058         flagC = newCarry; \
1059         flagV = flagN ^ flagC
1060
1061 static void Op67(void)                                                  // ASR ZP, X
1062 {
1063         uint8_t m;
1064         READ_ZP_X_WB(m);
1065         OP_ASR_HANDLER(m);
1066         WRITE_BACK(m);
1067 }
1068
1069 static void Op77(void)                                                  // ASR ABS
1070 {
1071         uint8_t m;
1072         READ_ABS_WB(m);
1073         OP_ASR_HANDLER(m);
1074         WRITE_BACK(m);
1075 }
1076
1077 static void Op47(void)                                                  // ASRA
1078 {
1079         OP_ASR_HANDLER(regs.a);
1080 }
1081
1082 static void Op57(void)                                                  // ASRB
1083 {
1084         OP_ASR_HANDLER(regs.b);
1085 }
1086
1087 /*
1088 Operation           |Mnem.|Immed.|Direct|Index |Extend|Inher.|Operation |CC Reg|
1089                     |     |OP ~ #|OP ~ #|OP ~ #|OP ~ #|OP ~ #|          |HINZVC|
1090 Logic Shift Right   |LSR  |      |      |64 7 2|74 6 3|      |Memory  *5|  TT6T|
1091                     |LSRA |      |      |      |      |44 2 1|Accum A *5|  TT6T|
1092                     |LSRB |      |      |      |      |54 2 1|Accum B *5|  TT6T|
1093 */
1094
1095 // LSR opcodes
1096
1097 #define OP_LSR_HANDLER(m) \
1098         uint8_t newCarry = m & 0x01; \
1099         m >>= 1; \
1100         SET_ZN(m); \
1101         flagC = newCarry; \
1102         flagV = flagN ^ flagC
1103
1104 static void Op64(void)                                                  // LSR ZP, X
1105 {
1106         uint8_t m;
1107         READ_ZP_X_WB(m);
1108         OP_LSR_HANDLER(m);
1109         WRITE_BACK(m);
1110 }
1111
1112 static void Op74(void)                                                  // LSR ABS
1113 {
1114         uint8_t m;
1115         READ_ABS_WB(m);
1116         OP_LSR_HANDLER(m);
1117         WRITE_BACK(m);
1118 }
1119
1120 static void Op44(void)                                                  // LSRA
1121 {
1122         OP_LSR_HANDLER(regs.a);
1123 }
1124
1125 static void Op54(void)                                                  // LSRB
1126 {
1127         OP_LSR_HANDLER(regs.b);
1128 }
1129
1130 /*
1131 Operation           |Mnem.|Immed.|Direct|Index |Extend|Inher.|Operation |CC Reg|
1132                     |     |OP ~ #|OP ~ #|OP ~ #|OP ~ #|OP ~ #|          |HINZVC|
1133 Store Accumulator   |STAA |      |97 4 2|A7 6 2|B7 5 3|      |M=A       |  TTR |
1134                     |STAB |      |D7 4 2|E7 6 2|F7 5 3|      |M=B       |  TTR |
1135 */
1136
1137 static void Op97(void)                                                  // STAA ZP
1138 {
1139         regs.WrMem(EA_ZP, regs.a);
1140 }
1141
1142 static void OpA7(void)                                                  // STAA ZP, X
1143 {
1144         regs.WrMem(EA_ZP_X, regs.a);
1145 }
1146
1147 static void OpB7(void)                                                  // STAA ABS
1148 {
1149         regs.WrMem(EA_ABS, regs.a);
1150 }
1151
1152 static void OpD7(void)                                                  // STAB ZP
1153 {
1154         regs.WrMem(EA_ZP, regs.b);
1155 }
1156
1157 static void OpE7(void)                                                  // STAB ZP, X
1158 {
1159         regs.WrMem(EA_ZP_X, regs.b);
1160 }
1161
1162 static void OpF7(void)                                                  // STAB ABS
1163 {
1164         regs.WrMem(EA_ABS, regs.b);
1165 }
1166
1167 /*
1168 Operation           |Mnem.|Immed.|Direct|Index |Extend|Inher.|Operation |CC Reg|
1169                     |     |OP ~ #|OP ~ #|OP ~ #|OP ~ #|OP ~ #|          |HINZVC|
1170 Subtract            |SUBA |80 2 2|90 3 2|A0 5 2|B0 4 3|      |A=A-M     |  TTTT|
1171                     |SUBB |C0 2 2|D0 3 2|E0 5 2|F0 4 3|      |B=B-M     |  TTTT|
1172 Subtract Accumulatrs|SBA  |      |      |      |      |10 2 1|A=A-B     |  TTTT|
1173 */
1174
1175 // SUB opcodes
1176
1177 #define OP_SUB_HANDLER(m, acc) \
1178         uint16_t sum = (uint16_t)acc - (m); \
1179         flagC = sum >> 15; \
1180         SET_V(m, acc, sum); \
1181         acc = (uint8_t)sum; \
1182         SET_ZN(acc)
1183
1184 static void Op80(void)                                                  // SUBA #
1185 {
1186         uint16_t m = READ_IMM;
1187         OP_SUB_HANDLER(m, regs.a);
1188 }
1189
1190 static void Op90(void)                                                  // SUBA ZP
1191 {
1192         uint16_t m = READ_ZP;
1193         OP_SUB_HANDLER(m, regs.a);
1194 }
1195
1196 static void OpA0(void)                                                  // SUBA ZP, X
1197 {
1198         uint16_t m = READ_ZP_X;
1199         OP_SUB_HANDLER(m, regs.a);
1200 }
1201
1202 static void OpB0(void)                                                  // SUBA ABS
1203 {
1204         uint16_t m = READ_ABS;
1205         OP_SUB_HANDLER(m, regs.a);
1206 }
1207
1208 static void OpC0(void)                                                  // SUBB #
1209 {
1210         uint16_t m = READ_IMM;
1211         OP_SUB_HANDLER(m, regs.b);
1212 }
1213
1214 static void OpD0(void)                                                  // SUBB ZP
1215 {
1216         uint16_t m = READ_ZP;
1217         OP_SUB_HANDLER(m, regs.b);
1218 }
1219
1220 static void OpE0(void)                                                  // SUBB ZP, X
1221 {
1222         uint16_t m = READ_ZP_X;
1223         OP_SUB_HANDLER(m, regs.b);
1224 }
1225
1226 static void OpF0(void)                                                  // SUBB ABS
1227 {
1228         uint16_t m = READ_ABS;
1229         OP_SUB_HANDLER(m, regs.b);
1230 }
1231
1232 static void Op10(void)                                                  // SBA
1233 {
1234         OP_SUB_HANDLER(regs.b, regs.a);
1235 }
1236
1237 /*
1238 Operation           |Mnem.|Immed.|Direct|Index |Extend|Inher.|Operation |CC Reg|
1239                     |     |OP ~ #|OP ~ #|OP ~ #|OP ~ #|OP ~ #|          |HINZVC|
1240 Subtract with Carry |SBCA |82 2 2|92 3 2|A2 5 2|B2 4 3|      |A=A-M-C   |  TTTT|
1241                     |SBCB |C2 2 2|D2 3 2|E2 5 2|F2 4 3|      |B=B-M-C   |  TTTT|
1242 */
1243
1244 // SBC opcodes
1245
1246 #define OP_SBC_HANDLER(m, acc) \
1247         uint16_t sum = (uint16_t)acc - (m) - (uint16_t)flagC; \
1248         flagC = sum >> 15; \
1249         SET_V(m, acc, sum); \
1250         acc = (uint8_t)sum; \
1251         SET_ZN(acc)
1252
1253 static void Op82(void)                                                  // SBCA #
1254 {
1255         uint16_t m = READ_IMM;
1256         OP_SBC_HANDLER(m, regs.a);
1257 }
1258
1259 static void Op92(void)                                                  // SBCA ZP
1260 {
1261         uint16_t m = READ_ZP;
1262         OP_SBC_HANDLER(m, regs.a);
1263 }
1264
1265 static void OpA2(void)                                                  // SBCA ZP, X
1266 {
1267         uint16_t m = READ_ZP_X;
1268         OP_SBC_HANDLER(m, regs.a);
1269 }
1270
1271 static void OpB2(void)                                                  // SBCA ABS
1272 {
1273         uint16_t m = READ_ABS;
1274         OP_SBC_HANDLER(m, regs.a);
1275 }
1276
1277 static void OpC2(void)                                                  // SBCB #
1278 {
1279         uint16_t m = READ_IMM;
1280         OP_SBC_HANDLER(m, regs.b);
1281 }
1282
1283 static void OpD2(void)                                                  // SBCB ZP
1284 {
1285         uint16_t m = READ_ZP;
1286         OP_SBC_HANDLER(m, regs.b);
1287 }
1288
1289 static void OpE2(void)                                                  // SBCB ZP, X
1290 {
1291         uint16_t m = READ_ZP_X;
1292         OP_SBC_HANDLER(m, regs.b);
1293 }
1294
1295 static void OpF2(void)                                                  // SBCB ABS
1296 {
1297         uint16_t m = READ_ABS;
1298         OP_SBC_HANDLER(m, regs.b);
1299 }
1300
1301 /*
1302 Operation           |Mnem.|Immed.|Direct|Index |Extend|Inher.|Operation |CC Reg|
1303                     |     |OP ~ #|OP ~ #|OP ~ #|OP ~ #|OP ~ #|          |HINZVC|
1304 Transfer Accumulatrs|TAB  |      |      |      |      |16 2 1|B=A       |  TTR |
1305                     |TBA  |      |      |      |      |17 2 1|A=B       |  TTR |
1306 */
1307
1308 static void Op16(void)                                                  // TAB
1309 {
1310         regs.b = regs.a;
1311         SET_ZN(regs.b);
1312         CLR_V;
1313 }
1314
1315 static void Op17(void)                                                  // TBA
1316 {
1317         regs.a = regs.b;
1318         SET_ZN(regs.a);
1319         CLR_V;
1320 }
1321
1322 /*
1323 Operation           |Mnem.|Immed.|Direct|Index |Extend|Inher.|Operation |CC Reg|
1324                     |     |OP ~ #|OP ~ #|OP ~ #|OP ~ #|OP ~ #|          |HINZVC|
1325 Test, Zero/Minus    |TST  |      |      |6D 7 2|7D 6 3|      |M-00      |  TTRR|
1326                     |TSTA |      |      |      |      |4D 2 1|A-00      |  TTRR|
1327                     |TSTB |      |      |      |      |5D 2 1|B-00      |  TTRR|
1328 */
1329
1330 // TST opcodes
1331
1332 #define OP_TST_HANDLER(m) \
1333         SET_ZN(m); \
1334         CLR_VC
1335
1336 static void Op6D(void)                                                  // TST ZP, X
1337 {
1338         uint8_t m;
1339         READ_ZP_X_WB(m);
1340         OP_TST_HANDLER(m);
1341         WRITE_BACK(m);
1342 }
1343
1344 static void Op7D(void)                                                  // TST ABS
1345 {
1346         uint8_t m;
1347         READ_ABS_WB(m);
1348         OP_TST_HANDLER(m);
1349         WRITE_BACK(m);
1350 }
1351
1352 static void Op4D(void)                                                  // TSTA
1353 {
1354         OP_TST_HANDLER(regs.a);
1355 }
1356
1357 static void Op5D(void)                                                  // TSTB
1358 {
1359         OP_TST_HANDLER(regs.b);
1360 }
1361
1362 /*
1363 Operation           |Mnem.|Immed.|Direct|Index |Extend|Inher.|Operation |CC Reg|
1364                     |     |OP ~ #|OP ~ #|OP ~ #|OP ~ #|OP ~ #|          |HINZVC|
1365 Compare Index Regstr|CPX  |8C 3 3|9C 4 2|AC 6 2|BC 5 3|      |Formula 1 |  7T8 |
1366 */
1367
1368 // CPX opcodes
1369
1370 /*
1371 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.
1372 */
1373
1374 #define OP_CPX_HANDLER(m) \
1375         uint32_t result = regs.x - (m); \
1376         SET_ZNVC_CMP16(m, regs.x, result)
1377
1378 static void Op8C(void)                                                  // CPX #
1379 {
1380         uint16_t m = READ_IMM16;
1381         OP_CPX_HANDLER(m);
1382 }
1383
1384 static void Op9C(void)                                                  // CPX ZP
1385 {
1386         uint16_t m = READ_ZP16;
1387         OP_CPX_HANDLER(m);
1388 }
1389
1390 static void OpAC(void)                                                  // CPX ZP, X
1391 {
1392         uint16_t m = READ_ZP_X16;
1393         OP_CPX_HANDLER(m);
1394 }
1395
1396 static void OpBC(void)                                                  // CPX ABS
1397 {
1398         uint16_t m = READ_ABS16;
1399         OP_CPX_HANDLER(m);
1400 }
1401
1402 /*
1403 Operation           |Mnem.|Immed.|Direct|Index |Extend|Inher.|Operation |CC Reg|
1404                     |     |OP ~ #|OP ~ #|OP ~ #|OP ~ #|OP ~ #|          |HINZVC|
1405 Decrement Index Regr|DEX  |      |      |      |      |09 4 1|X=X-1     |   T  |
1406 Dec Stack Pointer   |DES  |      |      |      |      |34 4 1|SP=SP-1   |      |
1407 Inc Index Regster   |INX  |      |      |      |      |08 4 1|X=X+1     |   T  |
1408 Inc Stack Pointer   |INS  |      |      |      |      |31 4 1|SP=SP+1   |      |
1409 */
1410
1411 static void Op09(void)                                                  // DEX
1412 {
1413         regs.x--;
1414         SET_Z(regs.x);
1415 }
1416
1417 static void Op34(void)                                                  // DES
1418 {
1419         regs.s--;
1420 }
1421
1422 static void Op08(void)                                                  // INX
1423 {
1424         regs.x++;
1425         SET_Z(regs.x);
1426 }
1427
1428 static void Op31(void)                                                  // INS
1429 {
1430         regs.s++;
1431 }
1432
1433 /*
1434 Operation           |Mnem.|Immed.|Direct|Index |Extend|Inher.|Operation |CC Reg|
1435                     |     |OP ~ #|OP ~ #|OP ~ #|OP ~ #|OP ~ #|          |HINZVC|
1436 Load Index Register |LDX  |CE 3 3|DE 4 2|EE 6 2|FE 5 3|      |Formula 2 |  9TR |
1437 Load Stack Pointer  |LDS  |8E 3 3|9E 4 2|AE 6 2|BE 5 3|      |Formula 3 |  9TR |
1438 */
1439
1440 // LD* opcode handler
1441
1442 #define OP_LD_HANDLER(acc) \
1443         SET_N16(acc); \
1444         SET_Z(acc); \
1445         CLR_V
1446
1447 static void OpCE(void)                                                  // LDX #
1448 {
1449         regs.x = READ_IMM16;
1450         OP_LD_HANDLER(regs.x);
1451 }
1452
1453 static void OpDE(void)                                                  // LDX ZP
1454 {
1455         regs.x = READ_ZP16;
1456         OP_LD_HANDLER(regs.x);
1457 }
1458
1459 static void OpEE(void)                                                  // LDX ZP, X
1460 {
1461         regs.x = READ_ZP_X16;
1462         OP_LD_HANDLER(regs.x);
1463 }
1464
1465 static void OpFE(void)                                                  // LDX ABS
1466 {
1467         regs.x = READ_ABS16;
1468         OP_LD_HANDLER(regs.x);
1469 }
1470
1471 static void Op8E(void)                                                  // LDS #
1472 {
1473         regs.s = READ_IMM16;
1474         OP_LD_HANDLER(regs.s);
1475 }
1476
1477 static void Op9E(void)                                                  // LDS ZP
1478 {
1479         regs.s = READ_ZP16;
1480         OP_LD_HANDLER(regs.s);
1481 }
1482
1483 static void OpAE(void)                                                  // LDS ZP, X
1484 {
1485         regs.s = READ_ZP_X16;
1486         OP_LD_HANDLER(regs.s);
1487 }
1488
1489 static void OpBE(void)                                                  // LDS ABS
1490 {
1491         regs.s = READ_ABS16;
1492         OP_LD_HANDLER(regs.s);
1493 }
1494
1495 /*
1496 Operation           |Mnem.|Immed.|Direct|Index |Extend|Inher.|Operation |CC Reg|
1497                     |     |OP ~ #|OP ~ #|OP ~ #|OP ~ #|OP ~ #|          |HINZVC|
1498 Store Index Register|STX  |      |DF 5 2|EF 7 2|FF 6 3|      |Formula 4 |  9TR |
1499 Store Stack Pointer |STS  |      |9F 5 2|AF 7 2|BF 6 3|      |Formula 5 |  9TR |
1500 */
1501
1502 // ST* opcode handler
1503
1504 #define OP_ST_HANDLER(m, acc) \
1505         regs.WrMem(m + 0, acc >> 8); \
1506         regs.WrMem(m + 1, acc & 0xFF); \
1507         SET_N16(acc); \
1508         SET_Z(acc); \
1509         CLR_V
1510
1511 static void OpDF(void)                                                  // STX ZP
1512 {
1513         uint16_t m = EA_ZP;
1514         OP_ST_HANDLER(m, regs.x);
1515 }
1516
1517 static void OpEF(void)                                                  // STX ZP, X
1518 {
1519         uint16_t m = EA_ZP_X;
1520         OP_ST_HANDLER(m, regs.x);
1521 }
1522
1523 static void OpFF(void)                                                  // STX ABS
1524 {
1525         uint16_t m = EA_ABS;
1526         OP_ST_HANDLER(m, regs.x);
1527 }
1528
1529 static void Op9F(void)                                                  // STS ZP
1530 {
1531         uint16_t m = EA_ZP;
1532         OP_ST_HANDLER(m, regs.s);
1533 }
1534
1535 static void OpAF(void)                                                  // STS ZP, X
1536 {
1537         uint16_t m = EA_ZP_X;
1538         OP_ST_HANDLER(m, regs.s);
1539 }
1540
1541 static void OpBF(void)                                                  // STS ABS
1542 {
1543         uint16_t m = EA_ABS;
1544         OP_ST_HANDLER(m, regs.s);
1545 }
1546
1547 /*
1548 Operation           |Mnem.|Immed.|Direct|Index |Extend|Inher.|Operation |CC Reg|
1549                     |     |OP ~ #|OP ~ #|OP ~ #|OP ~ #|OP ~ #|          |HINZVC|
1550 Indx Reg > Stack Ptr|TXS  |      |      |      |      |35 4 1|SP=X-1    |      |
1551 Stack Ptr > Indx Reg|TSX  |      |      |      |      |30 4 1|X=SP+1    |      |
1552 */
1553
1554 static void Op35(void)                                                  // TXS
1555 {
1556         regs.s = regs.x - 1;
1557 }
1558
1559 static void Op30(void)                                                  // TSX
1560 {
1561         regs.x = regs.s + 1;
1562 }
1563
1564 /*
1565 Operation           |Mnem.|Immed.|Direct|Index |Extend|Inher.|Operation |CC Reg|
1566                     |     |OP ~ #|OP ~ #|OP ~ #|OP ~ #|OP ~ #|          |HINZVC|
1567 Always              |BRA  |      |20 4 2|      |      |      |none      |      |
1568 Carry is Clear      |BCC  |      |24 4 2|      |      |      |C=0       |      |
1569 Carry is Set        |BCS  |      |25 4 2|      |      |      |C=1       |      |
1570 Equals Zero         |BEQ  |      |27 4 2|      |      |      |Z=1       |      |
1571 Greater / Equal to 0|BGE  |      |2C 4 2|      |      |      |N(+)V=0   |      |
1572 Greater than Zero   |BGT  |      |2E 4 2|      |      |      |Z+N(+)V=0 |      |
1573 Higher              |BHI  |      |22 4 2|      |      |      |C+Z=0     |      |
1574 Less / Equal than 0 |BLE  |      |2F 4 2|      |      |      |Z+N(+)V=1 |      |
1575 Lower or Same       |BLS  |      |23 4 2|      |      |      |C+Z=1     |      |
1576 Less Than Zero      |BLT  |      |2D 4 2|      |      |      |N(+)V=1   |      |
1577 Minus               |BMI  |      |2B 4 2|      |      |      |N=1       |      |
1578 Not Zero            |BNE  |      |26 4 2|      |      |      |Z=0       |      |
1579 Overflow Clear      |BVC  |      |28 4 2|      |      |      |V=0       |      |
1580 Overflow Set        |BVS  |      |29 4 2|      |      |      |V=1       |      |
1581 Plus                |BPL  |      |2A 4 2|      |      |      |N=0       |      |
1582 */
1583
1584 static void Op20(void)                                                  // BRA
1585 {
1586         int16_t m = (int16_t)(int8_t)READ_IMM;
1587         regs.pc += m;
1588 }
1589
1590 static void Op24(void)                                                  // BCC
1591 {
1592 // NOTE: We can optimize this by following the maxim: "Don't branch!" by converting the boolean
1593 //       result into a multiplication. The only way to know if this is a win is to do some profiling
1594 //       both with and without the optimization.
1595         int16_t m = (int16_t)(int8_t)READ_IMM;
1596
1597 #ifdef TEST_DONT_BRANCH_OPTIMIZATION
1598 //Note sure if the ! operator will do what we want, so we use ^ 1
1599         regs.pc += m * (flagC ^ 0x01);
1600 #else
1601         if (!flagC)
1602                 regs.pc += m;
1603 #endif
1604 }
1605
1606 static void Op25(void)                                                  // BCS
1607 {
1608         int16_t m = (int16_t)(int8_t)READ_IMM;
1609
1610 #ifdef TEST_DONT_BRANCH_OPTIMIZATION
1611         regs.pc += m * (flagC);
1612 #else
1613         if (flagC)
1614                 regs.pc += m;
1615 #endif
1616 }
1617
1618 static void Op27(void)                                                  // BEQ
1619 {
1620         int16_t m = (int16_t)(int8_t)READ_IMM;
1621
1622 #ifdef TEST_DONT_BRANCH_OPTIMIZATION
1623         regs.pc += m * (flagZ);
1624 #else
1625         if (flagZ)
1626                 regs.pc += m;
1627 #endif
1628 }
1629
1630 static void Op2C(void)                                                  // BGE
1631 {
1632         int16_t m = (int16_t)(int8_t)READ_IMM;
1633
1634 #ifdef TEST_DONT_BRANCH_OPTIMIZATION
1635         regs.pc += m * ((flagN ^ flagV) ^ 0x01);
1636 #else
1637         if (!(flagN ^ flagV))
1638                 regs.pc += m;
1639 #endif
1640 }
1641
1642 static void Op2E(void)                                                  // BGT
1643 {
1644         int16_t m = (int16_t)(int8_t)READ_IMM;
1645
1646 #ifdef TEST_DONT_BRANCH_OPTIMIZATION
1647         regs.pc += m * ((flagZ | (flagN ^ flagV)) ^ 0x01);
1648 #else
1649         if (!(flagZ | (flagN ^ flagV)))
1650                 regs.pc += m;
1651 #endif
1652 }
1653
1654 static void Op22(void)                                                  // BHI
1655 {
1656         int16_t m = (int16_t)(int8_t)READ_IMM;
1657
1658 #ifdef TEST_DONT_BRANCH_OPTIMIZATION
1659         regs.pc += m * ((flagZ | flagC) ^ 0x01);
1660 #else
1661         if (!(flagZ | flagC))
1662                 regs.pc += m;
1663 #endif
1664 }
1665
1666 static void Op2F(void)                                                  // BLE
1667 {
1668         int16_t m = (int16_t)(int8_t)READ_IMM;
1669
1670 #ifdef TEST_DONT_BRANCH_OPTIMIZATION
1671         regs.pc += m * (flagZ | (flagN ^ flagV));
1672 #else
1673         if (flagZ | (flagN ^ flagV))
1674                 regs.pc += m;
1675 #endif
1676 }
1677
1678 static void Op23(void)                                                  // BLS
1679 {
1680         int16_t m = (int16_t)(int8_t)READ_IMM;
1681
1682 #ifdef TEST_DONT_BRANCH_OPTIMIZATION
1683         regs.pc += m * (flagZ | flagC);
1684 #else
1685         if (flagZ | flagC)
1686                 regs.pc += m;
1687 #endif
1688 }
1689
1690 static void Op2D(void)                                                  // BLT
1691 {
1692         int16_t m = (int16_t)(int8_t)READ_IMM;
1693
1694 #ifdef TEST_DONT_BRANCH_OPTIMIZATION
1695         regs.pc += m * (flagN ^ flagV);
1696 #else
1697         if (flagN ^ flagV)
1698                 regs.pc += m;
1699 #endif
1700 }
1701
1702 static void Op2B(void)                                                  // BMI
1703 {
1704         int16_t m = (int16_t)(int8_t)READ_IMM;
1705
1706 #ifdef TEST_DONT_BRANCH_OPTIMIZATION
1707         regs.pc += m * (flagN);
1708 #else
1709         if (flagN)
1710                 regs.pc += m;
1711 #endif
1712 }
1713
1714 static void Op26(void)                                                  // BNE
1715 {
1716         int16_t m = (int16_t)(int8_t)READ_IMM;
1717
1718 #ifdef TEST_DONT_BRANCH_OPTIMIZATION
1719         regs.pc += m * (flagZ ^ 0x01);
1720 #else
1721         if (!flagZ)
1722                 regs.pc += m;
1723 #endif
1724 }
1725
1726 static void Op28(void)                                                  // BVC
1727 {
1728         int16_t m = (int16_t)(int8_t)READ_IMM;
1729
1730 #ifdef TEST_DONT_BRANCH_OPTIMIZATION
1731         regs.pc += m * (flagV ^ 0x01);
1732 #else
1733         if (!flagV)
1734                 regs.pc += m;
1735 #endif
1736 }
1737
1738 static void Op29(void)                                                  // BVS
1739 {
1740         int16_t m = (int16_t)(int8_t)READ_IMM;
1741
1742 #ifdef TEST_DONT_BRANCH_OPTIMIZATION
1743         regs.pc += m * (flagV);
1744 #else
1745         if (flagV)
1746                 regs.pc += m;
1747 #endif
1748 }
1749
1750 static void Op2A(void)                                                  // BPL
1751 {
1752         int16_t m = (int16_t)(int8_t)READ_IMM;
1753
1754 #ifdef TEST_DONT_BRANCH_OPTIMIZATION
1755         regs.pc += m * (flagN ^ 0x01);
1756 #else
1757         if (!flagN)
1758                 regs.pc += m;
1759 #endif
1760 }
1761
1762 /*
1763 Operation           |Mnem.|Immed.|Direct|Index |Extend|Inher.|Operation |CC Reg|
1764                     |     |OP ~ #|OP ~ #|OP ~ #|OP ~ #|OP ~ #|          |HINZVC|
1765 Branch to Subroutine|BSR  |      |8D 8 2|      |      |      |          |      |
1766 Jump                |JMP  |      |      |6E 4 2|7E 3 3|      |          |      |
1767 Jump to Subroutine  |JSR  |      |      |AD 8 2|BD 9 3|      |          |      |
1768 */
1769
1770 static void Op8D(void)                                                  // BSR
1771 {
1772         int16_t m = (int16_t)(int8_t)READ_IMM;
1773         PUSH16(regs.pc);
1774         regs.pc += m;
1775 }
1776
1777 static void Op6E(void)                                                  // JMP ZP, X
1778 {
1779         uint16_t m = EA_ZP_X;
1780         regs.pc = m;
1781 }
1782
1783 static void Op7E(void)                                                  // JMP ABS
1784 {
1785         regs.pc = EA_ABS;
1786 }
1787
1788 static void OpAD(void)                                                  // JSR ZP, X
1789 {
1790         uint16_t m = EA_ZP_X;
1791         PUSH16(regs.pc);
1792         regs.pc = m;
1793 }
1794
1795 static void OpBD(void)                                                  // JSR ABS
1796 {
1797         uint16_t m = EA_ABS;
1798         PUSH16(regs.pc);
1799         regs.pc = m;
1800 }
1801
1802 /*
1803 Operation           |Mnem.|Immed.|Direct|Index |Extend|Inher.|Operation |CC Reg|
1804                     |     |OP ~ #|OP ~ #|OP ~ #|OP ~ #|OP ~ #|          |HINZVC|
1805 No Operation        |NOP  |      |      |      |      |01 2 1|          |      |
1806 Return from Interrpt|RTI  |      |      |      |      |3B A 1|          |AAAAAA|
1807 Return from Subrtine|RTS  |      |      |      |      |39 5 1|          |      |
1808 Software Interrupt  |SWI  |      |      |      |      |3F C 1|          | S    |
1809 Wait For Interrupt  |WAI  |      |      |      |      |3E 9 1|          | B    |
1810 */
1811
1812 static void Op01(void)                                                  // NOP
1813 {
1814 }
1815
1816 static void Op3B(void)                                                  // RTI
1817 {
1818         regs.cc = PULL;
1819         regs.a  = PULL;
1820         regs.b  = PULL;
1821         regs.x  = PULL16;
1822         regs.pc = PULL16;
1823         UNPACK_FLAGS;
1824 }
1825
1826 static void Op39(void)                                                  // RTS
1827 {
1828         regs.pc = PULL16;
1829 }
1830
1831 static void Op3F(void)                                                  // SWI
1832 {
1833         // It seems that the SWI is non-maskable, unlike the IRQ...
1834         regs.cc = PACK_FLAGS;                                           // Mash flags back into the CC register
1835         PUSH16(regs.pc);                                                        // Save all regs...
1836         PUSH16(regs.x);
1837         PUSH(regs.b);
1838         PUSH(regs.a);
1839         PUSH(regs.cc);
1840         regs.pc = RdMemW(0xFFFA);                                       // And do it!
1841         flagI = 1;                                                                      // Also, set IRQ inhibit
1842 }
1843
1844 static void Op3E(void)                                                  // WAI
1845 {
1846 #ifdef __DEBUG__
1847 WriteLog("*** WAI STATE ASSERTED ***\n");
1848 #endif
1849         regs.cc = PACK_FLAGS;                                           // Mash flags back into the CC register
1850         PUSH16(regs.pc);                                                        // Save all regs...
1851         PUSH16(regs.x);
1852         PUSH(regs.b);
1853         PUSH(regs.a);
1854         PUSH(regs.cc);
1855         regs.cpuFlags |= V6808_STATE_WAI;                       // And signal that we're in WAI mode
1856 }
1857
1858 /*
1859 Operation           |Mnem.|Immed.|Direct|Index |Extend|Inher.|Operation |CC Reg|
1860                     |     |OP ~ #|OP ~ #|OP ~ #|OP ~ #|OP ~ #|          |HINZVC|
1861 Clear Carry         |CLC  |      |      |      |      |0C 2 1|C=0       |     R|
1862 Clear Interrupt     |CLI  |      |      |      |      |0E 2 1|I=0       | R    |
1863 Clear Overflow      |CLV  |      |      |      |      |0A 2 1|V=0       |    R |
1864 Set Carry           |SEC  |      |      |      |      |0D 2 1|C=1       |     S|
1865 Set Interrupt       |SEI  |      |      |      |      |0F 2 1|I=1       | S    |
1866 Set Overflow        |SEV  |      |      |      |      |0B 2 1|V=1       |    S |
1867 CCR=Accumulator A   |TAP  |      |      |      |      |06 2 1|CCR=A     |CCCCCC|
1868 Accumlator A=CCR    |TPA  |      |      |      |      |07 2 1|A=CCR     |      |
1869 */
1870
1871 static void Op0C(void)                                                  // CLC
1872 {
1873         flagC = 0;
1874 }
1875
1876 static void Op0E(void)                                                  // CLI
1877 {
1878         flagI = 0;
1879 }
1880
1881 static void Op0A(void)                                                  // CLV
1882 {
1883         flagV = 0;
1884 }
1885
1886 static void Op0D(void)                                                  // SEC
1887 {
1888         flagC = 1;
1889 }
1890
1891 static void Op0F(void)                                                  // SEI
1892 {
1893         flagI = 1;
1894 }
1895
1896 static void Op0B(void)                                                  // SEV
1897 {
1898         flagV = 1;
1899 }
1900
1901 static void Op06(void)                                                  // TAP
1902 {
1903         regs.cc = regs.a;
1904         UNPACK_FLAGS;
1905 }
1906
1907 static void Op07(void)                                                  // TPA
1908 {
1909         regs.a = PACK_FLAGS;
1910 }
1911
1912 /*
1913   OP  Operation Code, in Hexadecimal
1914   ~   Number of MPU cycles required
1915   #   Number of program bytes required
1916   +   Arithmetic Plus
1917   -   Arithmetic Minus
1918   +   Boolean AND
1919   Msp Contents of Memory pointed to be Stack Pointer
1920   +   Boolean Inclusive OR
1921   (+) Boolean Exclusive OR (XOR)
1922   *   Converts Binary Addition of BCD Characters into BCD Format
1923   *-  SP=SP-1
1924   *+  SP=SP+1
1925
1926   Condition Code Register Legend
1927      Not Affected
1928    R Reset (0, Low)
1929    S Set   (1, High)
1930    T Tests and sets if True, cleared otherise
1931    1 Test: Result=10000000?
1932    2 Test: Result=00000000?
1933    3 Test: Decimal value of most significant BCD character greater than nine?
1934            (Not cleared if previously set)
1935    4 Test: Operand=10000000 prior to execution?
1936    5 Test: Operand=01111111 prior to execution?
1937    6 Test: Set equal to result or N(+)C after shift has occurred.
1938    7 Test: Sign bit of most significant byte or result=1?
1939    8 Test: 2's compliment overflow from subtraction of least
1940            significant bytes?
1941    9 Test: Result less than zero? (Bit 15=1)
1942    A Load Condition Code Register from Stack.
1943    B Set when interrupt occurs.  If previously set, a NMI is
1944         required to exit the wait state.
1945    C Set according to the contents of Accumulator A.
1946
1947   *x SHIFT AND ROTATION DIAGRAMS
1948    *1     +-----------------+       C to LSB
1949           - C <- 76543210 <-+
1950
1951    *2    +-----------------+
1952          +> C -> 76543210 -+
1953
1954    *3       C <- 76543210 <- 0(Data)
1955                +-+
1956
1957    *4          �>76543210 -> C
1958
1959    *5 (Data)0 -> 76543210 -> C
1960
1961   FORMULAS
1962    1: (Xh/Xl)-(M/M+1)
1963    2: Xh=M, Xl=M+1
1964    3: SPh=M, SPl=M+1
1965    4: M=Xh, M+1=Xl
1966 */
1967
1968 static void Op__(void)
1969 {
1970         regs.cpuFlags |= V6808_STATE_ILLEGAL_INST;
1971 }
1972
1973 //
1974 // Ok, the exec_op[] array is globally defined here basically to save
1975 // a LOT of unnecessary typing.  Sure it's ugly, but hey, it works!
1976 //
1977 void (* exec_op[256])() = {
1978         Op__, Op01, Op__, Op__, Op__, Op__, Op06, Op07, Op08, Op09, Op0A, Op0B, Op0C, Op0D, Op0E, Op0F,
1979         Op10, Op11, Op__, Op__, Op__, Op__, Op16, Op17, Op__, Op19, Op__, Op1B, Op__, Op__, Op__, Op__,
1980         Op20, Op__, Op22, Op23, Op24, Op25, Op26, Op27, Op28, Op29, Op2A, Op2B, Op2C, Op2D, Op2E, Op2F,
1981         Op30, Op31, Op32, Op33, Op34, Op35, Op36, Op37, Op__, Op39, Op__, Op3B, Op__, Op__, Op3E, Op3F,
1982         Op40, Op__, Op__, Op43, Op44, Op__, Op46, Op47, Op48, Op49, Op4A, Op__, Op4C, Op4D, Op__, Op4F,
1983         Op50, Op__, Op__, Op53, Op54, Op__, Op56, Op57, Op58, Op59, Op5A, Op__, Op5C, Op5D, Op__, Op5F,
1984         Op60, Op__, Op__, Op63, Op64, Op__, Op66, Op67, Op68, Op69, Op6A, Op__, Op6C, Op6D, Op6E, Op6F,
1985         Op70, Op__, Op__, Op73, Op74, Op__, Op76, Op77, Op78, Op79, Op7A, Op__, Op7C, Op7D, Op7E, Op7F,
1986         Op80, Op81, Op82, Op__, Op84, Op85, Op86, Op__, Op88, Op89, Op8A, Op8B, Op8C, Op8D, Op8E, Op__,
1987         Op90, Op91, Op92, Op__, Op94, Op95, Op96, Op97, Op98, Op99, Op9A, Op9B, Op9C, Op__, Op9E, Op9F,
1988         OpA0, OpA1, OpA2, Op__, OpA4, OpA5, OpA6, OpA7, OpA8, OpA9, OpAA, OpAB, OpAC, OpAD, OpAE, OpAF,
1989         OpB0, OpB1, OpB2, Op__, OpB4, OpB5, OpB6, OpB7, OpB8, OpB9, OpBA, OpBB, OpBC, OpBD, OpBE, OpBF,
1990         OpC0, OpC1, OpC2, Op__, OpC4, OpC5, OpC6, Op__, OpC8, OpC9, OpCA, OpCB, Op__, Op__, OpCE, Op__,
1991         OpD0, OpD1, OpD2, Op__, OpD4, OpD5, OpD6, OpD7, OpD8, OpD9, OpDA, OpDB, Op__, Op__, OpDE, OpDF,
1992         OpE0, OpE1, OpE2, Op__, OpE4, OpE5, OpE6, OpE7, OpE8, OpE9, OpEA, OpEB, Op__, Op__, OpEE, OpEF,
1993         OpF0, OpF1, OpF2, Op__, OpF4, OpF5, OpF6, OpF7, OpF8, OpF9, OpFA, OpFB, Op__, Op__, OpFE, OpFF
1994 };
1995
1996 //
1997 // Internal "memcpy" (so we don't have to link with any external libraries!)
1998 //
1999 static void myMemcpy(void * dst, void * src, uint32_t size)
2000 {
2001         uint8_t * d = (uint8_t *)dst, * s = (uint8_t *)src;
2002
2003         for(uint32_t i=0; i<size; i++)
2004                 d[i] = s[i];
2005 }
2006
2007 //
2008 // Function to execute 6808 for "cycles" cycles
2009 //
2010 void Execute6808(V6808REGS * context, uint32_t cycles)
2011 {
2012 #warning "V6808_STATE_WAI is not properly handled yet! !!! FIX !!!"
2013 #warning "Need to convert from destructive clock to non-destructive. !!! FIX !!!"
2014         myMemcpy(&regs, context, sizeof(V6808REGS));
2015         UNPACK_FLAGS;                                           // Explode flags register into individual uint8_ts
2016
2017         // Execute here...
2018         while (regs.clock < cycles)
2019         {
2020                 uint8_t opcode = regs.RdMem(regs.pc++);
2021                 exec_op[opcode]();                              // Execute that opcode...
2022                 regs.clock += CPUCycles[opcode];
2023
2024                 if (regs.cpuFlags & V6808_LINE_RESET)
2025                 {
2026                         flagI = 1;                                      // Set I
2027                         regs.pc = RdMemW(0xFFFE);       // And load PC with the RESET vector
2028
2029                         context->cpuFlags &= ~V6808_LINE_RESET;
2030                         regs.cpuFlags &= ~V6808_LINE_RESET;
2031                 }
2032                 else if (regs.cpuFlags & V6808_LINE_NMI)
2033                 {
2034                         regs.cc = PACK_FLAGS;           // Mash flags back into the CC register
2035                         PUSH16(regs.pc);                        // Save all regs...
2036                         PUSH16(regs.x);
2037                         PUSH(regs.b);
2038                         PUSH(regs.a);
2039                         PUSH(regs.cc);
2040                         regs.pc = RdMemW(0xFFFC);       // And do it!
2041
2042 #warning "# of clock cycles for NMI unknown. !!! FIX !!!"
2043                         regs.clock += 0;                                                        // How many???
2044                         context->cpuFlags &= ~V6808_LINE_NMI;// Reset the asserted line (NMI)...
2045                         regs.cpuFlags &= ~V6808_LINE_NMI;       // Reset the asserted line (NMI)...
2046                 }
2047                 else if (regs.cpuFlags & V6808_LINE_IRQ)
2048                 {
2049                         if (!flagI)                                     // Process an interrupt (I=0)?
2050                         {
2051                                 regs.cc = PACK_FLAGS;   // Mash flags back into the CC register
2052                                 PUSH16(regs.pc);                // Save all regs...
2053                                 PUSH16(regs.x);
2054                                 PUSH(regs.b);
2055                                 PUSH(regs.a);
2056                                 PUSH(regs.cc);
2057                                 regs.pc = RdMemW(0xFFF8);// And do it!
2058
2059 #warning "# of clock cycles for IRQ unknown. !!! FIX !!!"
2060                                 regs.clock += 0;                                // How many???
2061 #warning "IRQ/NMI lines should not be cleared here... !!! FIX !!!"
2062                                 context->cpuFlags &= ~V6808_LINE_IRQ;   // Reset the asserted line (IRQ)...
2063                                 regs.cpuFlags &= ~V6808_LINE_IRQ;       // Reset the asserted line (IRQ)...
2064                         }
2065                 }
2066         }
2067
2068         regs.cc = PACK_FLAGS;                           // Mash flags back into the CC register
2069         myMemcpy(context, &regs, sizeof(V6808REGS));
2070 }
2071
2072 //
2073 // Get the clock of the currently executing CPU
2074 //
2075 uint64_t GetCurrentV6808Clock(void)
2076 {
2077         return regs.clock;
2078 }