summaryrefslogtreecommitdiff
path: root/cpu.c
diff options
context:
space:
mode:
authorvin <git@vineetk.net>2024-07-03 18:52:15 -0400
committervin <git@vineetk.net>2024-07-03 19:22:00 -0400
commitd8bb5a5ccf96fed7e8084cf691c987ce56a8c995 (patch)
tree5cfc546f2ae063d1261ef34ee054bd857033231d /cpu.c
parenta4b39966aed8d41ad4ddc6700683c4779e8d1cb2 (diff)
call opcode function pointer instead of using switch case
Also improve logging.
Diffstat (limited to 'cpu.c')
-rw-r--r--cpu.c1445
1 files changed, 172 insertions, 1273 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 %02X", regs.pc - 1, opcode);
-
- 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("%04X ", regs.pc);
+
+ op = peek(regs.pc++);
+
+ 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:
}