From e8ff6bf2ab9982c5e5ab8d8f4e7adcc5207d079d Mon Sep 17 00:00:00 2001 From: Peter Fors Date: Sat, 29 Mar 2025 19:57:00 +0100 Subject: first mknes commit --- cpu_opcodes.c | 2287 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 2287 insertions(+) create mode 100644 cpu_opcodes.c (limited to 'cpu_opcodes.c') diff --git a/cpu_opcodes.c b/cpu_opcodes.c new file mode 100644 index 0000000..2d308da --- /dev/null +++ b/cpu_opcodes.c @@ -0,0 +1,2287 @@ + + +// ADC + +static inline void adc(struct cpu_state * restrict cpu, uint8_t value) { +#ifdef ENABLE_DECIMAL_MODE + if(cpu->d) { + uint8_t al = (cpu->a & 0x0f) + (value & 0x0f) + cpu->c; + uint8_t ah = (cpu->a >> 4) + (value >> 4); + if(al > 9) { + al += 6; + ah++; + } + cpu->c = (ah > 9); + if(cpu->c) { + ah += 6; + } + cpu->a = (ah << 4) | (al & 0x0f); + update_zn(cpu, cpu->a); + // Note: overflow flag behavior in decimal mode is undefined on 6502 + return; + } +#endif + + uint16_t sum = cpu->a + value + cpu->c; + cpu->c = (sum > 0xff); + uint8_t result = sum & 0xff; + cpu->v = (~(cpu->a ^ value) & (cpu->a ^ result)) & 0x80 ? 1 : 0; + cpu->a = result; + update_zn(cpu, result); +} + + +// ADC ($nn,X) +static void opcode_adc_indx(struct nes_state * restrict state) { + struct cpu_state * restrict cpu = &state->cpu; + + uint8_t zp = memory_read(state, cpu->pc++); // T1 + memory_read_dummy(state, zp); // T2 + + uint8_t ptr = (zp + cpu->x) & 0xff; + uint8_t lo = memory_read(state, ptr); // T3 + uint8_t hi = memory_read(state, (ptr + 1) & 0xff); // T4 + uint16_t addr = lo | (hi << 8); + + uint8_t value = memory_read(state, addr); // T5 + + adc(cpu, value); // T6+ +} + +// ADC $nn +static void opcode_adc_zp(struct nes_state * restrict state) { + struct cpu_state * restrict cpu = &state->cpu; + + uint8_t addr = memory_read(state, cpu->pc++); // T1 + uint8_t value = memory_read(state, addr); // T2 + + adc(cpu, value); // T3 +} + +// ADC #$nn +static void opcode_adc_imm(struct nes_state * restrict state) { + struct cpu_state * restrict cpu = &state->cpu; + + uint8_t value = memory_read(state, cpu->pc++); // T1 + adc(cpu, value); // T2 +} + +// ADC $nnnn +static void opcode_adc_abs(struct nes_state * restrict state) { + struct cpu_state * restrict cpu = &state->cpu; + + uint8_t lo = memory_read(state, cpu->pc++); // T1 + uint8_t hi = memory_read(state, cpu->pc++); // T2 + uint16_t addr = lo | (hi << 8); + + uint8_t value = memory_read(state, addr); // T3 + adc(cpu, value); // T4 +} + +// ADC ($nn),Y +static void opcode_adc_indy(struct nes_state * restrict state) { + struct cpu_state * restrict cpu = &state->cpu; + + uint8_t zp = memory_read(state, cpu->pc++); // T1 + uint8_t lo = memory_read(state, zp); // T2 + uint8_t hi = memory_read(state, (zp + 1) & 0xff); // T3 + + uint16_t base = lo | (hi << 8); + uint16_t addr = base + cpu->y; + + if((base & 0xff00) != (addr & 0xff00)) { + memory_read_dummy(state, (base & 0xff00) | (addr & 0x00ff)); // T4 (dummy if crossed) + } + + uint8_t value = memory_read(state, addr); // T4 or T5 + adc(cpu, value); // T5 or T6 +} + +// ADC $nn,X +static void opcode_adc_zpx(struct nes_state * restrict state) { + struct cpu_state * restrict cpu = &state->cpu; + + uint8_t base = memory_read(state, cpu->pc++); // T1 + memory_read_dummy(state, base); // T2 + uint8_t addr = (base + cpu->x) & 0xff; + + uint8_t value = memory_read(state, addr); // T3 + adc(cpu, value); // T4 +} + +// ADC $nnnn,Y +static void opcode_adc_absy(struct nes_state * restrict state) { + struct cpu_state * restrict cpu = &state->cpu; + + uint8_t lo = memory_read(state, cpu->pc++); // T1 + uint8_t hi = memory_read(state, cpu->pc++); // T2 + uint16_t base = lo | (hi << 8); + uint16_t addr = base + cpu->y; + + if((base & 0xff00) != (addr & 0xff00)) { + memory_read_dummy(state, (base & 0xff00) | (addr & 0x00ff)); // T3 dummy + } + + uint8_t value = memory_read(state, addr); // T3 or T4 + adc(cpu, value); // T4 or T5 +} + +// ADC $nnnn,X +static void opcode_adc_absx(struct nes_state * restrict state) { + struct cpu_state * restrict cpu = &state->cpu; + + uint8_t lo = memory_read(state, cpu->pc++); // T1 + uint8_t hi = memory_read(state, cpu->pc++); // T2 + uint16_t base = lo | (hi << 8); + uint16_t addr = base + cpu->x; + + if((base & 0xff00) != (addr & 0xff00)) { + memory_read_dummy(state, (base & 0xff00) | (addr & 0x00ff)); // T3 dummy + } + + uint8_t value = memory_read(state, addr); // T3 or T4 + adc(cpu, value); // T4 or T5 +} + + +// AND ($nn,X) +static void opcode_and_indx(struct nes_state * restrict state) { + struct cpu_state * restrict cpu = &state->cpu; + + uint8_t zp = memory_read(state, cpu->pc++); // T1 + memory_read_dummy(state, zp); // T2 + + uint8_t ptr = (zp + cpu->x) & 0xff; + uint8_t lo = memory_read(state, ptr); // T3 + uint8_t hi = memory_read(state, (ptr + 1) & 0xff); // T4 + uint16_t addr = lo | (hi << 8); + + uint8_t value = memory_read(state, addr); // T5 + + cpu->a &= value; // T6+ + update_zn(cpu, cpu->a); +} + +// AND $nn +static void opcode_and_zp(struct nes_state * restrict state) { + struct cpu_state * restrict cpu = &state->cpu; + + uint8_t addr = memory_read(state, cpu->pc++); // T1 + uint8_t value = memory_read(state, addr); // T2 + + cpu->a &= value; // T3 + update_zn(cpu, cpu->a); +} + +// AND #$nn +static void opcode_and_imm(struct nes_state * restrict state) { + struct cpu_state * restrict cpu = &state->cpu; + + uint8_t value = memory_read(state, cpu->pc++); // T1 + cpu->a &= value; // T2 + update_zn(cpu, cpu->a); +} + +// AND $nnnn +static void opcode_and_abs(struct nes_state * restrict state) { + struct cpu_state * restrict cpu = &state->cpu; + + uint8_t lo = memory_read(state, cpu->pc++); // T1 + uint8_t hi = memory_read(state, cpu->pc++); // T2 + uint16_t addr = lo | (hi << 8); + + uint8_t value = memory_read(state, addr); // T3 + cpu->a &= value; // T4 + update_zn(cpu, cpu->a); +} + +// AND ($nn),Y +static void opcode_and_indy(struct nes_state * restrict state) { + struct cpu_state * restrict cpu = &state->cpu; + + uint8_t zp = memory_read(state, cpu->pc++); // T1 + uint8_t lo = memory_read(state, zp); // T2 + uint8_t hi = memory_read(state, (zp + 1) & 0xff); // T3 + + uint16_t base = lo | (hi << 8); + uint16_t addr = base + cpu->y; + + if((base & 0xff00) != (addr & 0xff00)) { + memory_read_dummy(state, (base & 0xff00) | (addr & 0x00ff)); // T4 dummy + } + + uint8_t value = memory_read(state, addr); // T4 or T5 + cpu->a &= value; // T5 or T6 + update_zn(cpu, cpu->a); +} + +// AND $nn,X +static void opcode_and_zpx(struct nes_state * restrict state) { + struct cpu_state * restrict cpu = &state->cpu; + + uint8_t base = memory_read(state, cpu->pc++); // T1 + memory_read_dummy(state, base); // T2 + uint8_t addr = (base + cpu->x) & 0xff; + + uint8_t value = memory_read(state, addr); // T3 + cpu->a &= value; // T4 + update_zn(cpu, cpu->a); +} + +// AND $nnnn,Y +static void opcode_and_absy(struct nes_state * restrict state) { + struct cpu_state * restrict cpu = &state->cpu; + + uint8_t lo = memory_read(state, cpu->pc++); // T1 + uint8_t hi = memory_read(state, cpu->pc++); // T2 + uint16_t base = lo | (hi << 8); + uint16_t addr = base + cpu->y; + + if((base & 0xff00) != (addr & 0xff00)) { + memory_read_dummy(state, (base & 0xff00) | (addr & 0x00ff)); // T3 dummy + } + + uint8_t value = memory_read(state, addr); // T3 or T4 + cpu->a &= value; // T4 or T5 + update_zn(cpu, cpu->a); +} + +// AND $nnnn,X +static void opcode_and_absx(struct nes_state * restrict state) { + struct cpu_state * restrict cpu = &state->cpu; + + uint8_t lo = memory_read(state, cpu->pc++); // T1 + uint8_t hi = memory_read(state, cpu->pc++); // T2 + uint16_t base = lo | (hi << 8); + uint16_t addr = base + cpu->x; + + if((base & 0xff00) != (addr & 0xff00)) { + memory_read_dummy(state, (base & 0xff00) | (addr & 0x00ff)); // T3 dummy + } + + uint8_t value = memory_read(state, addr); // T3 or T4 + cpu->a &= value; // T4 or T5 + update_zn(cpu, cpu->a); +} + + +// ASL + +// ASL $nn +static void opcode_asl_zp(struct nes_state * restrict state) { + struct cpu_state * restrict cpu = &state->cpu; + + uint8_t addr = memory_read(state, cpu->pc++); // T1 + uint8_t value = memory_read(state, addr); // T2 + + memory_write(state, addr, value); // T3 (dummy write) + + cpu->c = (value >> 7) & 1; + value <<= 1; + + memory_write(state, addr, value); // T4 + update_zn(cpu, value); +} + +// ASL A +static void opcode_asl_acc(struct nes_state * restrict state) { + struct cpu_state * restrict cpu = &state->cpu; + + memory_read_dummy(state, cpu->pc); // T1 (dummy read at PC) + + cpu->c = (cpu->a >> 7) & 1; + cpu->a <<= 1; + + update_zn(cpu, cpu->a); // T2 +} + +// ASL $nnnn +static void opcode_asl_abs(struct nes_state * restrict state) { + struct cpu_state * restrict cpu = &state->cpu; + + uint8_t lo = memory_read(state, cpu->pc++); // T1 + uint8_t hi = memory_read(state, cpu->pc++); // T2 + uint16_t addr = lo | (hi << 8); + + uint8_t value = memory_read(state, addr); // T3 + memory_write(state, addr, value); // T4 (dummy write) + + cpu->c = (value >> 7) & 1; + value <<= 1; + + memory_write(state, addr, value); // T5 + update_zn(cpu, value); +} + +// ASL $nn,X +static void opcode_asl_zpx(struct nes_state * restrict state) { + struct cpu_state * restrict cpu = &state->cpu; + + uint8_t base = memory_read(state, cpu->pc++); // T1 + memory_read_dummy(state, base); // T2 + uint8_t addr = (base + cpu->x) & 0xff; + + uint8_t value = memory_read(state, addr); // T3 + memory_write(state, addr, value); // T4 (dummy write) + + cpu->c = (value >> 7) & 1; + value <<= 1; + + memory_write(state, addr, value); // T5 + update_zn(cpu, value); +} + +// ASL $nnnn,X +static void opcode_asl_absx(struct nes_state * restrict state) { + struct cpu_state * restrict cpu = &state->cpu; + + uint8_t lo = memory_read(state, cpu->pc++); // T1 + uint8_t hi = memory_read(state, cpu->pc++); // T2 + uint16_t base = lo | (hi << 8); + uint16_t addr = base + cpu->x; + + memory_read_dummy(state, (base & 0xff00) | (addr & 0x00ff)); // T3 + + uint8_t value = memory_read(state, addr); // T4 + memory_write(state, addr, value); // T5 (dummy write) + + cpu->c = (value >> 7) & 1; + value <<= 1; + + memory_write(state, addr, value); // T6 + update_zn(cpu, value); +} + + +// BIT + +// BIT $nn +static void opcode_bit_zp(struct nes_state * restrict state) { + struct cpu_state * restrict cpu = &state->cpu; + + uint8_t addr = memory_read(state, cpu->pc++); // T1 + uint8_t value = memory_read(state, addr); // T2 + + cpu->z = ((cpu->a & value) == 0); + cpu->n = (value >> 7) & 1; + cpu->v = (value >> 6) & 1; // T3 +} + +// BIT $nnnn +static void opcode_bit_abs(struct nes_state * restrict state) { + struct cpu_state * restrict cpu = &state->cpu; + + uint8_t lo = memory_read(state, cpu->pc++); // T1 + uint8_t hi = memory_read(state, cpu->pc++); // T2 + uint16_t addr = lo | (hi << 8); + + uint8_t value = memory_read(state, addr); // T3 + + cpu->z = ((cpu->a & value) == 0); + cpu->n = (value >> 7) & 1; + cpu->v = (value >> 6) & 1; // T4 +} + + +// BRK +static void opcode_brk(struct nes_state * restrict state) { + struct cpu_state * restrict cpu = &state->cpu; + + cpu->pc++; // BRK is 1 byte, skip padding byte + memory_read_dummy(state, cpu->pc); // T1 padding read + + uint8_t pcl = cpu->pc & 0xff; + uint8_t pch = cpu->pc >> 8; + + memory_write(state, 0x0100 + cpu->sp--, pch); // T2 + memory_write(state, 0x0100 + cpu->sp--, pcl); // T3 + + memory_write(state, 0x0100 + cpu->sp--, pack_flags(cpu) | 0x10); // T4 + + uint8_t lo = memory_read(state, 0xfffe); // T5 + uint8_t hi = memory_read(state, 0xffff); // T6 + + cpu->pc = lo | (hi << 8); // T7 + cpu->i = 1; +} + + +// BRANCHES + +static inline int page_crossed(uint16_t a, uint16_t b) { + return (a & 0xff00) != (b & 0xff00); +} + +static void opcode_bpl(struct nes_state * restrict state) { + struct cpu_state * restrict cpu = &state->cpu; + + uint8_t offset = memory_read(state, cpu->pc++); // T1 + uint16_t new_pc = cpu->pc + (int8_t)offset; + + if(!cpu->n) { + memory_read_dummy(state, cpu->pc); // T2 + if(page_crossed(cpu->pc, new_pc)) { + memory_read_dummy(state, (cpu->pc & 0xff00) | (new_pc & 0x00ff)); // T3 + } + cpu->pc = new_pc; // T3 or T4 + } +} + +static void opcode_bmi(struct nes_state * restrict state) { + struct cpu_state * restrict cpu = &state->cpu; + + uint8_t offset = memory_read(state, cpu->pc++); + uint16_t new_pc = cpu->pc + (int8_t)offset; + + if(cpu->n) { + memory_read_dummy(state, cpu->pc); + if(page_crossed(cpu->pc, new_pc)) { + memory_read_dummy(state, (cpu->pc & 0xff00) | (new_pc & 0x00ff)); + } + cpu->pc = new_pc; + } +} + +static void opcode_bvc(struct nes_state * restrict state) { + struct cpu_state * restrict cpu = &state->cpu; + + uint8_t offset = memory_read(state, cpu->pc++); + uint16_t new_pc = cpu->pc + (int8_t)offset; + + if(!cpu->v) { + memory_read_dummy(state, cpu->pc); + if(page_crossed(cpu->pc, new_pc)) { + memory_read_dummy(state, (cpu->pc & 0xff00) | (new_pc & 0x00ff)); + } + cpu->pc = new_pc; + } +} + +static void opcode_bvs(struct nes_state * restrict state) { + struct cpu_state * restrict cpu = &state->cpu; + + uint8_t offset = memory_read(state, cpu->pc++); + uint16_t new_pc = cpu->pc + (int8_t)offset; + + if(cpu->v) { + memory_read_dummy(state, cpu->pc); + if(page_crossed(cpu->pc, new_pc)) { + memory_read_dummy(state, (cpu->pc & 0xff00) | (new_pc & 0x00ff)); + } + cpu->pc = new_pc; + } +} + +static void opcode_bcc(struct nes_state * restrict state) { + struct cpu_state * restrict cpu = &state->cpu; + + uint8_t offset = memory_read(state, cpu->pc++); + uint16_t new_pc = cpu->pc + (int8_t)offset; + + if(!cpu->c) { + memory_read_dummy(state, cpu->pc); + if(page_crossed(cpu->pc, new_pc)) { + memory_read_dummy(state, (cpu->pc & 0xff00) | (new_pc & 0x00ff)); + } + cpu->pc = new_pc; + } +} + +static void opcode_bcs(struct nes_state * restrict state) { + struct cpu_state * restrict cpu = &state->cpu; + + uint8_t offset = memory_read(state, cpu->pc++); + uint16_t new_pc = cpu->pc + (int8_t)offset; + + if(cpu->c) { + memory_read_dummy(state, cpu->pc); + if(page_crossed(cpu->pc, new_pc)) { + memory_read_dummy(state, (cpu->pc & 0xff00) | (new_pc & 0x00ff)); + } + cpu->pc = new_pc; + } +} + +static void opcode_bne(struct nes_state * restrict state) { + struct cpu_state * restrict cpu = &state->cpu; + + uint8_t offset = memory_read(state, cpu->pc++); + uint16_t new_pc = cpu->pc + (int8_t)offset; + + if(!cpu->z) { + memory_read_dummy(state, cpu->pc); + if(page_crossed(cpu->pc, new_pc)) { + memory_read_dummy(state, (cpu->pc & 0xff00) | (new_pc & 0x00ff)); + } + cpu->pc = new_pc; + } +} + +static void opcode_beq(struct nes_state * restrict state) { + struct cpu_state * restrict cpu = &state->cpu; + + uint8_t offset = memory_read(state, cpu->pc++); + uint16_t new_pc = cpu->pc + (int8_t)offset; + + if(cpu->z) { + memory_read_dummy(state, cpu->pc); + if(page_crossed(cpu->pc, new_pc)) { + memory_read_dummy(state, (cpu->pc & 0xff00) | (new_pc & 0x00ff)); + } + cpu->pc = new_pc; + } +} + + +// SET/CLEAR flags + +static void opcode_clc(struct nes_state * restrict state) { + struct cpu_state * restrict cpu = &state->cpu; + memory_read_dummy(state, cpu->pc); + cpu->c = 0; +} + +static void opcode_cld(struct nes_state * restrict state) { + struct cpu_state * restrict cpu = &state->cpu; + memory_read_dummy(state, cpu->pc); + cpu->d = 0; +} + +static void opcode_cli(struct nes_state * restrict state) { + struct cpu_state * restrict cpu = &state->cpu; + memory_read_dummy(state, cpu->pc); + cpu->i = 0; +} + +static void opcode_clv(struct nes_state * restrict state) { + struct cpu_state * restrict cpu = &state->cpu; + memory_read_dummy(state, cpu->pc); + cpu->v = 0; +} + +static void opcode_sec(struct nes_state * restrict state) { + struct cpu_state * restrict cpu = &state->cpu; + memory_read_dummy(state, cpu->pc); + cpu->c = 1; +} + +static void opcode_sed(struct nes_state * restrict state) { + struct cpu_state * restrict cpu = &state->cpu; + memory_read_dummy(state, cpu->pc); + cpu->d = 1; +} + +static void opcode_sei(struct nes_state * restrict state) { + struct cpu_state * restrict cpu = &state->cpu; + memory_read_dummy(state, cpu->pc); + cpu->i = 1; +} + + +// CMP + +static inline void cmp(struct cpu_state * restrict cpu, uint8_t value) { + uint8_t result = cpu->a - value; + cpu->c = (cpu->a >= value); + update_zn(cpu, result); +} + +static void opcode_cmp_indx(struct nes_state * restrict state) { + struct cpu_state * restrict cpu = &state->cpu; + + uint8_t zp = memory_read(state, cpu->pc++); // T1 + memory_read_dummy(state, zp); // T2 + + uint8_t ptr = (zp + cpu->x) & 0xff; + uint8_t lo = memory_read(state, ptr); // T3 + uint8_t hi = memory_read(state, (ptr + 1) & 0xff); // T4 + uint16_t addr = lo | (hi << 8); + + uint8_t value = memory_read(state, addr); // T5 + + cmp(cpu, value); // T6 +} + +static void opcode_cmp_zp(struct nes_state * restrict state) { + struct cpu_state * restrict cpu = &state->cpu; + + uint8_t addr = memory_read(state, cpu->pc++); // T1 + uint8_t value = memory_read(state, addr); // T2 + + cmp(cpu, value); // T3 +} + +static void opcode_cmp_imm(struct nes_state * restrict state) { + struct cpu_state * restrict cpu = &state->cpu; + + uint8_t value = memory_read(state, cpu->pc++); // T1 + cmp(cpu, value); // T2 +} + +static void opcode_cmp_abs(struct nes_state * restrict state) { + struct cpu_state * restrict cpu = &state->cpu; + + uint8_t lo = memory_read(state, cpu->pc++); // T1 + uint8_t hi = memory_read(state, cpu->pc++); // T2 + uint16_t addr = lo | (hi << 8); + + uint8_t value = memory_read(state, addr); // T3 + cmp(cpu, value); // T4 +} + +static void opcode_cmp_indy(struct nes_state * restrict state) { + struct cpu_state * restrict cpu = &state->cpu; + + uint8_t zp = memory_read(state, cpu->pc++); // T1 + uint8_t lo = memory_read(state, zp); // T2 + uint8_t hi = memory_read(state, (zp + 1) & 0xff); // T3 + + uint16_t base = lo | (hi << 8); + uint16_t addr = base + cpu->y; + + if((base & 0xff00) != (addr & 0xff00)) { + memory_read_dummy(state, (base & 0xff00) | (addr & 0x00ff)); // T4 dummy + } + + uint8_t value = memory_read(state, addr); // T4 or T5 + cmp(cpu, value); // T5 or T6 +} + +static void opcode_cmp_zpx(struct nes_state * restrict state) { + struct cpu_state * restrict cpu = &state->cpu; + + uint8_t base = memory_read(state, cpu->pc++); // T1 + memory_read_dummy(state, base); // T2 + uint8_t addr = (base + cpu->x) & 0xff; + + uint8_t value = memory_read(state, addr); // T3 + cmp(cpu, value); // T4 +} + +static void opcode_cmp_absy(struct nes_state * restrict state) { + struct cpu_state * restrict cpu = &state->cpu; + + uint8_t lo = memory_read(state, cpu->pc++); // T1 + uint8_t hi = memory_read(state, cpu->pc++); // T2 + uint16_t base = lo | (hi << 8); + uint16_t addr = base + cpu->y; + + if((base & 0xff00) != (addr & 0xff00)) { + memory_read_dummy(state, (base & 0xff00) | (addr & 0x00ff)); // T3 dummy + } + + uint8_t value = memory_read(state, addr); // T3 or T4 + cmp(cpu, value); // T4 or T5 +} + +static void opcode_cmp_absx(struct nes_state * restrict state) { + struct cpu_state * restrict cpu = &state->cpu; + + uint8_t lo = memory_read(state, cpu->pc++); // T1 + uint8_t hi = memory_read(state, cpu->pc++); // T2 + uint16_t base = lo | (hi << 8); + uint16_t addr = base + cpu->x; + + if((base & 0xff00) != (addr & 0xff00)) { + memory_read_dummy(state, (base & 0xff00) | (addr & 0x00ff)); // T3 dummy + } + + uint8_t value = memory_read(state, addr); // T3 or T4 + cmp(cpu, value); // T4 or T5 +} + + +// CPX + +static inline void cpx(struct cpu_state * restrict cpu, uint8_t value) { + uint8_t result = cpu->x - value; + cpu->c = (cpu->x >= value); + update_zn(cpu, result); +} + +static void opcode_cpx_imm(struct nes_state * restrict state) { + struct cpu_state * restrict cpu = &state->cpu; + + uint8_t value = memory_read(state, cpu->pc++); // T1 + cpx(cpu, value); // T2 +} + +static void opcode_cpx_zp(struct nes_state * restrict state) { + struct cpu_state * restrict cpu = &state->cpu; + + uint8_t addr = memory_read(state, cpu->pc++); // T1 + uint8_t value = memory_read(state, addr); // T2 + + cpx(cpu, value); // T3 +} + +static void opcode_cpx_abs(struct nes_state * restrict state) { + struct cpu_state * restrict cpu = &state->cpu; + + uint8_t lo = memory_read(state, cpu->pc++); // T1 + uint8_t hi = memory_read(state, cpu->pc++); // T2 + uint16_t addr = lo | (hi << 8); + + uint8_t value = memory_read(state, addr); // T3 + cpx(cpu, value); // T4 +} + + +// CPY + +static inline void cpy(struct cpu_state * restrict cpu, uint8_t value) { + uint8_t result = cpu->y - value; + cpu->c = (cpu->y >= value); + update_zn(cpu, result); +} + +static void opcode_cpy_imm(struct nes_state * restrict state) { + struct cpu_state * restrict cpu = &state->cpu; + + uint8_t value = memory_read(state, cpu->pc++); // T1 + cpy(cpu, value); // T2 +} + +static void opcode_cpy_zp(struct nes_state * restrict state) { + struct cpu_state * restrict cpu = &state->cpu; + + uint8_t addr = memory_read(state, cpu->pc++); // T1 + uint8_t value = memory_read(state, addr); // T2 + + cpy(cpu, value); // T3 +} + +static void opcode_cpy_abs(struct nes_state * restrict state) { + struct cpu_state * restrict cpu = &state->cpu; + + uint8_t lo = memory_read(state, cpu->pc++); // T1 + uint8_t hi = memory_read(state, cpu->pc++); // T2 + uint16_t addr = lo | (hi << 8); + + uint8_t value = memory_read(state, addr); // T3 + cpy(cpu, value); // T4 +} + + +// DEC + +static void opcode_dec_zp(struct nes_state * restrict state) { + struct cpu_state * restrict cpu = &state->cpu; + + uint8_t addr = memory_read(state, cpu->pc++); // T1 + uint8_t value = memory_read(state, addr); // T2 + + memory_write(state, addr, value); // T3 (dummy write) + value--; + memory_write(state, addr, value); // T4 + + update_zn(cpu, value); // T5 +} + +static void opcode_dec_zpx(struct nes_state * restrict state) { + struct cpu_state * restrict cpu = &state->cpu; + + uint8_t base = memory_read(state, cpu->pc++); // T1 + memory_read_dummy(state, base); // T2 + uint8_t addr = (base + cpu->x) & 0xff; + + uint8_t value = memory_read(state, addr); // T3 + memory_write(state, addr, value); // T4 (dummy write) + + value--; + memory_write(state, addr, value); // T5 + update_zn(cpu, value); // T6 +} + +static void opcode_dec_abs(struct nes_state * restrict state) { + struct cpu_state * restrict cpu = &state->cpu; + + uint8_t lo = memory_read(state, cpu->pc++); // T1 + uint8_t hi = memory_read(state, cpu->pc++); // T2 + uint16_t addr = lo | (hi << 8); + + uint8_t value = memory_read(state, addr); // T3 + memory_write(state, addr, value); // T4 (dummy write) + + value--; + memory_write(state, addr, value); // T5 + update_zn(cpu, value); // T6 +} + +static void opcode_dec_absx(struct nes_state * restrict state) { + struct cpu_state * restrict cpu = &state->cpu; + + uint8_t lo = memory_read(state, cpu->pc++); // T1 + uint8_t hi = memory_read(state, cpu->pc++); // T2 + uint16_t base = lo | (hi << 8); + uint16_t addr = base + cpu->x; + + memory_read_dummy(state, (base & 0xff00) | (addr & 0x00ff)); // T3 + + uint8_t value = memory_read(state, addr); // T4 + memory_write(state, addr, value); // T5 (dummy write) + + value--; + memory_write(state, addr, value); // T6 + update_zn(cpu, value); // T7 +} + + +// EOR + +static void opcode_eor_indx(struct nes_state * restrict state) { + struct cpu_state * restrict cpu = &state->cpu; + + uint8_t zp = memory_read(state, cpu->pc++); // T1 + memory_read_dummy(state, zp); // T2 + + uint8_t ptr = (zp + cpu->x) & 0xff; + uint8_t lo = memory_read(state, ptr); // T3 + uint8_t hi = memory_read(state, (ptr + 1) & 0xff); // T4 + uint16_t addr = lo | (hi << 8); + + uint8_t value = memory_read(state, addr); // T5 + + cpu->a ^= value; // T6 + update_zn(cpu, cpu->a); +} + +static void opcode_eor_zp(struct nes_state * restrict state) { + struct cpu_state * restrict cpu = &state->cpu; + + uint8_t addr = memory_read(state, cpu->pc++); // T1 + uint8_t value = memory_read(state, addr); // T2 + + cpu->a ^= value; // T3 + update_zn(cpu, cpu->a); +} + +static void opcode_eor_imm(struct nes_state * restrict state) { + struct cpu_state * restrict cpu = &state->cpu; + + uint8_t value = memory_read(state, cpu->pc++); // T1 + cpu->a ^= value; // T2 + update_zn(cpu, cpu->a); +} + +static void opcode_eor_abs(struct nes_state * restrict state) { + struct cpu_state * restrict cpu = &state->cpu; + + uint8_t lo = memory_read(state, cpu->pc++); // T1 + uint8_t hi = memory_read(state, cpu->pc++); // T2 + uint16_t addr = lo | (hi << 8); + + uint8_t value = memory_read(state, addr); // T3 + cpu->a ^= value; // T4 + update_zn(cpu, cpu->a); +} + +static void opcode_eor_indy(struct nes_state * restrict state) { + struct cpu_state * restrict cpu = &state->cpu; + + uint8_t zp = memory_read(state, cpu->pc++); // T1 + uint8_t lo = memory_read(state, zp); // T2 + uint8_t hi = memory_read(state, (zp + 1) & 0xff); // T3 + + uint16_t base = lo | (hi << 8); + uint16_t addr = base + cpu->y; + + if((base & 0xff00) != (addr & 0xff00)) { + memory_read_dummy(state, (base & 0xff00) | (addr & 0x00ff)); // T4 dummy + } + + uint8_t value = memory_read(state, addr); // T4 or T5 + cpu->a ^= value; // T5 or T6 + update_zn(cpu, cpu->a); +} + +static void opcode_eor_zpx(struct nes_state * restrict state) { + struct cpu_state * restrict cpu = &state->cpu; + + uint8_t base = memory_read(state, cpu->pc++); // T1 + memory_read_dummy(state, base); // T2 + uint8_t addr = (base + cpu->x) & 0xff; + + uint8_t value = memory_read(state, addr); // T3 + cpu->a ^= value; // T4 + update_zn(cpu, cpu->a); +} + +static void opcode_eor_absy(struct nes_state * restrict state) { + struct cpu_state * restrict cpu = &state->cpu; + + uint8_t lo = memory_read(state, cpu->pc++); // T1 + uint8_t hi = memory_read(state, cpu->pc++); // T2 + uint16_t base = lo | (hi << 8); + uint16_t addr = base + cpu->y; + + if((base & 0xff00) != (addr & 0xff00)) { + memory_read_dummy(state, (base & 0xff00) | (addr & 0x00ff)); // T3 dummy + } + + uint8_t value = memory_read(state, addr); // T3 or T4 + cpu->a ^= value; // T4 or T5 + update_zn(cpu, cpu->a); +} + +static void opcode_eor_absx(struct nes_state * restrict state) { + struct cpu_state * restrict cpu = &state->cpu; + + uint8_t lo = memory_read(state, cpu->pc++); // T1 + uint8_t hi = memory_read(state, cpu->pc++); // T2 + uint16_t base = lo | (hi << 8); + uint16_t addr = base + cpu->x; + + if((base & 0xff00) != (addr & 0xff00)) { + memory_read_dummy(state, (base & 0xff00) | (addr & 0x00ff)); // T3 dummy + } + + uint8_t value = memory_read(state, addr); // T3 or T4 + cpu->a ^= value; // T4 or T5 + update_zn(cpu, cpu->a); +} + + +// INC + +static void opcode_inc_zp(struct nes_state * restrict state) { + struct cpu_state * restrict cpu = &state->cpu; + + uint8_t addr = memory_read(state, cpu->pc++); // T1 + uint8_t value = memory_read(state, addr); // T2 + + memory_write(state, addr, value); // T3 (dummy write) + value++; + memory_write(state, addr, value); // T4 + + update_zn(cpu, value); // T5 +} + +static void opcode_inc_zpx(struct nes_state * restrict state) { + struct cpu_state * restrict cpu = &state->cpu; + + uint8_t base = memory_read(state, cpu->pc++); // T1 + memory_read_dummy(state, base); // T2 + uint8_t addr = (base + cpu->x) & 0xff; + + uint8_t value = memory_read(state, addr); // T3 + memory_write(state, addr, value); // T4 (dummy write) + + value++; + memory_write(state, addr, value); // T5 + update_zn(cpu, value); // T6 +} + +static void opcode_inc_abs(struct nes_state * restrict state) { + struct cpu_state * restrict cpu = &state->cpu; + + uint8_t lo = memory_read(state, cpu->pc++); // T1 + uint8_t hi = memory_read(state, cpu->pc++); // T2 + uint16_t addr = lo | (hi << 8); + + uint8_t value = memory_read(state, addr); // T3 + memory_write(state, addr, value); // T4 (dummy write) + + value++; + memory_write(state, addr, value); // T5 + update_zn(cpu, value); // T6 +} + +static void opcode_inc_absx(struct nes_state * restrict state) { + struct cpu_state * restrict cpu = &state->cpu; + + uint8_t lo = memory_read(state, cpu->pc++); // T1 + uint8_t hi = memory_read(state, cpu->pc++); // T2 + uint16_t base = lo | (hi << 8); + uint16_t addr = base + cpu->x; + + memory_read_dummy(state, (base & 0xff00) | (addr & 0x00ff)); // T3 + + uint8_t value = memory_read(state, addr); // T4 + memory_write(state, addr, value); // T5 (dummy write) + + value++; + memory_write(state, addr, value); // T6 + update_zn(cpu, value); // T7 +} + + +// JMP/JSR + +static void opcode_jmp_abs(struct nes_state * restrict state) { + struct cpu_state * restrict cpu = &state->cpu; + + uint8_t lo = memory_read(state, cpu->pc++); // T1 + uint8_t hi = memory_read(state, cpu->pc++); // T2 + cpu->pc = lo | (hi << 8); // T3 +} + +static void opcode_jmp_ind(struct nes_state * restrict state) { + struct cpu_state * restrict cpu = &state->cpu; + + uint8_t ptr_lo = memory_read(state, cpu->pc++); // T1 + uint8_t ptr_hi = memory_read(state, cpu->pc++); // T2 + uint16_t ptr = ptr_lo | (ptr_hi << 8); + + uint8_t lo = memory_read(state, ptr); // T3 + uint8_t hi; + if((ptr & 0x00ff) == 0x00ff) { + hi = memory_read(state, ptr & 0xff00); // Emulate 6502 bug + } else { + hi = memory_read(state, ptr + 1); + } // T4 + + cpu->pc = lo | (hi << 8); // T5 +} + +static void opcode_jsr(struct nes_state * restrict state) { + struct cpu_state * restrict cpu = &state->cpu; + + uint8_t lo = memory_read(state, cpu->pc++); + uint8_t hi = memory_read(state, cpu->pc++); + + uint16_t return_addr = cpu->pc - 1; + + memory_read_dummy(state, 0x0100 | cpu->sp); // T4 + memory_write(state, 0x0100 | cpu->sp--, (return_addr >> 8)); // T5 + memory_write(state, 0x0100 | cpu->sp--, (return_addr & 0xff)); // T6 + + cpu->pc = lo | (hi << 8); +} + + + +// LDA + +static void opcode_lda_indx(struct nes_state * restrict state) { + struct cpu_state * restrict cpu = &state->cpu; + + uint8_t zp = memory_read(state, cpu->pc++); // T1 + memory_read_dummy(state, zp); // T2 + + uint8_t ptr = (zp + cpu->x) & 0xff; + uint8_t lo = memory_read(state, ptr); // T3 + uint8_t hi = memory_read(state, (ptr + 1) & 0xff); // T4 + uint16_t addr = lo | (hi << 8); + + uint8_t value = memory_read(state, addr); // T5 + cpu->a = value; // T6 + update_zn(cpu, value); +} + +static void opcode_lda_zp(struct nes_state * restrict state) { + struct cpu_state * restrict cpu = &state->cpu; + + uint8_t addr = memory_read(state, cpu->pc++); // T1 + uint8_t value = memory_read(state, addr); // T2 + + cpu->a = value; // T3 + update_zn(cpu, value); +} + +static void opcode_lda_imm(struct nes_state * restrict state) { + struct cpu_state * restrict cpu = &state->cpu; + + uint8_t value = memory_read(state, cpu->pc++); // T1 + cpu->a = value; // T2 + update_zn(cpu, value); +} + +static void opcode_lda_abs(struct nes_state * restrict state) { + struct cpu_state * restrict cpu = &state->cpu; + + uint8_t lo = memory_read(state, cpu->pc++); // T1 + uint8_t hi = memory_read(state, cpu->pc++); // T2 + uint16_t addr = lo | (hi << 8); + + uint8_t value = memory_read(state, addr); // T3 + cpu->a = value; // T4 + update_zn(cpu, value); +} + +static void opcode_lda_indy(struct nes_state * restrict state) { + struct cpu_state * restrict cpu = &state->cpu; + + uint8_t zp = memory_read(state, cpu->pc++); // T1 + uint8_t lo = memory_read(state, zp); // T2 + uint8_t hi = memory_read(state, (zp + 1) & 0xff); // T3 + + uint16_t base = lo | (hi << 8); + uint16_t addr = base + cpu->y; + + if((base & 0xff00) != (addr & 0xff00)) { + memory_read_dummy(state, (base & 0xff00) | (addr & 0x00ff)); // T4 dummy + } + + uint8_t value = memory_read(state, addr); // T4 or T5 + cpu->a = value; // T5 or T6 + update_zn(cpu, value); +} + +static void opcode_lda_zpx(struct nes_state * restrict state) { + struct cpu_state * restrict cpu = &state->cpu; + + uint8_t base = memory_read(state, cpu->pc++); // T1 + memory_read_dummy(state, base); // T2 + uint8_t addr = (base + cpu->x) & 0xff; + + uint8_t value = memory_read(state, addr); // T3 + cpu->a = value; // T4 + update_zn(cpu, value); +} + +static void opcode_lda_absy(struct nes_state * restrict state) { + struct cpu_state * restrict cpu = &state->cpu; + + uint8_t lo = memory_read(state, cpu->pc++); // T1 + uint8_t hi = memory_read(state, cpu->pc++); // T2 + uint16_t base = lo | (hi << 8); + uint16_t addr = base + cpu->y; + + if((base & 0xff00) != (addr & 0xff00)) { + memory_read_dummy(state, (base & 0xff00) | (addr & 0x00ff)); // T3 + } + + uint8_t value = memory_read(state, addr); // T3 or T4 + cpu->a = value; // T4 or T5 + update_zn(cpu, value); +} + +static void opcode_lda_absx(struct nes_state * restrict state) { + struct cpu_state * restrict cpu = &state->cpu; + + uint8_t lo = memory_read(state, cpu->pc++); // T1 + uint8_t hi = memory_read(state, cpu->pc++); // T2 + uint16_t base = lo | (hi << 8); + uint16_t addr = base + cpu->x; + + if((base & 0xff00) != (addr & 0xff00)) { + memory_read_dummy(state, (base & 0xff00) | (addr & 0x00ff)); // T3 + } + + uint8_t value = memory_read(state, addr); // T3 or T4 + cpu->a = value; // T4 or T5 + update_zn(cpu, value); +} + + +// LDX + +static void opcode_ldx_imm(struct nes_state * restrict state) { + struct cpu_state * restrict cpu = &state->cpu; + + uint8_t value = memory_read(state, cpu->pc++); + cpu->x = value; + update_zn(cpu, value); +} + +static void opcode_ldx_zp(struct nes_state * restrict state) { + struct cpu_state * restrict cpu = &state->cpu; + + uint8_t addr = memory_read(state, cpu->pc++); + uint8_t value = memory_read(state, addr); + + cpu->x = value; + update_zn(cpu, value); +} + +static void opcode_ldx_zpy(struct nes_state * restrict state) { + struct cpu_state * restrict cpu = &state->cpu; + + uint8_t base = memory_read(state, cpu->pc++); + memory_read_dummy(state, base); + uint8_t addr = (base + cpu->y) & 0xff; + + uint8_t value = memory_read(state, addr); + cpu->x = value; + update_zn(cpu, value); +} + +static void opcode_ldx_abs(struct nes_state * restrict state) { + struct cpu_state * restrict cpu = &state->cpu; + + uint8_t lo = memory_read(state, cpu->pc++); + uint8_t hi = memory_read(state, cpu->pc++); + uint16_t addr = lo | (hi << 8); + + uint8_t value = memory_read(state, addr); + cpu->x = value; + update_zn(cpu, value); +} + +static void opcode_ldx_absy(struct nes_state * restrict state) { + struct cpu_state * restrict cpu = &state->cpu; + + uint8_t lo = memory_read(state, cpu->pc++); + uint8_t hi = memory_read(state, cpu->pc++); + uint16_t base = lo | (hi << 8); + uint16_t addr = base + cpu->y; + + if((base & 0xff00) != (addr & 0xff00)) { + memory_read_dummy(state, (base & 0xff00) | (addr & 0x00ff)); + } + + uint8_t value = memory_read(state, addr); + cpu->x = value; + update_zn(cpu, value); +} + + +// LDY + +static void opcode_ldy_imm(struct nes_state * restrict state) { + struct cpu_state * restrict cpu = &state->cpu; + + uint8_t value = memory_read(state, cpu->pc++); + cpu->y = value; + update_zn(cpu, value); +} + +static void opcode_ldy_zp(struct nes_state * restrict state) { + struct cpu_state * restrict cpu = &state->cpu; + + uint8_t addr = memory_read(state, cpu->pc++); + uint8_t value = memory_read(state, addr); + + cpu->y = value; + update_zn(cpu, value); +} + +static void opcode_ldy_zpx(struct nes_state * restrict state) { + struct cpu_state * restrict cpu = &state->cpu; + + uint8_t base = memory_read(state, cpu->pc++); + memory_read_dummy(state, base); + uint8_t addr = (base + cpu->x) & 0xff; + + uint8_t value = memory_read(state, addr); + cpu->y = value; + update_zn(cpu, value); +} + +static void opcode_ldy_abs(struct nes_state * restrict state) { + struct cpu_state * restrict cpu = &state->cpu; + + uint8_t lo = memory_read(state, cpu->pc++); + uint8_t hi = memory_read(state, cpu->pc++); + uint16_t addr = lo | (hi << 8); + + uint8_t value = memory_read(state, addr); + cpu->y = value; + update_zn(cpu, value); +} + +static void opcode_ldy_absx(struct nes_state * restrict state) { + struct cpu_state * restrict cpu = &state->cpu; + + uint8_t lo = memory_read(state, cpu->pc++); + uint8_t hi = memory_read(state, cpu->pc++); + uint16_t base = lo | (hi << 8); + uint16_t addr = base + cpu->x; + + if((base & 0xff00) != (addr & 0xff00)) { + memory_read_dummy(state, (base & 0xff00) | (addr & 0x00ff)); + } + + uint8_t value = memory_read(state, addr); + cpu->y = value; + update_zn(cpu, value); +} + + +// LSR + + +static void opcode_lsr_zp(struct nes_state * restrict state) { + struct cpu_state * restrict cpu = &state->cpu; + + uint8_t addr = memory_read(state, cpu->pc++); // T1 + uint8_t value = memory_read(state, addr); // T2 + + memory_write(state, addr, value); // T3 (dummy write) + cpu->c = value & 1; + value >>= 1; + memory_write(state, addr, value); // T4 + + update_zn(cpu, value); // T5 +} + +static void opcode_lsr_acc(struct nes_state * restrict state) { + struct cpu_state * restrict cpu = &state->cpu; + + memory_read_dummy(state, cpu->pc); // T1 + cpu->c = cpu->a & 1; + cpu->a >>= 1; + update_zn(cpu, cpu->a); // T2 +} + +static void opcode_lsr_abs(struct nes_state * restrict state) { + struct cpu_state * restrict cpu = &state->cpu; + + uint8_t lo = memory_read(state, cpu->pc++); // T1 + uint8_t hi = memory_read(state, cpu->pc++); // T2 + uint16_t addr = lo | (hi << 8); + + uint8_t value = memory_read(state, addr); // T3 + memory_write(state, addr, value); // T4 (dummy write) + + cpu->c = value & 1; + value >>= 1; + + memory_write(state, addr, value); // T5 + update_zn(cpu, value); // T6 +} + +static void opcode_lsr_zpx(struct nes_state * restrict state) { + struct cpu_state * restrict cpu = &state->cpu; + + uint8_t base = memory_read(state, cpu->pc++); // T1 + memory_read_dummy(state, base); // T2 + uint8_t addr = (base + cpu->x) & 0xff; + + uint8_t value = memory_read(state, addr); // T3 + memory_write(state, addr, value); // T4 (dummy write) + + cpu->c = value & 1; + value >>= 1; + + memory_write(state, addr, value); // T5 + update_zn(cpu, value); // T6 +} + +static void opcode_lsr_absx(struct nes_state * restrict state) { + struct cpu_state * restrict cpu = &state->cpu; + + uint8_t lo = memory_read(state, cpu->pc++); // T1 + uint8_t hi = memory_read(state, cpu->pc++); // T2 + uint16_t base = lo | (hi << 8); + uint16_t addr = base + cpu->x; + + memory_read_dummy(state, (base & 0xff00) | (addr & 0x00ff)); // T3 + + uint8_t value = memory_read(state, addr); // T4 + memory_write(state, addr, value); // T5 (dummy write) + + cpu->c = value & 1; + value >>= 1; + + memory_write(state, addr, value); // T6 + update_zn(cpu, value); // T7 +} + + +// NOP + +static void opcode_nop(struct nes_state * restrict state) { + struct cpu_state * restrict cpu = &state->cpu; + memory_read_dummy(state, cpu->pc); // T1: dummy read + // T2: nothing changes +} + + +// ORA + +static void opcode_ora_indx(struct nes_state * restrict state) { + struct cpu_state * restrict cpu = &state->cpu; + + uint8_t zp = memory_read(state, cpu->pc++); // T1 + memory_read_dummy(state, zp); // T2 + + uint8_t ptr = (zp + cpu->x) & 0xff; + uint8_t lo = memory_read(state, ptr); // T3 + uint8_t hi = memory_read(state, (ptr + 1) & 0xff); // T4 + uint16_t addr = lo | (hi << 8); + + uint8_t value = memory_read(state, addr); // T5 + cpu->a |= value; // T6 + update_zn(cpu, cpu->a); +} + +static void opcode_ora_zp(struct nes_state * restrict state) { + struct cpu_state * restrict cpu = &state->cpu; + + uint8_t addr = memory_read(state, cpu->pc++); + uint8_t value = memory_read(state, addr); + + cpu->a |= value; + update_zn(cpu, cpu->a); +} + +static void opcode_ora_imm(struct nes_state * restrict state) { + struct cpu_state * restrict cpu = &state->cpu; + + uint8_t value = memory_read(state, cpu->pc++); + cpu->a |= value; + update_zn(cpu, cpu->a); +} + +static void opcode_ora_abs(struct nes_state * restrict state) { + struct cpu_state * restrict cpu = &state->cpu; + + uint8_t lo = memory_read(state, cpu->pc++); + uint8_t hi = memory_read(state, cpu->pc++); + uint16_t addr = lo | (hi << 8); + + uint8_t value = memory_read(state, addr); + cpu->a |= value; + update_zn(cpu, cpu->a); +} + +static void opcode_ora_indy(struct nes_state * restrict state) { + struct cpu_state * restrict cpu = &state->cpu; + + uint8_t zp = memory_read(state, cpu->pc++); + uint8_t lo = memory_read(state, zp); + uint8_t hi = memory_read(state, (zp + 1) & 0xff); + + uint16_t base = lo | (hi << 8); + uint16_t addr = base + cpu->y; + + if((base & 0xff00) != (addr & 0xff00)) { + memory_read_dummy(state, (base & 0xff00) | (addr & 0x00ff)); + } + + uint8_t value = memory_read(state, addr); + cpu->a |= value; + update_zn(cpu, cpu->a); +} + +static void opcode_ora_zpx(struct nes_state * restrict state) { + struct cpu_state * restrict cpu = &state->cpu; + + uint8_t base = memory_read(state, cpu->pc++); + memory_read_dummy(state, base); + uint8_t addr = (base + cpu->x) & 0xff; + + uint8_t value = memory_read(state, addr); + cpu->a |= value; + update_zn(cpu, cpu->a); +} + +static void opcode_ora_absy(struct nes_state * restrict state) { + struct cpu_state * restrict cpu = &state->cpu; + + uint8_t lo = memory_read(state, cpu->pc++); + uint8_t hi = memory_read(state, cpu->pc++); + uint16_t base = lo | (hi << 8); + uint16_t addr = base + cpu->y; + + if((base & 0xff00) != (addr & 0xff00)) { + memory_read_dummy(state, (base & 0xff00) | (addr & 0x00ff)); + } + + uint8_t value = memory_read(state, addr); + cpu->a |= value; + update_zn(cpu, cpu->a); +} + +static void opcode_ora_absx(struct nes_state * restrict state) { + struct cpu_state * restrict cpu = &state->cpu; + + uint8_t lo = memory_read(state, cpu->pc++); + uint8_t hi = memory_read(state, cpu->pc++); + uint16_t base = lo | (hi << 8); + uint16_t addr = base + cpu->x; + + if((base & 0xff00) != (addr & 0xff00)) { + memory_read_dummy(state, (base & 0xff00) | (addr & 0x00ff)); + } + + uint8_t value = memory_read(state, addr); + cpu->a |= value; + update_zn(cpu, cpu->a); +} + +// PHA + +static void opcode_pha(struct nes_state * restrict state) { + struct cpu_state * restrict cpu = &state->cpu; + memory_read_dummy(state, cpu->pc); // T1 + memory_write(state, 0x0100 + cpu->sp--, cpu->a); // T2 +} + + +// PHP + +static void opcode_php(struct nes_state * restrict state) { + struct cpu_state * restrict cpu = &state->cpu; + memory_read_dummy(state, cpu->pc); // T1 + memory_write(state, 0x0100 + cpu->sp--, pack_flags(cpu) | 0x10); +} + + +// PLA + +static void opcode_pla(struct nes_state * restrict state) { + struct cpu_state * restrict cpu = &state->cpu; + + memory_read_dummy(state, cpu->pc); // T1 + memory_read_dummy(state, 0x0100 + ((cpu->sp + 1) & 0xff)); // T2 + uint8_t value = memory_read(state, 0x0100 + ((cpu->sp + 1) & 0xff)); // T3 + cpu->sp++; + cpu->a = value; + update_zn(cpu, value); // T4 +} + + +// PLP + +static void opcode_plp(struct nes_state * restrict state) { + struct cpu_state * restrict cpu = &state->cpu; + + memory_read_dummy(state, cpu->pc); // T1 + memory_read_dummy(state, 0x0100 + ((cpu->sp + 1) & 0xff)); // T2 + uint8_t value = memory_read(state, 0x0100 + ((cpu->sp + 1) & 0xff)); // T3 + cpu->sp++; + unpack_flags(cpu, value); // T4 +} + + +// RTI + +static void opcode_rti(struct nes_state * restrict state) { + struct cpu_state * restrict cpu = &state->cpu; + + memory_read_dummy(state, cpu->pc); // T1 + memory_read_dummy(state, 0x0100 + ((cpu->sp + 1) & 0xff)); // T2 + uint8_t flags = memory_read(state, 0x0100 + ((cpu->sp + 1) & 0xff)); // T3 + cpu->sp++; + unpack_flags(cpu, flags); // T4 + + uint8_t lo = memory_read(state, 0x0100 + ((cpu->sp + 1) & 0xff)); // T5 + cpu->sp++; + uint8_t hi = memory_read(state, 0x0100 + ((cpu->sp + 1) & 0xff)); // T6 + cpu->sp++; + + cpu->pc = lo | (hi << 8); +} + + +// RTS + +static void opcode_rts(struct nes_state * restrict state) { + struct cpu_state * restrict cpu = &state->cpu; + + memory_read_dummy(state, cpu->pc); // T1 + memory_read_dummy(state, 0x0100 | cpu->sp); // T2 (discard) + uint8_t lo = memory_read(state, 0x0100 | ++cpu->sp); // T3 + uint8_t hi = memory_read(state, 0x0100 | ++cpu->sp); // T4 + uint16_t ret = (hi << 8) | lo; + memory_read_dummy(state, ret); // T5 + cpu->pc = ret + 1; // Final PC set +} + + +// ROL + +static void opcode_rol_zp(struct nes_state * restrict state) { + struct cpu_state * restrict cpu = &state->cpu; + + uint8_t addr = memory_read(state, cpu->pc++); + uint8_t value = memory_read(state, addr); + + memory_write(state, addr, value); // Dummy write + + uint8_t in = cpu->c; + cpu->c = (value >> 7) & 1; + value = (value << 1) | in; + + memory_write(state, addr, value); + update_zn(cpu, value); +} + +static void opcode_rol_acc(struct nes_state * restrict state) { + struct cpu_state * restrict cpu = &state->cpu; + + memory_read_dummy(state, cpu->pc); + + uint8_t in = cpu->c; + cpu->c = (cpu->a >> 7) & 1; + cpu->a = (cpu->a << 1) | in; + + update_zn(cpu, cpu->a); +} + +static void opcode_rol_abs(struct nes_state * restrict state) { + struct cpu_state * restrict cpu = &state->cpu; + + uint8_t lo = memory_read(state, cpu->pc++); + uint8_t hi = memory_read(state, cpu->pc++); + uint16_t addr = lo | (hi << 8); + + uint8_t value = memory_read(state, addr); + memory_write(state, addr, value); // Dummy write + + uint8_t in = cpu->c; + cpu->c = (value >> 7) & 1; + value = (value << 1) | in; + + memory_write(state, addr, value); + update_zn(cpu, value); +} + +static void opcode_rol_zpx(struct nes_state * restrict state) { + struct cpu_state * restrict cpu = &state->cpu; + + uint8_t base = memory_read(state, cpu->pc++); + memory_read_dummy(state, base); + uint8_t addr = (base + cpu->x) & 0xff; + + uint8_t value = memory_read(state, addr); + memory_write(state, addr, value); // Dummy write + + uint8_t in = cpu->c; + cpu->c = (value >> 7) & 1; + value = (value << 1) | in; + + memory_write(state, addr, value); + update_zn(cpu, value); +} + +static void opcode_rol_absx(struct nes_state * restrict state) { + struct cpu_state * restrict cpu = &state->cpu; + + uint8_t lo = memory_read(state, cpu->pc++); + uint8_t hi = memory_read(state, cpu->pc++); + uint16_t base = lo | (hi << 8); + uint16_t addr = base + cpu->x; + + memory_read_dummy(state, (base & 0xff00) | (addr & 0x00ff)); + + uint8_t value = memory_read(state, addr); + memory_write(state, addr, value); // Dummy write + + uint8_t in = cpu->c; + cpu->c = (value >> 7) & 1; + value = (value << 1) | in; + + memory_write(state, addr, value); + update_zn(cpu, value); +} + + +// ROR + +static void opcode_ror_zp(struct nes_state * restrict state) { + struct cpu_state * restrict cpu = &state->cpu; + + uint8_t addr = memory_read(state, cpu->pc++); + uint8_t value = memory_read(state, addr); + + memory_write(state, addr, value); // Dummy write + + uint8_t in = cpu->c; + cpu->c = value & 1; + value = (value >> 1) | (in << 7); + + memory_write(state, addr, value); + update_zn(cpu, value); +} + +static void opcode_ror_acc(struct nes_state * restrict state) { + struct cpu_state * restrict cpu = &state->cpu; + + memory_read_dummy(state, cpu->pc); + + uint8_t in = cpu->c; + cpu->c = cpu->a & 1; + cpu->a = (cpu->a >> 1) | (in << 7); + + update_zn(cpu, cpu->a); +} + +static void opcode_ror_abs(struct nes_state * restrict state) { + struct cpu_state * restrict cpu = &state->cpu; + + uint8_t lo = memory_read(state, cpu->pc++); + uint8_t hi = memory_read(state, cpu->pc++); + uint16_t addr = lo | (hi << 8); + + uint8_t value = memory_read(state, addr); + memory_write(state, addr, value); // Dummy write + + uint8_t in = cpu->c; + cpu->c = value & 1; + value = (value >> 1) | (in << 7); + + memory_write(state, addr, value); + update_zn(cpu, value); +} + +static void opcode_ror_zpx(struct nes_state * restrict state) { + struct cpu_state * restrict cpu = &state->cpu; + + uint8_t base = memory_read(state, cpu->pc++); + memory_read_dummy(state, base); + uint8_t addr = (base + cpu->x) & 0xff; + + uint8_t value = memory_read(state, addr); + memory_write(state, addr, value); // Dummy write + + uint8_t in = cpu->c; + cpu->c = value & 1; + value = (value >> 1) | (in << 7); + + memory_write(state, addr, value); + update_zn(cpu, value); +} + +static void opcode_ror_absx(struct nes_state * restrict state) { + struct cpu_state * restrict cpu = &state->cpu; + + uint8_t lo = memory_read(state, cpu->pc++); + uint8_t hi = memory_read(state, cpu->pc++); + uint16_t base = lo | (hi << 8); + uint16_t addr = base + cpu->x; + + memory_read_dummy(state, (base & 0xff00) | (addr & 0x00ff)); + + uint8_t value = memory_read(state, addr); + memory_write(state, addr, value); // Dummy write + + uint8_t in = cpu->c; + cpu->c = value & 1; + value = (value >> 1) | (in << 7); + + memory_write(state, addr, value); + update_zn(cpu, value); +} + + +// SBC + +static inline void sbc(struct cpu_state * restrict cpu, uint8_t value) { +#ifdef ENABLE_DECIMAL_MODE + if(cpu->d) { + uint8_t al = (cpu->a & 0x0f) - (value & 0x0f) - (cpu->c ? 0 : 1); + uint8_t ah = (cpu->a >> 4) - (value >> 4); + if((int8_t)al < 0) { + al -= 6; + ah--; + } + cpu->c = ((int8_t)ah >= 0); + if(!cpu->c) { + ah -= 6; + } + cpu->a = (ah << 4) | (al & 0x0f); + update_zn(cpu, cpu->a); + // Note: overflow flag behavior in decimal mode is undefined on 6502 + return; + } +#endif + + uint16_t tmp = cpu->a - value - (cpu->c ? 0 : 1); + cpu->v = ((cpu->a ^ value) & (cpu->a ^ tmp)) & 0x80 ? 1 : 0; + cpu->c = (tmp < 0x100); + cpu->a = tmp & 0xff; + update_zn(cpu, cpu->a); +} + + +static void opcode_sbc_indx(struct nes_state * restrict state) { + struct cpu_state * restrict cpu = &state->cpu; + + uint8_t zp = memory_read(state, cpu->pc++); + memory_read_dummy(state, zp); + + uint8_t ptr = (zp + cpu->x) & 0xff; + uint8_t lo = memory_read(state, ptr); + uint8_t hi = memory_read(state, (ptr + 1) & 0xff); + uint16_t addr = lo | (hi << 8); + + uint8_t value = memory_read(state, addr); + sbc(cpu, value); +} + +static void opcode_sbc_zp(struct nes_state * restrict state) { + struct cpu_state * restrict cpu = &state->cpu; + + uint8_t addr = memory_read(state, cpu->pc++); + uint8_t value = memory_read(state, addr); + + sbc(cpu, value); +} + +static void opcode_sbc_imm(struct nes_state * restrict state) { + struct cpu_state * restrict cpu = &state->cpu; + + uint8_t value = memory_read(state, cpu->pc++); + sbc(cpu, value); +} + +static void opcode_sbc_abs(struct nes_state * restrict state) { + struct cpu_state * restrict cpu = &state->cpu; + + uint8_t lo = memory_read(state, cpu->pc++); + uint8_t hi = memory_read(state, cpu->pc++); + uint16_t addr = lo | (hi << 8); + + uint8_t value = memory_read(state, addr); + sbc(cpu, value); +} + +static void opcode_sbc_indy(struct nes_state * restrict state) { + struct cpu_state * restrict cpu = &state->cpu; + + uint8_t zp = memory_read(state, cpu->pc++); + uint8_t lo = memory_read(state, zp); + uint8_t hi = memory_read(state, (zp + 1) & 0xff); + + uint16_t base = lo | (hi << 8); + uint16_t addr = base + cpu->y; + + if((base & 0xff00) != (addr & 0xff00)) { + memory_read_dummy(state, (base & 0xff00) | (addr & 0x00ff)); + } + + uint8_t value = memory_read(state, addr); + sbc(cpu, value); +} + +static void opcode_sbc_zpx(struct nes_state * restrict state) { + struct cpu_state * restrict cpu = &state->cpu; + + uint8_t base = memory_read(state, cpu->pc++); + memory_read_dummy(state, base); + uint8_t addr = (base + cpu->x) & 0xff; + + uint8_t value = memory_read(state, addr); + sbc(cpu, value); +} + +static void opcode_sbc_absy(struct nes_state * restrict state) { + struct cpu_state * restrict cpu = &state->cpu; + + uint8_t lo = memory_read(state, cpu->pc++); + uint8_t hi = memory_read(state, cpu->pc++); + uint16_t base = lo | (hi << 8); + uint16_t addr = base + cpu->y; + + if((base & 0xff00) != (addr & 0xff00)) { + memory_read_dummy(state, (base & 0xff00) | (addr & 0x00ff)); + } + + uint8_t value = memory_read(state, addr); + sbc(cpu, value); +} + +static void opcode_sbc_absx(struct nes_state * restrict state) { + struct cpu_state * restrict cpu = &state->cpu; + + uint8_t lo = memory_read(state, cpu->pc++); + uint8_t hi = memory_read(state, cpu->pc++); + uint16_t base = lo | (hi << 8); + uint16_t addr = base + cpu->x; + + if((base & 0xff00) != (addr & 0xff00)) { + memory_read_dummy(state, (base & 0xff00) | (addr & 0x00ff)); + } + + uint8_t value = memory_read(state, addr); + sbc(cpu, value); +} + + +// TAX + +static void opcode_tax(struct nes_state * restrict state) { + struct cpu_state * restrict cpu = &state->cpu; + + memory_read_dummy(state, cpu->pc); + cpu->x = cpu->a; + update_zn(cpu, cpu->x); +} + +static void opcode_tay(struct nes_state * restrict state) { + struct cpu_state * restrict cpu = &state->cpu; + + memory_read_dummy(state, cpu->pc); + cpu->y = cpu->a; + update_zn(cpu, cpu->y); +} + +static void opcode_txa(struct nes_state * restrict state) { + struct cpu_state * restrict cpu = &state->cpu; + + memory_read_dummy(state, cpu->pc); + cpu->a = cpu->x; + update_zn(cpu, cpu->a); +} + +static void opcode_tya(struct nes_state * restrict state) { + struct cpu_state * restrict cpu = &state->cpu; + + memory_read_dummy(state, cpu->pc); + cpu->a = cpu->y; + update_zn(cpu, cpu->a); +} + +static void opcode_tsx(struct nes_state * restrict state) { + struct cpu_state * restrict cpu = &state->cpu; + + memory_read_dummy(state, cpu->pc); + cpu->x = cpu->sp; + update_zn(cpu, cpu->x); +} + +static void opcode_txs(struct nes_state * restrict state) { + struct cpu_state * restrict cpu = &state->cpu; + + memory_read_dummy(state, cpu->pc); + cpu->sp = cpu->x; +} + + +// INX + +static void opcode_inx(struct nes_state * restrict state) { + struct cpu_state * restrict cpu = &state->cpu; + + memory_read_dummy(state, cpu->pc); + cpu->x++; + update_zn(cpu, cpu->x); +} + + +// INY + +static void opcode_iny(struct nes_state * restrict state) { + struct cpu_state * restrict cpu = &state->cpu; + + memory_read_dummy(state, cpu->pc); + cpu->y++; + update_zn(cpu, cpu->y); +} + + +// DEX + +static void opcode_dex(struct nes_state * restrict state) { + struct cpu_state * restrict cpu = &state->cpu; + + memory_read_dummy(state, cpu->pc); + cpu->x--; + update_zn(cpu, cpu->x); +} + + +// DEY + +static void opcode_dey(struct nes_state * restrict state) { + struct cpu_state * restrict cpu = &state->cpu; + + memory_read_dummy(state, cpu->pc); + cpu->y--; + update_zn(cpu, cpu->y); +} + + +// STA + +static void opcode_sta_indx(struct nes_state * restrict state) { + struct cpu_state * restrict cpu = &state->cpu; + + uint8_t zp = memory_read(state, cpu->pc++); + memory_read_dummy(state, zp); + + uint8_t ptr = (zp + cpu->x) & 0xff; + uint8_t lo = memory_read(state, ptr); + uint8_t hi = memory_read(state, (ptr + 1) & 0xff); + uint16_t addr = lo | (hi << 8); + + memory_write(state, addr, cpu->a); +} + +static void opcode_sta_zp(struct nes_state * restrict state) { + struct cpu_state * restrict cpu = &state->cpu; + + uint8_t addr = memory_read(state, cpu->pc++); + memory_write(state, addr, cpu->a); +} + +static void opcode_sta_abs(struct nes_state * restrict state) { + struct cpu_state * restrict cpu = &state->cpu; + + uint8_t lo = memory_read(state, cpu->pc++); + uint8_t hi = memory_read(state, cpu->pc++); + uint16_t addr = lo | (hi << 8); + + memory_write(state, addr, cpu->a); +} + +static void opcode_sta_indy(struct nes_state * restrict state) { + struct cpu_state * restrict cpu = &state->cpu; + + uint8_t zp = memory_read(state, cpu->pc++); // T1 + uint8_t lo = memory_read(state, zp); // T2 + uint8_t hi = memory_read(state, (zp + 1) & 0xff); // T3 + + uint16_t base = lo | (hi << 8); + uint16_t addr = base + cpu->y; + + memory_read_dummy(state, (base & 0xff00) | (addr & 0x00ff)); + memory_write(state, addr, cpu->a); // T5 +} + +static void opcode_sta_zpx(struct nes_state * restrict state) { + struct cpu_state * restrict cpu = &state->cpu; + + uint8_t base = memory_read(state, cpu->pc++); + memory_read_dummy(state, base); + uint8_t addr = (base + cpu->x) & 0xff; + + memory_write(state, addr, cpu->a); +} + +static void opcode_sta_absy(struct nes_state * restrict state) { + struct cpu_state * restrict cpu = &state->cpu; + + uint8_t lo = memory_read(state, cpu->pc++); + uint8_t hi = memory_read(state, cpu->pc++); + uint16_t base = lo | (hi << 8); + uint16_t addr = base + cpu->y; + + memory_read_dummy(state, (base & 0xff00) | (addr & 0x00ff)); + memory_write(state, addr, cpu->a); +} + +static void opcode_sta_absx(struct nes_state * restrict state) { + struct cpu_state * restrict cpu = &state->cpu; + + uint8_t lo = memory_read(state, cpu->pc++); // T1 + uint8_t hi = memory_read(state, cpu->pc++); // T2 + uint16_t base = lo | (hi << 8); + uint16_t addr = base + cpu->x; + + memory_read_dummy(state, (base & 0xff00) | (addr & 0x00ff)); // T3 (always) + memory_write(state, addr, cpu->a); // T4 +} + + +// STX + +static void opcode_stx_zp(struct nes_state * restrict state) { + struct cpu_state * restrict cpu = &state->cpu; + + uint8_t addr = memory_read(state, cpu->pc++); + memory_write(state, addr, cpu->x); +} + +static void opcode_stx_abs(struct nes_state * restrict state) { + struct cpu_state * restrict cpu = &state->cpu; + + uint8_t lo = memory_read(state, cpu->pc++); + uint8_t hi = memory_read(state, cpu->pc++); + uint16_t addr = lo | (hi << 8); + + memory_write(state, addr, cpu->x); +} + +static void opcode_stx_zpy(struct nes_state * restrict state) { + struct cpu_state * restrict cpu = &state->cpu; + + uint8_t base = memory_read(state, cpu->pc++); + memory_read_dummy(state, base); + uint8_t addr = (base + cpu->y) & 0xff; + + memory_write(state, addr, cpu->x); +} + + +// STY + +static void opcode_sty_zp(struct nes_state * restrict state) { + struct cpu_state * restrict cpu = &state->cpu; + + uint8_t addr = memory_read(state, cpu->pc++); + memory_write(state, addr, cpu->y); +} + +static void opcode_sty_abs(struct nes_state * restrict state) { + struct cpu_state * restrict cpu = &state->cpu; + + uint8_t lo = memory_read(state, cpu->pc++); + uint8_t hi = memory_read(state, cpu->pc++); + uint16_t addr = lo | (hi << 8); + + memory_write(state, addr, cpu->y); +} + +static void opcode_sty_zpx(struct nes_state * restrict state) { + struct cpu_state * restrict cpu = &state->cpu; + + uint8_t base = memory_read(state, cpu->pc++); + memory_read_dummy(state, base); + uint8_t addr = (base + cpu->x) & 0xff; + + memory_write(state, addr, cpu->y); +} + + +__attribute__((noinline)) +static void init_opcode_lut(void) { + opcode_lut[0x00] = opcode_brk; + opcode_lut[0x01] = opcode_ora_indx; + opcode_lut[0x05] = opcode_ora_zp; + opcode_lut[0x06] = opcode_asl_zp; + opcode_lut[0x08] = opcode_php; + opcode_lut[0x09] = opcode_ora_imm; + opcode_lut[0x0a] = opcode_asl_acc; + opcode_lut[0x0d] = opcode_ora_abs; + opcode_lut[0x0e] = opcode_asl_abs; + opcode_lut[0x10] = opcode_bpl; + opcode_lut[0x11] = opcode_ora_indy; + opcode_lut[0x15] = opcode_ora_zpx; + opcode_lut[0x16] = opcode_asl_zpx; + opcode_lut[0x18] = opcode_clc; + opcode_lut[0x19] = opcode_ora_absy; + opcode_lut[0x1d] = opcode_ora_absx; + opcode_lut[0x1e] = opcode_asl_absx; + opcode_lut[0x20] = opcode_jsr; + opcode_lut[0x21] = opcode_and_indx; + opcode_lut[0x24] = opcode_bit_zp; + opcode_lut[0x25] = opcode_and_zp; + opcode_lut[0x26] = opcode_rol_zp; + opcode_lut[0x28] = opcode_plp; + opcode_lut[0x29] = opcode_and_imm; + opcode_lut[0x2a] = opcode_rol_acc; + opcode_lut[0x2c] = opcode_bit_abs; + opcode_lut[0x2d] = opcode_and_abs; + opcode_lut[0x2e] = opcode_rol_abs; + opcode_lut[0x30] = opcode_bmi; + opcode_lut[0x31] = opcode_and_indy; + opcode_lut[0x35] = opcode_and_zpx; + opcode_lut[0x36] = opcode_rol_zpx; + opcode_lut[0x38] = opcode_sec; + opcode_lut[0x39] = opcode_and_absy; + opcode_lut[0x3d] = opcode_and_absx; + opcode_lut[0x3e] = opcode_rol_absx; + opcode_lut[0x40] = opcode_rti; + opcode_lut[0x41] = opcode_eor_indx; + opcode_lut[0x45] = opcode_eor_zp; + opcode_lut[0x46] = opcode_lsr_zp; + opcode_lut[0x48] = opcode_pha; + opcode_lut[0x49] = opcode_eor_imm; + opcode_lut[0x4a] = opcode_lsr_acc; + opcode_lut[0x4c] = opcode_jmp_abs; + opcode_lut[0x4d] = opcode_eor_abs; + opcode_lut[0x4e] = opcode_lsr_abs; + opcode_lut[0x50] = opcode_bvc; + opcode_lut[0x51] = opcode_eor_indy; + opcode_lut[0x55] = opcode_eor_zpx; + opcode_lut[0x56] = opcode_lsr_zpx; + opcode_lut[0x58] = opcode_cli; + opcode_lut[0x59] = opcode_eor_absy; + opcode_lut[0x5d] = opcode_eor_absx; + opcode_lut[0x5e] = opcode_lsr_absx; + opcode_lut[0x60] = opcode_rts; + opcode_lut[0x61] = opcode_adc_indx; + opcode_lut[0x65] = opcode_adc_zp; + opcode_lut[0x66] = opcode_ror_zp; + opcode_lut[0x68] = opcode_pla; + opcode_lut[0x69] = opcode_adc_imm; + opcode_lut[0x6a] = opcode_ror_acc; + opcode_lut[0x6c] = opcode_jmp_ind; + opcode_lut[0x6d] = opcode_adc_abs; + opcode_lut[0x6e] = opcode_ror_abs; + opcode_lut[0x70] = opcode_bvs; + opcode_lut[0x71] = opcode_adc_indy; + opcode_lut[0x75] = opcode_adc_zpx; + opcode_lut[0x76] = opcode_ror_zpx; + opcode_lut[0x78] = opcode_sei; + opcode_lut[0x79] = opcode_adc_absy; + opcode_lut[0x7d] = opcode_adc_absx; + opcode_lut[0x7e] = opcode_ror_absx; + opcode_lut[0x81] = opcode_sta_indx; + opcode_lut[0x84] = opcode_sty_zp; + opcode_lut[0x85] = opcode_sta_zp; + opcode_lut[0x86] = opcode_stx_zp; + opcode_lut[0x88] = opcode_dey; + opcode_lut[0x8a] = opcode_txa; + opcode_lut[0x8c] = opcode_sty_abs; + opcode_lut[0x8d] = opcode_sta_abs; + opcode_lut[0x8e] = opcode_stx_abs; + opcode_lut[0x90] = opcode_bcc; + opcode_lut[0x91] = opcode_sta_indy; + opcode_lut[0x94] = opcode_sty_zpx; + opcode_lut[0x95] = opcode_sta_zpx; + opcode_lut[0x96] = opcode_stx_zpy; + opcode_lut[0x98] = opcode_tya; + opcode_lut[0x99] = opcode_sta_absy; + opcode_lut[0x9a] = opcode_txs; + opcode_lut[0x9d] = opcode_sta_absx; + opcode_lut[0xa0] = opcode_ldy_imm; + opcode_lut[0xa1] = opcode_lda_indx; + opcode_lut[0xa2] = opcode_ldx_imm; + opcode_lut[0xa4] = opcode_ldy_zp; + opcode_lut[0xa5] = opcode_lda_zp; + opcode_lut[0xa6] = opcode_ldx_zp; + opcode_lut[0xa8] = opcode_tay; + opcode_lut[0xa9] = opcode_lda_imm; + opcode_lut[0xaa] = opcode_tax; + opcode_lut[0xac] = opcode_ldy_abs; + opcode_lut[0xad] = opcode_lda_abs; + opcode_lut[0xae] = opcode_ldx_abs; + opcode_lut[0xb0] = opcode_bcs; + opcode_lut[0xb1] = opcode_lda_indy; + opcode_lut[0xb4] = opcode_ldy_zpx; + opcode_lut[0xb5] = opcode_lda_zpx; + opcode_lut[0xb6] = opcode_ldx_zpy; + opcode_lut[0xb8] = opcode_clv; + opcode_lut[0xb9] = opcode_lda_absy; + opcode_lut[0xba] = opcode_tsx; + opcode_lut[0xbc] = opcode_ldy_absx; + opcode_lut[0xbd] = opcode_lda_absx; + opcode_lut[0xbe] = opcode_ldx_absy; + opcode_lut[0xc0] = opcode_cpy_imm; + opcode_lut[0xc1] = opcode_cmp_indx; + opcode_lut[0xc4] = opcode_cpy_zp; + opcode_lut[0xc5] = opcode_cmp_zp; + opcode_lut[0xc6] = opcode_dec_zp; + opcode_lut[0xc8] = opcode_iny; + opcode_lut[0xc9] = opcode_cmp_imm; + opcode_lut[0xca] = opcode_dex; + opcode_lut[0xcc] = opcode_cpy_abs; + opcode_lut[0xcd] = opcode_cmp_abs; + opcode_lut[0xce] = opcode_dec_abs; + opcode_lut[0xd0] = opcode_bne; + opcode_lut[0xd1] = opcode_cmp_indy; + opcode_lut[0xd5] = opcode_cmp_zpx; + opcode_lut[0xd6] = opcode_dec_zpx; + opcode_lut[0xd8] = opcode_cld; + opcode_lut[0xd9] = opcode_cmp_absy; + opcode_lut[0xdd] = opcode_cmp_absx; + opcode_lut[0xde] = opcode_dec_absx; + opcode_lut[0xe0] = opcode_cpx_imm; + opcode_lut[0xe1] = opcode_sbc_indx; + opcode_lut[0xe4] = opcode_cpx_zp; + opcode_lut[0xe5] = opcode_sbc_zp; + opcode_lut[0xe6] = opcode_inc_zp; + opcode_lut[0xe8] = opcode_inx; + opcode_lut[0xe9] = opcode_sbc_imm; + opcode_lut[0xea] = opcode_nop; + opcode_lut[0xeb] = opcode_sbc_imm; + opcode_lut[0xec] = opcode_cpx_abs; + opcode_lut[0xed] = opcode_sbc_abs; + opcode_lut[0xee] = opcode_inc_abs; + opcode_lut[0xf0] = opcode_beq; + opcode_lut[0xf1] = opcode_sbc_indy; + opcode_lut[0xf5] = opcode_sbc_zpx; + opcode_lut[0xf6] = opcode_inc_zpx; + opcode_lut[0xf8] = opcode_sed; + opcode_lut[0xf9] = opcode_sbc_absy; + opcode_lut[0xfd] = opcode_sbc_absx; + opcode_lut[0xfe] = opcode_inc_absx; +} + + + + + + + + + + + + -- cgit v1.2.3