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