From d8bb5a5ccf96fed7e8084cf691c987ce56a8c995 Mon Sep 17 00:00:00 2001 From: vin Date: Wed, 3 Jul 2024 18:52:15 -0400 Subject: [PATCH] call opcode function pointer instead of using switch case Also improve logging. --- cpu.c | 1441 +++++++---------------------------------------------- opcodes.h | 304 +++++------ 2 files changed, 323 insertions(+), 1422 deletions(-) diff --git a/cpu.c b/cpu.c index edfe172..6e44c7f 100644 --- a/cpu.c +++ b/cpu.c @@ -106,10 +106,8 @@ opcode_arg(enum addressing_mode mode) if (mode != AM_ABS && mode != AM_ABS_X && mode != AM_ABS_Y) { arg = peek(regs.pc++); - printf(" %02X\t", arg); } else { arg = peek16(regs.pc); - printf(" %02X %02X\t", peek(regs.pc), peek(regs.pc + 1)); regs.pc += 2; } @@ -155,12 +153,12 @@ opcode_mem(enum addressing_mode mode) { uint16_t arg, val; - if (mode != AM_ABS && mode != AM_ABS_X && mode != AM_ABS_Y && mode != AM_IND && mode) { + if (mode == AM_ACC || mode == AM_NONE) { + return 0; + } else if (mode != AM_ABS && mode != AM_ABS_X && mode != AM_ABS_Y && mode != AM_IND && mode) { arg = peek(regs.pc++); - printf(" %02X\t", arg); } else { arg = peek16(regs.pc); - printf(" %02X %02X\t", peek(regs.pc), peek(regs.pc + 1)); regs.pc += 2; } @@ -175,6 +173,7 @@ opcode_mem(enum addressing_mode mode) val = (arg + regs.y) % 256; break; case AM_IMM: + case AM_REL: case AM_ABS: val = arg; break; @@ -194,15 +193,15 @@ opcode_mem(enum addressing_mode mode) val = peek(arg) + peek((arg + 1) % 256) * 256 + regs.y; break; default: - fprintf(stderr, "INVALID ADDRESSING MODE\n"); + fprintf(stderr, "opcode_mem INVALID ADDRESSING MODE %i\n", mode); abort(); } return val; } -static void -adc(uint8_t arg) +void +ADC(uint16_t arg) { uint16_t sum; // 16-bit sum makes it easier to determine carry flag @@ -216,16 +215,16 @@ adc(uint8_t arg) STATUS_UPDATE_NZ(regs.a); } -static void -and(uint8_t arg) +void +AND(uint16_t arg) { regs.a &= arg; STATUS_UPDATE_NZ(regs.a); } -static void -asl_acc(void) +void +ASL_acc(uint16_t arg) { uint16_t tmp; @@ -236,8 +235,8 @@ asl_acc(void) STATUS_UPDATE_NZ(regs.a); } -static void -asl(uint16_t mem) +void +ASL(uint16_t mem) { uint16_t tmp; @@ -248,109 +247,108 @@ asl(uint16_t mem) STATUS_UPDATE_NZ(tmp); } -static void -bcc(uint8_t arg) +void +BCC(uint16_t arg) { if (regs.status.carry == 0) - regs.pc += arg; + regs.pc += arg, cycles++; } -static void -bcs(uint8_t arg) +void +BCS(uint16_t arg) { if (regs.status.carry == 1) - regs.pc += arg; + regs.pc += arg, cycles++; } -static void -beq(uint8_t arg) +void +BEQ(uint16_t arg) { if (regs.status.zero == 1) - regs.pc += arg; + regs.pc += arg, cycles++; } -static uint8_t -bit(uint8_t arg) +void +BIT(uint16_t arg) { - regs.status.zero = (regs.a & arg) == 0; - regs.status.overflow = (arg & (1 << 6)) != 0; - STATUS_UPDATE_NEGATIVE(arg); - - return regs.a & arg; + uint8_t tmp = peek(arg); + regs.status.zero = (regs.a & tmp) == 0; + regs.status.overflow = (tmp & (1 << 6)) != 0; + STATUS_UPDATE_NEGATIVE(tmp); } -static void -bmi(uint8_t arg) +void +BMI(uint16_t arg) { if (regs.status.negative == 1) - regs.pc += arg; + regs.pc += arg, cycles++; } -static void -bne(uint8_t arg) +void +BNE(uint16_t arg) { if (regs.status.zero == 0) - regs.pc += arg; + regs.pc += arg, cycles++; } -static void -bpl(uint8_t arg) +void +BPL(uint16_t arg) { if (regs.status.negative == 0) - regs.pc += arg; + regs.pc += arg, cycles++; } -static void -brk(void) +void +BRK(uint16_t arg) { /* TODO: push regs.pc and regs.status to stack and load IRQ vector */ regs.status.brk = 1; // exit(0); } -static void -bvc(uint8_t arg) +void +BVC(uint16_t arg) { //regs.status.overflow = (STATUS_TO_INT() & (1 << 6)) == 0; //if (regs.status.overflow == 0) if ((STATUS_TO_INT() & (1 << 6)) == 0) - regs.pc += arg; + regs.pc += arg, cycles++; } -static void -bvs(uint8_t arg) +void +BVS(uint16_t arg) { regs.status.overflow = (STATUS_TO_INT() & (1 << 6)) != 0; if (regs.status.overflow == 1) - regs.pc += arg; + regs.pc += arg, cycles++; } -static void -clc(void) +void +CLC(uint16_t arg) { regs.status.carry = 0; } -static void -cld(void) +void +CLD(uint16_t arg) { regs.status.decimal_mode = 0; } -static void -cli(void) +void +CLI(uint16_t arg) { regs.status.interrupt_disable = 0; } -static void -clv(void) +void +CLV(uint16_t arg) { regs.status.overflow = 0; } -static void -cmp(uint8_t arg) +void +CMP(uint16_t arg) { uint8_t tmp; @@ -361,8 +359,8 @@ cmp(uint8_t arg) STATUS_UPDATE_NEGATIVE(tmp); } -static void -cpx(uint8_t arg) +void +CPX(uint16_t arg) { uint8_t tmp; @@ -373,8 +371,8 @@ cpx(uint8_t arg) STATUS_UPDATE_NEGATIVE(tmp); } -static void -cpy(uint8_t arg) +void +CPY(uint16_t arg) { uint8_t tmp; @@ -385,70 +383,70 @@ cpy(uint8_t arg) STATUS_UPDATE_NEGATIVE(tmp); } -static void -dec(uint16_t mem) +void +DEC(uint16_t mem) { memwrite(mem, peek(mem) - 1); STATUS_UPDATE_NZ(peek(mem)); } -static void -dex(void) +void +DEX(uint16_t arg) { regs.x--; STATUS_UPDATE_NZ(regs.x); } -static void -dey(void) +void +DEY(uint16_t arg) { regs.y--; STATUS_UPDATE_NZ(regs.y); } -static void -eor(uint8_t arg) +void +EOR(uint16_t arg) { regs.a ^= arg; STATUS_UPDATE_NZ(regs.a); } -static void -inc(uint16_t mem) +void +INC(uint16_t mem) { memwrite(mem, peek(mem) + 1); STATUS_UPDATE_NZ(peek(mem)); } -static void -inx(void) +void +INX(uint16_t arg) { regs.x++; STATUS_UPDATE_NZ(regs.x); } -static void -iny(void) +void +INY(uint16_t arg) { regs.y++; STATUS_UPDATE_NZ(regs.y); } -static void -jmp(uint16_t arg) +void +JMP(uint16_t arg) { regs.pc = arg; } -static void -jsr(uint16_t arg) +void +JSR(uint16_t arg) { uint16_t tmp = regs.pc - 1; @@ -461,32 +459,32 @@ jsr(uint16_t arg) regs.pc = arg; } -static void -lda(uint8_t arg) +void +LDA(uint16_t arg) { regs.a = arg; STATUS_UPDATE_NZ(regs.a); } -static void -ldx(uint8_t arg) +void +LDX(uint16_t arg) { regs.x = arg; STATUS_UPDATE_NZ(regs.x); } -static void -ldy(uint8_t arg) +void +LDY(uint16_t arg) { regs.y = arg; STATUS_UPDATE_NZ(regs.y); } -static void -lsr_acc(void) +void +LSR_acc(uint16_t arg) { regs.status.carry = regs.a & 1; // bit 0 in carry regs.a >>= 1; @@ -495,8 +493,8 @@ lsr_acc(void) STATUS_UPDATE_NZ(regs.a); } -static void -lsr(uint16_t mem) +void +LSR(uint16_t mem) { uint8_t tmp; @@ -511,42 +509,42 @@ lsr(uint16_t mem) STATUS_UPDATE_NZ(tmp); } -static void -nop(void) +void +NOP(uint16_t arg) { return; } -static void -ora(uint8_t arg) +void +ORA(uint16_t arg) { regs.a |= arg; STATUS_UPDATE_NZ(regs.a); } -static void -pha(void) +void +PHA(uint16_t arg) { PUSH(regs.a); } -static void -php(void) +void +PHP(uint16_t arg) { PUSH(STATUS_TO_INT() | (1 << 4)); } -static void -pla(void) +void +PLA(uint16_t arg) { regs.a = PULL(); STATUS_UPDATE_NZ(regs.a); } -static void -plp(void) +void +PLP(uint16_t arg) { uint8_t status; @@ -562,8 +560,8 @@ plp(void) regs.status.negative = (status & (1 << 7)) != 0; } -static void -rol_acc(void) +void +ROL_acc(uint16_t arg) { uint8_t carry; carry = (regs.a & (1 << 7)) != 0; @@ -575,8 +573,8 @@ rol_acc(void) STATUS_UPDATE_NZ(regs.a); } -static void -rol(uint16_t mem) +void +ROL(uint16_t mem) { uint8_t carry, tmp; carry = (peek(mem) & (1 << 7)) != 0; @@ -588,8 +586,8 @@ rol(uint16_t mem) STATUS_UPDATE_NZ(regs.a); } -static void -ror_acc(void) +void +ROR_acc(uint16_t arg) { uint8_t carry; carry = regs.a & 1; @@ -601,8 +599,8 @@ ror_acc(void) STATUS_UPDATE_NZ(regs.a); } -static void -ror(uint16_t mem) +void +ROR(uint16_t mem) { uint8_t carry, tmp; carry = peek(mem) & 1; @@ -614,89 +612,83 @@ ror(uint16_t mem) STATUS_UPDATE_NZ(tmp); } -static void -rti(void) +void +RTI(uint16_t arg) { - plp(); + PLP(0); regs.pc = PULL() | (PULL() << 8); } -static void -rts(void) +void +RTS(uint16_t arg) { regs.pc = (PULL() | (PULL() << 8)) + 1; } -static void -sbc(uint8_t arg) +void +SBC(uint16_t arg) { /* SBC is described online as ADC with argument as two's complement */ - adc(~arg); + ADC(~(uint8_t)arg); } -static void -sec(void) +void +SEC(uint16_t arg) { regs.status.carry = 1; } -static void -sed(void) +void +SED(uint16_t arg) { regs.status.decimal_mode = 1; } -static void -sei(void) +void +SEI(uint16_t arg) { regs.status.interrupt_disable = 1; } -static uint8_t -sta(uint16_t mem) +void +STA(uint16_t mem) { uint8_t tmp = peek(mem); memwrite(mem, regs.a); - - return tmp; } -static uint8_t -stx(uint16_t mem) +void +STX(uint16_t mem) { uint8_t tmp = peek(mem); memwrite(mem, regs.x); - - return tmp; } -static uint8_t -sty(uint16_t mem) +void +STY(uint16_t mem) { uint8_t tmp = peek(mem); memwrite(mem, regs.y); - - return tmp; } -static void -tax(void) +void +TAX(uint16_t arg) { regs.x = regs.a; STATUS_UPDATE_NZ(regs.x); } -static void -tay(void) +void +TAY(uint16_t arg) { regs.y = regs.a; STATUS_UPDATE_NZ(regs.y); } -static void -tsx(void) +void +TSX(uint16_t arg) { // regs.x = PULL(); regs.x = regs.sp; @@ -704,23 +696,23 @@ tsx(void) STATUS_UPDATE_NZ(regs.x); } -static void -txa(void) +void +TXA(uint16_t arg) { regs.a = regs.x; STATUS_UPDATE_NZ(regs.a); } -static void -txs(void) +void +TXS(uint16_t arg) { // PUSH(regs.x); regs.sp = regs.x; } -static void -tya(void) +void +TYA(uint16_t arg) { regs.a = regs.y; @@ -730,1161 +722,68 @@ tya(void) static void interpret(void) { - uint8_t opcode, did_memwrite, ret, status; + uint8_t op; uint16_t arg, mem, deref; - uint32_t cycles_; enum addressing_mode mode; - struct registers regs_; for (;;) { - opcode = peek(regs.pc++); - cycles_ = cycles; - did_memwrite = 0; - status = STATUS_TO_INT(); - regs_ = regs; + printf("%04X ", regs.pc); - printf("%04X %02X", regs.pc - 1, opcode); + op = peek(regs.pc++); - switch (opcode) { - case 0x69: - mode = AM_IMM; - arg = opcode_arg(mode); - adc(arg); - cycles += 2; - printf("ADC"); - break; - case 0x65: - mode = AM_ZP; - arg = opcode_arg(mode); - adc(arg); - cycles += 3; - printf("ADC"); - break; - case 0x75: - mode = AM_ZP_X; - arg = opcode_arg(mode); - adc(arg); - cycles += 4; - printf("ADC"); - break; - case 0x6d: - mode = AM_ABS; - arg = opcode_arg(mode); - adc(arg); - cycles += 4; - printf("ADC"); - break; - case 0x7d: - mode = AM_ABS_X; - arg = opcode_arg(mode); - adc(arg); - cycles += 4; - printf("ADC"); - break; - case 0x79: - mode = AM_ABS_Y; - arg = opcode_arg(mode); - adc(arg); - cycles += 4; - printf("ADC"); - break; - case 0x61: - mode = AM_IND_X; - arg = opcode_arg(mode); - adc(arg); - cycles += 6; - printf("ADC"); - break; - case 0x71: - mode = AM_IND_Y; - arg = opcode_arg(mode); - adc(arg); - cycles += 5; - printf("ADC"); - break; - case 0x29: - mode = AM_IMM; - arg = opcode_arg(mode); - and(arg); - cycles += 2; - printf("AND"); - break; - case 0x25: - mode = AM_ZP; - arg = opcode_arg(mode); - and(arg); - cycles += 3; - printf("AND"); - break; - case 0x35: - mode = AM_ZP_X; - arg = opcode_arg(mode); - and(arg); - cycles += 4; - printf("AND"); - break; - case 0x2d: - mode = AM_ABS; - arg = opcode_arg(mode); - and(arg); - cycles += 4; - printf("AND"); - break; - case 0x3d: - mode = AM_ABS_X; - arg = opcode_arg(mode); - and(arg); - cycles += 4; - printf("AND"); - break; - case 0x39: - mode = AM_ABS_Y; - arg = opcode_arg(mode); - and(arg); - cycles += 4; - printf("AND"); - break; - case 0x21: - mode = AM_IND_X; - arg = opcode_arg(mode); - and(arg); - cycles += 6; - printf("AND"); - break; - case 0x31: - mode = AM_IND_Y; - arg = opcode_arg(mode); - and(arg); - cycles += 5; - printf("AND"); - break; - case 0x0a: - mode = AM_ACC; - asl_acc(); - cycles += 2; - printf("\tASL"); - break; - case 0x06: - mode = AM_ZP; - arg = opcode_mem(mode); - asl(arg); - cycles += 5; - printf("ASL"); - break; - case 0x16: - mode = AM_ZP_X; - arg = opcode_mem(mode); - asl(arg); - cycles += 6; - printf("ASL"); - break; - case 0x0e: - mode = AM_ABS; - arg = opcode_mem(mode); - asl(arg); - cycles += 6; - printf("ASL"); - break; - case 0x1e: - mode = AM_ABS_X; - arg = opcode_mem(mode); - asl(arg); - cycles += 6; - printf("ASL"); - break; - case 0x90: - mode = AM_REL; - arg = opcode_arg(mode); - bcc(arg); - arg += regs_.pc + 1; - cycles += 2; - printf("BCC"); - break; - case 0xb0: - mode = AM_REL; - arg = opcode_arg(mode); - bcs(arg); - arg += regs_.pc + 1; - cycles += 2; - printf("BCS"); - break; - case 0xf0: - mode = AM_REL; - arg = opcode_arg(mode); - beq(arg); - arg += regs_.pc + 1; - cycles += 2; - printf("BEQ"); - break; - case 0x89: - mode = AM_IMM; - arg = opcode_arg(mode); - did_memwrite = 1; - ret = bit(arg); - cycles += 2; - printf("BIT"); - break; - case 0x24: - mode = AM_ZP; - arg = opcode_arg(mode); - did_memwrite = 1; - ret = bit(arg); - cycles += 3; - printf("BIT"); - break; - case 0x34: - mode = AM_ZP_X; - arg = opcode_arg(mode); - did_memwrite = 1; - ret = bit(arg); - cycles += 4; - printf("BIT"); - break; - case 0x2c: - mode = AM_ABS; - arg = opcode_arg(mode); - did_memwrite = 1; - ret = bit(arg); - cycles += 4; - printf("BIT"); - break; - case 0x3c: - mode = AM_ABS_X; - arg = opcode_arg(mode); - did_memwrite = 1; - ret = bit(arg); - cycles += 4; - printf("BIT"); - break; - case 0x30: - mode = AM_REL; - arg = opcode_arg(mode); - bmi(arg); - arg += regs_.pc + 1; - cycles += 2; - printf("BMI"); - break; - case 0xd0: - mode = AM_REL; - arg = opcode_arg(mode); - bne(arg); - arg += regs_.pc + 1; - cycles += 2; - printf("BNE"); - break; - case 0x10: - mode = AM_REL; - arg = opcode_arg(mode); - bpl(arg); - arg += regs_.pc + 1; - cycles += 2; - printf("BPL"); - break; - case 0x00: - mode = AM_IMPLICIT; - brk(); - cycles += 7; - printf("\tBRK"); - goto loop_exit; - case 0x50: - mode = AM_REL; - arg = opcode_arg(mode); - bvc(arg); - arg += regs_.pc + 1; - cycles += 2; - printf("BVC"); - break; - case 0x70: - mode = AM_REL; - arg = opcode_arg(mode); - bvs(arg); - arg += regs_.pc + 1; - cycles += 2; - printf("BVS"); - break; - case 0x18: - mode = AM_IMPLICIT; - clc(); - cycles += 2; - printf("\tCLC"); - break; - case 0xd8: - mode = AM_IMPLICIT; - cld(); - cycles += 2; - printf("\tCLD"); - break; - case 0x58: - mode = AM_IMPLICIT; - cli(); - cycles += 2; - printf("\tCLI"); - break; - case 0xb8: - mode = AM_IMPLICIT; - clv(); - cycles += 2; - printf("\tCLV"); - break; - case 0xc9: - mode = AM_IMM; - arg = opcode_arg(mode); - cmp(arg); - cycles += 2; - printf("CMP"); - break; - case 0xc5: - mode = AM_ZP; - arg = opcode_arg(mode); - cmp(arg); - cycles += 3; - printf("CMP"); - break; - case 0xd5: - mode = AM_ZP_X; - arg = opcode_arg(mode); - cmp(arg); - cycles += 4; - printf("CMP"); - break; - case 0xcd: - mode = AM_ABS; - arg = opcode_arg(mode); - cmp(arg); - cycles += 4; - printf("CMP"); - break; - case 0xdd: - mode = AM_ABS_X; - arg = opcode_arg(mode); - cmp(arg); - cycles += 4; - printf("CMP"); - break; - case 0xd9: - mode = AM_ABS_Y; - arg = opcode_arg(mode); - cmp(arg); - cycles += 4; - printf("CMP"); - break; - case 0xc1: - mode = AM_IND_X; - arg = opcode_arg(mode); - cmp(arg); - cycles += 6; - printf("CMP"); - break; - case 0xd1: - mode = AM_IND_Y; - arg = opcode_arg(mode); - cmp(arg); - cycles += 5; - printf("CMP"); - break; - case 0xe0: - mode = AM_IMM; - arg = opcode_arg(mode); - cpx(arg); - cycles += 2; - printf("CPX"); - break; - case 0xe4: - mode = AM_ZP; - arg = opcode_arg(mode); - cpx(arg); - cycles += 3; - printf("CPX"); - break; - case 0xec: - mode = AM_ABS; - arg = opcode_arg(mode); - cpx(arg); - cycles += 4; - printf("CPX"); - break; - case 0xc0: - mode = AM_IMM; - arg = opcode_arg(mode); - cpy(arg); - cycles += 2; - printf("CPY"); - break; - case 0xc4: - mode = AM_ZP; - arg = opcode_arg(mode); - cpy(arg); - cycles += 3; - printf("CPY"); - break; - case 0xcc: - mode = AM_ABS; - arg = opcode_arg(mode); - cpy(arg); - cycles += 4; - printf("CPY"); - break; - case 0xc6: - mode = AM_ZP; - arg = opcode_mem(mode); - dec(arg); - cycles += 5; - printf("DEC"); - break; - case 0xd6: - mode = AM_ZP_X; - arg = opcode_mem(mode); - dec(arg); - cycles += 6; - printf("DEC"); - break; - case 0xce: - mode = AM_ABS; - arg = opcode_mem(mode); - dec(arg); - cycles += 6; - printf("DEC"); - break; - case 0xde: - mode = AM_ABS_X; - arg = opcode_mem(mode); - dec(arg); - cycles += 7; - printf("DEC"); - break; - case 0xca: - mode = AM_IMPLICIT; - dex(); - cycles += 2; - printf("\tDEX"); - break; - case 0x88: - mode = AM_IMPLICIT; - dey(); - cycles += 2; - printf("\tDEY"); - break; - case 0x49: - mode = AM_IMM; - arg = opcode_arg(mode); - eor(arg); - cycles += 2; - printf("EOR"); - break; - case 0x45: - mode = AM_ZP; - arg = opcode_arg(mode); - eor(arg); - cycles += 3; - printf("EOR"); - break; - case 0x55: - mode = AM_ZP_X; - arg = opcode_arg(mode); - eor(arg); - cycles += 4; - printf("EOR"); - break; - case 0x4d: - mode = AM_ABS; - arg = opcode_arg(mode); - eor(arg); - cycles += 4; - printf("EOR"); - break; - case 0x5d: - mode = AM_ABS_X; - arg = opcode_arg(mode); - eor(arg); - cycles += 4; - printf("EOR"); - break; - case 0x59: - mode = AM_ABS_Y; - arg = opcode_arg(mode); - eor(arg); - cycles += 4; - printf("EOR"); - break; - case 0x41: - mode = AM_IND_X; - arg = opcode_arg(mode); - eor(arg); - cycles += 6; - printf("EOR"); - break; - case 0x51: - mode = AM_IND_Y; - arg = opcode_arg(mode); - eor(arg); - cycles += 5; - printf("EOR"); - break; - case 0xe6: - mode = AM_ZP; - arg = opcode_arg(mode); - inc(arg); - cycles += 5; - printf("INC"); - break; - case 0xf6: - mode = AM_ZP_X; - arg = opcode_arg(mode); - inc(arg); - cycles += 6; - printf("INC"); - break; - case 0xee: - mode = AM_ABS; - arg = opcode_mem(mode); - inc(arg); - cycles += 6; - printf("INC"); - break; - case 0xfe: - mode = AM_ABS_X; - arg = opcode_arg(mode); - inc(arg); - cycles += 7; - printf("INC"); - break; - case 0xe8: - mode = AM_IMPLICIT; - inx(); - cycles += 2; - printf("\tINX"); - break; - case 0xc8: - mode = AM_IMPLICIT; - iny(); - cycles += 2; - printf("\tINY"); - break; - case 0x4c: - mode = AM_ABS; - arg = opcode_mem(mode); - jmp(arg); - cycles += 3; - printf("JMP"); - break; - case 0x6c: - mode = AM_IND; - mem = peek16(regs.pc); - deref = peek16(mem); - arg = opcode_mem(mode); - deref = arg; - jmp(arg); - cycles += 6; - printf("JMP"); - break; - case 0x7c: - mode = AM_ABS_X; - arg = opcode_arg(mode); - jmp(arg); - cycles += 6; - printf("JMP"); - break; - case 0x20: - mode = AM_ABS; - arg = opcode_mem(mode); - jsr(arg); - cycles += 6; - printf("JSR"); - break; - case 0xa9: - mode = AM_IMM; - arg = opcode_arg(mode); - lda(arg); - cycles += 2; - printf("LDA"); - break; - case 0xa5: - mode = AM_ZP; - arg = opcode_arg(mode); - lda(arg); - cycles += 3; - printf("LDA"); - break; - case 0xb5: - mode = AM_ZP_X; - arg = opcode_arg(mode); - lda(arg); - cycles += 4; - printf("LDA"); - break; - case 0xad: - mode = AM_ABS; - arg = opcode_arg(mode); - lda(arg); - cycles += 4; - printf("LDA"); - break; - case 0xbd: - mode = AM_ABS_X; - arg = opcode_arg(mode); - lda(arg); - cycles += 4; - printf("LDA"); - break; - case 0xb9: - mode = AM_ABS_Y; - arg = opcode_arg(mode); - lda(arg); - cycles += 4; - printf("LDA"); - break; - case 0xa1: - mode = AM_IND_X; - arg = opcode_arg(mode); - lda(arg); - cycles += 6; - printf("LDA"); - break; - case 0xb1: - mode = AM_IND_Y; - arg = opcode_arg(mode); - lda(arg); - cycles += 5; - printf("LDA"); - break; - case 0xa2: - mode = AM_IMM; - arg = opcode_mem(mode); - ldx(arg); - cycles += 2; - printf("LDX"); - break; - case 0xa6: - mode = AM_ZP; - arg = opcode_arg(mode); - ldx(arg); - cycles += 3; - printf("LDX"); - break; - case 0xb6: - mode = AM_ZP_Y; - arg = opcode_arg(mode); - ldx(arg); - cycles += 4; - printf("LDX"); - break; - case 0xae: - mode = AM_ABS; - arg = opcode_arg(mode); - ldx(arg); - cycles += 4; - printf("LDX"); - break; - case 0xbe: - mode = AM_ABS_Y; - arg = opcode_arg(mode); - ldx(arg); - cycles += 4; - printf("LDX"); - break; - case 0xa0: - mode = AM_IMM; - arg = opcode_arg(mode); - ldy(arg); - cycles += 2; - printf("LDY"); - break; - case 0xa4: - mode = AM_ZP; - arg = opcode_arg(mode); - ldy(arg); - cycles += 3; - printf("LDY"); - break; - case 0xb4: - mode = AM_ZP_X; - arg = opcode_arg(mode); - ldy(arg); - cycles += 4; - printf("LDY"); - break; - case 0xac: - mode = AM_ABS; - arg = opcode_arg(mode); - ldy(arg); - cycles += 4; - printf("LDY"); - break; - case 0xbc: - mode = AM_ABS_X; - arg = opcode_arg(mode); - ldy(arg); - cycles += 4; - printf("LDY"); - break; - case 0x4a: - mode = AM_ACC; - lsr_acc(); - cycles += 2; - printf("\tLSR"); - break; - case 0x46: - mode = AM_ZP; - arg = opcode_arg(mode); - lsr(arg); - cycles += 5; - printf("LSR"); - break; - case 0x56: - mode = AM_ZP_X; - arg = opcode_arg(mode); - lsr(arg); - cycles += 6; - printf("LSR"); - break; - case 0x4e: - mode = AM_ABS; - arg = opcode_mem(mode); - lsr(arg); - cycles += 6; - printf("LSR"); - break; - case 0x5e: - mode = AM_ABS_X; - arg = opcode_mem(mode); - lsr(arg); - cycles += 6; - printf("LSR"); - break; - case 0xea: - mode = AM_IMPLICIT; - nop(); - cycles += 2; - printf("\tNOP"); - break; - case 0x09: - mode = AM_IMM; - arg = opcode_arg(mode); - ora(arg); - cycles += 2; - printf("ORA"); - break; - case 0x05: - mode = AM_ZP; - arg = opcode_arg(mode); - ora(arg); - cycles += 3; - printf("ORA"); - break; - case 0x15: - mode = AM_ZP_X; - arg = opcode_arg(mode); - ora(arg); - cycles += 4; - printf("ORA"); - break; - case 0x0d: - mode = AM_ABS; - arg = opcode_arg(mode); - ora(arg); - cycles += 4; - printf("ORA"); - break; - case 0x1d: - mode = AM_ABS_X; - arg = opcode_arg(mode); - ora(arg); - cycles += 4; - printf("ORA"); - break; - case 0x19: - mode = AM_ABS_Y; - arg = opcode_arg(mode); - ora(arg); - cycles += 4; - printf("ORA"); - break; - case 0x01: - mode = AM_IND_X; - arg = opcode_arg(mode); - ora(arg); - cycles += 6; - printf("ORA"); - break; - case 0x11: - mode = AM_IND_Y; - arg = opcode_arg(mode); - ora(arg); - cycles += 5; - printf("ORA"); - break; - case 0x48: - mode = AM_IMPLICIT; - pha(); - cycles += 3; - printf("\tPHA"); - break; - case 0x08: - mode = AM_IMPLICIT; - php(); - cycles += 3; - printf("\tPHP"); - break; - case 0x68: - mode = AM_IMPLICIT; - pla(); - cycles += 4; - printf("\tPLA"); - break; - case 0x28: - mode = AM_IMPLICIT; - plp(); - cycles += 4; - printf("\tPLP"); - break; - case 0x2a: - mode = AM_ACC; - rol_acc(); - cycles += 2; - printf("\tROL"); - break; - case 0x26: - mode = AM_ZP; - arg = opcode_arg(mode); - rol(arg); - cycles += 5; - printf("ROL"); - break; - case 0x36: - mode = AM_ZP_X; - arg = opcode_arg(mode); - rol(arg); - cycles += 6; - printf("ROL"); - break; - case 0x2e: - mode = AM_ABS; - arg = opcode_arg(mode); - rol(arg); - cycles += 6; - printf("ROL"); - break; - case 0x3e: - mode = AM_ABS_X; - arg = opcode_arg(mode); - rol(arg); - cycles += 6; - printf("ROL"); - break; - case 0x6a: - mode = AM_ACC; - ror_acc(); - cycles += 2; - printf("\tROR"); - break; - case 0x66: - mode = AM_ZP; - arg = opcode_arg(mode); - ror(arg); - cycles += 5; - printf("ROR"); - break; - case 0x76: - mode = AM_ZP_X; - arg = opcode_arg(mode); - ror(arg); - cycles += 6; - printf("ROR"); - break; - case 0x6e: - mode = AM_ABS; - arg = opcode_arg(mode); - ror(arg); - cycles += 6; - printf("ROR"); - break; - case 0x7e: - mode = AM_ABS_X; - arg = opcode_arg(mode); - ror(arg); - cycles += 6; - printf("ROR"); - break; - case 0x40: - mode = AM_IMPLICIT; - rti(); - cycles += 6; - printf("\tRTI"); - break; - case 0x60: - mode = AM_IMPLICIT; - rts(); - cycles += 6; - printf("\tRTS"); - break; - case 0xe9: - mode = AM_IMM; - arg = opcode_arg(mode); - sbc(arg); - cycles += 2; - printf("SBC"); - break; - case 0xe5: - mode = AM_ZP; - arg = opcode_arg(mode); - sbc(arg); - cycles += 3; - printf("SBC"); - break; - case 0xf5: - mode = AM_ZP_X; - arg = opcode_arg(mode); - sbc(arg); - cycles += 4; - printf("SBC"); - break; - case 0xed: - mode = AM_ABS; - arg = opcode_arg(mode); - sbc(arg); - cycles += 4; - printf("SBC"); - break; - case 0xfd: - mode = AM_ABS_X; - arg = opcode_arg(mode); - sbc(arg); - cycles += 4; - printf("SBC"); - break; - case 0xf9: - mode = AM_ABS_Y; - arg = opcode_arg(mode); - sbc(arg); - cycles += 4; - printf("SBC"); - break; - case 0xe1: - mode = AM_IND_X; - arg = opcode_arg(mode); - sbc(arg); - cycles += 6; - printf("SBC"); - break; - case 0xf1: - mode = AM_IND_Y; - arg = opcode_arg(mode); - sbc(arg); - cycles += 5; - printf("SBC"); - break; - case 0x38: - mode = AM_IMPLICIT; - sec(); - cycles += 2; - printf("\tSEC"); - break; - case 0xf8: - mode = AM_IMPLICIT; - sed(); - cycles += 2; - printf("\tSED"); - break; - case 0x78: - mode = AM_IMPLICIT; - sei(); - cycles += 2; - printf("\tSEI"); - break; - case 0x85: - mode = AM_ZP; - arg = opcode_mem(mode); - did_memwrite = 1; - ret = sta(arg); - cycles += 4; - printf("STA"); - break; - case 0x95: - mode = AM_ZP_X; - arg = opcode_mem(mode); - did_memwrite = 1; - ret = sta(arg); - cycles += 5; - printf("STA"); - break; - case 0x8d: - mode = AM_ABS; - arg = opcode_mem(mode); - did_memwrite = 1; - ret = sta(arg); - cycles += 5; - printf("STA"); - break; - case 0x9d: - mode = AM_ABS_X; - arg = opcode_mem(mode); - did_memwrite = 1; - ret = sta(arg); - cycles += 6; - printf("STA"); - break; - case 0x99: - mode = AM_ABS_Y; - arg = opcode_mem(mode); - did_memwrite = 1; - ret = sta(arg); - cycles += 6; - printf("STA"); - break; - case 0x81: - mode = AM_IND_X; - arg = opcode_mem(mode); - did_memwrite = 1; - ret = sta(arg); - cycles += 7; - printf("STA"); - break; - case 0x91: - mode = AM_IND_Y; - arg = opcode_mem(mode); - did_memwrite = 1; - ret = sta(arg); - cycles += 7; - printf("STA"); - break; - case 0x86: - mode = AM_ZP; - arg = opcode_mem(mode); - did_memwrite = 1; - ret = stx(arg); - cycles += 4; - printf("STX"); - break; - case 0x96: - mode = AM_ZP_Y; - arg = opcode_mem(mode); - did_memwrite = 1; - ret = stx(arg); - cycles += 5; - printf("STX"); - break; - case 0x8e: - mode = AM_ABS; - arg = opcode_mem(mode); - did_memwrite = 1; - ret = stx(arg); - cycles += 5; - printf("STX"); - break; - case 0x84: - mode = AM_ZP; - arg = opcode_mem(mode); - did_memwrite = 1; - ret = sty(arg); - cycles += 4; - printf("STY"); - break; - case 0x94: - mode = AM_ZP_X; - arg = opcode_mem(mode); - did_memwrite = 1; - ret = sty(arg); - cycles += 5; - printf("STY"); - break; - case 0x8c: - mode = AM_ABS; - arg = opcode_mem(mode); - did_memwrite = 1; - ret = sty(arg); - cycles += 5; - printf("STY"); - break; - case 0xaa: - mode = AM_IMPLICIT; - tax(); - cycles += 2; - printf("\tTAX"); - break; - case 0xa8: - mode = AM_IMPLICIT; - tay(); - cycles += 2; - printf("\tTAY"); - break; - case 0xba: - mode = AM_IMPLICIT; - tsx(); - cycles += 2; - printf("\tTSX"); - break; - case 0x8a: - mode = AM_IMPLICIT; - txa(); - cycles += 2; - printf("\tTXA"); - break; - case 0x9a: - mode = AM_IMPLICIT; - txs(); - cycles += 2; - printf("\tTXS"); - break; - case 0x98: - mode = AM_IMPLICIT; - tya(); - cycles += 2; - printf("\tTYA"); - break; - default: - printf("opcode $%02X not implemented\n", opcode); - break; - } + printf("%02X", op); + for (uint8_t i = 0; i < opcodes[op].bytes - 1; i++) + printf(" %02X", peek(regs.pc + i)); + printf("\t%s ", opcodes[op].name); + + mode = opcodes[op].mode; + arg = opcode_mem(mode); switch (mode) { case AM_IMM: - printf(" #$%02X", arg); - if (did_memwrite) printf(" = %02X\t\t\t", ret); - else printf("\t\t\t"); + printf("#$%02X", arg); break; case AM_ZP: - printf(" $%02X", arg); - if (did_memwrite) printf(" = %02X\t\t\t", ret); - else printf("\t\t\t\t"); + printf("$%02X", arg); break; case AM_ZP_X: - printf(" $%02X,X", arg); - if (did_memwrite) printf(" = %02X\t\t\t", ret); - else printf("\t\t\t"); + printf("$%02X,X", arg); break; case AM_ZP_Y: - printf(" $%02X,Y", arg); - if (did_memwrite) printf(" = %02X\t\t\t", ret); - else printf("\t\t\t\t"); + printf("$%02X,Y", arg); break; case AM_REL: + printf("$%04X", regs.pc + arg); + break; case AM_ABS: - printf(" $%04X", arg); - if (did_memwrite) printf(" = %02X\t\t\t", ret); - else printf("\t\t\t"); + printf("$%04X", arg); break; case AM_ABS_X: - printf(" $%04X,X", arg); - if (did_memwrite) printf(" = %02X\t\t", ret); - else printf("\t\t\t"); + printf("$%04X,X", arg); break; case AM_ABS_Y: - printf(" $%04X,Y", arg); - if (did_memwrite) printf(" = %02X\t\t\t", ret); - else printf("\t\t\t"); + printf("$%04X,Y", arg); break; case AM_IND: - printf(" ($%04X) = %04X\t\t", mem, deref); + printf("($%04X) = %04X\t\t", arg, peek16(arg)); break; case AM_ACC: - case AM_IMPLICIT: + case AM_NONE: + putchar('\t'); + break; default: printf("\t\t\t\t"); break; } - printf("A:%02X X:%02X Y:%02X P:%02X SP:%02X CYC:%d\n", - regs_.a, regs_.x, regs_.y, status, regs_.sp, cycles_); + if (opcodes[op].didmemory) printf(" = %02X", peek(arg)); + printf("\t\t\t"); + + printf("A:%02X X:%02X Y:%02X P:%02X SP:%02X CYC:%d %08b\n", + regs.a, regs.x, regs.y, STATUS_TO_INT(), regs.sp, cycles, STATUS_TO_INT()); + + opcodes[op].instr(arg); + cycles += opcodes[op].cycles; } loop_exit: } diff --git a/opcodes.h b/opcodes.h index defc427..ef57ab0 100644 --- a/opcodes.h +++ b/opcodes.h @@ -1,3 +1,4 @@ +#include #include #include "cpu.h" @@ -25,160 +26,161 @@ struct opcode { void (*instr)(uint16_t arg); uint8_t bytes; uint8_t cycles; + bool didmemory; enum addressing_mode mode; }; struct opcode opcodes[0x100] = { /* official opcodes */ - [0x69] = { "ADC", ADC, 2, 2, AM_IMM }, - [0x65] = { "ADC", ADC, 2, 3, AM_ZP }, - [0x75] = { "ADC", ADC, 2, 4, AM_ZP_X }, - [0x6D] = { "ADC", ADC, 3, 4, AM_ABS }, - [0x7D] = { "ADC", ADC, 3, 4, AM_ABS_X }, - [0x79] = { "ADC", ADC, 3, 4, AM_ABS_Y }, - [0x61] = { "ADC", ADC, 2, 6, AM_IND_X }, - [0x71] = { "ADC", ADC, 2, 5, AM_IND_Y }, - [0x29] = { "AND", AND, 2, 2, AM_IMM }, - [0x25] = { "AND", AND, 2, 3, AM_ZP }, - [0x35] = { "AND", AND, 2, 4, AM_ZP_X }, - [0x2D] = { "AND", AND, 3, 4, AM_ABS }, - [0x3D] = { "AND", AND, 3, 4, AM_ABS_X }, - [0x39] = { "AND", AND, 3, 4, AM_ABS_Y }, - [0x21] = { "AND", AND, 2, 6, AM_IND_X }, - [0x31] = { "AND", AND, 2, 5, AM_IND_Y }, - [0x0A] = { "ASL", ASL_acc, 1, 2, AM_ACC }, - [0x06] = { "ASL", ASL, 2, 5, AM_ZP }, - [0x16] = { "ASL", ASL, 2, 6, AM_ZP_X }, - [0x0E] = { "ASL", ASL, 3, 6, AM_ABS }, - [0x1E] = { "ASL", ASL, 3, 7, AM_ABS_X }, - [0x90] = { "BCC", BCC, 2, 2, AM_REL }, - [0xB0] = { "BCS", BCS, 2, 2, AM_REL }, - [0xF0] = { "BEQ", BEQ, 2, 2, AM_REL }, - [0x24] = { "BIT", BIT, 2, 3, AM_ZP }, - [0x2C] = { "BIT", BIT, 3, 4, AM_ABS }, - [0x30] = { "BMI", BMI, 2, 2, AM_REL }, - [0xD0] = { "BNE", BNE, 2, 2, AM_REL }, - [0x10] = { "BPL", BPL, 2, 2, AM_REL }, - [0x00] = { "BRK", BRK, 1, 7, AM_NONE }, - [0x50] = { "BVC", BVC, 2, 2, AM_REL }, - [0x70] = { "BVS", BVS, 2, 2, AM_REL }, - [0x18] = { "CLC", CLC, 1, 2, AM_NONE }, - [0xD8] = { "CLD", CLD, 1, 2, AM_NONE }, - [0x58] = { "CLI", CLI, 1, 2, AM_NONE }, - [0xB8] = { "CLV", CLV, 1, 2, AM_NONE }, - [0xC9] = { "CMP", CMP, 2, 2, AM_IMM }, - [0xC5] = { "CMP", CMP, 2, 3, AM_ZP }, - [0xD5] = { "CMP", CMP, 2, 4, AM_ZP_X }, - [0xCD] = { "CMP", CMP, 3, 4, AM_ABS }, - [0xDD] = { "CMP", CMP, 3, 4, AM_ABS_X }, - [0xD9] = { "CMP", CMP, 3, 4, AM_ABS_Y }, - [0xC1] = { "CMP", CMP, 2, 6, AM_IND_X }, - [0xD1] = { "CMP", CMP, 2, 5, AM_IND_Y }, - [0xE0] = { "CPX", CPX, 2, 2, AM_IMM }, - [0xE4] = { "CPX", CPX, 2, 3, AM_ZP }, - [0xEC] = { "CPX", CPX, 3, 4, AM_ABS }, - [0xC0] = { "CPY", CPY, 2, 2, AM_IMM }, - [0xC4] = { "CPY", CPY, 2, 3, AM_ZP }, - [0xCC] = { "CPY", CPY, 3, 4, AM_ABS }, - [0xC6] = { "DEC", DEC, 2, 5, AM_ZP }, - [0xD6] = { "DEC", DEC, 2, 6, AM_ZP_X }, - [0xCE] = { "DEC", DEC, 3, 6, AM_ABS }, - [0xDE] = { "DEC", DEC, 3, 7, AM_ABS_X }, - [0xCA] = { "DEX", DEX, 1, 2, AM_NONE }, - [0x88] = { "DEY", DEY, 1, 2, AM_NONE }, - [0x49] = { "EOR", EOR, 2, 2, AM_IMM }, - [0x45] = { "EOR", EOR, 2, 3, AM_ZP }, - [0x55] = { "EOR", EOR, 2, 4, AM_ZP_X }, - [0x4D] = { "EOR", EOR, 3, 4, AM_ABS }, - [0x5D] = { "EOR", EOR, 3, 4, AM_ABS_X }, - [0x59] = { "EOR", EOR, 3, 4, AM_ABS_Y }, - [0x41] = { "EOR", EOR, 2, 6, AM_IND_X }, - [0x51] = { "EOR", EOR, 2, 5, AM_IND_Y }, - [0xE6] = { "INC", INC, 2, 5, AM_ZP }, - [0xF6] = { "INC", INC, 2, 6, AM_ZP_X }, - [0xEE] = { "INC", INC, 3, 6, AM_ABS }, - [0xFE] = { "INC", INC, 3, 7, AM_ABS_X }, - [0xE8] = { "INX", INX, 1, 2, AM_NONE }, - [0xC8] = { "INY", INY, 1, 2, AM_NONE }, - [0x4C] = { "JMP", JMP, 3, 3, AM_ABS }, - [0x6C] = { "JMP", JMP, 3, 5, AM_IND }, - [0x20] = { "JSR", JSR, 3, 6, AM_ABS }, - [0xA9] = { "LDA", LDA, 2, 2, AM_IMM }, - [0xA5] = { "LDA", LDA, 2, 3, AM_ZP }, - [0xB5] = { "LDA", LDA, 2, 4, AM_ZP_X }, - [0xAD] = { "LDA", LDA, 3, 4, AM_ABS }, - [0xBD] = { "LDA", LDA, 3, 4, AM_ABS_X }, - [0xB9] = { "LDA", LDA, 3, 4, AM_ABS_Y }, - [0xA1] = { "LDA", LDA, 2, 6, AM_IND_X }, - [0xB1] = { "LDA", LDA, 2, 5, AM_IND_Y }, - [0xA2] = { "LDX", LDX, 2, 2, AM_IMM }, - [0xA6] = { "LDX", LDX, 2, 3, AM_ZP }, - [0xB6] = { "LDX", LDX, 2, 4, AM_ZP_Y }, - [0xAE] = { "LDX", LDX, 3, 4, AM_ABS }, - [0xBE] = { "LDX", LDX, 3, 4, AM_ABS_Y }, - [0xA0] = { "LDY", LDY, 2, 2, AM_IMM }, - [0xA4] = { "LDY", LDY, 2, 3, AM_ZP }, - [0xB4] = { "LDY", LDY, 2, 4, AM_ZP_X }, - [0xAC] = { "LDY", LDY, 3, 4, AM_ABS }, - [0xBC] = { "LDY", LDY, 3, 4, AM_ABS_X }, - [0x4A] = { "LSR", LSR_acc, 1, 2, AM_ACC }, - [0x46] = { "LSR", LSR, 2, 5, AM_ZP }, - [0x56] = { "LSR", LSR, 2, 6, AM_ZP_X }, - [0x4E] = { "LSR", LSR, 3, 6, AM_ABS }, - [0x5E] = { "LSR", LSR, 3, 7, AM_ABS_X }, - [0xEA] = { "NOP", NOP, 1, 2, AM_NONE }, - [0x09] = { "ORA", ORA, 2, 2, AM_IMM }, - [0x05] = { "ORA", ORA, 2, 3, AM_ZP }, - [0x15] = { "ORA", ORA, 2, 4, AM_ZP_X }, - [0x0D] = { "ORA", ORA, 3, 4, AM_ABS }, - [0x1D] = { "ORA", ORA, 3, 4, AM_ABS_X }, - [0x19] = { "ORA", ORA, 3, 4, AM_ABS_Y }, - [0x01] = { "ORA", ORA, 2, 6, AM_IND_X }, - [0x11] = { "ORA", ORA, 2, 5, AM_IND_Y }, - [0x48] = { "PHA", PHA, 1, 3, AM_NONE }, - [0x08] = { "PHP", PHP, 1, 3, AM_NONE }, - [0x68] = { "PLA", PLA, 1, 4, AM_NONE }, - [0x28] = { "PLP", PLP, 1, 4, AM_NONE }, - [0x2A] = { "ROL", ROL_acc, 1, 2, AM_ACC }, - [0x26] = { "ROL", ROL, 2, 5, AM_ZP }, - [0x36] = { "ROL", ROL, 2, 6, AM_ZP_X }, - [0x2E] = { "ROL", ROL, 3, 6, AM_ABS }, - [0x3E] = { "ROL", ROL, 3, 7, AM_ABS_X }, - [0x6A] = { "ROR", ROR_acc, 1, 2, AM_ACC }, - [0x66] = { "ROR", ROR, 2, 5, AM_ZP }, - [0x76] = { "ROR", ROR, 2, 6, AM_ZP_X }, - [0x6E] = { "ROR", ROR, 3, 6, AM_ABS }, - [0x7E] = { "ROR", ROR, 3, 7, AM_ABS_X }, - [0x40] = { "RTI", RTI, 1, 6, AM_NONE }, - [0x60] = { "RTS", RTS, 1, 6, AM_NONE }, - [0xE9] = { "SBC", SBC, 2, 2, AM_IMM }, - [0xE5] = { "SBC", SBC, 2, 3, AM_ZP }, - [0xF5] = { "SBC", SBC, 2, 4, AM_ZP_X }, - [0xED] = { "SBC", SBC, 3, 4, AM_ABS }, - [0xFD] = { "SBC", SBC, 3, 4, AM_ABS_X }, - [0xF9] = { "SBC", SBC, 3, 4, AM_ABS_Y }, - [0xE1] = { "SBC", SBC, 2, 6, AM_IND_X }, - [0xF1] = { "SBC", SBC, 2, 5, AM_IND_Y }, - [0x38] = { "SEC", SEC, 1, 2, AM_NONE }, - [0xF8] = { "SED", SED, 1, 2, AM_NONE }, - [0x78] = { "SEI", SEI, 1, 2, AM_NONE }, - [0x85] = { "STA", STA, 2, 3, AM_ZP }, - [0x95] = { "STA", STA, 2, 4, AM_ZP_X }, - [0x8D] = { "STA", STA, 3, 4, AM_ABS }, - [0x9D] = { "STA", STA, 3, 5, AM_ABS_X }, - [0x99] = { "STA", STA, 3, 5, AM_ABS_Y }, - [0x81] = { "STA", STA, 2, 6, AM_IND_X }, - [0x91] = { "STA", STA, 2, 6, AM_IND_Y }, - [0x86] = { "STX", STX, 2, 3, AM_ZP }, - [0x96] = { "STX", STX, 2, 4, AM_ZP_Y }, - [0x8E] = { "STX", STX, 3, 4, AM_ABS }, - [0x84] = { "STY", STY, 2, 3, AM_ZP }, - [0x94] = { "STY", STY, 2, 4, AM_ZP_X }, - [0x8C] = { "STY", STY, 3, 4, AM_ABS }, - [0xAA] = { "TAX", TAX, 1, 2, AM_NONE }, - [0xA8] = { "TAY", TAY, 1, 2, AM_NONE }, - [0xBA] = { "TSX", TSX, 1, 2, AM_NONE }, - [0x8A] = { "TXA", TXA, 1, 2, AM_NONE }, - [0x9A] = { "TXS", TXS, 1, 2, AM_NONE }, - [0x98] = { "TYA", TYA, 1, 2, AM_NONE }, + [0x69] = { "ADC", ADC, 2, 2, false, AM_IMM }, + [0x65] = { "ADC", ADC, 2, 3, false, AM_ZP }, + [0x75] = { "ADC", ADC, 2, 4, false, AM_ZP_X }, + [0x6D] = { "ADC", ADC, 3, 4, false, AM_ABS }, + [0x7D] = { "ADC", ADC, 3, 4, false, AM_ABS_X }, + [0x79] = { "ADC", ADC, 3, 4, false, AM_ABS_Y }, + [0x61] = { "ADC", ADC, 2, 6, false, AM_IND_X }, + [0x71] = { "ADC", ADC, 2, 5, false, AM_IND_Y }, + [0x29] = { "AND", AND, 2, 2, false, AM_IMM }, + [0x25] = { "AND", AND, 2, 3, false, AM_ZP }, + [0x35] = { "AND", AND, 2, 4, false, AM_ZP_X }, + [0x2D] = { "AND", AND, 3, 4, false, AM_ABS }, + [0x3D] = { "AND", AND, 3, 4, false, AM_ABS_X }, + [0x39] = { "AND", AND, 3, 4, false, AM_ABS_Y }, + [0x21] = { "AND", AND, 2, 6, false, AM_IND_X }, + [0x31] = { "AND", AND, 2, 5, false, AM_IND_Y }, + [0x0A] = { "ASL", ASL_acc, 1, 2, false, AM_ACC }, + [0x06] = { "ASL", ASL, 2, 5, true, AM_ZP }, + [0x16] = { "ASL", ASL, 2, 6, true, AM_ZP_X }, + [0x0E] = { "ASL", ASL, 3, 6, true, AM_ABS }, + [0x1E] = { "ASL", ASL, 3, 7, true, AM_ABS_X }, + [0x90] = { "BCC", BCC, 2, 2, false, AM_REL }, + [0xB0] = { "BCS", BCS, 2, 2, false, AM_REL }, + [0xF0] = { "BEQ", BEQ, 2, 2, false, AM_REL }, + [0x24] = { "BIT", BIT, 2, 3, true, AM_ZP }, + [0x2C] = { "BIT", BIT, 3, 4, true, AM_ABS }, + [0x30] = { "BMI", BMI, 2, 2, false, AM_REL }, + [0xD0] = { "BNE", BNE, 2, 2, false, AM_REL }, + [0x10] = { "BPL", BPL, 2, 2, false, AM_REL }, + [0x00] = { "BRK", BRK, 1, 7, false, AM_NONE }, + [0x50] = { "BVC", BVC, 2, 2, false, AM_REL }, + [0x70] = { "BVS", BVS, 2, 2, false, AM_REL }, + [0x18] = { "CLC", CLC, 1, 2, false, AM_NONE }, + [0xD8] = { "CLD", CLD, 1, 2, false, AM_NONE }, + [0x58] = { "CLI", CLI, 1, 2, false, AM_NONE }, + [0xB8] = { "CLV", CLV, 1, 2, false, AM_NONE }, + [0xC9] = { "CMP", CMP, 2, 2, false, AM_IMM }, + [0xC5] = { "CMP", CMP, 2, 3, false, AM_ZP }, + [0xD5] = { "CMP", CMP, 2, 4, false, AM_ZP_X }, + [0xCD] = { "CMP", CMP, 3, 4, false, AM_ABS }, + [0xDD] = { "CMP", CMP, 3, 4, false, AM_ABS_X }, + [0xD9] = { "CMP", CMP, 3, 4, false, AM_ABS_Y }, + [0xC1] = { "CMP", CMP, 2, 6, false, AM_IND_X }, + [0xD1] = { "CMP", CMP, 2, 5, false, AM_IND_Y }, + [0xE0] = { "CPX", CPX, 2, 2, false, AM_IMM }, + [0xE4] = { "CPX", CPX, 2, 3, false, AM_ZP }, + [0xEC] = { "CPX", CPX, 3, 4, false, AM_ABS }, + [0xC0] = { "CPY", CPY, 2, 2, false, AM_IMM }, + [0xC4] = { "CPY", CPY, 2, 3, false, AM_ZP }, + [0xCC] = { "CPY", CPY, 3, 4, false, AM_ABS }, + [0xC6] = { "DEC", DEC, 2, 5, true, AM_ZP }, + [0xD6] = { "DEC", DEC, 2, 6, true, AM_ZP_X }, + [0xCE] = { "DEC", DEC, 3, 6, true, AM_ABS }, + [0xDE] = { "DEC", DEC, 3, 7, true, AM_ABS_X }, + [0xCA] = { "DEX", DEX, 1, 2, false, AM_NONE }, + [0x88] = { "DEY", DEY, 1, 2, false, AM_NONE }, + [0x49] = { "EOR", EOR, 2, 2, false, AM_IMM }, + [0x45] = { "EOR", EOR, 2, 3, false, AM_ZP }, + [0x55] = { "EOR", EOR, 2, 4, false, AM_ZP_X }, + [0x4D] = { "EOR", EOR, 3, 4, false, AM_ABS }, + [0x5D] = { "EOR", EOR, 3, 4, false, AM_ABS_X }, + [0x59] = { "EOR", EOR, 3, 4, false, AM_ABS_Y }, + [0x41] = { "EOR", EOR, 2, 6, false, AM_IND_X }, + [0x51] = { "EOR", EOR, 2, 5, false, AM_IND_Y }, + [0xE6] = { "INC", INC, 2, 5, true, AM_ZP }, + [0xF6] = { "INC", INC, 2, 6, true, AM_ZP_X }, + [0xEE] = { "INC", INC, 3, 6, true, AM_ABS }, + [0xFE] = { "INC", INC, 3, 7, true, AM_ABS_X }, + [0xE8] = { "INX", INX, 1, 2, false, AM_NONE }, + [0xC8] = { "INY", INY, 1, 2, false, AM_NONE }, + [0x4C] = { "JMP", JMP, 3, 3, false, AM_ABS }, + [0x6C] = { "JMP", JMP, 3, 5, false, AM_IND }, + [0x20] = { "JSR", JSR, 3, 6, false, AM_ABS }, + [0xA9] = { "LDA", LDA, 2, 2, false, AM_IMM }, + [0xA5] = { "LDA", LDA, 2, 3, false, AM_ZP }, + [0xB5] = { "LDA", LDA, 2, 4, false, AM_ZP_X }, + [0xAD] = { "LDA", LDA, 3, 4, false, AM_ABS }, + [0xBD] = { "LDA", LDA, 3, 4, false, AM_ABS_X }, + [0xB9] = { "LDA", LDA, 3, 4, false, AM_ABS_Y }, + [0xA1] = { "LDA", LDA, 2, 6, false, AM_IND_X }, + [0xB1] = { "LDA", LDA, 2, 5, false, AM_IND_Y }, + [0xA2] = { "LDX", LDX, 2, 2, false, AM_IMM }, + [0xA6] = { "LDX", LDX, 2, 3, true, AM_ZP }, + [0xB6] = { "LDX", LDX, 2, 4, false, AM_ZP_Y }, + [0xAE] = { "LDX", LDX, 3, 4, true, AM_ABS }, + [0xBE] = { "LDX", LDX, 3, 4, false, AM_ABS_Y }, + [0xA0] = { "LDY", LDY, 2, 2, false, AM_IMM }, + [0xA4] = { "LDY", LDY, 2, 3, false, AM_ZP }, + [0xB4] = { "LDY", LDY, 2, 4, false, AM_ZP_X }, + [0xAC] = { "LDY", LDY, 3, 4, false, AM_ABS }, + [0xBC] = { "LDY", LDY, 3, 4, false, AM_ABS_X }, + [0x4A] = { "LSR", LSR_acc, 1, 2, false, AM_ACC }, + [0x46] = { "LSR", LSR, 2, 5, true, AM_ZP }, + [0x56] = { "LSR", LSR, 2, 6, true, AM_ZP_X }, + [0x4E] = { "LSR", LSR, 3, 6, true, AM_ABS }, + [0x5E] = { "LSR", LSR, 3, 7, true, AM_ABS_X }, + [0xEA] = { "NOP", NOP, 1, 2, false, AM_NONE }, + [0x09] = { "ORA", ORA, 2, 2, false, AM_IMM }, + [0x05] = { "ORA", ORA, 2, 3, false, AM_ZP }, + [0x15] = { "ORA", ORA, 2, 4, false, AM_ZP_X }, + [0x0D] = { "ORA", ORA, 3, 4, false, AM_ABS }, + [0x1D] = { "ORA", ORA, 3, 4, false, AM_ABS_X }, + [0x19] = { "ORA", ORA, 3, 4, false, AM_ABS_Y }, + [0x01] = { "ORA", ORA, 2, 6, false, AM_IND_X }, + [0x11] = { "ORA", ORA, 2, 5, false, AM_IND_Y }, + [0x48] = { "PHA", PHA, 1, 3, false, AM_NONE }, + [0x08] = { "PHP", PHP, 1, 3, false, AM_NONE }, + [0x68] = { "PLA", PLA, 1, 4, false, AM_NONE }, + [0x28] = { "PLP", PLP, 1, 4, false, AM_NONE }, + [0x2A] = { "ROL", ROL_acc, 1, 2, false, AM_ACC }, + [0x26] = { "ROL", ROL, 2, 5, true, AM_ZP }, + [0x36] = { "ROL", ROL, 2, 6, true, AM_ZP_X }, + [0x2E] = { "ROL", ROL, 3, 6, true, AM_ABS }, + [0x3E] = { "ROL", ROL, 3, 7, true, AM_ABS_X }, + [0x6A] = { "ROR", ROR_acc, 1, 2, false, AM_ACC }, + [0x66] = { "ROR", ROR, 2, 5, true, AM_ZP }, + [0x76] = { "ROR", ROR, 2, 6, true, AM_ZP_X }, + [0x6E] = { "ROR", ROR, 3, 6, true, AM_ABS }, + [0x7E] = { "ROR", ROR, 3, 7, true, AM_ABS_X }, + [0x40] = { "RTI", RTI, 1, 6, false, AM_NONE }, + [0x60] = { "RTS", RTS, 1, 6, false, AM_NONE }, + [0xE9] = { "SBC", SBC, 2, 2, false, AM_IMM }, + [0xE5] = { "SBC", SBC, 2, 3, false, AM_ZP }, + [0xF5] = { "SBC", SBC, 2, 4, false, AM_ZP_X }, + [0xED] = { "SBC", SBC, 3, 4, false, AM_ABS }, + [0xFD] = { "SBC", SBC, 3, 4, false, AM_ABS_X }, + [0xF9] = { "SBC", SBC, 3, 4, false, AM_ABS_Y }, + [0xE1] = { "SBC", SBC, 2, 6, false, AM_IND_X }, + [0xF1] = { "SBC", SBC, 2, 5, false, AM_IND_Y }, + [0x38] = { "SEC", SEC, 1, 2, false, AM_NONE }, + [0xF8] = { "SED", SED, 1, 2, false, AM_NONE }, + [0x78] = { "SEI", SEI, 1, 2, false, AM_NONE }, + [0x85] = { "STA", STA, 2, 3, true, AM_ZP }, + [0x95] = { "STA", STA, 2, 4, true, AM_ZP_X }, + [0x8D] = { "STA", STA, 3, 4, true, AM_ABS }, + [0x9D] = { "STA", STA, 3, 5, true, AM_ABS_X }, + [0x99] = { "STA", STA, 3, 5, true, AM_ABS_Y }, + [0x81] = { "STA", STA, 2, 6, true, AM_IND_X }, + [0x91] = { "STA", STA, 2, 6, true, AM_IND_Y }, + [0x86] = { "STX", STX, 2, 3, true, AM_ZP }, + [0x96] = { "STX", STX, 2, 4, true, AM_ZP_Y }, + [0x8E] = { "STX", STX, 3, 4, true, AM_ABS }, + [0x84] = { "STY", STY, 2, 3, true, AM_ZP }, + [0x94] = { "STY", STY, 2, 4, true, AM_ZP_X }, + [0x8C] = { "STY", STY, 3, 4, true, AM_ABS }, + [0xAA] = { "TAX", TAX, 1, 2, false, AM_NONE }, + [0xA8] = { "TAY", TAY, 1, 2, false, AM_NONE }, + [0xBA] = { "TSX", TSX, 1, 2, false, AM_NONE }, + [0x8A] = { "TXA", TXA, 1, 2, false, AM_NONE }, + [0x9A] = { "TXS", TXS, 1, 2, false, AM_NONE }, + [0x98] = { "TYA", TYA, 1, 2, false, AM_NONE }, };