diff options
Diffstat (limited to 'cpu.c')
-rw-r--r-- | cpu.c | 89 |
1 files changed, 29 insertions, 60 deletions
@@ -99,55 +99,6 @@ memwrite16(uint16_t addr, uint16_t word) memory[addr + 1] = (word & 0xFF00) >> 8; } -static uint8_t -opcode_arg(enum addressing_mode mode) -{ - uint16_t arg, val; - - if (mode != AM_ABS && mode != AM_ABS_X && mode != AM_ABS_Y) { - arg = peek(regs.pc++); - } else { - arg = peek16(regs.pc); - regs.pc += 2; - } - - switch (mode) { - case AM_IMM: - case AM_REL: - val = arg; - break; - case AM_ZP: - val = peek(arg % 256); - break; - case AM_ZP_X: - val = peek((arg + regs.x) % 256); - break; - case AM_ZP_Y: - val = peek((arg + regs.y) % 256); - break; - case AM_ABS: - val = peek16(arg); - break; - case AM_ABS_X: - val = peek16(arg + regs.x); - break; - case AM_ABS_Y: - val = peek16(arg + regs.y); - break; - case AM_IND_X: - val = peek(peek((arg + regs.x) % 256) + peek((arg + regs.x + 1) % 256) * 256); - break; - case AM_IND_Y: - val = peek(peek(arg) + peek((arg + 1) % 256) * 256 + regs.y); - break; - default: - fprintf(stderr, "INVALID ADDRESSING MODE %i\n", mode); - abort(); - } - - return val; -} - static uint16_t opcode_mem(enum addressing_mode mode) { @@ -193,7 +144,7 @@ opcode_mem(enum addressing_mode mode) val = peek(arg) + peek((arg + 1) % 256) * 256 + regs.y; break; default: - fprintf(stderr, "opcode_mem INVALID ADDRESSING MODE %i\n", mode); + fprintf(stderr, "INVALID ADDRESSING MODE %i\n", mode); abort(); } @@ -271,7 +222,8 @@ BEQ(uint16_t arg) void BIT(uint16_t arg) { - uint8_t tmp = peek(arg); + uint8_t tmp = arg; + regs.status.zero = (regs.a & tmp) == 0; regs.status.overflow = (tmp & (1 << 6)) != 0; STATUS_UPDATE_NEGATIVE(tmp); @@ -628,8 +580,18 @@ RTS(uint16_t arg) void SBC(uint16_t arg) { - /* SBC is described online as ADC with argument as two's complement */ - ADC(~(uint8_t)arg); + uint8_t tmp = arg & 0xFF; + uint16_t diff; + + diff = regs.a - tmp - !regs.status.carry; + + regs.status.carry = diff > 0xFF; + regs.status.carry = !regs.status.carry; + /* overflow flag formula: https://stackoverflow.com/a/29224684 */ + regs.status.overflow = ((regs.a ^ arg) & (regs.a ^ diff) & 0x80) != 0; + regs.a = diff & 0xFF; + + STATUS_UPDATE_NZ(regs.a); } void @@ -759,10 +721,10 @@ interpret(void) printf("$%04X", arg); break; case AM_ABS_X: - printf("$%04X,X", arg); + printf("$%04X,X @ %04X", arg - regs.x, arg); break; case AM_ABS_Y: - printf("$%04X,Y", arg); + printf("$%04X,Y @ %04X", arg - regs.y, arg); break; case AM_IND: printf("($%04X) = %04X\t\t", arg, peek16(arg)); @@ -776,13 +738,20 @@ interpret(void) break; } - if (opcodes[op].didmemory) printf(" = %02X", peek(arg)); - printf("\t\t\t"); + if (opcodes[op].memread || opcodes[op].memwrite) + printf(" = %02X", peek(arg)); + + if (mode != AM_ABS_X && mode != AM_ABS_Y) + putchar('\t'); + printf("\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()); + printf("A:%02X X:%02X Y:%02X P:%02X SP:%02X CYC:%d\n", + regs.a, regs.x, regs.y, STATUS_TO_INT(), regs.sp, cycles); - opcodes[op].instr(arg); + if (opcodes[op].memread) + opcodes[op].instr(peek(arg)); + else + opcodes[op].instr(arg); cycles += opcodes[op].cycles; } loop_exit: |