]> Shamusworld >> Repos - stargem2/blobdiff - src/v6808.cpp
Converted to SDL 2, added fullscreen support (F12 to toggle).
[stargem2] / src / v6808.cpp
index e9c4253dce603a899047ad7a3d98b1729073590c..ac1352ce49652775b3755e08c6e85d985f441bf0 100755 (executable)
@@ -1,8 +1,8 @@
 //
-// Virtual 6808 Emulator v1.2
+// Virtual 6808 Emulator v2.1
 //
 // by James L. Hammons
-// (c) 2006 Underground Software
+// (C) 2006 Underground Software
 //
 // JLH = James L. Hammons <jlhamm@acm.org>
 //
 // ---  ----------  ------------------------------------------------------------
 // JLH  06/15/2006  Added changelog ;-)
 // JLH  06/15/2006  Scrubbed all BYTE, WORD & DWORD references from the code
+// JLH  11/13/2006  Converted core to V65C02 macro style :-)
+// JLH  11/13/2006  Converted flags to unpacked and separate flags
+// JLH  07/21/2009  Converted clock from 32-bit to 64-bit value, added possible
+//                  "don't branch" optimization
+// JLH  09/21/2009  Fixed EA_ABS macros
 //
 
-// Mebbe someday I'll get around to fixing the core to be more like V65C02...
+// NOTE: V6808_STATE_WAI is not handled in the main loop correctly. !!! FIX !!!
+
+// Some random thoughts: Could there be a performance gain by breaking
+// out the flags in regs.cc into separate uint8_t variables (or bools)?
+// You'd have to convert on entering and exiting the emulation loop, but I
+// think the perfomance hit would be negligible compared to the gain in not
+// having to mask and shift flags all the time. Investigate after the
+// conversion to macro style opcodes is completed. :-)
+// [DONE--remain to be seen if there is any performance increase]
 
 //#define __DEBUG__
+#define TEST_DONT_BRANCH_OPTIMIZATION
 
 #include "v6808.h"
 
 #include "log.h"
 #endif
 
+// Various macros
+
+#define CLR_Z                                  (flagZ = 0)
+#define CLR_ZN                                 (flagZ = flagN = 0)
+#define CLR_ZNC                                        (flagZ = flagN = flagC = 0)
+#define CLR_NVC                                        (flagN = flagV = flagC = 0)
+#define CLR_VC                                 (flagV = flagC = 0)
+#define CLR_V                                  (flagV = 0)
+#define CLR_N                                  (flagN = 0)
+#define SET_Z(r)                               (flagZ = ((r) == 0 ? 1 : 0))
+#define SET_N(r)                               (flagN = ((r) & 0x80) >> 7)
+#define SET_V(a,b,r)                   (flagV = (((b) ^ (a) ^ (r) ^ ((r) >> 1)) & 0x80) >> 7)
+
+#define SET_C_CMP(a,b)                 (flagC = ((uint8_t)(b) < (uint8_t)(a) ? 1 : 0))
+#define SET_ZN(r)                              SET_N(r); SET_Z(r)
+#define SET_ZNC_ADD(a,b,r)             SET_N(r); SET_Z(r); SET_C_ADD(a,b)
+#define SET_ZNVC_CMP(a,b,r)            SET_N(r); SET_Z(r); SET_C_CMP(a,b); SET_V(a,b,r)
+
+#define SET_N16(r)                             (flagN = ((r) & 0x8000) >> 15)
+#define SET_V16(a,b,r)                 (flagV = (((b) ^ (a) ^ (r) ^ ((r) >> 1)) & 0x8000) >> 15)
+#define SET_C_CMP16(a,b)               (flagC = ((uint16_t)(b) < (uint16_t)(a) ? 1 : 0))
+#define SET_ZNVC_CMP16(a,b,r)  SET_N16(r); SET_Z(r); SET_C_CMP16(a,b); SET_V16(a,b,r)
+
+#define EA_IMM                         regs.pc++
+#define EA_ZP                          regs.RdMem(regs.pc++)
+#define EA_ZP_X                                (regs.RdMem(regs.pc++) + regs.x)
+#define EA_ABS                         FetchMemW(regs.pc)
+
+#define READ_IMM                       regs.RdMem(EA_IMM)
+#define READ_ZP                                regs.RdMem(EA_ZP)
+#define READ_ZP_X                      regs.RdMem(EA_ZP_X)
+#define READ_ABS                       regs.RdMem(EA_ABS)
+
+#define READ_IMM16                     FetchMemW(regs.pc);
+#define READ_ZP16                      RdMemW(EA_ZP)
+#define READ_ZP_X16                    RdMemW(EA_ZP_X)
+#define READ_ABS16                     RdMemW(EA_ABS)
+
+#define READ_IMM_WB(v)         uint16_t addr = EA_IMM;         v = regs.RdMem(addr)
+#define READ_ZP_WB(v)          uint16_t addr = EA_ZP;          v = regs.RdMem(addr)
+#define READ_ZP_X_WB(v)                uint16_t addr = EA_ZP_X;                v = regs.RdMem(addr)
+#define READ_ABS_WB(v)         uint16_t addr = EA_ABS;         v = regs.RdMem(addr)
+
+#define WRITE_BACK(d)          regs.WrMem(addr, (d))
+
+#define PULL                           regs.RdMem(regs.s++)
+#define PUSH(r)                                regs.WrMem(--regs.s, (r))
+#define PULL16                         RdMemW(regs.s);                         regs.s += 2
+#define PUSH16(r)                      regs.WrMem(--regs.s, (r) & 0xFF); regs.WrMem(--regs.s, (r) >> 8)
+
+#define PACK_FLAGS                     ((regs.cc & 0xC0) | (flagH << 5) | (flagI << 4) | (flagN << 3) | (flagZ << 2) | (flagV << 1) | flagC)
+#define UNPACK_FLAGS           flagH = (regs.cc & FLAG_H) >> 5; \
+       flagI = (regs.cc & FLAG_I) >> 4; \
+       flagN = (regs.cc & FLAG_N) >> 3; \
+       flagZ = (regs.cc & FLAG_Z) >> 2; \
+       flagV = (regs.cc & FLAG_V) >> 1; \
+       flagC = (regs.cc & FLAG_C)
+
 // Private global variables
 
 static V6808REGS regs;
-static uint16 addr;
-static uint8 tmp;
+static uint8_t flagH, flagI, flagN, flagZ, flagV, flagC;
 
-static uint8 CPUCycles[256] = {
+static uint8_t CPUCycles[256] = {
        1,  2,  1,  1,  1,  1,  2,  2,  4,  4,  2,  2,  2,  2,  2,  2,
        2,  2,  1,  1,  1,  1,  2,  2,  1,  2,  1,  2,  1,  1,  1,  1,
        4,  1,  4,  4,  4,  4,  4,  4,  4,  4,  4,  4,  4,  4,  4,  4,
@@ -50,1757 +121,1858 @@ static uint8 CPUCycles[256] = {
 
 // Private function prototypes
 
-static uint16 FetchW(void);
-static uint16 RdMemW(uint16);
-static void WrMemW(uint16, uint16);
-
-//
-// Fetch a word out of 6808 memory (little endian format)
-// This is a leftover from when fetches were separated from garden variety reads...
-//
-static uint16 FetchW()
-{
-       uint16 w = RdMemW(regs.pc);
-       regs.pc += 2;
-       return w;
-}
+static uint16_t RdMemW(uint16_t);
+static uint16_t FetchMemW(uint16_t);
 
 //
 // Read a word out of 6808 memory (little endian format)
 //
-static uint16 RdMemW(uint16 address)
+static inline uint16_t RdMemW(uint16_t address)
 {
-       return (uint16)(regs.RdMem(address) << 8) | regs.RdMem(address + 1);
+       return (uint16_t)(regs.RdMem(address) << 8) | regs.RdMem(address + 1);
 }
 
 //
-// Write a word into 6808 memory (little endian format)
+// Fetch a word out of 6808 memory (little endian format). Increments PC
 //
-static void WrMemW(uint16 address, uint16 w)
+static inline uint16_t FetchMemW(uint16_t address)
 {
-       regs.WrMem(address + 0, w >> 8);
-       regs.WrMem(address + 1, w & 0xFF);
+       regs.pc += 2;
+       return (uint16_t)(regs.RdMem(address) << 8) | regs.RdMem(address + 1);
 }
 
 //
-// Function to decode IDX data
+// 6808 OPCODE IMPLEMENTATION
+//
+// NOTE: Lots of macros are used here to save a LOT of typing. Also
+//       helps speed the debugging process. :-) Because of this, combining
+//       certain lines may look like a good idea but would end in disaster.
+//       You have been warned! ;-)
 //
-inline uint16 DecodeIDX(uint8 code)
-{
-       return regs.x + code;
-}
 
+/*
+Operation               |Mnem.|Immed.|Direct|Index |Extend|Inher.|Operation |CC Reg|
+                        |     |OP ~ #|OP ~ #|OP ~ #|OP ~ #|OP ~ #|          |HINZVC|
+Add                     |ADDA |8B 2 2|9B 3 2|AB 5 2|BB 4 3|      |A=A+M     |T TTTT|
+                        |ADDB |CB 2 2|DB 3 2|EB 5 2|FB 4 3|      |B=B+M     |T TTTT|
+Add Accumulators        |ABA  |      |      |      |      |1B 2 1|A=A+B     |T TTTT|
+*/
 
-//
-// Opcode Functions (Mostly correct... Yikes!)
-//
+// ADD opcodes
 
-static void Op01(void)                                                 // NOP
+#define OP_ADD_HANDLER(m, acc) \
+       uint16_t sum = (uint16_t)(acc) + (m); \
+       flagC = sum >> 8; \
+       flagH = (sum >> 4) & 0x01; \
+       SET_V(m, acc, sum); \
+       (acc) = sum & 0xFF; \
+       SET_ZN(acc)
+
+static void Op8B(void)                                                 // ADDA #
 {
+       uint16_t m = READ_IMM;
+       OP_ADD_HANDLER(m, regs.a);
 }
 
-static void Op06(void)                                                 // TAP
+static void Op9B(void)                                                 // ADDA ZP
 {
-       regs.cc = regs.a;
+       uint16_t m = READ_ZP;
+       OP_ADD_HANDLER(m, regs.a);
 }
 
-static void Op07(void)                                                 // TPA
+static void OpAB(void)                                                 // ADDA ZP, X
 {
-       regs.a = regs.cc;
+       uint16_t m = READ_ZP_X;
+       OP_ADD_HANDLER(m, regs.a);
 }
 
-static void Op08(void)                                                 // INX
+static void OpBB(void)                                                 // ADDA ABS
 {
-       regs.x++;
-
-       (regs.x == 0 ? regs.cc |= FLAG_Z : regs.cc &= ~FLAG_Z);
+       uint16_t m = READ_ABS;
+       OP_ADD_HANDLER(m, regs.a);
 }
 
-static void Op09(void)                                                 // DEX
+static void OpCB(void)                                                 // ADDB #
 {
-       regs.x--;
-
-       (regs.x == 0 ? regs.cc |= FLAG_Z : regs.cc &= ~FLAG_Z);
+       uint16_t m = READ_IMM;
+       OP_ADD_HANDLER(m, regs.b);
 }
 
-static void Op0A(void)                                                 // CLV
+static void OpDB(void)                                                 // ADDB ZP
 {
-       regs.cc &= ~FLAG_V;
+       uint16_t m = READ_ZP;
+       OP_ADD_HANDLER(m, regs.b);
 }
 
-static void Op0B(void)                                                 // SEV
+static void OpEB(void)                                                 // ADDB ZP, X
 {
-       regs.cc |= FLAG_V;
+       uint16_t m = READ_ZP_X;
+       OP_ADD_HANDLER(m, regs.b);
 }
 
-static void Op0C(void)                                                 // CLC
+static void OpFB(void)                                                 // ADDB ABS
 {
-       regs.cc &= ~FLAG_C;
+       uint16_t m = READ_ABS;
+       OP_ADD_HANDLER(m, regs.b);
 }
 
-static void Op0D(void)                                                 // SEC
+static void Op1B(void)                                                 // ABA
 {
-       regs.cc |= FLAG_C;
+       OP_ADD_HANDLER(regs.b, regs.a);
 }
 
-static void Op0E(void)                                                 // CLI
+/*
+Operation               |Mnem.|Immed.|Direct|Index |Extend|Inher.|Operation |CC Reg|
+                        |     |OP ~ #|OP ~ #|OP ~ #|OP ~ #|OP ~ #|          |HINZVC|
+Add with Carry          |ADCA |89 2 2|99 3 2|A9 5 2|B9 4 3|      |A=A+M+C   |T TTTT|
+                        |ADCB |C9 2 2|D9 3 2|E9 5 2|F9 4 3|      |B=B+M+C   |T TTTT|
+*/
+
+// ADC opcodes
+
+#define OP_ADC_HANDLER(m, acc) \
+       uint16_t sum = (uint16_t)acc + (m) + (uint16_t)flagC; \
+       flagC = sum >> 8; \
+       flagH = (sum >> 4) & 0x01; \
+       SET_V(m, acc, sum); \
+       acc = sum & 0xFF; \
+       SET_ZN(acc)
+
+static void Op89(void)                                                 // ADCA #
 {
-       regs.cc &= ~FLAG_I;
+       uint16_t m = READ_IMM;
+       OP_ADC_HANDLER(m, regs.a);
 }
 
-static void Op0F(void)                                                 // SEI
+static void Op99(void)                                                 // ADCA ZP
 {
-       regs.cc |= FLAG_I;
+       uint16_t m = READ_ZP;
+       OP_ADC_HANDLER(m, regs.a);
 }
 
-static void Op10(void)                                                 // SBA
+static void OpA9(void)                                                 // ADCA ZP, X
 {
-       uint8 as = regs.a; 
-       regs.a -= regs.b;
-
-       regs.cc &= ~(FLAG_N | FLAG_Z | FLAG_V | FLAG_C);        // Clear NZVC
-
-       if (as < regs.b)
-               regs.cc |= FLAG_C;
-
-       if ((as ^ regs.b ^ regs.a ^ (regs.cc << 7)) & 0x80)
-               regs.cc |= FLAG_V;
-
-       if (regs.a == 0)
-               regs.cc |= FLAG_Z;
-
-       if (regs.a & 0x80)
-               regs.cc |= FLAG_N;
+       uint16_t m = READ_ZP_X;
+       OP_ADC_HANDLER(m, regs.a);
 }
 
-static void Op11(void)                                                 // CBA (Compare B to A)
+static void OpB9(void)                                                 // ADCA ABS
 {
-       tmp = regs.a - regs.b;
-
-       regs.cc &= ~(FLAG_N | FLAG_Z | FLAG_V | FLAG_C);        // Clear NZVC
-
-       if (regs.a < regs.b)
-               regs.cc |= FLAG_C;
-
-       if ((tmp ^ regs.b ^ regs.a ^ (regs.cc << 7)) & 0x80)
-               regs.cc |= FLAG_V;
-
-       if (regs.a == 0)
-               regs.cc |= FLAG_Z;
-
-       if (regs.a & 0x80)
-               regs.cc |= FLAG_N;
+       uint16_t m = READ_ABS;
+       OP_ADC_HANDLER(m, regs.a);
 }
 
-static void Op16(void)                                                 // TAB
+static void OpC9(void)                                                 // ADCB #
 {
-       regs.b = regs.a;
-
-       regs.cc &= ~(FLAG_N | FLAG_Z | FLAG_V);         // Clear NZV
+       uint16_t m = READ_IMM;
+       OP_ADC_HANDLER(m, regs.b);
+}
 
-       if (regs.b == 0)
-               regs.cc |= FLAG_Z;
+static void OpD9(void)                                                 // ADCB ZP
+{
+       uint16_t m = READ_ZP;
+       OP_ADC_HANDLER(m, regs.b);
+}
 
-       if (regs.b & 0x80)
-               regs.cc |= FLAG_N;
+static void OpE9(void)                                                 // ADCB ZP, X
+{
+       uint16_t m = READ_ZP_X;
+       OP_ADC_HANDLER(m, regs.b);
 }
 
-static void Op17(void)                                                 // TBA
+static void OpF9(void)                                                 // ADCB ABS
 {
-       regs.a = regs.b;
+       uint16_t m = READ_ABS;
+       OP_ADC_HANDLER(m, regs.b);
+}
 
-       regs.cc &= ~(FLAG_N | FLAG_Z | FLAG_V);         // Clear NZV
+/*
+Operation               |Mnem.|Immed.|Direct|Index |Extend|Inher.|Operation |CC Reg|
+                        |     |OP ~ #|OP ~ #|OP ~ #|OP ~ #|OP ~ #|          |HINZVC|
+And                     |ANDA |84 2 2|94 3 2|A4 5 2|B4 4 3|      |A=A+M     |  TTR |
+                        |ANDB |C4 2 2|D4 3 2|E4 5 2|F4 4 3|      |B=B+M     |  TTR |
+*/
 
-       if (regs.a == 0)
-               regs.cc |= FLAG_Z;
+// AND opcodes
 
-       if (regs.a & 0x80)
-               regs.cc |= FLAG_N;
-}
+#define OP_AND_HANDLER(m, acc) \
+       acc &= m; \
+       SET_ZN(acc); \
+       CLR_V
 
-static void Op19(void)                                                 // DAA
+static void Op84(void)                                                 // ANDA #
 {
-  addr = regs.a;
-//  if (regs.cc&0x20)              addr += 6;    // H set? adjust
-  if ((addr&0x000F) > 9)     addr += 6;
-  if (regs.cc&0x01)              addr += 0x60; // C set? adjust
-  if ((addr&0x00F0) > 0x90)  addr += 0x60;
-  regs.cc &= 0xFD;                             // CLV
-  (addr > 0xFF ? regs.cc |= 0x01 : regs.cc &= 0xFE);  // Adjust Carry flag
-  regs.a = addr;
-  (regs.a == 0 ? regs.cc |= 0x04 : regs.cc &= 0xFB);   // Adjust Zero flag 
-  (regs.a&0x80 ? regs.cc |= 0x08 : regs.cc &= 0xF7);   // Adjust Negative flag 
+       uint8_t m = READ_IMM;
+       OP_AND_HANDLER(m, regs.a);
 }
 
-static void Op1B(void)                                                 // ABA
+static void Op94(void)                                                 // ANDA ZP
 {
-  addr = regs.a + regs.b;
-  regs.cc &= 0xF0;
-  if (addr > 0xFF)  regs.cc |= 0x01;    // Set Carry flag
-  if ((regs.a^regs.b^addr^(regs.cc<<7))&0x80)  regs.cc |= 0x02; // Set oVerflow 
-  regs.a = addr;                        // Set accumulator
-  if (regs.a == 0)      regs.cc |= 0x04;    // Set Zero flag
-  if (regs.a&0x80)      regs.cc |= 0x08;    // Set Negative flag
+       uint8_t m = READ_ZP;
+       OP_AND_HANDLER(m, regs.a);
 }
 
-static void Op20(void)                                                 // BRA (BRanch Always)
+static void OpA4(void)                                                 // ANDA ZP, X
 {
-       regs.pc += (int16)(int8)regs.RdMem(regs.pc++);
+       uint16_t m = READ_ZP_X;
+       OP_AND_HANDLER(m, regs.a);
 }
 
-static void Op22(void)                                                 // BHI
+static void OpB4(void)                                                 // ANDA ABS
 {
-       tmp = regs.RdMem(regs.pc++);
-
-       if (!(regs.cc & (FLAG_C | FLAG_Z)))
-               regs.pc += (signed short int)(signed char)tmp;
+       uint16_t m = READ_ABS;
+       OP_AND_HANDLER(m, regs.a);
 }
 
-static void Op23(void)                                                 // BLS
+static void OpC4(void)                                                 // ANDB #
 {
-       tmp = regs.RdMem(regs.pc++);
-
-       if (regs.cc & (FLAG_C | FLAG_Z))
-               regs.pc += (signed short int)(signed char)tmp;
+       uint8_t m = READ_IMM;
+       OP_AND_HANDLER(m, regs.b);
 }
 
-static void Op24(void)                                                 // BCC (BHS)
+static void OpD4(void)                                                 // ANDB ZP
 {
-  tmp = regs.RdMem(regs.pc++);
-  if (!(regs.cc&0x01))  regs.pc += (signed short int)(signed char)tmp;
+       uint8_t m = READ_ZP;
+       OP_AND_HANDLER(m, regs.b);
 }
 
-static void Op25(void)                                                 // BCS (BLO)
+static void OpE4(void)                                                 // ANDB ZP, X
 {
-  tmp = regs.RdMem(regs.pc++);
-  if (regs.cc&0x01)  regs.pc += (signed short int)(signed char)tmp;
+       uint16_t m = READ_ZP_X;
+       OP_AND_HANDLER(m, regs.b);
 }
 
-static void Op26(void)                                                 // BNE
+static void OpF4(void)                                                 // ANDB ABS
 {
-  tmp = regs.RdMem(regs.pc++);
-  if (!(regs.cc&0x04))  regs.pc += (signed short int)(signed char)tmp;
+       uint16_t m = READ_ABS;
+       OP_AND_HANDLER(m, regs.b);
 }
 
-static void Op27(void)                                                 // BEQ
+/*
+Operation               |Mnem.|Immed.|Direct|Index |Extend|Inher.|Operation |CC Reg|
+                        |     |OP ~ #|OP ~ #|OP ~ #|OP ~ #|OP ~ #|          |HINZVC|
+Bit Test                |BITA |85 2 2|95 3 2|A5 5 2|B5 4 3|      |A+M       |  TTR |
+                        |BITB |C5 2 2|D5 3 2|E5 5 2|F5 4 3|      |B+M       |  TTR |
+*/
+
+// BIT opcodes
+
+#define OP_BIT_HANDLER(m, acc) \
+       int8_t result = acc & (m); \
+       SET_ZN(result)
+
+static void Op85(void)                                                 // BITA #
 {
-  tmp = regs.RdMem(regs.pc++);
-  if (regs.cc&0x04)  regs.pc += (signed short int)(signed char)tmp;
+       uint8_t m = READ_IMM;
+       OP_BIT_HANDLER(m, regs.a);
 }
 
-static void Op28(void)                                                 // BVC
+static void Op95(void)                                                 // BITA ZP
 {
-  tmp = regs.RdMem(regs.pc++);
-  if (!(regs.cc&0x02))  regs.pc += (signed short int)(signed char)tmp;
+       uint8_t m = READ_ZP;
+       OP_BIT_HANDLER(m, regs.a);
 }
 
-static void Op29(void)                                                 // BVS
+static void OpA5(void)                                                 // BITA ZP, X
 {
-  tmp = regs.RdMem(regs.pc++);
-  if (regs.cc&0x02)  regs.pc += (signed short int)(signed char)tmp;
+       uint8_t m = READ_ZP_X;
+       OP_BIT_HANDLER(m, regs.a);
 }
 
-static void Op2A(void)                                                 // BPL
+static void OpB5(void)                                                 // BITA ABS
 {
-  tmp = regs.RdMem(regs.pc++);
-  if (!(regs.cc&0x08))  regs.pc += (signed short int)(signed char)tmp;
+       uint8_t m = READ_ABS;
+       OP_BIT_HANDLER(m, regs.a);
 }
 
-static void Op2B(void)                                                 // BMI
+static void OpC5(void)                                                 // BITB #
 {
-  tmp = regs.RdMem(regs.pc++);
-  if (regs.cc&0x08)  regs.pc += (signed short int)(signed char)tmp;
+       uint8_t m = READ_IMM;
+       OP_BIT_HANDLER(m, regs.b);
 }
 
-static void Op2C(void)                                                 // BGE
+static void OpD5(void)                                                 // BITB ZP
 {
-  tmp = regs.RdMem(regs.pc++);
-  if (!(((regs.cc&0x08) >> 2) ^ (regs.cc&0x02)))  regs.pc += (signed short int)(signed char)tmp;
+       uint8_t m = READ_ZP;
+       OP_BIT_HANDLER(m, regs.b);
 }
 
-static void Op2D(void)                                                 // BLT
+static void OpE5(void)                                                 // BITB ZP, X
 {
-  tmp = regs.RdMem(regs.pc++);
-  if (((regs.cc&0x08) >> 2) ^ (regs.cc&0x02))  regs.pc += (signed short int)(signed char)tmp;
+       uint8_t m = READ_ZP_X;
+       OP_BIT_HANDLER(m, regs.b);
 }
 
-static void Op2E(void)                                                 // BGT
+static void OpF5(void)                                                 // BITB ABS
 {
-  tmp = regs.RdMem(regs.pc++);
-  if (!((regs.cc&0x04) | (((regs.cc&0x08) >> 2) ^ (regs.cc&0x02))))  regs.pc += (signed short int)(signed char)tmp;
+       uint8_t m = READ_ABS;
+       OP_BIT_HANDLER(m, regs.b);
 }
 
-static void Op2F(void)                                                 // BLE
+/*
+Operation               |Mnem.|Immed.|Direct|Index |Extend|Inher.|Operation |CC Reg|
+                        |     |OP ~ #|OP ~ #|OP ~ #|OP ~ #|OP ~ #|          |HINZVC|
+Clear                   |CLR  |      |      |6F 7 2|7F 6 3|      |M=00      |  RSRR|
+                        |CLRA |      |      |      |      |4F 2 1|A=00      |  RSRR|
+                        |CLRB |      |      |      |      |5F 2 1|B=00      |  RSRR|
+*/
+
+// CLR opcodes
+
+static void Op6F(void)                                                 // CLR ZP, X
 {
-  tmp = regs.RdMem(regs.pc++);
-  if ((regs.cc&0x04) | (((regs.cc&0x08) >> 2) ^ (regs.cc&0x02)))  regs.pc += (signed short int)(signed char)tmp;
+       regs.WrMem(EA_ZP_X, 0);
+       CLR_NVC;
+       SET_Z(0);
 }
 
-static void Op30(void)                                                 // TSX
+static void Op7F(void)                                                 // CLR ABS
 {
-  regs.x = regs.s;
+       regs.WrMem(EA_ABS, 0);
+       CLR_NVC;
+       SET_Z(0);
 }
 
-static void Op31(void)                                                 // INS
+static void Op4F(void)                                                 // CLRA
 {
-  regs.s++;
+       regs.a = 0;
+       CLR_NVC;
+       SET_Z(0);
 }
 
-static void Op32(void)                                                 // PULA
+static void Op5F(void)                                                 // CLRB
 {
-  regs.a  = regs.RdMem(regs.s++);
+       regs.b = 0;
+       CLR_NVC;
+       SET_Z(0);
 }
 
-static void Op33(void)                                                 // PULB
+/*
+Operation               |Mnem.|Immed.|Direct|Index |Extend|Inher.|Operation |CC Reg|
+                        |     |OP ~ #|OP ~ #|OP ~ #|OP ~ #|OP ~ #|          |HINZVC|
+Compare                 |CMPA |81 2 2|91 3 2|A1 5 2|B1 4 3|      |A-M       |  TTTT|
+                        |CMPB |C1 2 2|D1 3 2|E1 5 2|F1 4 3|      |B-M       |  TTTT|
+Compare Accumulators    |CBA  |      |      |      |      |11 2 1|A-B       |  TTTT|
+*/
+
+// CMP opcodes
+
+/*
+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.
+*/
+
+#define OP_CMP_HANDLER(m, acc) \
+       uint16_t result = acc - (m); \
+       SET_ZNVC_CMP(m, acc, result)
+
+static void Op81(void)                                                 // CMPA #
 {
-  regs.b  = regs.RdMem(regs.s++);
+       uint8_t m = READ_IMM;
+       OP_CMP_HANDLER(m, regs.a);
 }
 
-static void Op34(void)                                                 // DES
+static void Op91(void)                                                 // CMPA ZP
 {
-  regs.s--;
+       uint8_t m = READ_ZP;
+       OP_CMP_HANDLER(m, regs.a);
 }
 
-static void Op35(void)                                                 // TXS
+static void OpA1(void)                                                 // CMPA ZP, X
 {
-  regs.s = regs.x;
+       uint8_t m = READ_ZP_X;
+       OP_CMP_HANDLER(m, regs.a);
 }
 
-static void Op36(void)                                                 // PSHA
+static void OpB1(void)                                                 // CMPA ABS
 {
-       regs.WrMem(--regs.s, regs.a);
+       uint8_t m = READ_ABS;
+       OP_CMP_HANDLER(m, regs.a);
 }
 
-static void Op37(void)                                                 // PSHB
+static void OpC1(void)                                                 // CMPB #
 {
-       regs.WrMem(--regs.s, regs.b);
+       uint8_t m = READ_IMM;
+       OP_CMP_HANDLER(m, regs.b);
 }
 
-static void Op39(void)                                                 // RTS
+static void OpD1(void)                                                 // CMPB ZP
 {
-       regs.pc = (regs.RdMem(regs.s++) << 8) | regs.RdMem(regs.s++);
+       uint8_t m = READ_ZP;
+       OP_CMP_HANDLER(m, regs.b);
 }
 
-static void Op3B(void)                                                 // RTI
+static void OpE1(void)                                                 // CMPB ZP, X
 {
-       regs.cc = regs.RdMem(regs.s++);
-       regs.a  = regs.RdMem(regs.s++);
-       regs.b  = regs.RdMem(regs.s++);
-       regs.x  = (regs.RdMem(regs.s++) << 8) | regs.RdMem(regs.s++);
-       regs.pc = (regs.RdMem(regs.s++) << 8) | regs.RdMem(regs.s++);
+       uint8_t m = READ_ZP_X;
+       OP_CMP_HANDLER(m, regs.b);
 }
 
-static void Op3E(void)                                                 // WAI (wait for interrupt)
+static void OpF1(void)                                                 // CMPB ABS
 {
-       regs.cc &= regs.RdMem(regs.pc++);
-       regs.cc |= 0x80;//???Is this right???
+       uint8_t m = READ_ABS;
+       OP_CMP_HANDLER(m, regs.b);
 }
 
-static void Op3F(void)                                                 // SWI (software interrupt)
+static void Op11(void)                                                 // CBA
 {
-//Does this respect the I flag???
-       regs.WrMem(--regs.s, regs.pc & 0xFF);           // Save all regs...
-       regs.WrMem(--regs.s, regs.pc >> 8);
-       regs.WrMem(--regs.s, regs.x & 0xFF);
-       regs.WrMem(--regs.s, regs.x >> 8);
-       regs.WrMem(--regs.s, regs.b);
-       regs.WrMem(--regs.s, regs.a);
-       regs.WrMem(--regs.s, regs.cc);
-       regs.pc = RdMemW(0xFFFA);                                       // And do it!
-
-       regs.cc |= FLAG_I;                                                      // Also, set IRQ inhibit
+       OP_CMP_HANDLER(regs.b, regs.a);
 }
 
-static void Op40(void)                                                 // NEGA
-{ 
-  regs.a = 256 - regs.a;  regs.cc &= 0xF0;
-  if (regs.a > 0x7F)   regs.cc |= 0x01;   // Set Carry
-  if (regs.a == 0x80)  regs.cc |= 0x02;   // Set oVerflow
-  if (regs.a == 0)     regs.cc |= 0x04;   // Set Zero flag
-  if (regs.a&0x80)     regs.cc |= 0x08;   // Set Negative flag
-}
+/*
+Operation               |Mnem.|Immed.|Direct|Index |Extend|Inher.|Operation |CC Reg|
+                        |     |OP ~ #|OP ~ #|OP ~ #|OP ~ #|OP ~ #|          |HINZVC|
+Complement 1's          |COM  |      |      |63 7 2|73 6 3|      |M=-M      |  TTRS|
+                        |COMA |      |      |      |      |43 2 1|A=-A      |  TTRS|
+                        |COMB |      |      |      |      |53 2 1|B=-B      |  TTRS|
+*/
 
-static void Op43(void)                                                 // COMA
+// COM opcodes
+
+#define OP_COM_HANDLER(m) \
+       m = m ^ 0xFF; \
+       SET_ZN(m); \
+       CLR_V; \
+       flagC = 1
+
+static void Op63(void)                                                 // COM ZP, X
 {
-  regs.a ^= 0xFF;
-  regs.cc &= 0xF0;  regs.cc |= 0x01;                   // CLV, SEC
-  if (regs.a == 0)  regs.cc |= 0x04;                   // Set Zero flag
-  if (regs.a&0x80)  regs.cc |= 0x08;                   // Set Negative flag
+       uint8_t m;
+       READ_ZP_X_WB(m);
+       OP_COM_HANDLER(m);
+       WRITE_BACK(m);
 }
 
-static void Op44(void)                                                 // LSRA
+static void Op73(void)                                                 // COM ABS
 {
-  (regs.a&0x01 ? regs.cc |= 0x01 : regs.cc &= 0xFE);  // Shift low bit into Carry
-  regs.a >>= 1;
-  (regs.a == 0 ? regs.cc |= 0x04 : regs.cc &= 0xFB);  // Adjust Zero flag
-  (regs.a&0x80 ? regs.cc |= 0x08 : regs.cc &= 0xF7);  // Adjust Negative flag
+       uint8_t m;
+       READ_ABS_WB(m);
+       OP_COM_HANDLER(m);
+       WRITE_BACK(m);
 }
 
-static void Op46(void)  // RORA
+static void Op43(void)                                                 // COMA
 {
-  tmp = regs.a;  regs.a = (tmp>>1) + (regs.cc&0x01)*128;
-  (tmp&0x01 ? regs.cc |= 0x01 : regs.cc &= 0xFE); // Shift bit into Carry
-  (regs.a == 0  ? regs.cc |= 0x04 : regs.cc &= 0xFB); // Adjust Zero flag
-  (regs.a&0x80  ? regs.cc |= 0x08 : regs.cc &= 0xF7); // Adjust Negative flag
+       OP_COM_HANDLER(regs.a);
 }
 
-static void Op47(void)  // ASRA
+static void Op53(void)                                                 // COMB
 {
-  (regs.a&0x01 ? regs.cc |= 0x01 : regs.cc &= 0xFE);  // Shift bit into Carry
-  regs.a >>= 1;                               // Do the shift
-  if (regs.a&0x40)  regs.a |= 0x80;               // Set neg if it was set
-  (regs.a == 0 ? regs.cc |= 0x04 : regs.cc &= 0xFB);  // Adjust Zero flag
-  (regs.a&0x80 ? regs.cc |= 0x08 : regs.cc &= 0xF7);  // Adjust Negative flag
+       OP_COM_HANDLER(regs.b);
 }
 
-static void Op48(void)  // LSLA (ASLA) [Keep checking from here...]
+/*
+Operation               |Mnem.|Immed.|Direct|Index |Extend|Inher.|Operation |CC Reg|
+                        |     |OP ~ #|OP ~ #|OP ~ #|OP ~ #|OP ~ #|          |HINZVC|
+Complement 2's          |NEG  |      |      |60 7 2|70 6 3|      |M=00-M    |  TT12|
+                        |NEGA |      |      |      |      |40 2 1|A=00-A    |  TT12|
+                        |NEGB |      |      |      |      |50 2 1|B=00-B    |  TT12|
+*/
+
+// NEG opcodes
+
+#define OP_NEG_HANDLER(m) \
+       m = -m; \
+       SET_ZN(m); \
+       flagV = (m == 0x80 ? 1 : 0); \
+       flagC = (m == 0x00 ? 1 : 0)
+
+static void Op60(void)                                                 // NEG ZP, X
 {
-  (regs.a&0x80 ? regs.cc |= 0x01 : regs.cc &= 0xFE);  // Shift hi bit into Carry
-  regs.a <<= 1;
-  (regs.a == 0 ? regs.cc |= 0x04 : regs.cc &= 0xFB);  // Adjust Zero flag
-  (regs.a&0x80 ? regs.cc |= 0x08 : regs.cc &= 0xF7);  // Adjust Negative flag
+       uint8_t m;
+       READ_ZP_X_WB(m);
+       OP_NEG_HANDLER(m);
+       WRITE_BACK(m);
 }
 
-static void Op49(void)  // ROLA  
+static void Op70(void)                                                 // NEG ABS
 {
-  tmp = regs.a;  regs.a = (tmp<<1) + (regs.cc&0x01);
-  (tmp&0x80 ? regs.cc |= 0x01 : regs.cc &= 0xFE); // Shift hi bit into Carry
-  (regs.a == 0  ? regs.cc |= 0x04 : regs.cc &= 0xFB); // Adjust Zero flag
-  (regs.a&0x80  ? regs.cc |= 0x08 : regs.cc &= 0xF7); // Adjust Negative flag
+       uint8_t m;
+       READ_ABS_WB(m);
+       OP_NEG_HANDLER(m);
+       WRITE_BACK(m);
 }
 
-static void Op4A(void)  // DECA
+static void Op40(void)                                                 // NEGA
 {
-  regs.a--;
-  (regs.a == 0x7F ? regs.cc |= 0x02 : regs.cc &= 0xFD); // Adjust oVerflow flag
-  (regs.a == 0    ? regs.cc |= 0x04 : regs.cc &= 0xFB); // Adjust Zero flag
-  (regs.a&0x80    ? regs.cc |= 0x08 : regs.cc &= 0xF7); // Adjust Negative flag
+       OP_NEG_HANDLER(regs.a);
 }
 
-static void Op4C(void)  // INCA
+static void Op50(void)                                                 // NEGB
 {
-regs.a++;
-(regs.a == 0x80 ? regs.cc |= 0x02 : regs.cc &= 0xFD); // Adjust oVerflow flag
-(regs.a == 0 ? regs.cc |= 0x04 : regs.cc &= 0xFB);    // Adjust Zero flag
-(regs.a&0x80 ? regs.cc |= 0x08 : regs.cc &= 0xF7);    // Adjust Negative flag
+       OP_NEG_HANDLER(regs.b);
 }
 
-static void Op4D(void)  // TSTA
+/*
+Operation               |Mnem.|Immed.|Direct|Index |Extend|Inher.|Operation |CC Reg|
+                        |     |OP ~ #|OP ~ #|OP ~ #|OP ~ #|OP ~ #|          |HINZVC|
+Decimal Adjust          |DAA  |      |      |      |      |19 2 1|*         |  TTT3|
+*/
+
+static void Op19(void)                                                 // DAA
 {
-regs.cc &= 0xFD;                            // Clear oVerflow flag
-(regs.a == 0 ? regs.cc |= 0x04 : regs.cc &= 0xFB);  // Adjust Zero flag
-(regs.a&0x80 ? regs.cc |= 0x08 : regs.cc &= 0xF7);  // Adjust Negative flag
+       uint16_t result = (uint16_t)regs.a;
+
+       if ((regs.a & 0x0F) > 0x09 || flagH)
+               result += 0x06;
+
+       if ((regs.a & 0xF0) > 0x90 || flagC || ((regs.a & 0xF0) > 0x80 && (regs.a & 0x0F) > 0x09))
+               result += 0x60;
+
+       regs.a = (uint8_t)result;
+       SET_ZN(result);
+       CLR_V;                                                                          // Not sure this is correct...
+       flagC |= (result & 0x100) >> 8;                         // Overwrite carry if it was 0, otherwise, ignore
 }
 
-static void Op4F(void)  // CLRA
+/*
+Operation               |Mnem.|Immed.|Direct|Index |Extend|Inher.|Operation |CC Reg|
+                        |     |OP ~ #|OP ~ #|OP ~ #|OP ~ #|OP ~ #|          |HINZVC|
+Decrement               |DEC  |      |      |6A 7 2|7A 6 3|      |M=M-1     |  TT4 |
+                        |DECA |      |      |      |      |4A 2 1|A=A-1     |  TT4 |
+                        |DECB |      |      |      |      |5A 2 1|B=B-1     |  TT4 |
+*/
+
+// DEC opcodes
+
+#define OP_DEC_HANDLER(m) \
+       m--; \
+       SET_ZN(m); \
+       flagV = (m == 0x7F ? 1 : 0)
+
+static void Op6A(void)                                                 // DEC ZP, X
 {
-  regs.a = 0;
-  regs.cc &= 0xF0;  regs.cc |= 0x04;                // Set NZVC
+       uint8_t m;
+       READ_ZP_X_WB(m);
+       OP_DEC_HANDLER(m);
+       WRITE_BACK(m);
 }
 
-static void Op50(void)  // NEGB
-{ 
-regs.b = 256 - regs.b;
-//        ((regs.b^tmp)&0x10 ? regs.cc |= 0x20 : regs.cc &= 0xDF); // Adjust H Carry
-(regs.b == 0x80 ? regs.cc |= 0x02 : regs.cc &= 0xFD); // oVerflow
-(regs.b == 0 ? regs.cc |= 0x04 : regs.cc &= 0xFB);   // Adjust Zero flag
-(regs.b&0x80 ? regs.cc |= 0x08 : regs.cc &= 0xF7);   // Adjust Negative flag
-(regs.b > 0x7F ? regs.cc |= 0x01 : regs.cc &= 0xFE); // Adjust Carry
+static void Op7A(void)                                                 // DEC ABS
+{
+       uint8_t m;
+       READ_ABS_WB(m);
+       OP_DEC_HANDLER(m);
+       WRITE_BACK(m);
 }
 
-static void Op53(void)  // COMB
+static void Op4A(void)                                                 // DECA
 {
-regs.b ^= 0xFF;
-regs.cc &= 0xFD;  regs.cc |= 0x01;              // CLV, SEC
-(regs.b == 0 ? regs.cc |= 0x04 : regs.cc &= 0xFB);  // Adjust Zero flag
-(regs.b&0x80 ? regs.cc |= 0x08 : regs.cc &= 0xF7);  // Adjust Negative flag
+       OP_DEC_HANDLER(regs.a);
 }
 
-static void Op54(void)  // LSRB
+static void Op5A(void)                                                 // DECB
 {
-(regs.b&0x01 ? regs.cc |= 0x01 : regs.cc &= 0xFE);  // Shift low bit into Carry
-regs.b >>= 1;
-(regs.b == 0 ? regs.cc |= 0x04 : regs.cc &= 0xFB);  // Adjust Zero flag
-(regs.b&0x80 ? regs.cc |= 0x08 : regs.cc &= 0xF7);  // Adjust Negative flag
+       OP_DEC_HANDLER(regs.b);
 }
 
-static void Op56(void)  // RORB
+/*
+Operation               |Mnem.|Immed.|Direct|Index |Extend|Inher.|Operation |CC Reg|
+                        |     |OP ~ #|OP ~ #|OP ~ #|OP ~ #|OP ~ #|          |HINZVC|
+Exclusive OR            |EORA |88 2 2|98 3 2|A8 5 2|B8 4 3|      |A=A(+)M   |  TTR |
+                        |EORB |C8 2 2|D8 3 2|E8 5 2|F8 4 3|      |B=B(+)M   |  TTR |
+*/
+
+// EOR opcodes
+
+#define OP_EOR_HANDLER(m, acc) \
+       acc ^= m; \
+       SET_ZN(acc); \
+       CLR_V
+
+static void Op88(void)                                                 // EORA #
 {
-tmp = regs.b;  regs.b = (regs.b >> 1) + (regs.cc&0x01)*128;
-(tmp&0x01 ? regs.cc |=0x01 : regs.cc &= 0xFE);  // Shift bit into Carry
-(regs.b == 0 ? regs.cc |= 0x04 : regs.cc &= 0xFB);  // Adjust Zero flag
-(regs.b&0x80 ? regs.cc |= 0x08 : regs.cc &= 0xF7);  // Adjust Negative flag
+       uint8_t m = READ_IMM;
+       OP_EOR_HANDLER(m, regs.a);
 }
 
-static void Op57(void)  // ASRB
+static void Op98(void)                                                 // EORA ZP
 {
-(regs.b&0x01 ? regs.cc |= 0x01 : regs.cc &= 0xFE);  // Shift bit into Carry
-regs.b >>= 1;                               // Do the shift
-if (regs.b&0x40)  regs.b |= 0x80;               // Set neg if it was set
-(regs.b == 0 ? regs.cc |= 0x04 : regs.cc &= 0xFB);  // Adjust Zero flag
-(regs.b&0x80 ? regs.cc |= 0x08 : regs.cc &= 0xF7);  // Adjust Negative flag
+       uint8_t m = READ_ZP;
+       OP_EOR_HANDLER(m, regs.a);
 }
 
-static void Op58(void)  // LSLB
+static void OpA8(void)                                                 // EORA ZP, X
 {
-(regs.b&0x80 ? regs.cc |= 0x01 : regs.cc &= 0xFE);  // Shift hi bit into Carry
-regs.b <<= 1;
-(regs.b == 0 ? regs.cc |= 0x04 : regs.cc &= 0xFB);  // Adjust Zero flag
-(regs.b&0x80 ? regs.cc |= 0x08 : regs.cc &= 0xF7);  // Adjust Negative flag
+       uint8_t m = READ_ZP_X;
+       OP_EOR_HANDLER(m, regs.a);
 }
 
-static void Op59(void)  // ROLB
+static void OpB8(void)                                                 // EORA ABS
 {
-  tmp = regs.b;
-  regs.b = (tmp<<1) + (regs.cc&0x01);
-  (tmp&0x80 ? regs.cc |= 0x01 : regs.cc &= 0xFE); // Shift hi bit into Carry
-  (regs.b == 0 ? regs.cc |= 0x04 : regs.cc &= 0xFB);  // Adjust Zero flag
-  (regs.b&0x80 ? regs.cc |= 0x08 : regs.cc &= 0xF7);  // Adjust Negative flag
+       uint8_t m = READ_ABS;
+       OP_EOR_HANDLER(m, regs.a);
 }
 
-static void Op5A(void)  // DECB
+static void OpC8(void)                                                 // EORB #
 {
-regs.b--;
-(regs.b == 0x7F ? regs.cc |= 0x02 : regs.cc &= 0xFD); // Adjust oVerflow flag
-(regs.b == 0 ? regs.cc |= 0x04 : regs.cc &= 0xFB);    // Adjust Zero flag
-(regs.b&0x80 ? regs.cc |= 0x08 : regs.cc &= 0xF7);    // Adjust Negative flag
+       uint8_t m = READ_IMM;
+       OP_EOR_HANDLER(m, regs.b);
 }
 
-static void Op5C(void)  // INCB
+static void OpD8(void)                                                 // EORB ZP
 {
-regs.b++;
-(regs.b == 0x80 ? regs.cc |= 0x02 : regs.cc &= 0xFD); // Adjust oVerflow flag 
-(regs.b == 0 ? regs.cc |= 0x04 : regs.cc &= 0xFB);    // Adjust Zero flag
-(regs.b&0x80 ? regs.cc |= 0x08 : regs.cc &= 0xF7);    // Adjust Negative flag
+       uint8_t m = READ_ZP;
+       OP_EOR_HANDLER(m, regs.b);
 }
 
-static void Op5D(void)  // TSTB
+static void OpE8(void)                                                 // EORB ZP, X
 {
-regs.cc &= 0xFD;                            // Cleregs.a oVerflow flag
-(regs.b == 0 ? regs.cc |= 0x04 : regs.cc &= 0xFB);  // Adjust Zero flag
-(regs.b&0x80 ? regs.cc |= 0x08 : regs.cc &= 0xF7);  // Adjust Negative flag
+       uint8_t m = READ_ZP_X;
+       OP_EOR_HANDLER(m, regs.b);
 }
 
-static void Op5F(void)  // CLRB
+static void OpF8(void)                                                 // EORB ABS
 {
-regs.b = 0;
-regs.cc &= 0xF0;  regs.cc |= 0x04;                // Set NZVC
+       uint8_t m = READ_ABS;
+       OP_EOR_HANDLER(m, regs.b);
 }
 
-static void Op60(void)  // NEG IDX
-{ 
-addr = DecodeIDX(regs.RdMem(regs.pc++));
-tmp = regs.RdMem(addr);  uint8 res = 256 - tmp;
-regs.WrMem(addr, res);
-//        ((res^tmp)&0x10 ? regs.cc |= 0x20 : regs.cc &= 0xDF); // Adjust H Carry
-(res == 0x80 ? regs.cc |= 0x02 : regs.cc &= 0xFD); // oVerflow
-(res == 0 ? regs.cc |= 0x04 : regs.cc &= 0xFB);   // Adjust Zero flag
-(res&0x80 ? regs.cc |= 0x08 : regs.cc &= 0xF7);   // Adjust Negative flag
-(res > 0x7F ? regs.cc |= 0x01 : regs.cc &= 0xFE); // Adjust Carry
+/*
+Operation               |Mnem.|Immed.|Direct|Index |Extend|Inher.|Operation |CC Reg|
+                        |     |OP ~ #|OP ~ #|OP ~ #|OP ~ #|OP ~ #|          |HINZVC|
+Increment               |INC  |      |      |6C 7 2|7C 6 3|      |M=M+1     |  TT5 |
+                        |INCA |      |      |      |      |4C 2 1|A=A+1     |  TT5 |
+                        |INCB |      |      |      |      |5C 2 1|B=B+1     |  TT5 |
+*/
+
+// INC opcodes
+
+#define OP_INC_HANDLER(m) \
+       m++; \
+       SET_ZN(m); \
+       flagV = (m == 0x80 ? 1 : 0)
+
+static void Op6C(void)                                                 // INC ZP, X
+{
+       uint8_t m;
+       READ_ZP_X_WB(m);
+       OP_INC_HANDLER(m);
+       WRITE_BACK(m);
 }
 
-static void Op63(void)  // COM IDX
+static void Op7C(void)                                                 // INC ABS
 {
-addr = DecodeIDX(regs.RdMem(regs.pc++));
-tmp = regs.RdMem(addr) ^ 0xFF;
-regs.WrMem(addr, tmp);
-regs.cc &= 0xFD;  regs.cc |= 0x01;               // CLV, SEC
-(tmp == 0 ? regs.cc |= 0x04 : regs.cc &= 0xFB);  // Adjust Zero flag
-(tmp&0x80 ? regs.cc |= 0x08 : regs.cc &= 0xF7);  // Adjust Negative flag
+       uint8_t m;
+       READ_ABS_WB(m);
+       OP_INC_HANDLER(m);
+       WRITE_BACK(m);
 }
 
-static void Op64(void)  // LSR IDX
+static void Op4C(void)                                                 // INCA
 {
-addr = DecodeIDX(regs.RdMem(regs.pc++));
-tmp = regs.RdMem(addr);
-(tmp&0x01 ? regs.cc |= 0x01 : regs.cc &= 0xFE);  // Shift low bit into Carry
-tmp >>= 1;  regs.WrMem(addr, tmp);
-regs.cc &= 0xF7;                             // CLN
-(tmp == 0 ? regs.cc |= 0x04 : regs.cc &= 0xFB);  // Adjust Zero flag
+       OP_INC_HANDLER(regs.a);
 }
 
-static void Op66(void)  // ROR IDX
+static void Op5C(void)                                                 // INCB
 {
-addr = DecodeIDX(regs.RdMem(regs.pc++));
-tmp = regs.RdMem(addr);  uint8 tmp2 = tmp;
-tmp = (tmp >> 1) + (regs.cc&0x01)*128;
-regs.WrMem(addr, tmp);
-(tmp2&0x01 ? regs.cc |= 0x01 : regs.cc &= 0xFE); // Shift bit into Carry
-(tmp == 0 ? regs.cc |= 0x04 : regs.cc &= 0xFB);  // Adjust Zero flag
-(tmp&0x80 ? regs.cc |= 0x08 : regs.cc &= 0xF7);  // Adjust Negative flag
+       OP_INC_HANDLER(regs.b);
 }
 
-static void Op67(void)  // ASR IDX
+/*
+Operation               |Mnem.|Immed.|Direct|Index |Extend|Inher.|Operation |CC Reg|
+                        |     |OP ~ #|OP ~ #|OP ~ #|OP ~ #|OP ~ #|          |HINZVC|
+Load Accumulator        |LDAA |86 2 2|96 3 2|A6 5 2|B6 4 3|      |A=M       |  TTR |
+                        |LDAB |C6 2 2|D6 3 2|E6 5 2|F6 4 3|      |B=M       |  TTR |
+*/
+
+// LDA opcodes
+
+#define OP_LDA_HANDLER(m, acc) \
+       acc = m; \
+       SET_ZN(acc); \
+       CLR_V
+
+static void Op86(void)                                                 // LDAA #
 {
-addr = DecodeIDX(regs.RdMem(regs.pc++));
-tmp = regs.RdMem(addr);
-(tmp&0x01 ? regs.cc |= 0x01 : regs.cc &= 0xFE);  // Shift bit into Carry
-tmp >>= 1;
-if (tmp&0x40)  tmp |= 0x80;              // Set Neg if it was set
-regs.WrMem(addr, tmp);
-(tmp == 0 ? regs.cc |= 0x04 : regs.cc &= 0xFB);  // Adjust Zero flag
-(tmp&0x80 ? regs.cc |= 0x08 : regs.cc &= 0xF7);  // Adjust Negative flag
+       uint8_t m = READ_IMM;
+       OP_LDA_HANDLER(m, regs.a);
 }
 
-static void Op68(void)  // LSL IDX
+static void Op96(void)                                                 // LDAA ZP
 {
-addr = DecodeIDX(regs.RdMem(regs.pc++));
-tmp = regs.RdMem(addr);
-(tmp&0x80 ? regs.cc |= 0x01 : regs.cc &= 0xFE);  // Shift hi bit into Carry
-tmp <<= 1;
-regs.WrMem(addr, tmp);
-(tmp == 0 ? regs.cc |= 0x04 : regs.cc &= 0xFB);  // Adjust Zero flag
-(tmp&0x80 ? regs.cc |= 0x08 : regs.cc &= 0xF7);  // Adjust Negative flag
+       uint8_t m = READ_ZP;
+       OP_LDA_HANDLER(m, regs.a);
 }
 
-static void Op69(void)  // ROL IDX
+static void OpA6(void)                                                 // LDAA ZP, X
 {
-  uint8 tmp2 = regs.RdMem(DecodeIDX(regs.RdMem(regs.pc++)));
-  tmp = (tmp2<<1) + (regs.cc&0x01);
-  regs.WrMem(addr, tmp);
-  (tmp2&0x80 ? regs.cc |= 0x01 : regs.cc &= 0xFE); // Shift hi bit into Carry
-  (tmp == 0 ? regs.cc |= 0x04 : regs.cc &= 0xFB);  // Adjust Zero flag
-  (tmp&0x80 ? regs.cc |= 0x08 : regs.cc &= 0xF7);  // Adjust Negative flag
+       uint8_t m = READ_ZP_X;
+       OP_LDA_HANDLER(m, regs.a);
 }
 
-static void Op6A(void)  // DEC IDX
+static void OpB6(void)                                                 // LDAA ABS
 {
-uint8 tmp;  uint16 addr;
-addr = DecodeIDX(regs.RdMem(regs.pc++));
-tmp = regs.RdMem(addr) - 1;
-regs.WrMem(addr, tmp);
-(tmp == 0x7F ? regs.cc |= 0x02 : regs.cc &= 0xFD); // Adjust oVerflow flag
-(tmp == 0 ? regs.cc |= 0x04 : regs.cc &= 0xFB);    // Adjust Zero flag
-(tmp&0x80 ? regs.cc |= 0x08 : regs.cc &= 0xF7);    // Adjust Negative flag
+       uint8_t m = READ_ABS;
+       OP_LDA_HANDLER(m, regs.a);
 }
 
-static void Op6C(void)  // INC IDX
-{       
-addr = DecodeIDX(regs.RdMem(regs.pc++));
-tmp = regs.RdMem(addr) + 1;
-regs.WrMem(addr, tmp);
-(tmp == 0x80 ? regs.cc |= 0x02 : regs.cc &= 0xFD); // Adjust oVerflow flag
-(tmp == 0 ? regs.cc |= 0x04 : regs.cc &= 0xFB);    // Adjust Zero flag
-(tmp&0x80 ? regs.cc |= 0x08 : regs.cc &= 0xF7);    // Adjust Negative flag
+static void OpC6(void)                                                 // LDAB #
+{
+       uint8_t m = READ_IMM;
+       OP_LDA_HANDLER(m, regs.b);
 }
 
-static void Op6D(void)  // TST IDX
+static void OpD6(void)                                                 // LDAB ZP
 {
-tmp = regs.RdMem(DecodeIDX(regs.RdMem(regs.pc++)));
-(tmp == 0 ? regs.cc |= 0x04 : regs.cc &= 0xFB);   // Adjust Zero flag 
-(tmp&0x80 ? regs.cc |= 0x08 : regs.cc &= 0xF7);   // Adjust Negative flag 
+       uint8_t m = READ_ZP;
+       OP_LDA_HANDLER(m, regs.b);
 }
 
-static void Op6E(void)  // JMP IDX
+static void OpE6(void)                                                 // LDAB ZP, X
 {
-  regs.pc = DecodeIDX(regs.RdMem(regs.pc++));
+       uint8_t m = READ_ZP_X;
+       OP_LDA_HANDLER(m, regs.b);
 }
 
-static void Op6F(void)  // CLR IDX
+static void OpF6(void)                                                 // LDAB ABS
 {
-  addr = DecodeIDX(regs.RdMem(regs.pc++));
-  regs.WrMem(addr, 0);
-  regs.cc &= 0xF0;  regs.cc |= 0x04;                // Set NZVC
+       uint8_t m = READ_ABS;
+       OP_LDA_HANDLER(m, regs.b);
 }
 
-static void Op70(void)  // NEG ABS
-{ 
-addr = FetchW();
-tmp = regs.RdMem(addr);  uint8 res = 256 - tmp;
-regs.WrMem(addr, res);
-(res == 0x80 ? regs.cc |= 0x02 : regs.cc &= 0xFD); // oVerflow
-(res == 0 ? regs.cc |= 0x04 : regs.cc &= 0xFB);   // Adjust Zero flag
-(res&0x80 ? regs.cc |= 0x08 : regs.cc &= 0xF7);   // Adjust Negative flag
-(res > 0x7F ? regs.cc |= 0x01 : regs.cc &= 0xFE); // Adjust Carry
+/*
+Operation               |Mnem.|Immed.|Direct|Index |Extend|Inher.|Operation |CC Reg|
+                        |     |OP ~ #|OP ~ #|OP ~ #|OP ~ #|OP ~ #|          |HINZVC|
+OR, Inclusive           |ORAA |8A 2 2|9A 3 2|AA 5 2|BA 4 3|      |A=A+M     |  TTR |
+                        |ORAB |CA 2 2|DA 3 2|EA 5 2|FA 4 3|      |B=B+M     |  TTR |
+*/
+
+// ORA opcodes
+
+#define OP_ORA_HANDLER(m, acc) \
+       acc |= m; \
+       SET_ZN(acc); \
+       CLR_V
+
+static void Op8A(void)                                                 // ORAA #
+{
+       uint8_t m = READ_IMM;
+       OP_ORA_HANDLER(m, regs.a);
 }
 
-static void Op73(void)  // COM ABS
+static void Op9A(void)                                                 // ORAA ZP
 {
-addr = FetchW();
-tmp = regs.RdMem(addr) ^ 0xFF;
-regs.WrMem(addr, tmp);
-regs.cc &= 0xFD;  regs.cc |= 0x01;               // CLV, SEC
-(tmp == 0 ? regs.cc |= 0x04 : regs.cc &= 0xFB);  // Adjust Zero flag
-(tmp&0x80 ? regs.cc |= 0x08 : regs.cc &= 0xF7);  // Adjust Negative flag
+       uint8_t m = READ_ZP;
+       OP_ORA_HANDLER(m, regs.a);
 }
 
-static void Op74(void)  // LSR ABS
+static void OpAA(void)                                                 // ORAA ZP, X
 {
-addr = FetchW();
-tmp = regs.RdMem(addr);
-(tmp&0x01 ? regs.cc |= 0x01 : regs.cc &= 0xFE);  // Shift low bit into Carry
-tmp >>= 1;  regs.WrMem(addr, tmp);
-regs.cc &= 0xF7;                             // CLN
-(tmp == 0 ? regs.cc |= 0x04 : regs.cc &= 0xFB);  // Adjust Zero flag
+       uint8_t m = READ_ZP_X;
+       OP_ORA_HANDLER(m, regs.a);
 }
 
-static void Op76(void)  // ROR ABS
+static void OpBA(void)                                                 // ORAA ABS
 {
-uint8 tmp;  uint16 addr;
-addr = FetchW();
-tmp = regs.RdMem(addr);  uint8 tmp2 = tmp;
-tmp = (tmp >> 1) + (regs.cc&0x01)*128;
-regs.WrMem(addr, tmp);
-(tmp2&0x01 ? regs.cc |= 0x01 : regs.cc &= 0xFE); // Shift bit into Carry
-(tmp == 0 ? regs.cc |= 0x04 : regs.cc &= 0xFB);  // Adjust Zero flag
-(tmp&0x80 ? regs.cc |= 0x08 : regs.cc &= 0xF7);  // Adjust Negative flag
+       uint8_t m = READ_ABS;
+       OP_ORA_HANDLER(m, regs.a);
 }
 
-static void Op77(void)  // ASR ABS
+static void OpCA(void)                                                 // ORAB #
 {
-uint8 tmp;  uint16 addr;
-addr = FetchW();
-tmp = regs.RdMem(addr);
-(tmp&0x01 ? regs.cc |= 0x01 : regs.cc &= 0xFE);  // Shift bit into Carry
-tmp >>= 1;
-if (tmp&0x40)  tmp |= 0x80;              // Set Neg if it was set
-regs.WrMem(addr, tmp);
-(tmp == 0 ? regs.cc |= 0x04 : regs.cc &= 0xFB);  // Adjust Zero flag
-(tmp&0x80 ? regs.cc |= 0x08 : regs.cc &= 0xF7);  // Adjust Negative flag
+       uint8_t m = READ_IMM;
+       OP_ORA_HANDLER(m, regs.b);
 }
 
-static void Op78(void)  // LSL ABS
+static void OpDA(void)                                                 // ORAB ZP
 {
-uint8 tmp;  uint16 addr;
-addr = FetchW();
-tmp = regs.RdMem(addr);
-(tmp&0x80 ? regs.cc |= 0x01 : regs.cc &= 0xFE);  // Shift hi bit into Carry
-tmp <<= 1;
-regs.WrMem(addr, tmp);
-(tmp == 0 ? regs.cc |= 0x04 : regs.cc &= 0xFB);  // Adjust Zero flag
-(tmp&0x80 ? regs.cc |= 0x08 : regs.cc &= 0xF7);  // Adjust Negative flag
+       uint8_t m = READ_ZP;
+       OP_ORA_HANDLER(m, regs.b);
 }
 
-static void Op79(void)  // ROL ABS
+static void OpEA(void)                                                 // ORAB ZP, X
 {
-  uint8 tmp2 = regs.RdMem(FetchW());
-  tmp = (tmp2<<1) + (regs.cc&0x01);
-  regs.WrMem(addr, tmp);
-  (tmp2&0x80 ? regs.cc |= 0x01 : regs.cc &= 0xFE); // Shift hi bit into Carry
-  (tmp == 0 ? regs.cc |= 0x04 : regs.cc &= 0xFB);  // Adjust Zero flag
-  (tmp&0x80 ? regs.cc |= 0x08 : regs.cc &= 0xF7);  // Adjust Negative flag
+       uint8_t m = READ_ZP_X;
+       OP_ORA_HANDLER(m, regs.b);
 }
 
-static void Op7A(void)  // DEC ABS
+static void OpFA(void)                                                 // ORAB ABS
 {
-uint8 tmp;  uint16 addr;
-addr = FetchW();
-tmp = regs.RdMem(addr) - 1;
-regs.WrMem(addr, tmp);
-(tmp == 0x7F ? regs.cc |= 0x02 : regs.cc &= 0xFD); // Adjust oVerflow flag
-(tmp == 0 ? regs.cc |= 0x04 : regs.cc &= 0xFB);    // Adjust Zero flag
-(tmp&0x80 ? regs.cc |= 0x08 : regs.cc &= 0xF7);    // Adjust Negative flag
+       uint8_t m = READ_ABS;
+       OP_ORA_HANDLER(m, regs.b);
 }
 
-static void Op7C(void)                                                                 // INC ABS
-{       
-       addr = FetchW();
-       tmp = regs.RdMem(addr) + 1;
-       regs.WrMem(addr, tmp);
+/*
+Operation               |Mnem.|Immed.|Direct|Index |Extend|Inher.|Operation |CC Reg|
+                        |     |OP ~ #|OP ~ #|OP ~ #|OP ~ #|OP ~ #|          |HINZVC|
+Push Data               |PSHA |      |      |      |      |36 4 1|Msp=A, *- |      |
+                        |PSHB |      |      |      |      |37 4 1|Msp=B, *- |      |
+Pull Data               |PULA |      |      |      |      |32 4 1|A=Msp, *+ |      |
+                        |PULB |      |      |      |      |33 4 1|B=Msp, *+ |      |
+*/
 
-       (tmp == 0x80 ? regs.cc |= 0x02 : regs.cc &= 0xFD); // Adjust oVerflow flag
-       (tmp == 0 ? regs.cc |= 0x04 : regs.cc &= 0xFB);    // Adjust Zero flag
-       (tmp&0x80 ? regs.cc |= 0x08 : regs.cc &= 0xF7);    // Adjust Negative flag
+static void Op36(void)                                                 // PSHA
+{
+       PUSH(regs.a);
 }
 
-static void Op7D(void)                                                                 // TST ABS
+static void Op37(void)                                                 // PSHB
 {
-       uint8 tmp = regs.RdMem(FetchW());
-
-       (tmp == 0   ? regs.cc |= 0x04 : regs.cc &= 0xFB);               // Adjust Zero flag 
-       (tmp & 0x80 ? regs.cc |= 0x08 : regs.cc &= 0xF7);               // Adjust Negative flag 
+       PUSH(regs.b);
 }
 
-static void Op7E(void)                                                                 // JMP ABS
+static void Op32(void)                                                 // PULA
 {
-       regs.pc = FetchW();
+       regs.a = PULL;
 }
 
-static void Op7F(void)  // CLR ABS
+static void Op33(void)                                                 // PULB
 {
-regs.WrMem(FetchW(), 0);
-regs.cc &= 0xF0;  regs.cc |= 0x04;                // Set NZVC
+       regs.b = PULL;
 }
 
-static void Op80(void)  // SUBA #
-{ 
-  uint8 tmp = regs.RdMem(regs.pc++);  uint8 as = regs.a; 
-  regs.a -= tmp;
-  (as < tmp ? regs.cc |= 0x01 : regs.cc &= 0xFE);  // Adjust Carry flag
-  ((as^tmp^regs.a^(regs.cc<<7))&0x80 ? regs.cc |= 0x02 : regs.cc &= 0xFD); // oVerflow
-  (regs.a == 0  ? regs.cc |= 0x04 : regs.cc &= 0xFB);  // Adjust Zero flag
-  (regs.a&0x80  ? regs.cc |= 0x08 : regs.cc &= 0xF7);  // Adjust Negative flag
+/*
+Operation               |Mnem.|Immed.|Direct|Index |Extend|Inher.|Operation |CC Reg|
+                        |     |OP ~ #|OP ~ #|OP ~ #|OP ~ #|OP ~ #|          |HINZVC|
+Rotate Left             |ROL  |      |      |69 7 2|79 6 3|      |Memory  *1|  TT6T|
+                        |ROLA |      |      |      |      |49 2 1|Accum A *1|  TT6T|
+                        |ROLB |      |      |      |      |59 2 1|Accum B *1|  TT6T|
+*/
+
+// ROL opcodes
+
+#define OP_ROL_HANDLER(m) \
+       uint8_t newCarry = (m & 0x80) >> 7; \
+       m = (m << 1) | flagC; \
+       SET_ZN(m); \
+       flagC = newCarry; \
+       flagV = flagN ^ flagC
+
+static void Op69(void)                                                 // ROL ZP, X
+{
+       uint8_t m;
+       READ_ZP_X_WB(m);
+       OP_ROL_HANDLER(m);
+       WRITE_BACK(m);
 }
 
-static void Op81(void)  // CMPA #
+static void Op79(void)                                                 // ROL ABS
 {
-  tmp = regs.RdMem(regs.pc++);
-  uint8 db = regs.a - tmp;
-  (regs.a < tmp ? regs.cc |= 0x01 : regs.cc &= 0xFE);  // Adjust Carry flag
-  ((regs.a^tmp^db^(regs.cc<<7))&0x80 ? regs.cc |= 0x02 : regs.cc &= 0xFD); // oVerflow
-  (db == 0  ? regs.cc |= 0x04 : regs.cc &= 0xFB);  // Adjust Zero flag
-  (db&0x80  ? regs.cc |= 0x08 : regs.cc &= 0xF7);  // Adjust Negative flag
+       uint8_t m;
+       READ_ABS_WB(m);
+       OP_ROL_HANDLER(m);
+       WRITE_BACK(m);
 }
 
-static void Op82(void)  // SBCA #
+static void Op49(void)                                                 // ROLA
 {
-  tmp = regs.RdMem(regs.pc++);  uint8 as = regs.a; 
-  regs.a = regs.a - tmp - (regs.cc&0x01);
-  (as < (tmp+(regs.cc&0x01)) ? regs.cc |= 0x01 : regs.cc &= 0xFE);  // Adjust Carry flag
-  ((as^tmp^regs.a^(regs.cc<<7))&0x80 ? regs.cc |= 0x02 : regs.cc &= 0xFD); // oVerflow
-  (regs.a == 0  ? regs.cc |= 0x04 : regs.cc &= 0xFB);  // Adjust Zero flag
-  (regs.a&0x80  ? regs.cc |= 0x08 : regs.cc &= 0xF7);  // Adjust Negative flag
+       OP_ROL_HANDLER(regs.a);
 }
 
-static void Op84(void)  // ANDA #
+static void Op59(void)                                                 // ROLB
 {
-regs.a &= regs.RdMem(regs.pc++);
-regs.cc &= 0xFD;                            // Cleregs.a oVerflow flag
-(regs.a == 0 ? regs.cc |= 0x04 : regs.cc &= 0xFB);  // Adjust Zero flag
-(regs.a&0x80 ? regs.cc |= 0x08 : regs.cc &= 0xF7);  // Adjust Negative flag
+       OP_ROL_HANDLER(regs.b);
 }
 
-static void Op85(void)  // BITA #
+/*
+Operation               |Mnem.|Immed.|Direct|Index |Extend|Inher.|Operation |CC Reg|
+                        |     |OP ~ #|OP ~ #|OP ~ #|OP ~ #|OP ~ #|          |HINZVC|
+Rotate Right            |ROR  |      |      |66 7 2|76 6 3|      |Memory  *2|  TT6T|
+                        |RORA |      |      |      |      |46 2 1|Accum A *2|  TT6T|
+                        |RORB |      |      |      |      |56 2 1|Accum B *2|  TT6T|
+*/
+
+// ROR opcodes
+
+#define OP_ROR_HANDLER(m) \
+       uint8_t newCarry = m & 0x01; \
+       m = (m >> 1) | (flagC << 7); \
+       SET_ZN(m); \
+       flagC = newCarry; \
+       flagV = flagN ^ flagC
+
+static void Op66(void)                                                 // ROR ZP, X
 {
-tmp = regs.a & regs.RdMem(regs.pc++);
-regs.cc &= 0xFD;                             // Cleregs.a oVerflow flag
-(tmp == 0 ? regs.cc |= 0x04 : regs.cc &= 0xFB);  // Adjust Zero flag
-(tmp&0x80 ? regs.cc |= 0x08 : regs.cc &= 0xF7);  // Adjust Negative flag
+       uint8_t m;
+       READ_ZP_X_WB(m);
+       OP_ROR_HANDLER(m);
+       WRITE_BACK(m);
 }
 
-static void Op86(void)  // LDAA #
+static void Op76(void)                                                 // ROR ABS
 {
-regs.a = regs.RdMem(regs.pc++);
-regs.cc &= 0xFD;                            // CLV
-(regs.a == 0 ? regs.cc |= 0x04 : regs.cc &= 0xFB);  // Adjust Zero flag
-(regs.a&0x80 ? regs.cc |= 0x08 : regs.cc &= 0xF7);  // Adjust Negative flag
+       uint8_t m;
+       READ_ABS_WB(m);
+       OP_ROR_HANDLER(m);
+       WRITE_BACK(m);
 }
 
-static void Op88(void)  // EORA #
+static void Op46(void)                                                 // RORA
 {
-regs.a ^= regs.RdMem(regs.pc++);
-regs.cc &= 0xFD;                            // CLV
-(regs.a == 0 ? regs.cc |= 0x04 : regs.cc &= 0xFB);  // Adjust Zero flag
-(regs.a&0x80 ? regs.cc |= 0x08 : regs.cc &= 0xF7);  // Adjust Negative flag
+       OP_ROR_HANDLER(regs.a);
 }
 
-static void Op89(void)  // ADCA #
+static void Op56(void)                                                 // RORB
 {
-  tmp = regs.RdMem(regs.pc++);
-  addr = (uint16)regs.a + (uint16)tmp + (uint16)(regs.cc&0x01);
-  (addr > 0x00FF ? regs.cc |= 0x01 : regs.cc &= 0xFE);  // Adjust Carry
-//    ((regs.a^tmp^addr)&0x10 ? regs.cc |= 0x20 : regs.cc &= 0xDF);  // Set Half Carry
-  ((regs.a^tmp^addr^(regs.cc<<7))&0x80 ? regs.cc |= 0x02 : regs.cc &= 0xFD); // oVerflow 
-  regs.a = addr & 0xFF;                       // Set accumulator
-  (regs.a == 0 ? regs.cc |= 0x04 : regs.cc &= 0xFB);  // Adjust Zero
-  (regs.a&0x80 ? regs.cc |= 0x08 : regs.cc &= 0xF7);  // Adjust Negative
+       OP_ROR_HANDLER(regs.b);
 }
 
-static void Op8A(void)  // ORAA #
+/*
+Operation               |Mnem.|Immed.|Direct|Index |Extend|Inher.|Operation |CC Reg|
+                        |     |OP ~ #|OP ~ #|OP ~ #|OP ~ #|OP ~ #|          |HINZVC|
+Arithmetic Shift Left   |ASL  |      |      |68 7 2|78 6 3|      |Memory  *3|  TT6T|
+                        |ASLA |      |      |      |      |48 2 1|Accum A *3|  TT6T|
+                        |ASLB |      |      |      |      |58 2 1|Accum B *3|  TT6T|
+*/
+
+// ASL opcodes
+
+#define OP_ASL_HANDLER(m) \
+       uint8_t newCarry = (m & 0x80) >> 7; \
+       m <<= 1; \
+       SET_ZN(m); \
+       flagC = newCarry; \
+       flagV = flagN ^ flagC
+
+static void Op68(void)                                                 // ASL ZP, X
 {
-regs.a |= regs.RdMem(regs.pc++);
-regs.cc &= 0xFD;                            // CLV
-(regs.a == 0 ? regs.cc |= 0x04 : regs.cc &= 0xFB);  // Adjust Zero flag
-(regs.a&0x80 ? regs.cc |= 0x08 : regs.cc &= 0xF7);  // Adjust Negative flag
+       uint8_t m;
+       READ_ZP_X_WB(m);
+       OP_ASL_HANDLER(m);
+       WRITE_BACK(m);
 }
 
-static void Op8B(void)  // ADDA #
-{       
-  tmp = regs.RdMem(regs.pc++);  addr = regs.a + tmp;
-  (addr > 0xFF ? regs.cc |= 0x01 : regs.cc &= 0xFE); // Set Carry flag
-  ((regs.a^tmp^addr^(regs.cc<<7))&0x80 ? regs.cc |= 0x02 : regs.cc &= 0xFD); // oVerflow 
-  regs.a = addr & 0xFF;                       // Set accumulator
-  (regs.a == 0 ? regs.cc |= 0x04 : regs.cc &= 0xFB);  // Set Zero flag
-  (regs.a&0x80 ? regs.cc |= 0x08 : regs.cc &= 0xF7);  // Set Negative flag
+static void Op78(void)                                                 // ASL ABS
+{
+       uint8_t m;
+       READ_ABS_WB(m);
+       OP_ASL_HANDLER(m);
+       WRITE_BACK(m);
 }
 
-static void Op8C(void)  // CPX #
+static void Op48(void)                                                 // ASLA
 {
-       addr = FetchW();
-       uint16 dw = regs.x - addr;
-       (regs.x < addr ? regs.cc |= 0x01 : regs.cc &= 0xFE);  // Adjust Carry flag
-       ((regs.x^addr^dw^(regs.cc<<15))&0x8000 ? regs.cc |= 0x02 : regs.cc &= 0xFD); // oVerfl
-       (dw == 0   ? regs.cc |= 0x04 : regs.cc &= 0xFB);  // Adjust Zero flag
-       (dw&0x8000 ? regs.cc |= 0x08 : regs.cc &= 0xF7);  // Adjust Negative flag
+       OP_ASL_HANDLER(regs.a);
 }
 
-static void Op8D(void)                                                                 // BSR
+static void Op58(void)                                                 // ASLB
 {
-       tmp = regs.RdMem(regs.pc++);
+       OP_ASL_HANDLER(regs.b);
+}
 
-       regs.s -= 2;
-       WrMemW(regs.s, regs.pc);
+/*
+Operation               |Mnem.|Immed.|Direct|Index |Extend|Inher.|Operation |CC Reg|
+                        |     |OP ~ #|OP ~ #|OP ~ #|OP ~ #|OP ~ #|          |HINZVC|
+Arithmetic Shift Right  |ASR  |      |      |67 7 2|77 6 3|      |Memory  *4|  TT6T|
+                        |ASRA |      |      |      |      |47 2 1|Accum A *4|  TT6T|
+                        |ASRB |      |      |      |      |57 2 1|Accum B *4|  TT6T|
+*/
 
-       regs.pc += (signed short int)(signed char)tmp;
-}
+// ASR opcodes
+
+#define OP_ASR_HANDLER(m) \
+       uint8_t newCarry = m & 0x01; \
+       m = (m >> 1) | (m & 0x80); \
+       SET_ZN(m); \
+       flagC = newCarry; \
+       flagV = flagN ^ flagC
 
-static void Op8E(void)  // LDS #
+static void Op67(void)                                                 // ASR ZP, X
 {
-regs.s = FetchW();
-regs.cc &= 0xFD;                              // CLV
-(regs.s == 0   ? regs.cc |= 0x04 : regs.cc &= 0xFB);  // Adjust Zero flag
-(regs.s&0x8000 ? regs.cc |= 0x08 : regs.cc &= 0xF7);  // Adjust Negative flag
+       uint8_t m;
+       READ_ZP_X_WB(m);
+       OP_ASR_HANDLER(m);
+       WRITE_BACK(m);
 }
 
-static void Op90(void)  // SUBA ZP
-{ 
-  tmp = regs.RdMem(regs.RdMem(regs.pc++));  uint8 as = regs.a; 
-  regs.a -= tmp;
-  (regs.a == 0  ? regs.cc |= 0x04 : regs.cc &= 0xFB);  // Adjust Zero flag
-  (regs.a&0x80  ? regs.cc |= 0x08 : regs.cc &= 0xF7);  // Adjust Negative flag
-  (as < tmp ? regs.cc |= 0x01 : regs.cc &= 0xFE);  // Adjust Carry flag
-  ((as^tmp^regs.a^(regs.cc<<7))&0x80 ? regs.cc |= 0x02 : regs.cc &= 0xFD); // oVerflow
+static void Op77(void)                                                 // ASR ABS
+{
+       uint8_t m;
+       READ_ABS_WB(m);
+       OP_ASR_HANDLER(m);
+       WRITE_BACK(m);
 }
 
-static void Op91(void)  // CMPA ZP
+static void Op47(void)                                                 // ASRA
 {
-tmp = regs.RdMem(regs.RdMem(regs.pc++));
-uint8 db = regs.a - tmp;
-(db == 0  ? regs.cc |= 0x04 : regs.cc &= 0xFB);  // Adjust Zero flag
-(db&0x80  ? regs.cc |= 0x08 : regs.cc &= 0xF7);  // Adjust Negative flag
-(regs.a < tmp ? regs.cc |= 0x01 : regs.cc &= 0xFE);  // Adjust Carry flag
-((regs.a^tmp^db^(regs.cc<<7))&0x80 ? regs.cc |= 0x02 : regs.cc &= 0xFD); // oVerflow
+       OP_ASR_HANDLER(regs.a);
 }
 
-static void Op92(void)  // SBCA ZP
+static void Op57(void)                                                 // ASRB
 {
-  tmp = regs.RdMem(regs.RdMem(regs.pc++));  uint8 as = regs.a; 
-  regs.a = regs.a - tmp - (regs.cc&0x01);
-  (as < (tmp+(regs.cc&0x01)) ? regs.cc |= 0x01 : regs.cc &= 0xFE);  // Adjust Carry flag
-  ((as^tmp^regs.a^(regs.cc<<7))&0x80 ? regs.cc |= 0x02 : regs.cc &= 0xFD); // oVerflow
-  (regs.a == 0  ? regs.cc |= 0x04 : regs.cc &= 0xFB);  // Adjust Zero flag
-  (regs.a&0x80  ? regs.cc |= 0x08 : regs.cc &= 0xF7);  // Adjust Negative flag
+       OP_ASR_HANDLER(regs.b);
 }
 
-static void Op94(void)  // ANDA ZP
+/*
+Operation               |Mnem.|Immed.|Direct|Index |Extend|Inher.|Operation |CC Reg|
+                        |     |OP ~ #|OP ~ #|OP ~ #|OP ~ #|OP ~ #|          |HINZVC|
+Logic Shift Right       |LSR  |      |      |64 7 2|74 6 3|      |Memory  *5|  TT6T|
+                        |LSRA |      |      |      |      |44 2 1|Accum A *5|  TT6T|
+                        |LSRB |      |      |      |      |54 2 1|Accum B *5|  TT6T|
+*/
+
+// LSR opcodes
+
+#define OP_LSR_HANDLER(m) \
+       uint8_t newCarry = m & 0x01; \
+       m >>= 1; \
+       SET_ZN(m); \
+       flagC = newCarry; \
+       flagV = flagN ^ flagC
+
+static void Op64(void)                                                 // LSR ZP, X
 {
-  regs.a &= regs.RdMem(regs.RdMem(regs.pc++));
-  regs.cc &= 0xF1;                   // CLV CLZ CLN
-  if (regs.a == 0)  regs.cc |= 0x04;     // Adjust Zero flag
-  if (regs.a&0x80)  regs.cc |= 0x08;     // Adjust Negative flag
+       uint8_t m;
+       READ_ZP_X_WB(m);
+       OP_LSR_HANDLER(m);
+       WRITE_BACK(m);
 }
 
-static void Op95(void)  // BITA ZP
+static void Op74(void)                                                 // LSR ABS
 {
-tmp = regs.a & regs.RdMem(regs.RdMem(regs.pc++));
-regs.cc &= 0xFD;                             // Cleregs.a oVerflow flag
-(tmp == 0 ? regs.cc |= 0x04 : regs.cc &= 0xFB);  // Adjust Zero flag
-(tmp&0x80 ? regs.cc |= 0x08 : regs.cc &= 0xF7);  // Adjust Negative flag
+       uint8_t m;
+       READ_ABS_WB(m);
+       OP_LSR_HANDLER(m);
+       WRITE_BACK(m);
 }
 
-static void Op96(void)  // LDAA ZP
+static void Op44(void)                                                 // LSRA
 {
-  regs.a = regs.RdMem(regs.RdMem(regs.pc++));
-  regs.cc &= 0xF1;                            // CLN CLZ CLV
-  if (regs.a == 0)  regs.cc |= 0x04;              // Set Zero flag
-  if (regs.a&0x80)  regs.cc |= 0x08;              // Set Negative flag
+       OP_LSR_HANDLER(regs.a);
 }
 
-static void Op97(void)  // STAA ZP
+static void Op54(void)                                                 // LSRB
 {
-regs.WrMem(regs.RdMem(regs.pc++), regs.a);
-regs.cc &= 0xFD;                            // CLV
-(regs.a == 0 ? regs.cc |= 0x04 : regs.cc &= 0xFB);  // Adjust Zero flag
-(regs.a&0x80 ? regs.cc |= 0x08 : regs.cc &= 0xF7);  // Adjust Negative flag
+       OP_LSR_HANDLER(regs.b);
 }
 
-static void Op98(void)  // EORA ZP
+/*
+Operation               |Mnem.|Immed.|Direct|Index |Extend|Inher.|Operation |CC Reg|
+                        |     |OP ~ #|OP ~ #|OP ~ #|OP ~ #|OP ~ #|          |HINZVC|
+Store Accumulator       |STAA |      |97 4 2|A7 6 2|B7 5 3|      |M=A       |  TTR |
+                        |STAB |      |D7 4 2|E7 6 2|F7 5 3|      |M=B       |  TTR |
+*/
+
+static void Op97(void)                                                 // STAA ZP
 {
-regs.a ^= regs.RdMem(regs.RdMem(regs.pc++));
-regs.cc &= 0xFD;                            // CLV
-(regs.a == 0 ? regs.cc |= 0x04 : regs.cc &= 0xFB);  // Adjust Zero flag
-(regs.a&0x80 ? regs.cc |= 0x08 : regs.cc &= 0xF7);  // Adjust Negative flag
+       regs.WrMem(EA_ZP, regs.a);
 }
 
-static void Op99(void)  // ADCA ZP
+static void OpA7(void)                                                 // STAA ZP, X
 {
-  tmp = regs.RdMem(regs.RdMem(regs.pc++));
-  addr = (uint16)regs.a + (uint16)tmp + (uint16)(regs.cc&0x01);
-  (addr > 0x00FF ? regs.cc |= 0x01 : regs.cc &= 0xFE);  // Adjust Carry
-  ((regs.a^tmp^addr^(regs.cc<<7))&0x80 ? regs.cc |= 0x02 : regs.cc &= 0xFD); // oVerflow 
-  regs.a = addr & 0xFF;                       // Set accumulator
-  (regs.a == 0 ? regs.cc |= 0x04 : regs.cc &= 0xFB);  // Adjust Zero
-  (regs.a&0x80 ? regs.cc |= 0x08 : regs.cc &= 0xF7);  // Adjust Negative
+       regs.WrMem(EA_ZP_X, regs.a);
 }
 
-static void Op9A(void)  // ORAA ZP
+static void OpB7(void)                                                 // STAA ABS
 {
-regs.a |= regs.RdMem(regs.RdMem(regs.pc++));
-regs.cc &= 0xFD;                            // CLV
-(regs.a == 0 ? regs.cc |= 0x04 : regs.cc &= 0xFB);  // Adjust Zero flag
-(regs.a&0x80 ? regs.cc |= 0x08 : regs.cc &= 0xF7);  // Adjust Negative flag
+       regs.WrMem(EA_ABS, regs.a);
 }
 
-static void Op9B(void)  // ADDA ZP
-{       
-  tmp = regs.RdMem(regs.RdMem(regs.pc++));
-  addr = (uint16)regs.a + (uint16)tmp;
-  (addr > 0x00FF ? regs.cc |= 0x01 : regs.cc &= 0xFE);  // Set Carry flag
-  ((regs.a^tmp^addr^(regs.cc<<7))&0x80 ? regs.cc |= 0x02 : regs.cc &= 0xFD); // oVerflo 
-  regs.a = addr & 0xFF;                       // Set accumulator
-  (regs.a == 0 ? regs.cc |= 0x04 : regs.cc &= 0xFB);  // Set Zero flag
-  (regs.a&0x80 ? regs.cc |= 0x08 : regs.cc &= 0xF7);  // Set Negative flag
+static void OpD7(void)                                                 // STAB ZP
+{
+       regs.WrMem(EA_ZP, regs.b);
 }
 
-static void Op9C(void)  // CPX ZP
+static void OpE7(void)                                                 // STAB ZP, X
 {
-addr = regs.RdMem(regs.pc++);
-uint16 adr2 = (regs.RdMem(addr)<<8) | regs.RdMem(addr+1);
-uint16 dw = regs.x - adr2;
-(dw == 0   ? regs.cc |= 0x04 : regs.cc &= 0xFB);  // Adjust Zero flag
-(dw&0x8000 ? regs.cc |= 0x08 : regs.cc &= 0xF7);  // Adjust Negative flag
-(regs.x < adr2 ? regs.cc |= 0x01 : regs.cc &= 0xFE);  // Adjust Carry flag
-((regs.x^adr2^dw^(regs.cc<<15))&0x8000 ? regs.cc |= 0x02 : regs.cc &= 0xFD); // oVerfl
+       regs.WrMem(EA_ZP_X, regs.b);
 }
 
-static void Op9E(void)                                                                 // LDS ZP
+static void OpF7(void)                                                 // STAB ABS
 {
-       regs.s = RdMemW(regs.RdMem(regs.pc++));
-
-       regs.cc &= 0xFD;                              // CLV
-       (regs.s == 0   ? regs.cc |= 0x04 : regs.cc &= 0xFB);  // Adjust Zero flag
-       (regs.s&0x8000 ? regs.cc |= 0x08 : regs.cc &= 0xF7);  // Adjust Negative flag
+       regs.WrMem(EA_ABS, regs.b);
 }
 
-static void Op9F(void)                                                                 // STS ZP
-{
-       WrMemW(regs.RdMem(regs.pc++), regs.s);
+/*
+Operation               |Mnem.|Immed.|Direct|Index |Extend|Inher.|Operation |CC Reg|
+                        |     |OP ~ #|OP ~ #|OP ~ #|OP ~ #|OP ~ #|          |HINZVC|
+Subtract                |SUBA |80 2 2|90 3 2|A0 5 2|B0 4 3|      |A=A-M     |  TTTT|
+                        |SUBB |C0 2 2|D0 3 2|E0 5 2|F0 4 3|      |B=B-M     |  TTTT|
+Subtract Accumulators   |SBA  |      |      |      |      |10 2 1|A=A-B     |  TTTT|
+*/
 
-       regs.cc &= 0xFD;                              // CLV
-       (regs.s == 0   ? regs.cc |= 0x04 : regs.cc &= 0xFB);  // Adjust Zero flag
-       (regs.s&0x8000 ? regs.cc |= 0x08 : regs.cc &= 0xF7);  // Adjust Negative flag
-}
+// SUB opcodes
 
-static void OpA0(void)  // SUBA IDX
-{ 
-tmp = regs.RdMem(DecodeIDX(regs.RdMem(regs.pc++)));  uint8 as = regs.a; 
-regs.a -= tmp;
-(regs.a == 0  ? regs.cc |= 0x04 : regs.cc &= 0xFB);  // Adjust Zero flag
-(regs.a&0x80  ? regs.cc |= 0x08 : regs.cc &= 0xF7);  // Adjust Negative flag
-(as < tmp ? regs.cc |= 0x01 : regs.cc &= 0xFE);  // Adjust Carry flag
-((as^tmp^regs.a^(regs.cc<<7))&0x80 ? regs.cc |= 0x02 : regs.cc &= 0xFD); // oVerflow
-}
+#define OP_SUB_HANDLER(m, acc) \
+       uint16_t sum = (uint16_t)acc - (m); \
+       flagC = sum >> 15; \
+       SET_V(m, acc, sum); \
+       acc = (uint8_t)sum; \
+       SET_ZN(acc)
 
-static void OpA1(void)  // CMPA IDX
+static void Op80(void)                                                 // SUBA #
 {
-tmp = regs.RdMem(DecodeIDX(regs.RdMem(regs.pc++)));
-uint8 db = regs.a - tmp;
-(db == 0  ? regs.cc |= 0x04 : regs.cc &= 0xFB);  // Adjust Zero flag
-(db&0x80  ? regs.cc |= 0x08 : regs.cc &= 0xF7);  // Adjust Negative flag
-(regs.a < tmp ? regs.cc |= 0x01 : regs.cc &= 0xFE);  // Adjust Carry flag
-((regs.a^tmp^db^(regs.cc<<7))&0x80 ? regs.cc |= 0x02 : regs.cc &= 0xFD); // oVerflow
+       uint16_t m = READ_IMM;
+       OP_SUB_HANDLER(m, regs.a);
 }
 
-static void OpA2(void)  // SBCA IDX
+static void Op90(void)                                                 // SUBA ZP
 {
-  tmp = regs.RdMem(DecodeIDX(regs.RdMem(regs.pc++)));  uint8 as = regs.a; 
-  regs.a = regs.a - tmp - (regs.cc&0x01);
-  (as < (tmp+(regs.cc&0x01)) ? regs.cc |= 0x01 : regs.cc &= 0xFE);  // Adjust Carry flag
-  ((as^tmp^regs.a^(regs.cc<<7))&0x80 ? regs.cc |= 0x02 : regs.cc &= 0xFD); // oVerflow
-  (regs.a == 0  ? regs.cc |= 0x04 : regs.cc &= 0xFB);  // Adjust Zero flag
-  (regs.a&0x80  ? regs.cc |= 0x08 : regs.cc &= 0xF7);  // Adjust Negative flag
+       uint16_t m = READ_ZP;
+       OP_SUB_HANDLER(m, regs.a);
 }
 
-static void OpA4(void)  // ANDA IDX
+static void OpA0(void)                                                 // SUBA ZP, X
 {
-regs.a &= regs.RdMem(DecodeIDX(regs.RdMem(regs.pc++)));
-regs.cc &= 0xFD;                            // Cleregs.a oVerflow flag
-(regs.a == 0 ? regs.cc |= 0x04 : regs.cc &= 0xFB);  // Adjust Zero flag
-(regs.a&0x80 ? regs.cc |= 0x08 : regs.cc &= 0xF7);  // Adjust Negative flag
+       uint16_t m = READ_ZP_X;
+       OP_SUB_HANDLER(m, regs.a);
 }
 
-static void OpA5(void)  // BITA IDX
+static void OpB0(void)                                                 // SUBA ABS
 {
-tmp = regs.a & regs.RdMem(DecodeIDX(regs.RdMem(regs.pc++)));
-regs.cc &= 0xFD;                             // Cleregs.a oVerflow flag
-(tmp == 0 ? regs.cc |= 0x04 : regs.cc &= 0xFB);  // Adjust Zero flag
-(tmp&0x80 ? regs.cc |= 0x08 : regs.cc &= 0xF7);  // Adjust Negative flag
+       uint16_t m = READ_ABS;
+       OP_SUB_HANDLER(m, regs.a);
 }
 
-static void OpA6(void)  // LDAA IDX
+static void OpC0(void)                                                 // SUBB #
 {
-  regs.a = regs.RdMem(DecodeIDX(regs.RdMem(regs.pc++)));
-  regs.cc &= 0xF1;                        // CLV CLZ CLN
-  if (regs.a == 0)  regs.cc |= 0x04;          // Set Zero flag
-  if (regs.a&0x80)  regs.cc |= 0x08;          // Set Negative flag
+       uint16_t m = READ_IMM;
+       OP_SUB_HANDLER(m, regs.b);
 }
 
-static void OpA7(void)  // STAA IDX
+static void OpD0(void)                                                 // SUBB ZP
 {
-  regs.WrMem(DecodeIDX(regs.RdMem(regs.pc++)), regs.a);
-  regs.cc &= 0xF1;                        // CLV CLZ CLN
-  if (regs.a == 0)  regs.cc |= 0x04;          // Set Zero flag
-  if (regs.a&0x80)  regs.cc |= 0x08;          // Set Negative flag
+       uint16_t m = READ_ZP;
+       OP_SUB_HANDLER(m, regs.b);
 }
 
-static void OpA8(void)  // EORA IDX
+static void OpE0(void)                                                 // SUBB ZP, X
 {
-regs.a ^= regs.RdMem(DecodeIDX(regs.RdMem(regs.pc++)));
-regs.cc &= 0xFD;                            // CLV
-(regs.a == 0 ? regs.cc |= 0x04 : regs.cc &= 0xFB);  // Adjust Zero flag
-(regs.a&0x80 ? regs.cc |= 0x08 : regs.cc &= 0xF7);  // Adjust Negative flag
+       uint16_t m = READ_ZP_X;
+       OP_SUB_HANDLER(m, regs.b);
 }
 
-static void OpA9(void)  // ADCA IDX
+static void OpF0(void)                                                 // SUBB ABS
 {
-  tmp = regs.RdMem(DecodeIDX(regs.RdMem(regs.pc++)));
-  addr = (uint16)regs.a + (uint16)tmp + (uint16)(regs.cc&0x01);
-  (addr > 0x00FF ? regs.cc |= 0x01 : regs.cc &= 0xFE);  // Set Carry flag
-  ((regs.a^tmp^addr^(regs.cc<<7))&0x80 ? regs.cc |= 0x02 : regs.cc &= 0xFD); // oVerflo 
-  regs.a = addr & 0xFF;                       // Set accumulator
-  (regs.a == 0 ? regs.cc |= 0x04 : regs.cc &= 0xFB);  // Set Zero flag
-  (regs.a&0x80 ? regs.cc |= 0x08 : regs.cc &= 0xF7);  // Set Negative flag
+       uint16_t m = READ_ABS;
+       OP_SUB_HANDLER(m, regs.b);
 }
 
-static void OpAA(void)  // ORAA IDX
+static void Op10(void)                                                 // SBA
 {
-  regs.a |= regs.RdMem(DecodeIDX(regs.RdMem(regs.pc++)));
-  regs.cc &= 0xFD;                            // CLV
-  (regs.a == 0 ? regs.cc |= 0x04 : regs.cc &= 0xFB);  // Adjust Zero flag
-  (regs.a&0x80 ? regs.cc |= 0x08 : regs.cc &= 0xF7);  // Adjust Negative flag
+       OP_SUB_HANDLER(regs.b, regs.a);
 }
 
-static void OpAB(void)  // ADDA IDX
-{       
-  tmp = regs.RdMem(DecodeIDX(regs.RdMem(regs.pc++)));
-  addr = (uint16)regs.a + (uint16)tmp;
-  (addr > 0x00FF ? regs.cc |= 0x01 : regs.cc &= 0xFE);  // Set Carry flag
-  ((regs.a^tmp^addr^(regs.cc<<7))&0x80 ? regs.cc |= 0x02 : regs.cc &= 0xFD); // oVerflo 
-  regs.a = addr & 0xFF;                       // Set accumulator
-  (regs.a == 0 ? regs.cc |= 0x04 : regs.cc &= 0xFB);  // Set Zero flag
-  (regs.a&0x80 ? regs.cc |= 0x08 : regs.cc &= 0xF7);  // Set Negative flag
-}
+/*
+Operation               |Mnem.|Immed.|Direct|Index |Extend|Inher.|Operation |CC Reg|
+                        |     |OP ~ #|OP ~ #|OP ~ #|OP ~ #|OP ~ #|          |HINZVC|
+Subtract with Carry     |SBCA |82 2 2|92 3 2|A2 5 2|B2 4 3|      |A=A-M-C   |  TTTT|
+                        |SBCB |C2 2 2|D2 3 2|E2 5 2|F2 4 3|      |B=B-M-C   |  TTTT|
+*/
+
+// SBC opcodes
 
-static void OpAC(void)  // CPX IDX
+#define OP_SBC_HANDLER(m, acc) \
+       uint16_t sum = (uint16_t)acc - (m) - (uint16_t)flagC; \
+       flagC = sum >> 15; \
+       SET_V(m, acc, sum); \
+       acc = (uint8_t)sum; \
+       SET_ZN(acc)
+
+static void Op82(void)                                                 // SBCA #
 {
-  addr = DecodeIDX(regs.RdMem(regs.pc++));
-  uint16 addr2 = (regs.RdMem(addr)<<8) | regs.RdMem(addr+1);
-  uint16 dw = regs.x - addr2;
-  (dw == 0    ? regs.cc |= 0x04 : regs.cc &= 0xFB);  // Adjust Zero flag
-  (dw&0x8000  ? regs.cc |= 0x08 : regs.cc &= 0xF7);  // Adjust Negative flag
-  (regs.x < addr2 ? regs.cc |= 0x01 : regs.cc &= 0xFE);  // Adjust Carry flag
-  ((regs.x^addr2^dw^(regs.cc<<15))&0x8000 ? regs.cc |= 0x02 : regs.cc &= 0xFD); // oVerflow
+       uint16_t m = READ_IMM;
+       OP_SBC_HANDLER(m, regs.a);
 }
 
-static void OpAD(void)                                                                 // JSR IDX
+static void Op92(void)                                                 // SBCA ZP
 {
-       addr = DecodeIDX(regs.RdMem(regs.pc++));
-
-       regs.s -= 2;
-       WrMemW(regs.s, regs.pc);
-
-       regs.pc = addr;                                                                         // JSR directly to IDX ptr
+       uint16_t m = READ_ZP;
+       OP_SBC_HANDLER(m, regs.a);
 }
 
-static void OpAE(void)                                                                 // LDS IDX
+static void OpA2(void)                                                 // SBCA ZP, X
 {
-       regs.s = RdMemW(DecodeIDX(regs.RdMem(regs.pc++)));
-
-       regs.cc &= ~FLAG_V;
-       (regs.s == 0   ? regs.cc |= 0x04 : regs.cc &= 0xFB);  // Adjust Zero flag
-       (regs.s&0x8000 ? regs.cc |= 0x08 : regs.cc &= 0xF7);  // Adjust Negative flag
+       uint16_t m = READ_ZP_X;
+       OP_SBC_HANDLER(m, regs.a);
 }
 
-static void OpAF(void)                                                                 // STS IDX
+static void OpB2(void)                                                 // SBCA ABS
 {
-       WrMemW(DecodeIDX(regs.RdMem(regs.pc++)), regs.s);
+       uint16_t m = READ_ABS;
+       OP_SBC_HANDLER(m, regs.a);
+}
 
-       regs.cc &= ~(FLAG_N | FLAG_Z | FLAG_V);                         // Clear NZV
-       if (regs.s & 0x8000)  regs.cc |= FLAG_N;                        // Set Negative flag
-       if (regs.s == 0)      regs.cc |= FLAG_Z;                        // Set Zero flag
+static void OpC2(void)                                                 // SBCB #
+{
+       uint16_t m = READ_IMM;
+       OP_SBC_HANDLER(m, regs.b);
 }
 
-static void OpB0(void)  // SUBA ABS
-{ 
-tmp = regs.RdMem(FetchW());  uint8 as = regs.a; 
-regs.a -= tmp;
-(regs.a == 0  ? regs.cc |= 0x04 : regs.cc &= 0xFB);  // Adjust Zero flag
-(regs.a&0x80  ? regs.cc |= 0x08 : regs.cc &= 0xF7);  // Adjust Negative flag
-(as < tmp ? regs.cc |= 0x01 : regs.cc &= 0xFE);  // Adjust Carry flag
-((as^tmp^regs.a^(regs.cc<<7))&0x80 ? regs.cc |= 0x02 : regs.cc &= 0xFD); // oVerflow
+static void OpD2(void)                                                 // SBCB ZP
+{
+       uint16_t m = READ_ZP;
+       OP_SBC_HANDLER(m, regs.b);
 }
 
-static void OpB1(void)  // CMPA ABS
+static void OpE2(void)                                                 // SBCB ZP, X
 {
-tmp = regs.RdMem(FetchW());
-uint8 db = regs.a - tmp;
-(db == 0  ? regs.cc |= 0x04 : regs.cc &= 0xFB);  // Adjust Zero flag
-(db&0x80  ? regs.cc |= 0x08 : regs.cc &= 0xF7);  // Adjust Negative flag
-(regs.a < tmp ? regs.cc |= 0x01 : regs.cc &= 0xFE);  // Adjust Carry flag
-((regs.a^tmp^db^(regs.cc<<7))&0x80 ? regs.cc |= 0x02 : regs.cc &= 0xFD); // oVerflow
+       uint16_t m = READ_ZP_X;
+       OP_SBC_HANDLER(m, regs.b);
 }
 
-static void OpB2(void)  // SBCA ABS
+static void OpF2(void)                                                 // SBCB ABS
 {
-  tmp = regs.RdMem(FetchW());  uint8 as = regs.a; 
-  regs.a = regs.a - tmp - (regs.cc&0x01);
-  (as < (tmp+(regs.cc&0x01)) ? regs.cc |= 0x01 : regs.cc &= 0xFE);  // Adjust Carry flag
-  ((as^tmp^regs.a^(regs.cc<<7))&0x80 ? regs.cc |= 0x02 : regs.cc &= 0xFD); // oVerflow
-  (regs.a == 0  ? regs.cc |= 0x04 : regs.cc &= 0xFB);  // Adjust Zero flag
-  (regs.a&0x80  ? regs.cc |= 0x08 : regs.cc &= 0xF7);  // Adjust Negative flag
+       uint16_t m = READ_ABS;
+       OP_SBC_HANDLER(m, regs.b);
 }
 
-static void OpB4(void)  // ANDA ABS
+/*
+Operation               |Mnem.|Immed.|Direct|Index |Extend|Inher.|Operation |CC Reg|
+                        |     |OP ~ #|OP ~ #|OP ~ #|OP ~ #|OP ~ #|          |HINZVC|
+Transfer Accumulators   |TAB  |      |      |      |      |16 2 1|B=A       |  TTR |
+                        |TBA  |      |      |      |      |17 2 1|A=B       |  TTR |
+*/
+
+static void Op16(void)                                                 // TAB
 {
-  regs.a &= regs.RdMem(FetchW());
-  regs.cc &= 0xFD;                            // Cleregs.a oVerflow flag
-  (regs.a == 0 ? regs.cc |= 0x04 : regs.cc &= 0xFB);  // Adjust Zero flag
-  (regs.a&0x80 ? regs.cc |= 0x08 : regs.cc &= 0xF7);  // Adjust Negative flag
+       regs.b = regs.a;
+       SET_ZN(regs.b);
+       CLR_V;
 }
 
-static void OpB5(void)  // BITA ABS
+static void Op17(void)                                                 // TBA
 {
-  tmp = regs.a & regs.RdMem(FetchW());
-  regs.cc &= 0xFD;                             // Cleregs.a oVerflow flag
-  (tmp == 0 ? regs.cc |= 0x04 : regs.cc &= 0xFB);  // Adjust Zero flag
-  (tmp&0x80 ? regs.cc |= 0x08 : regs.cc &= 0xF7);  // Adjust Negative flag
+       regs.a = regs.b;
+       SET_ZN(regs.a);
+       CLR_V;
 }
 
-static void OpB6(void)  // LDAA ABS
+/*
+Operation               |Mnem.|Immed.|Direct|Index |Extend|Inher.|Operation |CC Reg|
+                        |     |OP ~ #|OP ~ #|OP ~ #|OP ~ #|OP ~ #|          |HINZVC|
+Test, Zero/Minus        |TST  |      |      |6D 7 2|7D 6 3|      |M-00      |  TTRR|
+                        |TSTA |      |      |      |      |4D 2 1|A-00      |  TTRR|
+                        |TSTB |      |      |      |      |5D 2 1|B-00      |  TTRR|
+*/
+
+// TST opcodes
+
+#define OP_TST_HANDLER(m) \
+       SET_ZN(m); \
+       CLR_VC
+
+static void Op6D(void)                                                 // TST ZP, X
 {
-  regs.a = regs.RdMem(FetchW());
-  regs.cc &= 0xFD;                            // CLV
-  (regs.a == 0 ? regs.cc |= 0x04 : regs.cc &= 0xFB);  // Adjust Zero flag
-  (regs.a&0x80 ? regs.cc |= 0x08 : regs.cc &= 0xF7);  // Adjust Negative flag
+       uint8_t m;
+       READ_ZP_X_WB(m);
+       OP_TST_HANDLER(m);
+       WRITE_BACK(m);
 }
 
-static void OpB7(void)  // STAA ABS
+static void Op7D(void)                                                 // TST ABS
 {
-  regs.WrMem(FetchW(), regs.a);
-  regs.cc &= 0xFD;                            // CLV
-  (regs.a == 0 ? regs.cc |= 0x04 : regs.cc &= 0xFB);  // Adjust Zero flag
-  (regs.a&0x80 ? regs.cc |= 0x08 : regs.cc &= 0xF7);  // Adjust Negative flag
+       uint8_t m;
+       READ_ABS_WB(m);
+       OP_TST_HANDLER(m);
+       WRITE_BACK(m);
 }
 
-static void OpB8(void)  // EORA ABS
+static void Op4D(void)                                                 // TSTA
 {
-  regs.a ^= regs.RdMem(FetchW());
-  regs.cc &= 0xFD;                            // CLV
-  (regs.a == 0 ? regs.cc |= 0x04 : regs.cc &= 0xFB);  // Adjust Zero flag
-  (regs.a&0x80 ? regs.cc |= 0x08 : regs.cc &= 0xF7);  // Adjust Negative flag
+       OP_TST_HANDLER(regs.a);
 }
 
-static void OpB9(void)  // ADCA ABS
+static void Op5D(void)                                                 // TSTB
 {
-  tmp = regs.RdMem(FetchW());
-  addr = (uint16)regs.a + (uint16)tmp + (uint16)(regs.cc&0x01);
-  (addr > 0x00FF ? regs.cc |= 0x01 : regs.cc &= 0xFE);  // Set Carry flag
-  ((regs.a^tmp^addr^(regs.cc<<7))&0x80 ? regs.cc |= 0x02 : regs.cc &= 0xFD); // oVerflow 
-  regs.a = addr;                              // Set accumulator
-  (regs.a == 0 ? regs.cc |= 0x04 : regs.cc &= 0xFB);  // Set Zero flag
-  (regs.a&0x80 ? regs.cc |= 0x08 : regs.cc &= 0xF7);  // Set Negative flag
+       OP_TST_HANDLER(regs.b);
 }
 
-static void OpBA(void)  // ORAA ABS
+/*
+Operation               |Mnem.|Immed.|Direct|Index |Extend|Inher.|Operation |CC Reg|
+                        |     |OP ~ #|OP ~ #|OP ~ #|OP ~ #|OP ~ #|          |HINZVC|
+Compare Index Register  |CPX  |8C 3 3|9C 4 2|AC 6 2|BC 5 3|      |Formula 1 |  7T8 |
+*/
+
+// CPX opcodes
+
+/*
+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.
+*/
+
+#define OP_CPX_HANDLER(m) \
+       uint32_t result = regs.x - (m); \
+       SET_ZNVC_CMP16(m, regs.x, result)
+
+static void Op8C(void)                                                 // CPX #
 {
-  regs.a |= regs.RdMem(FetchW());
-  regs.cc &= 0xFD;                            // CLV
-  (regs.a == 0 ? regs.cc |= 0x04 : regs.cc &= 0xFB);  // Adjust Zero flag
-  (regs.a&0x80 ? regs.cc |= 0x08 : regs.cc &= 0xF7);  // Adjust Negative flag
+       uint16_t m = READ_IMM16;
+       OP_CPX_HANDLER(m);
 }
 
-static void OpBB(void)  // ADDA ABS
-{       
-  tmp = regs.RdMem(FetchW());
-  addr = (uint16)regs.a + (uint16)tmp;
-  (addr > 0x00FF ? regs.cc |= 0x01 : regs.cc &= 0xFE);  // Set Carry flag
-  ((regs.a^tmp^addr^(regs.cc<<7))&0x80 ? regs.cc |= 0x02 : regs.cc &= 0xFD); // oVerflo
-  regs.a = addr & 0xFF;                       // Set accumulator
-  (regs.a == 0 ? regs.cc |= 0x04 : regs.cc &= 0xFB);  // Set Zero flag
-  (regs.a&0x80 ? regs.cc |= 0x08 : regs.cc &= 0xF7);  // Set Negative flag
+static void Op9C(void)                                                 // CPX ZP
+{
+       uint16_t m = READ_ZP16;
+       OP_CPX_HANDLER(m);
 }
 
-static void OpBC(void)  // CPX ABS
+static void OpAC(void)                                                 // CPX ZP, X
 {
-  addr = FetchW();  uint16 addr2 = (regs.RdMem(addr)<<8) | regs.RdMem(addr+1);
-  uint16 dw = regs.x - addr2;
-  (dw == 0   ? regs.cc |= 0x04 : regs.cc &= 0xFB);  // Adjust Zero flag
-  (dw&0x8000 ? regs.cc |= 0x08 : regs.cc &= 0xF7);  // Adjust Negative flag
-  (regs.x < addr2 ? regs.cc |= 0x01 : regs.cc &= 0xFE);  // Adjust Carry flag
-  ((regs.x^addr2^dw^(regs.cc<<15))&0x8000 ? regs.cc |= 0x02 : regs.cc &= 0xFD); // oVerflow
+       uint16_t m = READ_ZP_X16;
+       OP_CPX_HANDLER(m);
 }
 
-static void OpBD(void)                                                                 // JSR ABS
+static void OpBC(void)                                                 // CPX ABS
 {
-       addr = FetchW();
+       uint16_t m = READ_ABS16;
+       OP_CPX_HANDLER(m);
+}
 
-       regs.s -= 2;
-       WrMemW(regs.s, regs.pc);
+/*
+Operation               |Mnem.|Immed.|Direct|Index |Extend|Inher.|Operation |CC Reg|
+                        |     |OP ~ #|OP ~ #|OP ~ #|OP ~ #|OP ~ #|          |HINZVC|
+Decrement Index Register|DEX  |      |      |      |      |09 4 1|X=X-1     |   T  |
+Dec Stack Pointer       |DES  |      |      |      |      |34 4 1|SP=SP-1   |      |
+Inc Index Regster       |INX  |      |      |      |      |08 4 1|X=X+1     |   T  |
+Inc Stack Pointer       |INS  |      |      |      |      |31 4 1|SP=SP+1   |      |
+*/
 
-       regs.pc = addr;                                                                         // Go to absolute address (Not indir)
+static void Op09(void)                                                 // DEX
+{
+       regs.x--;
+       SET_Z(regs.x);
 }
 
-static void OpBE(void)  // LDS ABS
+static void Op34(void)                                                 // DES
 {
-  addr = FetchW();
-  regs.s = (regs.RdMem(addr) << 8) | regs.RdMem(addr+1);
-  regs.cc &= 0xFD;                              // CLV
-  (regs.s == 0   ? regs.cc |= 0x04 : regs.cc &= 0xFB);  // Adjust Zero flag
-  (regs.s&0x8000 ? regs.cc |= 0x08 : regs.cc &= 0xF7);  // Adjust Negative flag
+       regs.s--;
 }
 
-static void OpBF(void)  // STS ABS
+static void Op08(void)                                                 // INX
 {
-addr = FetchW();
-regs.WrMem(addr, regs.s>>8);  regs.WrMem(addr+1, regs.s&0xFF);
-regs.cc &= 0xFD;                              // CLV
-(regs.s == 0   ? regs.cc |= 0x04 : regs.cc &= 0xFB);  // Adjust Zero flag
-(regs.s&0x8000 ? regs.cc |= 0x08 : regs.cc &= 0xF7);  // Adjust Negative flag
+       regs.x++;
+       SET_Z(regs.x);
 }
 
-static void OpC0(void)  // SUBB #
-{ 
-tmp = regs.RdMem(regs.pc++);  uint8 bs = regs.b; 
-regs.b -= tmp;
-(regs.b == 0  ? regs.cc |= 0x04 : regs.cc &= 0xFB);  // Adjust Zero flag
-(regs.b&0x80  ? regs.cc |= 0x08 : regs.cc &= 0xF7);  // Adjust Negative flag
-(bs < tmp ? regs.cc |= 0x01 : regs.cc &= 0xFE);  // Adjust Carry flag
-((bs^tmp^regs.b^(regs.cc<<7))&0x80 ? regs.cc |= 0x02 : regs.cc &= 0xFD); // oVerflow
+static void Op31(void)                                                 // INS
+{
+       regs.s++;
 }
 
-static void OpC1(void)  // CMPB #
+/*
+Operation               |Mnem.|Immed.|Direct|Index |Extend|Inher.|Operation |CC Reg|
+                        |     |OP ~ #|OP ~ #|OP ~ #|OP ~ #|OP ~ #|          |HINZVC|
+Load Index Register     |LDX  |CE 3 3|DE 4 2|EE 6 2|FE 5 3|      |Formula 2 |  9TR |
+Load Stack Pointer      |LDS  |8E 3 3|9E 4 2|AE 6 2|BE 5 3|      |Formula 3 |  9TR |
+*/
+
+// LD* opcode handler
+
+#define OP_LD_HANDLER(acc) \
+       SET_N16(acc); \
+       SET_Z(acc); \
+       CLR_V
+
+static void OpCE(void)                                                 // LDX #
 {
-tmp = regs.RdMem(regs.pc++);
-uint8 db = regs.b - tmp;
-(regs.b < tmp ? regs.cc |= 0x01 : regs.cc &= 0xFE);  // Adjust Carry flag
-((regs.b^tmp^db^(regs.cc<<7))&0x80 ? regs.cc |= 0x02 : regs.cc &= 0xFD); // oVerflow
-(db == 0  ? regs.cc |= 0x04 : regs.cc &= 0xFB);  // Adjust Zero flag
-(db&0x80  ? regs.cc |= 0x08 : regs.cc &= 0xF7);  // Adjust Negative flag
+       regs.x = READ_IMM16;
+       OP_LD_HANDLER(regs.x);
 }
 
-static void OpC2(void)  // SBCB #
+static void OpDE(void)                                                 // LDX ZP
 {
-  tmp = regs.RdMem(regs.pc++);  uint8 bs = regs.b; 
-  regs.b = regs.b - tmp - (regs.cc&0x01);
-  (bs < (tmp+(regs.cc&0x01)) ? regs.cc |= 0x01 : regs.cc &= 0xFE);  // Adjust Carry flag
-  ((bs^tmp^regs.b^(regs.cc<<7))&0x80 ? regs.cc |= 0x02 : regs.cc &= 0xFD); // oVerflow
-  (regs.b == 0  ? regs.cc |= 0x04 : regs.cc &= 0xFB);  // Adjust Zero flag
-  (regs.b&0x80  ? regs.cc |= 0x08 : regs.cc &= 0xF7);  // Adjust Negative flag
+       regs.x = READ_ZP16;
+       OP_LD_HANDLER(regs.x);
 }
 
-static void OpC4(void)  // ANDB #
+static void OpEE(void)                                                 // LDX ZP, X
 {
-regs.b &= regs.RdMem(regs.pc++);
-regs.cc &= 0xFD;                            // Cleregs.a oVerflow flag
-(regs.b == 0 ? regs.cc |= 0x04 : regs.cc &= 0xFB);  // Adjust Zero flag
-(regs.b&0x80 ? regs.cc |= 0x08 : regs.cc &= 0xF7);  // Adjust Negative flag
+       regs.x = READ_ZP_X16;
+       OP_LD_HANDLER(regs.x);
 }
 
-static void OpC5(void)  // BITB #
+static void OpFE(void)                                                 // LDX ABS
 {
-  tmp = regs.b & regs.RdMem(regs.pc++);
-  regs.cc &= 0xF1;                             // CLV CLZ CLN
-  if (tmp == 0)  regs.cc |= 0x04;              // Set Zero flag
-  if (tmp&0x80)  regs.cc |= 0x08;              // Set Negative flag
+       regs.x = READ_ABS16;
+       OP_LD_HANDLER(regs.x);
 }
 
-static void OpC6(void)  // LDAB #
+static void Op8E(void)                                                 // LDS #
 {
-  regs.b = regs.RdMem(regs.pc++);
-  regs.cc &= 0xF1;                             // CLV CLZ CLN
-  if (regs.b == 0)  regs.cc |= 0x04;               // Set Zero flag
-  if (regs.b&0x80)  regs.cc |= 0x08;               // Set Negative flag
+       regs.s = READ_IMM16;
+       OP_LD_HANDLER(regs.s);
 }
 
-static void OpC8(void)  // EORB #
+static void Op9E(void)                                                 // LDS ZP
 {
-regs.b ^= regs.RdMem(regs.pc++);
-regs.cc &= 0xFD;                            // CLV
-(regs.b == 0 ? regs.cc |= 0x04 : regs.cc &= 0xFB);  // Adjust Zero flag
-(regs.b&0x80 ? regs.cc |= 0x08 : regs.cc &= 0xF7);  // Adjust Negative flag
+       regs.s = READ_ZP16;
+       OP_LD_HANDLER(regs.s);
 }
 
-static void OpC9(void)  // ADCB #
+static void OpAE(void)                                                 // LDS ZP, X
 {
-  tmp = regs.RdMem(regs.pc++);
-  addr = (uint16)regs.b + (uint16)tmp + (uint16)(regs.cc&0x01);
-  (addr > 0x00FF ? regs.cc |= 0x01 : regs.cc &= 0xFE);  // Set Carry flag
-  ((regs.b^tmp^addr^(regs.cc<<7))&0x80 ? regs.cc |= 0x02 : regs.cc &= 0xFD); // oVerflo 
-  regs.b = addr & 0xFF;                       // Set accumulator
-  (regs.b == 0 ? regs.cc |= 0x04 : regs.cc &= 0xFB);  // Set Zero flag
-  (regs.b&0x80 ? regs.cc |= 0x08 : regs.cc &= 0xF7);  // Set Negative flag
+       regs.s = READ_ZP_X16;
+       OP_LD_HANDLER(regs.s);
 }
 
-static void OpCA(void)  // ORAB #
+static void OpBE(void)                                                 // LDS ABS
 {
-regs.b |= regs.RdMem(regs.pc++);
-regs.cc &= 0xFD;                            // CLV
-(regs.b == 0 ? regs.cc |= 0x04 : regs.cc &= 0xFB);  // Adjust Zero flag
-(regs.b&0x80 ? regs.cc |= 0x08 : regs.cc &= 0xF7);  // Adjust Negative flag
+       regs.s = READ_ABS16;
+       OP_LD_HANDLER(regs.s);
 }
 
-static void OpCB(void)  // ADDB #
-{       
-  tmp = regs.RdMem(regs.pc++);  addr = regs.b + tmp;
-  (addr > 0xFF ? regs.cc |= 0x01 : regs.cc &= 0xFE);  // Set Carry flag
-  ((regs.b^tmp^addr^(regs.cc<<7))&0x80 ? regs.cc |= 0x02 : regs.cc &= 0xFD); // oVerflo 
-  regs.b = addr & 0xFF;                       // Set accumulator
-  (regs.b == 0 ? regs.cc |= 0x04 : regs.cc &= 0xFB);  // Set Zero flag
-  (regs.b&0x80 ? regs.cc |= 0x08 : regs.cc &= 0xF7);  // Set Negative flag
-}
+/*
+Operation               |Mnem.|Immed.|Direct|Index |Extend|Inher.|Operation |CC Reg|
+                        |     |OP ~ #|OP ~ #|OP ~ #|OP ~ #|OP ~ #|          |HINZVC|
+Store Index Register    |STX  |      |DF 5 2|EF 7 2|FF 6 3|      |Formula 4 |  9TR |
+Store Stack Pointer     |STS  |      |9F 5 2|AF 7 2|BF 6 3|      |Formula 5 |  9TR |
+*/
+
+// ST* opcode handler
+
+#define OP_ST_HANDLER(m, acc) \
+       regs.WrMem(m + 0, acc >> 8); \
+       regs.WrMem(m + 1, acc & 0xFF); \
+       SET_N16(acc); \
+       SET_Z(acc); \
+       CLR_V
 
-static void OpCE(void)  // LDX #
+static void OpDF(void)                                                 // STX ZP
 {
-  regs.x = FetchW();
-  regs.cc &= 0xFD;                              // CLV
-  (regs.x == 0   ? regs.cc |= 0x04 : regs.cc &= 0xFB);  // Adjust Zero flag
-  (regs.x&0x8000 ? regs.cc |= 0x08 : regs.cc &= 0xF7);  // Adjust Negative flag
+       uint16_t m = EA_ZP;
+       OP_ST_HANDLER(m, regs.x);
 }
 
-static void OpD0(void)  // SUBB ZP
-{ 
-  tmp = regs.RdMem(regs.RdMem(regs.pc++));  uint8 bs = regs.b; 
-  regs.b -= tmp;
-  (regs.b == 0  ? regs.cc |= 0x04 : regs.cc &= 0xFB);  // Adjust Zero flag
-  (regs.b&0x80  ? regs.cc |= 0x08 : regs.cc &= 0xF7);  // Adjust Negative flag
-  (bs < tmp ? regs.cc |= 0x01 : regs.cc &= 0xFE);  // Adjust Carry flag
-  ((bs^tmp^regs.b^(regs.cc<<7))&0x80 ? regs.cc |= 0x02 : regs.cc &= 0xFD); // oVerflow
+static void OpEF(void)                                                 // STX ZP, X
+{
+       uint16_t m = EA_ZP_X;
+       OP_ST_HANDLER(m, regs.x);
 }
 
-static void OpD1(void)  // CMPB ZP
+static void OpFF(void)                                                 // STX ABS
 {
-  tmp = regs.RdMem(regs.RdMem(regs.pc++));
-  uint8 db = regs.b - tmp;
-  (db == 0  ? regs.cc |= 0x04 : regs.cc &= 0xFB);  // Adjust Zero flag
-  (db&0x80  ? regs.cc |= 0x08 : regs.cc &= 0xF7);  // Adjust Negative flag
-  (regs.b < tmp ? regs.cc |= 0x01 : regs.cc &= 0xFE);  // Adjust Carry flag
-  ((regs.b^tmp^db^(regs.cc<<7))&0x80 ? regs.cc |= 0x02 : regs.cc &= 0xFD); // oVerflow
+       uint16_t m = EA_ABS;
+       OP_ST_HANDLER(m, regs.x);
 }
 
-static void OpD2(void)  // SBCB ZP
+static void Op9F(void)                                                 // STS ZP
 {
-  tmp = regs.RdMem(regs.RdMem(regs.pc++));  uint8 bs = regs.b; 
-  regs.b = regs.b - tmp - (regs.cc&0x01);
-  (bs < (tmp+(regs.cc&0x01)) ? regs.cc |= 0x01 : regs.cc &= 0xFE);  // Adjust Carry flag
-  ((bs^tmp^regs.b^(regs.cc<<7))&0x80 ? regs.cc |= 0x02 : regs.cc &= 0xFD); // oVerflow
-  (regs.b == 0  ? regs.cc |= 0x04 : regs.cc &= 0xFB);  // Adjust Zero flag
-  (regs.b&0x80  ? regs.cc |= 0x08 : regs.cc &= 0xF7);  // Adjust Negative flag
+       uint16_t m = EA_ZP;
+       OP_ST_HANDLER(m, regs.s);
 }
 
-static void OpD4(void)  // ANDB ZP
+static void OpAF(void)                                                 // STS ZP, X
 {
-regs.b &= regs.RdMem(regs.RdMem(regs.pc++));
-regs.cc &= 0xFD;                            // Clear oVerflow flag
-(regs.b == 0 ? regs.cc |= 0x04 : regs.cc &= 0xFB);  // Adjust Zero flag
-(regs.b&0x80 ? regs.cc |= 0x08 : regs.cc &= 0xF7);  // Adjust Negative flag
+       uint16_t m = EA_ZP_X;
+       OP_ST_HANDLER(m, regs.s);
 }
 
-static void OpD5(void)  // BITB ZP
+static void OpBF(void)                                                 // STS ABS
 {
-tmp = regs.b & regs.RdMem(regs.RdMem(regs.pc++));
-regs.cc &= 0xFD;                             // Clear oVerflow flag
-(tmp == 0 ? regs.cc |= 0x04 : regs.cc &= 0xFB);  // Adjust Zero flag
-(tmp&0x80 ? regs.cc |= 0x08 : regs.cc &= 0xF7);  // Adjust Negative flag
+       uint16_t m = EA_ABS;
+       OP_ST_HANDLER(m, regs.s);
 }
 
-static void OpD6(void)  // LDAB ZP
+/*
+Operation               |Mnem.|Immed.|Direct|Index |Extend|Inher.|Operation |CC Reg|
+                        |     |OP ~ #|OP ~ #|OP ~ #|OP ~ #|OP ~ #|          |HINZVC|
+Index Reg > Stack Pnter |TXS  |      |      |      |      |35 4 1|SP=X-1    |      |
+Stack Ptr > Index Regtr |TSX  |      |      |      |      |30 4 1|X=SP+1    |      |
+*/
+
+static void Op35(void)                                                 // TXS
 {
-  regs.b = regs.RdMem(regs.RdMem(regs.pc++));
-  regs.cc &= 0xFD;                            // CLV
-  (regs.b == 0 ? regs.cc |= 0x04 : regs.cc &= 0xFB);  // Adjust Zero flag
-  (regs.b&0x80 ? regs.cc |= 0x08 : regs.cc &= 0xF7);  // Adjust Negative flag
+       regs.s = regs.x - 1;
 }
 
-static void OpD7(void)  // STAB ZP
+static void Op30(void)                                                 // TSX
 {
-regs.WrMem(regs.RdMem(regs.pc++), regs.b);
-regs.cc &= 0xFD;                            // CLV
-(regs.b == 0 ? regs.cc |= 0x04 : regs.cc &= 0xFB);  // Adjust Zero flag
-(regs.b&0x80 ? regs.cc |= 0x08 : regs.cc &= 0xF7);  // Adjust Negative flag
+       regs.x = regs.s + 1;
+}
+
+/*
+Operation               |Mnem.|Immed.|Direct|Index |Extend|Inher.|Operation |CC Reg|
+                        |     |OP ~ #|OP ~ #|OP ~ #|OP ~ #|OP ~ #|          |HINZVC|
+Always                  |BRA  |      |20 4 2|      |      |      |none      |      |
+Carry is Clear          |BCC  |      |24 4 2|      |      |      |C=0       |      |
+Carry is Set            |BCS  |      |25 4 2|      |      |      |C=1       |      |
+Equals Zero             |BEQ  |      |27 4 2|      |      |      |Z=1       |      |
+Greater or Equal to Zero|BGE  |      |2C 4 2|      |      |      |N(+)V=0   |      |
+Greater than Zero       |BGT  |      |2E 4 2|      |      |      |Z+N(+)V=0 |      |
+Higher                  |BHI  |      |22 4 2|      |      |      |C+Z=0     |      |
+Less or Equal than Zero |BLE  |      |2F 4 2|      |      |      |Z+N(+)V=1 |      |
+Lower or Same           |BLS  |      |23 4 2|      |      |      |C+Z=1     |      |
+Less Than Zero          |BLT  |      |2D 4 2|      |      |      |N(+)V=1   |      |
+Minus                   |BMI  |      |2B 4 2|      |      |      |N=1       |      |
+Not Zero                |BNE  |      |26 4 2|      |      |      |Z=0       |      |
+Overflow Clear          |BVC  |      |28 4 2|      |      |      |V=0       |      |
+Overflow Set            |BVS  |      |29 4 2|      |      |      |V=1       |      |
+Plus                    |BPL  |      |2A 4 2|      |      |      |N=0       |      |
+*/
+
+static void Op20(void)                                                 // BRA
+{
+       int16_t m = (int16_t)(int8_t)READ_IMM;
+       regs.pc += m;
+}
+
+static void Op24(void)                                                 // BCC
+{
+// NOTE: We can optimize this by following the maxim: "Don't branch!" by converting the boolean
+//       result into a multiplication. The only way to know if this is a win is to do some profiling
+//       both with and without the optimization.
+       int16_t m = (int16_t)(int8_t)READ_IMM;
+
+#ifdef TEST_DONT_BRANCH_OPTIMIZATION
+//Note sure if the ! operator will do what we want, so we use ^ 1
+       regs.pc += m * (flagC ^ 0x01);
+#else
+       if (!flagC)
+               regs.pc += m;
+#endif
 }
 
-static void OpD8(void)  // EORB ZP
+static void Op25(void)                                                 // BCS
 {
-regs.b ^= regs.RdMem(regs.RdMem(regs.pc++));
-regs.cc &= 0xFD;                            // CLV
-(regs.b == 0 ? regs.cc |= 0x04 : regs.cc &= 0xFB);  // Adjust Zero flag
-(regs.b&0x80 ? regs.cc |= 0x08 : regs.cc &= 0xF7);  // Adjust Negative flag
+       int16_t m = (int16_t)(int8_t)READ_IMM;
+
+#ifdef TEST_DONT_BRANCH_OPTIMIZATION
+       regs.pc += m * (flagC);
+#else
+       if (flagC)
+               regs.pc += m;
+#endif
 }
 
-static void OpD9(void)  // ADCB ZP
+static void Op27(void)                                                 // BEQ
 {
-  tmp = regs.RdMem(regs.RdMem(regs.pc++));
-  addr = (uint16)regs.b + (uint16)tmp + (uint16)(regs.cc&0x01);
-  (addr > 0x00FF ? regs.cc |= 0x01 : regs.cc &= 0xFE);  // Set Carry flag
-  ((regs.b^tmp^addr^(regs.cc<<7))&0x80 ? regs.cc |= 0x02 : regs.cc &= 0xFD); // oVerflow 
-  regs.b = addr;                              // Set accumulator
-  (regs.b == 0 ? regs.cc |= 0x04 : regs.cc &= 0xFB);  // Set Zero flag
-  (regs.b&0x80 ? regs.cc |= 0x08 : regs.cc &= 0xF7);  // Set Negative flag
+       int16_t m = (int16_t)(int8_t)READ_IMM;
+
+#ifdef TEST_DONT_BRANCH_OPTIMIZATION
+       regs.pc += m * (flagZ);
+#else
+       if (flagZ)
+               regs.pc += m;
+#endif
 }
 
-static void OpDA(void)  // ORAB ZP
+static void Op2C(void)                                                 // BGE
 {
-regs.b |= regs.RdMem(regs.RdMem(regs.pc++));
-regs.cc &= 0xFD;                            // CLV
-(regs.b == 0 ? regs.cc |= 0x04 : regs.cc &= 0xFB);  // Adjust Zero flag
-(regs.b&0x80 ? regs.cc |= 0x08 : regs.cc &= 0xF7);  // Adjust Negative flag
-}
+       int16_t m = (int16_t)(int8_t)READ_IMM;
 
-static void OpDB(void)  // ADDB ZP
-{       
-  tmp = regs.RdMem(regs.RdMem(regs.pc++));
-  addr = (uint16)regs.b + (uint16)tmp;
-  (addr > 0x00FF ? regs.cc |= 0x01 : regs.cc &= 0xFE);  // Set Carry flag
-  ((regs.b^tmp^addr^(regs.cc<<7))&0x80 ? regs.cc |= 0x02 : regs.cc &= 0xFD); // oVerflow 
-  regs.b = addr & 0xFF;                       // Set accumulator
-  (regs.b == 0 ? regs.cc |= 0x04 : regs.cc &= 0xFB);  // Set Zero flag
-  (regs.b&0x80 ? regs.cc |= 0x08 : regs.cc &= 0xF7);  // Set Negative flag
+#ifdef TEST_DONT_BRANCH_OPTIMIZATION
+       regs.pc += m * ((flagN ^ flagV) ^ 0x01);
+#else
+       if (!(flagN ^ flagV))
+               regs.pc += m;
+#endif
 }
 
-static void OpDE(void)  // LDX ZP
+static void Op2E(void)                                                 // BGT
 {
-  addr = regs.RdMem(regs.pc++);
-  regs.x = (regs.RdMem(addr) << 8) | regs.RdMem(addr+1);
-  regs.cc &= 0xFD;                              // CLV
-  (regs.x == 0   ? regs.cc |= 0x04 : regs.cc &= 0xFB);  // Adjust Zero flag
-  (regs.x&0x8000 ? regs.cc |= 0x08 : regs.cc &= 0xF7);  // Adjust Negative flag
+       int16_t m = (int16_t)(int8_t)READ_IMM;
+
+#ifdef TEST_DONT_BRANCH_OPTIMIZATION
+       regs.pc += m * ((flagZ | (flagN ^ flagV)) ^ 0x01);
+#else
+       if (!(flagZ | (flagN ^ flagV)))
+               regs.pc += m;
+#endif
 }
 
-static void OpDF(void)  // STX ZP
+static void Op22(void)                                                 // BHI
 {
-  addr = regs.RdMem(regs.pc++);
-  regs.WrMem(addr, regs.x>>8);  regs.WrMem(addr+1, regs.x&0xFF);
-  regs.cc &= 0xFD;                              // CLV
-  (regs.x == 0   ? regs.cc |= 0x04 : regs.cc &= 0xFB);  // Adjust Zero flag
-  (regs.x&0x8000 ? regs.cc |= 0x08 : regs.cc &= 0xF7);  // Adjust Negative flag
-}
+       int16_t m = (int16_t)(int8_t)READ_IMM;
 
-static void OpE0(void)  // SUBB IDX
-{ 
-  tmp = regs.RdMem(DecodeIDX(regs.RdMem(regs.pc++)));  uint8 bs = regs.b; 
-  regs.b -= tmp;
-  (regs.b == 0  ? regs.cc |= 0x04 : regs.cc &= 0xFB);  // Adjust Zero flag
-  (regs.b&0x80  ? regs.cc |= 0x08 : regs.cc &= 0xF7);  // Adjust Negative flag
-  (bs < tmp ? regs.cc |= 0x01 : regs.cc &= 0xFE);  // Adjust Carry flag
-  ((bs^tmp^regs.b^(regs.cc<<7))&0x80 ? regs.cc |= 0x02 : regs.cc &= 0xFD); // oVerflow
+#ifdef TEST_DONT_BRANCH_OPTIMIZATION
+       regs.pc += m * ((flagZ | flagC) ^ 0x01);
+#else
+       if (!(flagZ | flagC))
+               regs.pc += m;
+#endif
 }
 
-static void OpE1(void)  // CMPB IDX
+static void Op2F(void)                                                 // BLE
 {
-  tmp = regs.RdMem(DecodeIDX(regs.RdMem(regs.pc++)));
-  uint8 db = regs.b - tmp;
-  (db == 0  ? regs.cc |= 0x04 : regs.cc &= 0xFB);  // Adjust Zero flag
-  (db&0x80  ? regs.cc |= 0x08 : regs.cc &= 0xF7);  // Adjust Negative flag
-  (regs.b < tmp ? regs.cc |= 0x01 : regs.cc &= 0xFE);  // Adjust Carry flag
-  ((regs.b^tmp^db^(regs.cc<<7))&0x80 ? regs.cc |= 0x02 : regs.cc &= 0xFD); // oVerflow
+       int16_t m = (int16_t)(int8_t)READ_IMM;
+
+#ifdef TEST_DONT_BRANCH_OPTIMIZATION
+       regs.pc += m * (flagZ | (flagN ^ flagV));
+#else
+       if (flagZ | (flagN ^ flagV))
+               regs.pc += m;
+#endif
 }
 
-static void OpE2(void)  // SBCB IDX
+static void Op23(void)                                                 // BLS
 {
-  tmp = regs.RdMem(DecodeIDX(regs.RdMem(regs.pc++)));  uint8 bs = regs.b; 
-  regs.b = regs.b - tmp - (regs.cc&0x01);
-  (bs < (tmp+(regs.cc&0x01)) ? regs.cc |= 0x01 : regs.cc &= 0xFE);  // Adjust Carry flag
-  ((bs^tmp^regs.b^(regs.cc<<7))&0x80 ? regs.cc |= 0x02 : regs.cc &= 0xFD); // oVerflow
-  (regs.b == 0  ? regs.cc |= 0x04 : regs.cc &= 0xFB);  // Adjust Zero flag
-  (regs.b&0x80  ? regs.cc |= 0x08 : regs.cc &= 0xF7);  // Adjust Negative flag
+       int16_t m = (int16_t)(int8_t)READ_IMM;
+
+#ifdef TEST_DONT_BRANCH_OPTIMIZATION
+       regs.pc += m * (flagZ | flagC);
+#else
+       if (flagZ | flagC)
+               regs.pc += m;
+#endif
 }
 
-static void OpE4(void)  // ANDB IDX
+static void Op2D(void)                                                 // BLT
 {
-regs.b &= regs.RdMem(DecodeIDX(regs.RdMem(regs.pc++)));
-regs.cc &= 0xFD;                            // Clear oVerflow flag
-(regs.b == 0 ? regs.cc |= 0x04 : regs.cc &= 0xFB);  // Adjust Zero flag
-(regs.b&0x80 ? regs.cc |= 0x08 : regs.cc &= 0xF7);  // Adjust Negative flag
+       int16_t m = (int16_t)(int8_t)READ_IMM;
+
+#ifdef TEST_DONT_BRANCH_OPTIMIZATION
+       regs.pc += m * (flagN ^ flagV);
+#else
+       if (flagN ^ flagV)
+               regs.pc += m;
+#endif
 }
 
-static void OpE5(void)  // BITB IDX
+static void Op2B(void)                                                 // BMI
 {
-tmp = regs.b & regs.RdMem(DecodeIDX(regs.RdMem(regs.pc++)));
-regs.cc &= 0xFD;                             // Clear oVerflow flag
-(tmp == 0 ? regs.cc |= 0x04 : regs.cc &= 0xFB);  // Adjust Zero flag
-(tmp&0x80 ? regs.cc |= 0x08 : regs.cc &= 0xF7);  // Adjust Negative flag
+       int16_t m = (int16_t)(int8_t)READ_IMM;
+
+#ifdef TEST_DONT_BRANCH_OPTIMIZATION
+       regs.pc += m * (flagN);
+#else
+       if (flagN)
+               regs.pc += m;
+#endif
 }
 
-static void OpE6(void)  // LDB IDX
+static void Op26(void)                                                 // BNE
 {
-regs.b = regs.RdMem(DecodeIDX(regs.RdMem(regs.pc++)));
-regs.cc &= 0xFD;                            // CLV
-(regs.b == 0 ? regs.cc |= 0x04 : regs.cc &= 0xFB);  // Adjust Zero flag
-(regs.b&0x80 ? regs.cc |= 0x08 : regs.cc &= 0xF7);  // Adjust Negative flag
+       int16_t m = (int16_t)(int8_t)READ_IMM;
+
+#ifdef TEST_DONT_BRANCH_OPTIMIZATION
+       regs.pc += m * (flagZ ^ 0x01);
+#else
+       if (!flagZ)
+               regs.pc += m;
+#endif
 }
 
-static void OpE7(void)  // STB IDX
+static void Op28(void)                                                 // BVC
 {
-  regs.WrMem(DecodeIDX(regs.RdMem(regs.pc++)), regs.b);
-  regs.cc &= 0xF1;                            // CLV CLZ CLN
-  if (regs.b == 0)  regs.cc |= 0x04;              // Adjust Zero flag
-  if (regs.b&0x80)  regs.cc |= 0x08;              // Adjust Negative flag
+       int16_t m = (int16_t)(int8_t)READ_IMM;
+
+#ifdef TEST_DONT_BRANCH_OPTIMIZATION
+       regs.pc += m * (flagV ^ 0x01);
+#else
+       if (!flagV)
+               regs.pc += m;
+#endif
 }
 
-static void OpE8(void)  // EORB IDX
+static void Op29(void)                                                 // BVS
 {
-regs.b ^= regs.RdMem(DecodeIDX(regs.RdMem(regs.pc++)));
-regs.cc &= 0xFD;                            // CLV
-(regs.b == 0 ? regs.cc |= 0x04 : regs.cc &= 0xFB);  // Adjust Zero flag
-(regs.b&0x80 ? regs.cc |= 0x08 : regs.cc &= 0xF7);  // Adjust Negative flag
+       int16_t m = (int16_t)(int8_t)READ_IMM;
+
+#ifdef TEST_DONT_BRANCH_OPTIMIZATION
+       regs.pc += m * (flagV);
+#else
+       if (flagV)
+               regs.pc += m;
+#endif
 }
 
-static void OpE9(void)  // ADCB IDX
+static void Op2A(void)                                                 // BPL
 {
-  tmp = regs.RdMem(DecodeIDX(regs.RdMem(regs.pc++)));
-  addr = (uint16)regs.b + (uint16)tmp + (uint16)(regs.cc&0x01);
-  (addr > 0x00FF ? regs.cc |= 0x01 : regs.cc &= 0xFE);  // Set Carry flag
-  ((regs.b^tmp^addr^(regs.cc<<7))&0x80 ? regs.cc |= 0x02 : regs.cc &= 0xFD); // oVerflow 
-  regs.b = addr;                                  // Set accumulator
-  (regs.b == 0 ? regs.cc |= 0x04 : regs.cc &= 0xFB);  // Set Zero flag
-  (regs.b&0x80 ? regs.cc |= 0x08 : regs.cc &= 0xF7);  // Set Negative flag
+       int16_t m = (int16_t)(int8_t)READ_IMM;
+
+#ifdef TEST_DONT_BRANCH_OPTIMIZATION
+       regs.pc += m * (flagN ^ 0x01);
+#else
+       if (!flagN)
+               regs.pc += m;
+#endif
 }
 
-static void OpEA(void)  // ORB IDX
+/*
+Operation               |Mnem.|Immed.|Direct|Index |Extend|Inher.|Operation |CC Reg|
+                        |     |OP ~ #|OP ~ #|OP ~ #|OP ~ #|OP ~ #|          |HINZVC|
+Branch to Subroutine    |BSR  |      |8D 8 2|      |      |      |          |      |
+Jump                    |JMP  |      |      |6E 4 2|7E 3 3|      |          |      |
+Jump to Subroutine      |JSR  |      |      |AD 8 2|BD 9 3|      |          |      |
+*/
+
+static void Op8D(void)                                                 // BSR
 {
-regs.b |= regs.RdMem(DecodeIDX(regs.RdMem(regs.pc++)));
-regs.cc &= 0xFD;                            // CLV
-(regs.b == 0 ? regs.cc |= 0x04 : regs.cc &= 0xFB);  // Adjust Zero flag
-(regs.b&0x80 ? regs.cc |= 0x08 : regs.cc &= 0xF7);  // Adjust Negative flag
+       int16_t m = (int16_t)(int8_t)READ_IMM;
+       PUSH16(regs.pc);
+       regs.pc += m;
 }
 
-static void OpEB(void)  // ADDB IDX
-{       
-  tmp = regs.RdMem(DecodeIDX(regs.RdMem(regs.pc++)));
-  addr = (uint16)regs.b + (uint16)tmp;
-  (addr > 0x00FF ? regs.cc |= 0x01 : regs.cc &= 0xFE);  // Set Carry flag
-  ((regs.b^tmp^addr^(regs.cc<<7))&0x80 ? regs.cc |= 0x02 : regs.cc &= 0xFD); // oVerflow 
-  regs.b = addr;                              // Set accumulator
-  (regs.b == 0 ? regs.cc |= 0x04 : regs.cc &= 0xFB);  // Set Zero flag
-  (regs.b&0x80 ? regs.cc |= 0x08 : regs.cc &= 0xF7);  // Set Negative flag
+static void Op6E(void)                                                 // JMP ZP, X
+{
+       regs.pc = EA_ZP_X;
 }
 
-static void OpEE(void)  // LDX IDX
+static void Op7E(void)                                                 // JMP ABS
 {
-  addr = DecodeIDX(regs.RdMem(regs.pc++));
-  regs.x = (regs.RdMem(addr) << 8) | regs.RdMem(addr+1);
-  regs.cc &= 0xF1;                              // CLV CLZ CLN
-  if (regs.x == 0)    regs.cc |= 0x04;              // Set Zero flag
-  if (regs.x&0x8000)  regs.cc |= 0x08;              // Set Negative flag
+       regs.pc = EA_ABS;
 }
 
-static void OpEF(void)  // STX IDX
+static void OpAD(void)                                                 // JSR ZP, X
 {
-  addr = DecodeIDX(regs.RdMem(regs.pc++));
-  regs.WrMem(addr, regs.x>>8);  regs.WrMem(addr+1, regs.x&0xFF);
-  regs.cc &= 0xF1;                              // CLV CLZ CLN
-  if (regs.x == 0)    regs.cc |= 0x04;              // Set Zero flag
-  if (regs.x&0x8000)  regs.cc |= 0x08;              // Set Negative flag
+       uint16_t m = EA_ZP_X;
+       PUSH16(regs.pc);
+       regs.pc = m;
 }
 
-static void OpF0(void)  // SUBB ABS
-{ 
-tmp = regs.RdMem(FetchW());  uint8 bs = regs.b; 
-regs.b -= tmp;
-(regs.b == 0  ? regs.cc |= 0x04 : regs.cc &= 0xFB);  // Adjust Zero flag
-(regs.b&0x80  ? regs.cc |= 0x08 : regs.cc &= 0xF7);  // Adjust Negative flag
-(bs < tmp ? regs.cc |= 0x01 : regs.cc &= 0xFE);  // Adjust Carry flag
-((bs^tmp^regs.b^(regs.cc<<7))&0x80 ? regs.cc |= 0x02 : regs.cc &= 0xFD); // oVerflow
+static void OpBD(void)                                                 // JSR ABS
+{
+       uint16_t m = EA_ABS;
+       PUSH16(regs.pc);
+       regs.pc = m;
 }
 
-static void OpF1(void)  // CMPB ABS
+/*
+Operation               |Mnem.|Immed.|Direct|Index |Extend|Inher.|Operation |CC Reg|
+                        |     |OP ~ #|OP ~ #|OP ~ #|OP ~ #|OP ~ #|          |HINZVC|
+No Operation            |NOP  |      |      |      |      |01 2 1|          |      |
+Return from Interrupt   |RTI  |      |      |      |      |3B A 1|          |AAAAAA|
+Return from Subroutine  |RTS  |      |      |      |      |39 5 1|          |      |
+Software Interrupt      |SWI  |      |      |      |      |3F C 1|          | S    |
+Wait For Interrupt      |WAI  |      |      |      |      |3E 9 1|          | B    |
+*/
+
+static void Op01(void)                                                 // NOP
 {
-tmp = regs.RdMem(FetchW());
-uint8 db = regs.b - tmp;
-(db == 0  ? regs.cc |= 0x04 : regs.cc &= 0xFB);  // Adjust Zero flag
-(db&0x80  ? regs.cc |= 0x08 : regs.cc &= 0xF7);  // Adjust Negative flag
-(regs.b < tmp ? regs.cc |= 0x01 : regs.cc &= 0xFE);  // Adjust Carry flag
-((regs.b^tmp^db^(regs.cc<<7))&0x80 ? regs.cc |= 0x02 : regs.cc &= 0xFD); // oVerflow
 }
 
-static void OpF2(void)  // SBCB ABS
+static void Op3B(void)                                                 // RTI
 {
-  tmp = regs.RdMem(FetchW());  uint8 bs = regs.b; 
-  regs.b = regs.b - tmp - (regs.cc&0x01);
-  (regs.b == 0  ? regs.cc |= 0x04 : regs.cc &= 0xFB);  // Adjust Zero flag
-  (regs.b&0x80  ? regs.cc |= 0x08 : regs.cc &= 0xF7);  // Adjust Negative flag
-  (bs < tmp ? regs.cc |= 0x01 : regs.cc &= 0xFE);  // Adjust Carry flag
-  ((bs^tmp^regs.b^(regs.cc<<7))&0x80 ? regs.cc |= 0x02 : regs.cc &= 0xFD); // oVerflow
+       regs.cc = PULL;
+       regs.a  = PULL;
+       regs.b  = PULL;
+       regs.x  = PULL16;
+       regs.pc = PULL16;
+       UNPACK_FLAGS;
 }
 
-static void OpF4(void)  // ANDB ABS
+static void Op39(void)                                                 // RTS
 {
-regs.b &= regs.RdMem(FetchW());
-regs.cc &= 0xFD;                            // Clear oVerflow flag
-(regs.b == 0 ? regs.cc |= 0x04 : regs.cc &= 0xFB);  // Adjust Zero flag
-(regs.b&0x80 ? regs.cc |= 0x08 : regs.cc &= 0xF7);  // Adjust Negative flag
+       regs.pc = PULL16;
 }
 
-static void OpF5(void)  // BITB ABS
+static void Op3F(void)                                                 // SWI
 {
-tmp = regs.b & regs.RdMem(FetchW());
-regs.cc &= 0xFD;                             // Clear oVerflow flag
-(tmp == 0 ? regs.cc |= 0x04 : regs.cc &= 0xFB);  // Adjust Zero flag
-(tmp&0x80 ? regs.cc |= 0x08 : regs.cc &= 0xF7);  // Adjust Negative flag
+       // It seems that the SWI is non-maskable, unlike the IRQ...
+       regs.cc = PACK_FLAGS;                                           // Mash flags back into the CC register
+       PUSH16(regs.pc);                                                        // Save all regs...
+       PUSH16(regs.x);
+       PUSH(regs.b);
+       PUSH(regs.a);
+       PUSH(regs.cc);
+       regs.pc = RdMemW(0xFFFA);                                       // And do it!
+       flagI = 1;                                                                      // Also, set IRQ inhibit
 }
 
-static void OpF6(void)  // LDB ABS
+static void Op3E(void)                                                 // WAI
 {
-regs.b = regs.RdMem(FetchW());
-regs.cc &= 0xFD;                            // CLV
-(regs.b == 0 ? regs.cc |= 0x04 : regs.cc &= 0xFB);  // Adjust Zero flag
-(regs.b&0x80 ? regs.cc |= 0x08 : regs.cc &= 0xF7);  // Adjust Negative flag
-}
+#ifdef __DEBUG__
+WriteLog("*** WAI STATE ASSERTED ***\n");
+#endif
+       regs.cc = PACK_FLAGS;                                           // Mash flags back into the CC register
+       PUSH16(regs.pc);                                                        // Save all regs...
+       PUSH16(regs.x);
+       PUSH(regs.b);
+       PUSH(regs.a);
+       PUSH(regs.cc);
+       regs.cpuFlags |= V6808_STATE_WAI;                       // And signal that we're in WAI mode
+}
+
+/*
+Operation               |Mnem.|Immed.|Direct|Index |Extend|Inher.|Operation |CC Reg|
+                        |     |OP ~ #|OP ~ #|OP ~ #|OP ~ #|OP ~ #|          |HINZVC|
+Clear Carry             |CLC  |      |      |      |      |0C 2 1|C=0       |     R|
+Clear Interrupt         |CLI  |      |      |      |      |0E 2 1|I=0       | R    |
+Clear Overflow          |CLV  |      |      |      |      |0A 2 1|V=0       |    R |
+Set Carry               |SEC  |      |      |      |      |0D 2 1|C=1       |     S|
+Set Interrupt           |SEI  |      |      |      |      |0F 2 1|I=1       | S    |
+Set Overflow            |SEV  |      |      |      |      |0B 2 1|V=1       |    S |
+CCR=Accumulator A       |TAP  |      |      |      |      |06 2 1|CCR=A     |CCCCCC|
+Accumlator A=CCR        |TPA  |      |      |      |      |07 2 1|A=CCR     |      |
+*/
 
-static void OpF7(void)  // STB ABS
+static void Op0C(void)                                                 // CLC
 {
-regs.WrMem(FetchW(), regs.b);
-regs.cc &= 0xFD;                            // CLV
-(regs.b == 0 ? regs.cc |= 0x04 : regs.cc &= 0xFB);  // Adjust Zero flag
-(regs.b&0x80 ? regs.cc |= 0x08 : regs.cc &= 0xF7);  // Adjust Negative flag
+       flagC = 0;
 }
 
-static void OpF8(void)  // EORB ABS
+static void Op0E(void)                                                 // CLI
 {
-regs.b ^= regs.RdMem(FetchW());
-regs.cc &= 0xFD;                            // CLV
-(regs.b == 0 ? regs.cc |= 0x04 : regs.cc &= 0xFB);  // Adjust Zero flag
-(regs.b&0x80 ? regs.cc |= 0x08 : regs.cc &= 0xF7);  // Adjust Negative flag
+       flagI = 0;
 }
 
-static void OpF9(void)  // ADCB ABS
+static void Op0A(void)                                                 // CLV
 {
-  tmp = regs.RdMem(FetchW());
-  addr = (uint16)regs.b + (uint16)tmp + (uint16)(regs.cc&0x01);
-  (addr > 0x00FF ? regs.cc |= 0x01 : regs.cc &= 0xFE);  // Set Carry flag
-  ((regs.b^tmp^addr^(regs.cc<<7))&0x80 ? regs.cc |= 0x02 : regs.cc &= 0xFD); // oVerflo 
-  regs.b = addr & 0xFF;                       // Set accumulator
-  (regs.b == 0 ? regs.cc |= 0x04 : regs.cc &= 0xFB);  // Set Zero flag
-  (regs.b&0x80 ? regs.cc |= 0x08 : regs.cc &= 0xF7);  // Set Negative flag
+       flagV = 0;
 }
 
-static void OpFA(void)  // ORB ABS
+static void Op0D(void)                                                 // SEC
 {
-regs.b |= regs.RdMem(FetchW());
-regs.cc &= 0xFD;                            // CLV
-(regs.b == 0 ? regs.cc |= 0x04 : regs.cc &= 0xFB);  // Adjust Zero flag
-(regs.b&0x80 ? regs.cc |= 0x08 : regs.cc &= 0xF7);  // Adjust Negative flag
-}       
+       flagC = 1;
+}
 
-static void OpFB(void)  // ADDB ABS
-{       
-  tmp = regs.RdMem(FetchW());
-  addr = (uint16)regs.b + (uint16)tmp;
-  (addr > 0x00FF ? regs.cc |= 0x01 : regs.cc &= 0xFE);  // Set Carry flag
-  ((regs.b^tmp^addr^(regs.cc<<7))&0x80 ? regs.cc |= 0x02 : regs.cc &= 0xFD); // oVerflo 
-  regs.b = addr & 0xFF;                       // Set accumulator
-  (regs.b == 0 ? regs.cc |= 0x04 : regs.cc &= 0xFB);  // Set Zero flag
-  (regs.b&0x80 ? regs.cc |= 0x08 : regs.cc &= 0xF7);  // Set Negative flag
+static void Op0F(void)                                                 // SEI
+{
+       flagI = 1;
 }
 
-static void OpFE(void)  // LDX ABS
+static void Op0B(void)                                                 // SEV
 {
-addr = FetchW();
-regs.x = (regs.RdMem(addr) << 8) | regs.RdMem(addr+1);
-regs.cc &= 0xFD;                              // CLV
-(regs.x == 0   ? regs.cc |= 0x04 : regs.cc &= 0xFB);  // Adjust Zero flag
-(regs.x&0x8000 ? regs.cc |= 0x08 : regs.cc &= 0xF7);  // Adjust Negative flag
+       flagV = 1;
 }
 
-static void OpFF(void)  // STX ABS
+static void Op06(void)                                                 // TAP
 {
-addr = FetchW();
-regs.WrMem(addr, regs.x>>8);  regs.WrMem(addr+1, regs.x&0xFF);
-regs.cc &= 0xFD;                              // CLV
-(regs.x == 0   ? regs.cc |= 0x04 : regs.cc &= 0xFB);  // Adjust Zero flag
-(regs.x&0x8000 ? regs.cc |= 0x08 : regs.cc &= 0xF7);  // Adjust Negative flag
+       regs.cc = regs.a;
+       UNPACK_FLAGS;
 }
 
+static void Op07(void)                                                 // TPA
+{
+       regs.a = PACK_FLAGS;
+}
+
+/*
+  OP  Operation Code, in Hexadecimal
+  ~   Number of MPU cycles required
+  #   Number of program bytes required
+  +   Arithmetic Plus
+  -   Arithmetic Minus
+  +   Boolean AND
+  Msp Contents of Memory pointed to be Stack Pointer
+  +   Boolean Inclusive OR
+  (+) Boolean Exclusive OR (XOR)
+  *   Converts Binary Addition of BCD Characters into BCD Format
+  *-  SP=SP-1
+  *+  SP=SP+1
+
+  Condition Code Register Legend
+     Not Affected
+   R Reset (0, Low)
+   S Set   (1, High)
+   T Tests and sets if True, cleared otherise
+   1 Test: Result=10000000?
+   2 Test: Result=00000000?
+   3 Test: Decimal value of most significant BCD character greater than nine?
+           (Not cleared if previously set)
+   4 Test: Operand=10000000 prior to execution?
+   5 Test: Operand=01111111 prior to execution?
+   6 Test: Set equal to result or N(+)C after shift has occurred.
+   7 Test: Sign bit of most significant byte or result=1?
+   8 Test: 2's compliment overflow from subtraction of least
+           significant bytes?
+   9 Test: Result less than zero? (Bit 15=1)
+   A Load Condition Code Register from Stack.
+   B Set when interrupt occurs.  If previously set, a NMI is
+        required to exit the wait state.
+   C Set according to the contents of Accumulator A.
+
+  *x SHIFT AND ROTATION DIAGRAMS
+   *1     +-----------------+       C to LSB
+          - C <- 76543210 <-+
+
+   *2    +-----------------+
+         +> C -> 76543210 -+
+
+   *3       C <- 76543210 <- 0(Data)
+               +-+
+
+   *4          �>76543210 -> C
+
+   *5 (Data)0 -> 76543210 -> C
+
+  FORMULAS
+   1: (Xh/Xl)-(M/M+1)
+   2: Xh=M, Xl=M+1
+   3: SPh=M, SPl=M+1
+   4: M=Xh, M+1=Xl
+*/
+
 static void Op__(void)
 {
        regs.cpuFlags |= V6808_STATE_ILLEGAL_INST;
@@ -1834,89 +2006,117 @@ void (* exec_op[256])() = {
 //
 // Internal "memcpy" (so we don't have to link with any external libraries!)
 //
-static void myMemcpy(void * dst, void * src, uint32 size)
+static void myMemcpy(void * dst, void * src, uint32_t size)
 {
-       uint8 * d = (uint8 *)dst, * s = (uint8 *)src;
+       uint8_t * d = (uint8_t *)dst, * s = (uint8_t *)src;
 
-       for(uint32 i=0; i<size; i++)
+       for(uint32_t i=0; i<size; i++)
                d[i] = s[i];
 }
 
+#ifdef __DEBUG__
 //int instCount[256];
+static bool logGo = false;
+#endif
 //
 // Function to execute 6808 for "cycles" cycles
 //
-void Execute6808(V6808REGS * context, uint32 cycles)
+void Execute6808(V6808REGS * context, uint32_t cycles)
 {
+#warning "V6808_STATE_WAI is not properly handled yet! !!! FIX !!!"
+#warning "Need to convert from destructive clock to non-destructive. !!! FIX !!!"
+
        myMemcpy(&regs, context, sizeof(V6808REGS));
+       UNPACK_FLAGS;                                                           // Explode flags register into individual uint8_ts
 
        // Execute here...
        while (regs.clock < cycles)
        {
 #ifdef __DEBUG__
-Decode6808(regs.pc);
+if (logGo)
+       Decode6808(regs.pc);
 #endif
-               uint8 opcode = regs.RdMem(regs.pc++);
+               uint8_t opcode = regs.RdMem(regs.pc++);
 
+#ifdef __DEBUG__
 //if (!(regs.cpuFlags & V6808_STATE_ILLEGAL_INST))
 //instCount[opcode]++;
+#endif
 
-               exec_op[opcode]();                                                              // Execute that opcode...
+               exec_op[opcode]();                                              // Execute that opcode...
                regs.clock += CPUCycles[opcode];
 #ifdef __DEBUG__
-WriteLog(" [PC=%04X, S=%04X, X=%04X, A=%02X, B=%02X, CC=%02X]\n", regs.pc, regs.s, regs.x, regs.a, regs.b, regs.cc);
+if (logGo)
+//     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" : " "));
+       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" : " "));
 #endif
 
                if (regs.cpuFlags & V6808_ASSERT_LINE_RESET)
                {
-                       regs.cc |= FLAG_I;                                                      // Set I
-                       regs.pc = RdMemW(0xFFFE);                                       // And load PC with the RESET vector
+#ifdef __DEBUG__
+WriteLog("*** RESET LINE ASSERTED ***\n");
+#endif
+                       flagI = 1;                                                      // Set I
+                       regs.pc = RdMemW(0xFFFE);                       // And load PC with the RESET vector
 
                        context->cpuFlags &= ~V6808_ASSERT_LINE_RESET;
                        regs.cpuFlags &= ~V6808_ASSERT_LINE_RESET;
                }
                else if (regs.cpuFlags & V6808_ASSERT_LINE_NMI)
                {
-                       regs.WrMem(--regs.s, regs.pc & 0xFF);           // Save all regs...
-                       regs.WrMem(--regs.s, regs.pc >> 8);
-                       regs.WrMem(--regs.s, regs.x & 0xFF);
-                       regs.WrMem(--regs.s, regs.x >> 8);
-                       regs.WrMem(--regs.s, regs.b);
-                       regs.WrMem(--regs.s, regs.a);
-                       regs.WrMem(--regs.s, regs.cc);
-                       regs.pc = RdMemW(0xFFFC);                                       // And do it!
-
+#ifdef __DEBUG__
+WriteLog("*** NMI LINE ASSERTED ***\n");
+#endif
+                       regs.cc = PACK_FLAGS;                           // Mash flags back into the CC register
+                       PUSH16(regs.pc);                                        // Save all regs...
+                       PUSH16(regs.x);
+                       PUSH(regs.b);
+                       PUSH(regs.a);
+                       PUSH(regs.cc);
+                       regs.pc = RdMemW(0xFFFC);                       // And do it!
+
+#warning "# of clock cycles for NMI unknown. !!! FIX !!!"
                        regs.clock += 0;                                                        // How many???
                        context->cpuFlags &= ~V6808_ASSERT_LINE_NMI;// Reset the asserted line (NMI)...
                        regs.cpuFlags &= ~V6808_ASSERT_LINE_NMI;        // Reset the asserted line (NMI)...
                }
                else if (regs.cpuFlags & V6808_ASSERT_LINE_IRQ)
                {
-                       if (!(regs.cc & FLAG_I))                                        // Process an interrupt (I=0)?
+#ifdef __DEBUG__
+WriteLog("*** IRQ LINE ASSERTED ***\n");
+#endif
+//                     if (!(regs.cc & FLAG_I))                        // Process an interrupt (I=0)?
+                       if (!flagI)                                                     // Process an interrupt (I=0)?
                        {
-                               regs.WrMem(--regs.s, regs.pc & 0xFF);   // Save all regs...
-                               regs.WrMem(--regs.s, regs.pc >> 8);
-                               regs.WrMem(--regs.s, regs.x & 0xFF);
-                               regs.WrMem(--regs.s, regs.x >> 8);
-                               regs.WrMem(--regs.s, regs.b);
-                               regs.WrMem(--regs.s, regs.a);
-                               regs.WrMem(--regs.s, regs.cc);
-                               regs.pc = RdMemW(0xFFF8);                       // And do it!
-
-                               regs.clock += 0;                                                // How many???
+#ifdef __DEBUG__
+WriteLog("    IRQ TAKEN!\n");
+logGo = true;
+#endif
+                               regs.cc = PACK_FLAGS;                   // Mash flags back into the CC register
+                               PUSH16(regs.pc);                                // Save all regs...
+                               PUSH16(regs.x);
+                               PUSH(regs.b);
+                               PUSH(regs.a);
+                               PUSH(regs.cc);
+                               regs.pc = RdMemW(0xFFF8);               // And do it!
+
+#warning "# of clock cycles for IRQ unknown. !!! FIX !!!"
+                               regs.clock += 0;                                // How many???
+#warning "IRQ/NMI lines should not be cleared here... !!! FIX !!!"
                                context->cpuFlags &= ~V6808_ASSERT_LINE_IRQ;    // Reset the asserted line (IRQ)...
                                regs.cpuFlags &= ~V6808_ASSERT_LINE_IRQ;        // Reset the asserted line (IRQ)...
                        }
                }
        }
 
+       regs.cc = PACK_FLAGS;                                           // Mash flags back into the CC register
        myMemcpy(context, &regs, sizeof(V6808REGS));
 }
 
 //
 // Get the clock of the currently executing CPU
 //
-uint32 GetCurrentV6808Clock(void)
+uint64_t GetCurrentV6808Clock(void)
 {
        return regs.clock;
 }