diff options
Diffstat (limited to 'c64/cpu.c')
| -rw-r--r-- | c64/cpu.c | 678 |
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 + + |
