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