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