aboutsummaryrefslogtreecommitdiff
path: root/c64/cpu.c
diff options
context:
space:
mode:
authorReiner Herrmann <reiner@reiner-h.de>2012-02-10 14:25:38 +0100
committerReiner Herrmann <reiner@reiner-h.de>2012-02-10 14:25:38 +0100
commita5d7e68af96d9b62821d8fd47f5039c5bae5d421 (patch)
treeab7d1a70312afb74dc7184d8b269b08f332f4b74 /c64/cpu.c
added original sam_player code
Diffstat (limited to 'c64/cpu.c')
-rw-r--r--c64/cpu.c678
1 files changed, 678 insertions, 0 deletions
diff --git a/c64/cpu.c b/c64/cpu.c
new file mode 100644
index 0000000..ba206fe
--- /dev/null
+++ b/c64/cpu.c
@@ -0,0 +1,678 @@
+// cpu.c
+//
+// 20050125 Markku Alén
+
+#include "cpu.h"
+
+#define NMI_VECTOR 0xfffa
+#define RST_VECTOR 0xfffc
+#define IRQ_VECTOR 0xfffe
+
+static int (*read_bus)(int);
+static void (*write_bus)(int, int);
+static int (*read_page)(int);
+static void (*write_page)(int, int);
+static void (*jam_handler)(int, int);
+
+unsigned int cycles;
+
+void (*reset_cpu)(void);
+void (*raise_nmi)(void);
+void (*raise_irq)(void);
+void (*exec_cpu)(void);
+
+static trap_t *first_trap;
+
+static int ea, tmp1, tmp2;
+static int accumulator;
+static int register_x;
+static int register_y;
+static int pc, sp;
+static int sr, c, nz;
+
+#define FLAG_N 0x80
+#define FLAG_V 0x40
+#define FLAG_X 0x20
+#define FLAG_B 0x10
+#define FLAG_D 0x08
+#define FLAG_I 0x04
+#define FLAG_Z 0x02
+#define FLAG_C 0x01
+
+#define TEST_N() ((nz & 0x8080) != 0)
+#define TEST_V() ((sr & 0x40) != 0)
+#define TEST_X() ((sr & 0x20) != 0)
+#define TEST_B() ((sr & 0x10) != 0)
+#define TEST_D() ((sr & 0x08) != 0)
+#define TEST_I() ((sr & 0x04) != 0)
+#define TEST_Z() ((nz & 0xff) == 0)
+#define TEST_C() ((c & 0x100) != 0)
+
+#define SET_V() sr |= 0x40;
+#define SET_D() sr |= 0x08;
+#define SET_I() sr |= 0x04;
+#define SET_C() c = 0x100;
+
+#define CLEAR_V() sr &= 0xbf;
+#define CLEAR_D() sr &= 0xf7;
+#define CLEAR_I() sr &= 0xfb;
+#define CLEAR_C() c = 0;
+
+static const int z_tbl[4] = { 0xffff, 0xffff, 0x8000, 0x8000 };
+
+#define get_sr() ((nz & 0x80) | ((nz & 0x8000) >> 8) | (sr & 0x7c) | ((((nz & 0xff) == 0) & 1) << 1) | ((c & 0x100) >> 8))
+#define set_sr(SR) { c = sr = (SR); c <<= 8; nz = (sr | (c & 0x8000)) & z_tbl[sr & 0x02]; }
+
+#define DECL(NAME) static void NAME(void);
+#define BEGIN(NAME) static void NAME(void) {
+#define END exec_cpu = op_code[read_bus(pc++)]; }
+
+DECL(jam) DECL(nmi) DECL(rst) DECL(irq)
+DECL(brk_imm) DECL(nop)
+DECL(rti) DECL(rts) DECL(jsr_abs) DECL(jmp_abs) DECL(jmp_ind)
+DECL(php) DECL(plp) DECL(pha) DECL(pla)
+DECL(tax) DECL(txa) DECL(tay) DECL(tya) DECL(txs) DECL(tsx)
+DECL(clc) DECL(sec) DECL(cli) DECL(sei) DECL(clv) DECL(cld) DECL(sed)
+DECL(bpl) DECL(bmi) DECL(bvc) DECL(bvs) DECL(bcc) DECL(bcs) DECL(bne) DECL(beq)
+DECL(lda_imm) DECL(lda_zp) DECL(lda_zp_x) DECL(lda_abs) DECL(lda_abs_x) DECL(lda_abs_y) DECL(lda_ind_x) DECL(lda_ind_y)
+DECL(ldx_imm) DECL(ldx_zp) DECL(ldx_zp_y) DECL(ldx_abs) DECL(ldx_abs_y)
+DECL(ldy_imm) DECL(ldy_zp) DECL(ldy_zp_x) DECL(ldy_abs) DECL(ldy_abs_x)
+DECL(sta_zp) DECL(sta_zp_x) DECL(sta_abs) DECL(sta_abs_x) DECL(sta_abs_y) DECL(sta_ind_x) DECL(sta_ind_y)
+DECL(stx_zp) DECL(stx_zp_y) DECL(stx_abs)
+DECL(sty_zp) DECL(sty_zp_x) DECL(sty_abs)
+DECL(cmp_imm) DECL(cmp_zp) DECL(cmp_zp_x) DECL(cmp_abs) DECL(cmp_abs_x) DECL(cmp_abs_y) DECL(cmp_ind_x) DECL(cmp_ind_y)
+DECL(cpx_imm) DECL(cpx_zp) DECL(cpx_abs)
+DECL(cpy_imm) DECL(cpy_zp) DECL(cpy_abs)
+DECL(ora_imm) DECL(ora_zp) DECL(ora_zp_x) DECL(ora_abs) DECL(ora_abs_x) DECL(ora_abs_y) DECL(ora_ind_x) DECL(ora_ind_y)
+DECL(eor_imm) DECL(eor_zp) DECL(eor_zp_x) DECL(eor_abs) DECL(eor_abs_x) DECL(eor_abs_y) DECL(eor_ind_x) DECL(eor_ind_y)
+DECL(and_imm) DECL(and_zp) DECL(and_zp_x) DECL(and_abs) DECL(and_abs_x) DECL(and_abs_y) DECL(and_ind_x) DECL(and_ind_y)
+DECL(adc_imm) DECL(adc_zp) DECL(adc_zp_x) DECL(adc_abs) DECL(adc_abs_x) DECL(adc_abs_y) DECL(adc_ind_x) DECL(adc_ind_y)
+DECL(sbc_imm) DECL(sbc_zp) DECL(sbc_zp_x) DECL(sbc_abs) DECL(sbc_abs_x) DECL(sbc_abs_y) DECL(sbc_ind_x) DECL(sbc_ind_y)
+DECL(bit_zp) DECL(bit_abs)
+DECL(inc_zp) DECL(inc_zp_x) DECL(inc_abs) DECL(inc_abs_x)
+DECL(dec_zp) DECL(dec_zp_x) DECL(dec_abs) DECL(dec_abs_x)
+DECL(asl_a) DECL(asl_zp) DECL(asl_zp_x) DECL(asl_abs) DECL(asl_abs_x)
+DECL(lsr_a) DECL(lsr_zp) DECL(lsr_zp_x) DECL(lsr_abs) DECL(lsr_abs_x)
+DECL(rol_a) DECL(rol_zp) DECL(rol_zp_x) DECL(rol_abs) DECL(rol_abs_x)
+DECL(ror_a) DECL(ror_zp) DECL(ror_zp_x) DECL(ror_abs) DECL(ror_abs_x)
+DECL(inx) DECL(dex) DECL(iny) DECL(dey)
+
+static void (* const (op_code[256]))(void) =
+{
+ brk_imm ,ora_ind_x ,jam ,jam ,jam ,ora_zp ,asl_zp ,jam ,
+ php ,ora_imm ,asl_a ,jam ,jam ,ora_abs ,asl_abs ,jam ,
+ bpl ,ora_ind_y ,jam ,jam ,jam ,ora_zp_x ,asl_zp_x ,jam ,
+ clc ,ora_abs_y ,jam ,jam ,jam ,ora_abs_x ,asl_abs_x ,jam ,
+ jsr_abs ,and_ind_x ,jam ,jam ,bit_zp ,and_zp ,rol_zp ,jam ,
+ plp ,and_imm ,rol_a ,jam ,bit_abs ,and_abs ,rol_abs ,jam ,
+ bmi ,and_ind_y ,jam ,jam ,jam ,and_zp_x ,rol_zp_x ,jam ,
+ sec ,and_abs_y ,jam ,jam ,jam ,and_abs_x ,rol_abs_x ,jam ,
+ rti ,eor_ind_x ,jam ,jam ,jam ,eor_zp ,lsr_zp ,jam ,
+ pha ,eor_imm ,lsr_a ,jam ,jmp_abs ,eor_abs ,lsr_abs ,jam ,
+ bvc ,eor_ind_y ,jam ,jam ,jam ,eor_zp_x ,lsr_zp_x ,jam ,
+ cli ,eor_abs_y ,jam ,jam ,jam ,eor_abs_x ,lsr_abs_x ,jam ,
+ rts ,adc_ind_x ,jam ,jam ,jam ,adc_zp ,ror_zp ,jam ,
+ pla ,adc_imm ,ror_a ,jam ,jmp_ind ,adc_abs ,ror_abs ,jam ,
+ bvs ,adc_ind_y ,jam ,jam ,jam ,adc_zp_x ,ror_zp_x ,jam ,
+ sei ,adc_abs_y ,jam ,jam ,jam ,adc_abs_x ,ror_abs_x ,jam ,
+ jam ,sta_ind_x ,jam ,jam ,sty_zp ,sta_zp ,stx_zp ,jam ,
+ dey ,jam ,txa ,jam ,sty_abs ,sta_abs ,stx_abs ,jam ,
+ bcc ,sta_ind_y ,jam ,jam ,sty_zp_x ,sta_zp_x ,stx_zp_y ,jam ,
+ tya ,sta_abs_y ,txs ,jam ,jam ,sta_abs_x ,jam ,jam ,
+ ldy_imm ,lda_ind_x ,ldx_imm ,jam ,ldy_zp ,lda_zp ,ldx_zp ,jam ,
+ tay ,lda_imm ,tax ,jam ,ldy_abs ,lda_abs ,ldx_abs ,jam ,
+ bcs ,lda_ind_y ,jam ,jam ,ldy_zp_x ,lda_zp_x ,ldx_zp_y ,jam ,
+ clv ,lda_abs_y ,tsx ,jam ,ldy_abs_x ,lda_abs_x ,ldx_abs_y ,jam ,
+ cpy_imm ,cmp_ind_x ,jam ,jam ,cpy_zp ,cmp_zp ,dec_zp ,jam ,
+ iny ,cmp_imm ,dex ,jam ,cpy_abs ,cmp_abs ,dec_abs ,jam ,
+ bne ,cmp_ind_y ,jam ,jam ,jam ,cmp_zp_x ,dec_zp_x ,jam ,
+ cld ,cmp_abs_y ,jam ,jam ,jam ,cmp_abs_x ,dec_abs_x ,jam ,
+ cpx_imm ,sbc_ind_x ,jam ,jam ,cpx_zp ,sbc_zp ,inc_zp ,jam ,
+ inx ,sbc_imm ,nop ,jam ,cpx_abs ,sbc_abs ,inc_abs ,jam ,
+ beq ,sbc_ind_y ,jam ,jam ,jam ,sbc_zp_x ,inc_zp_x ,jam ,
+ sed ,sbc_abs_y ,jam ,jam ,jam ,sbc_abs_x ,inc_abs_x ,jam ,
+};
+
+void set_c_flag(int enable)
+{
+ int tmp;
+ tmp = get_sr();
+ tmp &= ~FLAG_C;
+ if(enable)
+ tmp |= FLAG_C;
+ set_sr(tmp);
+}
+
+void set_z_flag(int enable)
+{
+ int tmp;
+ tmp = get_sr();
+ tmp &= ~FLAG_Z;
+ if(enable)
+ tmp |= FLAG_Z;
+ set_sr(tmp);
+}
+
+void set_pc(int addr)
+{
+ pc = addr;
+}
+
+int get_pc(void)
+{
+ return pc;
+}
+
+int get_a(void)
+{
+ return accumulator;
+}
+
+int get_x(void)
+{
+ return register_x;
+}
+
+int get_y(void)
+{
+ return register_y;
+}
+
+void init_cpu(int (*cpu_read)(int), void (*cpu_write)(int, int), int (*cpu_read_page)(int), void (*cpu_write_page)(int, int), void (*cpu_jam)(int, int))
+{
+ read_bus = cpu_read;
+ write_bus = cpu_write;
+ read_page = cpu_read_page;
+ write_page = cpu_write_page;
+ jam_handler = cpu_jam;
+ accumulator = 0;
+ register_x = 0;
+ register_y = 0;
+ pc = sp = 0;
+ set_sr(FLAG_X | FLAG_B | FLAG_I);
+ cycles = 0;
+ reset_cpu = rst;
+ raise_nmi = nmi;
+ raise_irq = irq;
+ exec_cpu = jam;
+ first_trap = 0;
+}
+
+static int trap(void)
+{
+ trap_t *trap;
+ for(trap = first_trap;trap != 0;trap = trap->next_trap)
+ {
+ if(trap->addr == (pc - 1))
+ return trap->handler();
+ }
+ return -1;
+}
+
+static int install_trap(trap_t *trap, void (*poke)(int, int), int (*peek)(int))
+{
+ int i;
+ for(i = sizeof(trap->org) / sizeof(trap->org[0]);i-- > 0;)
+ {
+ if(peek(trap->addr + i) != trap->org[i])
+ return -1;
+ }
+ poke(trap->addr, 0x00);
+ trap->next_trap = first_trap;
+ first_trap = trap;
+ return 0;
+}
+
+void install_traps(int cnt, trap_t *tbl, void (*poke)(int, int), int (*peek)(int))
+{
+ while(cnt-- > 0)
+ (void)install_trap(&tbl[cnt], poke, peek);
+}
+
+#define CYCLES(AMOUNT) cycles += AMOUNT;
+
+#define PUSH(DATA) { write_page(sp | 0x0100, DATA); sp = (sp - 1) & 0xff; }
+#define POP() read_page((sp = (sp + 1) & 0xff) | 0x0100)
+
+#define JMP_ABSOLUTE(EA) \
+{ \
+ (EA) = read_bus(tmp1 = pc); \
+ (EA) |= read_bus(tmp1 + 1) << 8; \
+ CYCLES(3); \
+}
+
+#define JMP_INDIRECT(EA) \
+{ \
+ tmp2 = read_bus(pc++); \
+ tmp1 = read_bus(pc++) << 8; \
+ (EA) = read_bus(tmp2 | tmp1); \
+ (EA) |= read_bus((((tmp2 + 1) & 0x00ff) | tmp1)) << 8; \
+ CYCLES(5); \
+}
+
+#define READ_IMMEDIATE(EA) \
+{ \
+ (EA) = pc++; \
+ CYCLES(2); \
+}
+
+#define READ_ZERO_PAGE(EA) \
+{ \
+ (EA) = read_bus(pc++); \
+ CYCLES(3); \
+}
+
+#define READ_ZERO_PAGE_X(EA) \
+{ \
+ (EA) = (read_bus(pc++) + register_x) & 0xff; \
+ CYCLES(4); \
+}
+
+#define READ_ZERO_PAGE_Y(EA) \
+{ \
+ (EA) = (read_bus(pc++) + register_y) & 0xff; \
+ CYCLES(4); \
+}
+
+#define READ_ABSOLUTE(EA) \
+{ \
+ tmp1 = read_bus(pc++); \
+ (EA) = tmp1 + (read_bus(pc++) << 8); \
+ CYCLES(4); \
+}
+
+#define READ_ABSOLUTE_X(EA) \
+{ \
+ tmp1 = read_bus(pc++) + register_x; \
+ (EA) = tmp1 + (read_bus(pc++) << 8); \
+ CYCLES(tmp1 > 0xff ? 5 : 4); \
+}
+
+#define READ_ABSOLUTE_Y(EA) \
+{ \
+ tmp1 = read_bus(pc++) + register_y; \
+ (EA) = tmp1 + (read_bus(pc++) << 8); \
+ CYCLES(tmp1 > 0xff ? 5 : 4); \
+}
+
+#define READ_INDIRECT_X(EA) \
+{ \
+ tmp1 = read_bus(pc++) + register_x; \
+ (EA) = read_page(tmp1) + (read_page((tmp1 + 1) & 0xff) << 8); \
+ CYCLES(6); \
+}
+
+#define READ_INDIRECT_Y(EA) \
+{ \
+ tmp1 = read_bus(pc++); \
+ tmp2 = read_page(tmp1++) + register_y; \
+ (EA) = tmp2 + ((read_page(tmp1 & 0xff)) << 8); \
+ CYCLES(tmp2 > 0xff ? 6 : 5); \
+}
+
+#define WRITE_ZERO_PAGE(EA) READ_ZERO_PAGE(EA)
+#define WRITE_ZERO_PAGE_X(EA) READ_ZERO_PAGE_X(EA)
+#define WRITE_ZERO_PAGE_Y(EA) READ_ZERO_PAGE_Y(EA)
+#define WRITE_ABSOLUTE(EA) READ_ABSOLUTE(EA)
+
+#define WRITE_ABSOLUTE_X(EA) \
+{ \
+ tmp1 = read_bus(pc++) + register_x; \
+ (EA) = tmp1 + (read_bus(pc++) << 8); \
+ CYCLES(5); \
+}
+
+#define WRITE_ABSOLUTE_Y(EA) \
+{ \
+ tmp1 = read_bus(pc++) + register_y; \
+ (EA) = tmp1 + (read_bus(pc++) << 8); \
+ CYCLES(5); \
+}
+
+#define WRITE_INDIRECT_X(EA) READ_INDIRECT_X(EA)
+
+#define WRITE_INDIRECT_Y(EA) \
+{ \
+ tmp1 = read_bus(pc++); \
+ tmp2 = read_page(tmp1++) + register_y; \
+ (EA) = tmp2 + (read_page(tmp1 & 0xff) << 8); \
+ CYCLES(6); \
+}
+
+#define RELATIVE(S) \
+{ \
+ tmp1 = read_bus(pc++); \
+ if((S) != 0) \
+ { \
+ if((tmp1 & 0x0080) != 0) tmp1 -= 0x100; \
+ CYCLES((((pc ^ (pc + tmp1)) & 0xff00) != 0) ? 4 : 3); \
+ pc += tmp1; \
+ } \
+ else \
+ { \
+ CYCLES(2); \
+ } \
+}
+
+BEGIN(jam)
+ --pc;
+ if(jam_handler != 0)
+ jam_handler(pc, read_bus(pc));
+ CYCLES(1);
+END
+
+BEGIN(nmi)
+ --pc;
+ PUSH(pc >> 8);
+ PUSH(pc);
+ PUSH(get_sr() & ~FLAG_B);
+ pc = read_bus(NMI_VECTOR) | (read_bus(NMI_VECTOR + 1) << 8);
+ CYCLES(7);
+END
+
+BEGIN(rst)
+ PUSH(get_sr() & ~FLAG_B);
+ pc = read_bus(RST_VECTOR) | (read_bus(RST_VECTOR + 1) << 8);
+ CYCLES(5);
+END
+
+BEGIN(irq)
+ if(TEST_I()) return;
+ --pc;
+ PUSH(pc >> 8);
+ PUSH(pc);
+ PUSH(get_sr() & ~FLAG_B);
+ SET_I();
+ pc = read_bus(IRQ_VECTOR) | (read_bus(IRQ_VECTOR + 1) << 8);
+ CYCLES(7);
+END
+
+BEGIN(brk_imm)
+ if(trap() != 0)
+ {
+ pc++;
+ PUSH(get_sr());
+ PUSH(pc >> 8);
+ PUSH(pc);
+ SET_I();
+ pc = read_bus(IRQ_VECTOR) | (read_bus(IRQ_VECTOR + 1) << 8);
+ CYCLES(7);
+ }
+END
+
+BEGIN(nop) CYCLES(2) END
+
+BEGIN(rti)
+ set_sr(POP() | FLAG_B);
+ tmp1 = POP();
+ pc = tmp1 | (POP() << 8);
+ CYCLES(6);
+END
+
+BEGIN(rts)
+ tmp1 = POP();
+ pc = (tmp1 | (POP() << 8)) + 1;
+CYCLES(6) END
+
+BEGIN(jsr_abs)
+ tmp1 = read_bus(pc++);
+ PUSH(pc >> 8);
+ PUSH(pc);
+ pc = tmp1 | (read_bus(pc++) << 8);
+ CYCLES(6);
+END
+
+BEGIN(jmp_abs) JMP_ABSOLUTE(pc) END
+BEGIN(jmp_ind) JMP_INDIRECT(pc) END
+
+BEGIN(php) PUSH(get_sr()) CYCLES(3) END
+BEGIN(plp) set_sr(POP() | FLAG_B); CYCLES(4) END
+BEGIN(pha) PUSH(accumulator) CYCLES(3) END
+BEGIN(pla) nz = accumulator = POP(); CYCLES(4) END
+
+BEGIN(tax) nz = register_x = accumulator; CYCLES(2) END
+BEGIN(txa) nz = accumulator = register_x; CYCLES(2) END
+BEGIN(tay) nz = register_y = accumulator; CYCLES(2) END
+BEGIN(tya) nz = accumulator = register_y; CYCLES(2) END
+BEGIN(txs) sp = register_x; CYCLES(2) END
+BEGIN(tsx) nz = register_x = sp; CYCLES(2) END
+
+BEGIN(inx) nz = register_x = (register_x + 1) & 0xff; CYCLES(2) END
+BEGIN(dex) nz = register_x = (register_x - 1) & 0xff; CYCLES(2) END
+BEGIN(iny) nz = register_y = (register_y + 1) & 0xff; CYCLES(2) END
+BEGIN(dey) nz = register_y = (register_y - 1) & 0xff; CYCLES(2) END
+
+BEGIN(clc) CLEAR_C() CYCLES(2) END
+BEGIN(sec) SET_C() CYCLES(2) END
+BEGIN(cli) CLEAR_I() CYCLES(2) END
+BEGIN(sei) SET_I() CYCLES(2) END
+BEGIN(clv) CLEAR_V() CYCLES(2) END
+BEGIN(cld) CLEAR_D() CYCLES(2) END
+BEGIN(sed) SET_D() CYCLES(2) END
+
+BEGIN(bpl) RELATIVE(!TEST_N()) END
+BEGIN(bmi) RELATIVE(TEST_N()) END
+BEGIN(bvc) RELATIVE(!TEST_V()) END
+BEGIN(bvs) RELATIVE(TEST_V()) END
+BEGIN(bcc) RELATIVE(!TEST_C()) END
+BEGIN(bcs) RELATIVE(TEST_C()) END
+BEGIN(bne) RELATIVE(!TEST_Z()) END
+BEGIN(beq) RELATIVE(TEST_Z()) END
+
+BEGIN(lda_imm) READ_IMMEDIATE(ea) nz = accumulator = read_bus(ea); END
+BEGIN(lda_zp) READ_ZERO_PAGE(ea) nz = accumulator = read_page(ea); END
+BEGIN(lda_zp_x) READ_ZERO_PAGE_X(ea) nz = accumulator = read_page(ea); END
+BEGIN(lda_abs) READ_ABSOLUTE(ea) nz = accumulator = read_bus(ea); END
+BEGIN(lda_abs_x) READ_ABSOLUTE_X(ea) nz = accumulator = read_bus(ea); END
+BEGIN(lda_abs_y) READ_ABSOLUTE_Y(ea) nz = accumulator = read_bus(ea); END
+BEGIN(lda_ind_x) READ_INDIRECT_X(ea) nz = accumulator = read_bus(ea); END
+BEGIN(lda_ind_y) READ_INDIRECT_Y(ea) nz = accumulator = read_bus(ea); END
+
+BEGIN(ldx_imm) READ_IMMEDIATE(ea) nz = register_x = read_bus(ea); END
+BEGIN(ldx_zp) READ_ZERO_PAGE(ea) nz = register_x = read_page(ea); END
+BEGIN(ldx_zp_y) READ_ZERO_PAGE_Y(ea) nz = register_x = read_page(ea); END
+BEGIN(ldx_abs) READ_ABSOLUTE(ea) nz = register_x = read_bus(ea); END
+BEGIN(ldx_abs_y) READ_ABSOLUTE_Y(ea) nz = register_x = read_bus(ea); END
+
+BEGIN(ldy_imm) READ_IMMEDIATE(ea) nz = register_y = read_bus(ea); END
+BEGIN(ldy_zp) READ_ZERO_PAGE(ea) nz = register_y = read_page(ea); END
+BEGIN(ldy_zp_x) READ_ZERO_PAGE_X(ea) nz = register_y = read_page(ea); END
+BEGIN(ldy_abs) READ_ABSOLUTE(ea) nz = register_y = read_bus(ea); END
+BEGIN(ldy_abs_x) READ_ABSOLUTE_X(ea) nz = register_y = read_bus(ea); END
+
+BEGIN(sta_zp) WRITE_ZERO_PAGE(ea) write_page(ea, accumulator); END
+BEGIN(sta_zp_x) WRITE_ZERO_PAGE_X(ea) write_page(ea, accumulator); END
+BEGIN(sta_abs) WRITE_ABSOLUTE(ea) write_bus(ea, accumulator); END
+BEGIN(sta_abs_x) WRITE_ABSOLUTE_X(ea) write_bus(ea, accumulator); END
+BEGIN(sta_abs_y) WRITE_ABSOLUTE_Y(ea) write_bus(ea, accumulator); END
+BEGIN(sta_ind_x) WRITE_INDIRECT_X(ea) write_bus(ea, accumulator); END
+BEGIN(sta_ind_y) WRITE_INDIRECT_Y(ea) write_bus(ea, accumulator); END
+
+BEGIN(stx_zp) WRITE_ZERO_PAGE(ea) write_page(ea, register_x); END
+BEGIN(stx_zp_y) WRITE_ZERO_PAGE_Y(ea) write_page(ea, register_x); END
+BEGIN(stx_abs) WRITE_ABSOLUTE(ea) write_bus(ea, register_x); END
+
+BEGIN(sty_zp) WRITE_ZERO_PAGE(ea) write_page(ea, register_y); END
+BEGIN(sty_zp_x) WRITE_ZERO_PAGE_X(ea) write_page(ea, register_y); END
+BEGIN(sty_abs) WRITE_ABSOLUTE(ea) write_bus(ea, register_y); END
+
+#define COMPARE(A, B) \
+{ \
+ nz = ((A) & 0xff) - ((B) & 0xff); \
+ c = ~nz; \
+ nz &= 0xff;\
+}
+
+BEGIN(cmp_imm) READ_IMMEDIATE(ea) COMPARE(accumulator, read_bus(ea)) END
+BEGIN(cmp_zp) READ_ZERO_PAGE(ea) COMPARE(accumulator, read_bus(ea)) END
+BEGIN(cmp_zp_x) READ_ZERO_PAGE_X(ea) COMPARE(accumulator, read_bus(ea)) END
+BEGIN(cmp_abs) READ_ABSOLUTE(ea) COMPARE(accumulator, read_bus(ea)) END
+BEGIN(cmp_abs_x) READ_ABSOLUTE_X(ea) COMPARE(accumulator, read_bus(ea)) END
+BEGIN(cmp_abs_y) READ_ABSOLUTE_Y(ea) COMPARE(accumulator, read_bus(ea)) END
+BEGIN(cmp_ind_x) READ_INDIRECT_X(ea) COMPARE(accumulator, read_bus(ea)) END
+BEGIN(cmp_ind_y) READ_INDIRECT_Y(ea) COMPARE(accumulator, read_bus(ea)) END
+
+BEGIN(cpx_imm) READ_IMMEDIATE(ea) COMPARE(register_x, read_bus(ea)) END
+BEGIN(cpx_zp) READ_ZERO_PAGE(ea) COMPARE(register_x, read_bus(ea)) END
+BEGIN(cpx_abs) READ_ABSOLUTE(ea) COMPARE(register_x, read_bus(ea)) END
+
+BEGIN(cpy_imm) READ_IMMEDIATE(ea) COMPARE(register_y, read_bus(ea)) END
+BEGIN(cpy_zp) READ_ZERO_PAGE(ea) COMPARE(register_y, read_bus(ea)) END
+BEGIN(cpy_abs) READ_ABSOLUTE(ea) COMPARE(register_y, read_bus(ea)) END
+
+#define ORA(A, B) \
+{ \
+ (A) |= (B); \
+ nz = (A) & 0xff; \
+}
+
+BEGIN(ora_imm) READ_IMMEDIATE(ea) ORA(accumulator, read_bus(ea)) END
+BEGIN(ora_zp) READ_ZERO_PAGE(ea) ORA(accumulator, read_bus(ea)) END
+BEGIN(ora_zp_x) READ_ZERO_PAGE_X(ea) ORA(accumulator, read_bus(ea)) END
+BEGIN(ora_abs) READ_ABSOLUTE(ea) ORA(accumulator, read_bus(ea)) END
+BEGIN(ora_abs_x) READ_ABSOLUTE_X(ea) ORA(accumulator, read_bus(ea)) END
+BEGIN(ora_abs_y) READ_ABSOLUTE_Y(ea) ORA(accumulator, read_bus(ea)) END
+BEGIN(ora_ind_x) READ_INDIRECT_X(ea) ORA(accumulator, read_bus(ea)) END
+BEGIN(ora_ind_y) READ_INDIRECT_Y(ea) ORA(accumulator, read_bus(ea)) END
+
+#define EOR(A, B) \
+{ \
+ (A) ^= (B); \
+ nz = (A) & 0xff; \
+}
+
+BEGIN(eor_imm) READ_IMMEDIATE(ea) EOR(accumulator, read_bus(ea)) END
+BEGIN(eor_zp) READ_ZERO_PAGE(ea) EOR(accumulator, read_bus(ea)) END
+BEGIN(eor_zp_x) READ_ZERO_PAGE_X(ea) EOR(accumulator, read_bus(ea)) END
+BEGIN(eor_abs) READ_ABSOLUTE(ea) EOR(accumulator, read_bus(ea)) END
+BEGIN(eor_abs_x) READ_ABSOLUTE_X(ea) EOR(accumulator, read_bus(ea)) END
+BEGIN(eor_abs_y) READ_ABSOLUTE_Y(ea) EOR(accumulator, read_bus(ea)) END
+BEGIN(eor_ind_x) READ_INDIRECT_X(ea) EOR(accumulator, read_bus(ea)) END
+BEGIN(eor_ind_y) READ_INDIRECT_Y(ea) EOR(accumulator, read_bus(ea)) END
+
+#define AND(A, B) \
+{ \
+ (A) &= (B); \
+ nz = (A) & 0xff; \
+}
+
+BEGIN(and_imm) READ_IMMEDIATE(ea) AND(accumulator, read_bus(ea)) END
+BEGIN(and_zp) READ_ZERO_PAGE(ea) AND(accumulator, read_bus(ea)) END
+BEGIN(and_zp_x) READ_ZERO_PAGE_X(ea) AND(accumulator, read_bus(ea)) END
+BEGIN(and_abs) READ_ABSOLUTE(ea) AND(accumulator, read_bus(ea)) END
+BEGIN(and_abs_x) READ_ABSOLUTE_X(ea) AND(accumulator, read_bus(ea)) END
+BEGIN(and_abs_y) READ_ABSOLUTE_Y(ea) AND(accumulator, read_bus(ea)) END
+BEGIN(and_ind_x) READ_INDIRECT_X(ea) AND(accumulator, read_bus(ea)) END
+BEGIN(and_ind_y) READ_INDIRECT_Y(ea) AND(accumulator, read_bus(ea)) END
+
+#define ADC(B)\
+{\
+ tmp2 = (B) & 0xff;\
+ c = nz = tmp1 = (accumulator & 0xff) + tmp2 + ((c & 0x100) >> 8);\
+ sr = ((~(accumulator ^ tmp2)) & (accumulator ^ tmp1) & 0x80) ? sr | FLAG_V : sr & ~FLAG_V; \
+ accumulator = tmp1;\
+ nz &= 0xff;\
+}
+
+BEGIN(adc_imm) READ_IMMEDIATE(ea) ADC(read_bus(ea)) END
+BEGIN(adc_zp) READ_ZERO_PAGE(ea) ADC(read_bus(ea)) END
+BEGIN(adc_zp_x) READ_ZERO_PAGE_X(ea) ADC(read_bus(ea)) END
+BEGIN(adc_abs) READ_ABSOLUTE(ea) ADC(read_bus(ea)) END
+BEGIN(adc_abs_x) READ_ABSOLUTE_X(ea) ADC(read_bus(ea)) END
+BEGIN(adc_abs_y) READ_ABSOLUTE_Y(ea) ADC(read_bus(ea)) END
+BEGIN(adc_ind_x) READ_INDIRECT_X(ea) ADC(read_bus(ea)) END
+BEGIN(adc_ind_y) READ_INDIRECT_Y(ea) ADC(read_bus(ea)) END
+
+#define SBC(B)\
+{\
+ tmp2 = (B) & 0xff;\
+ c = nz = tmp1 = (accumulator & 0xff) - tmp2 - (((~c) & 0x100) >> 8);\
+ c = ~c;\
+ sr = ((accumulator ^ (B)) & (accumulator ^ tmp1) & 0x80) ? sr | FLAG_V : sr & ~FLAG_V; \
+ accumulator = tmp1;\
+ nz &= 0xff;\
+}
+
+BEGIN(sbc_imm) READ_IMMEDIATE(ea) SBC(read_bus(ea)) END
+BEGIN(sbc_zp) READ_ZERO_PAGE(ea) SBC(read_bus(ea)) END
+BEGIN(sbc_zp_x) READ_ZERO_PAGE_X(ea) SBC(read_bus(ea)) END
+BEGIN(sbc_abs) READ_ABSOLUTE(ea) SBC(read_bus(ea)) END
+BEGIN(sbc_abs_x) READ_ABSOLUTE_X(ea) SBC(read_bus(ea)) END
+BEGIN(sbc_abs_y) READ_ABSOLUTE_Y(ea) SBC(read_bus(ea)) END
+BEGIN(sbc_ind_x) READ_INDIRECT_X(ea) SBC(read_bus(ea)) END
+BEGIN(sbc_ind_y) READ_INDIRECT_Y(ea) SBC(read_bus(ea)) END
+
+#define BIT(B) \
+{ \
+ tmp2 = (B);\
+ sr = get_sr();\
+ sr = (tmp2 & 0x40) != 0 ? sr | FLAG_V : sr & ~FLAG_V; \
+ sr = (tmp2 & 0x80) != 0 ? sr | FLAG_N : sr & ~FLAG_N; \
+ sr = ((accumulator & 0xff) & tmp2) == 0 ? sr | FLAG_Z : sr & ~FLAG_Z; \
+ set_sr(sr);\
+}
+
+BEGIN(bit_zp) READ_ZERO_PAGE(ea) BIT(read_page(ea)) END
+BEGIN(bit_abs) READ_ABSOLUTE(ea) BIT(read_page(ea)) END
+
+BEGIN(inc_zp) READ_ZERO_PAGE(ea) nz = (read_page(ea) + 1) & 0xff; write_page(ea, nz); END
+BEGIN(inc_zp_x) READ_ZERO_PAGE_X(ea) nz = (read_page(ea) + 1) & 0xff; write_page(ea, nz); END
+BEGIN(inc_abs) READ_ABSOLUTE(ea) nz = (read_bus(ea) + 1) & 0xff; write_bus(ea, nz); END
+BEGIN(inc_abs_x) READ_ABSOLUTE_X(ea) nz = (read_bus(ea) + 1) & 0xff; write_bus(ea, nz); END
+
+BEGIN(dec_zp) READ_ZERO_PAGE(ea) nz = (read_page(ea) - 1) & 0xff; write_page(ea, nz); END
+BEGIN(dec_zp_x) READ_ZERO_PAGE_X(ea) nz = (read_page(ea) - 1) & 0xff; write_page(ea, nz); END
+BEGIN(dec_abs) READ_ABSOLUTE(ea) nz = (read_bus(ea) - 1) & 0xff; write_bus(ea, nz); END
+BEGIN(dec_abs_x) READ_ABSOLUTE_X(ea) nz = (read_bus(ea) - 1) & 0xff; write_bus(ea, nz); END
+
+#define ASL(A) \
+{\
+ (A) = nz = c = (((A) & 0xff) << 1);\
+ nz &= 0xff;\
+}
+
+BEGIN(asl_a) ASL(accumulator) CYCLES(2) END
+BEGIN(asl_zp) READ_ZERO_PAGE(ea) tmp1 = read_page(ea); ASL(tmp1) write_page(ea, tmp1); CYCLES(2) END
+BEGIN(asl_zp_x) READ_ZERO_PAGE_X(ea) tmp1 = read_page(ea); ASL(tmp1) write_page(ea, tmp1); CYCLES(2) END
+BEGIN(asl_abs) READ_ABSOLUTE(ea) tmp1 = read_bus(ea); ASL(tmp1) write_bus(ea, tmp1); CYCLES(2) END
+BEGIN(asl_abs_x) READ_ABSOLUTE_X(ea) tmp1 = read_bus(ea); ASL(tmp1) write_bus(ea, tmp1); CYCLES(2) END
+
+#define LSR(A)\
+{\
+ nz = ((A) & 0xff);\
+ c = nz << 8;\
+ nz = (A) = nz >> 1;\
+}
+
+BEGIN(lsr_a) LSR(accumulator) CYCLES(2) END
+BEGIN(lsr_zp) READ_ZERO_PAGE(ea) tmp1 = read_page(ea); LSR(tmp1) write_page(ea, tmp1); CYCLES(2) END
+BEGIN(lsr_zp_x) READ_ZERO_PAGE_X(ea) tmp1 = read_page(ea); LSR(tmp1) write_page(ea, tmp1); CYCLES(2) END
+BEGIN(lsr_abs) READ_ABSOLUTE(ea) tmp1 = read_bus(ea); LSR(tmp1) write_bus(ea, tmp1); CYCLES(2) END
+BEGIN(lsr_abs_x) READ_ABSOLUTE_X(ea) tmp1 = read_bus(ea); LSR(tmp1) write_bus(ea, tmp1); CYCLES(2) END
+
+#define ROL(A) \
+{\
+ (A) = nz = c = (((A) & 0xff) << 1) | ((c & 0x100) >> 8);\
+ nz &= 0xff;\
+}
+
+BEGIN(rol_a) ROL(accumulator) CYCLES(2) END
+BEGIN(rol_zp) READ_ZERO_PAGE(ea) tmp1 = read_page(ea); ROL(tmp1) write_page(ea, tmp1); CYCLES(2) END
+BEGIN(rol_zp_x) READ_ZERO_PAGE_X(ea) tmp1 = read_page(ea); ROL(tmp1) write_page(ea, tmp1); CYCLES(2) END
+BEGIN(rol_abs) READ_ABSOLUTE(ea) tmp1 = read_bus(ea); ROL(tmp1) write_bus(ea, tmp1); CYCLES(2) END
+BEGIN(rol_abs_x) READ_ABSOLUTE_X(ea) tmp1 = read_bus(ea); ROL(tmp1) write_bus(ea, tmp1); CYCLES(2) END
+
+#define ROR(A)\
+{\
+ nz = ((A) & 0xff) | (c & 0x100);\
+ c = nz << 8; \
+ nz = (A) = nz >> 1;\
+}
+
+BEGIN(ror_a) ROR(accumulator) CYCLES(2) END
+BEGIN(ror_zp) READ_ZERO_PAGE(ea) tmp1 = read_page(ea); ROR(tmp1) write_page(ea, tmp1); CYCLES(2) END
+BEGIN(ror_zp_x) READ_ZERO_PAGE_X(ea) tmp1 = read_page(ea); ROR(tmp1) write_page(ea, tmp1); CYCLES(2) END
+BEGIN(ror_abs) READ_ABSOLUTE(ea) tmp1 = read_bus(ea); ROR(tmp1) write_bus(ea, tmp1); CYCLES(2) END
+BEGIN(ror_abs_x) READ_ABSOLUTE_X(ea) tmp1 = read_bus(ea); ROR(tmp1) write_bus(ea, tmp1); CYCLES(2) END
+
+