diff --git a/include/mos6502/mos6502.h b/include/mos6502/mos6502.h index 062a3f1..017f910 100644 --- a/include/mos6502/mos6502.h +++ b/include/mos6502/mos6502.h @@ -104,6 +104,11 @@ typedef struct { */ vm_16bit eff_addr; + /* + * This is the address mode of the current execution. + */ + int addr_mode; + /* * These are the last opcode and last effective address that was * used in the instruction previous to the one currently being diff --git a/src/mos6502/arith.c b/src/mos6502/arith.c index 8e916de..ee40e3c 100644 --- a/src/mos6502/arith.c +++ b/src/mos6502/arith.c @@ -154,19 +154,14 @@ DEFINE_INST(cpy) */ DEFINE_INST(dec) { - vm_8bit opcode = mos6502_get(cpu, cpu->PC); - bool is_acc = mos6502_addr_mode(opcode) == ACC; - - if (!is_acc) { - MOS_CHECK_NZ(oper - 1); - mos6502_set(cpu, cpu->eff_addr, oper - 1); + if (cpu->addr_mode == ACC) { + MOS_CHECK_NZ(cpu->A - 1); + cpu->A--; return; } - // If we get here, then this is ACC mode, and we should work off - // that. - MOS_CHECK_NZ(cpu->A - 1); - cpu->A--; + MOS_CHECK_NZ(oper - 1); + mos6502_set(cpu, cpu->eff_addr, oper - 1); } /* @@ -192,17 +187,14 @@ DEFINE_INST(dey) */ DEFINE_INST(inc) { - vm_8bit opcode = mos6502_get(cpu, cpu->PC); - bool is_acc = mos6502_addr_mode(opcode) == ACC; - - if (!is_acc) { - MOS_CHECK_NZ(oper + 1); - mos6502_set(cpu, cpu->eff_addr, oper + 1); + if (cpu->addr_mode == ACC) { + MOS_CHECK_NZ(cpu->A + 1); + cpu->A++; return; } - MOS_CHECK_NZ(cpu->A + 1); - cpu->A++; + MOS_CHECK_NZ(oper + 1); + mos6502_set(cpu, cpu->eff_addr, oper + 1); } /* diff --git a/src/mos6502/bits.c b/src/mos6502/bits.c index d16845d..7f5be2f 100644 --- a/src/mos6502/bits.c +++ b/src/mos6502/bits.c @@ -31,9 +31,6 @@ DEFINE_INST(and) */ DEFINE_INST(asl) { - vm_8bit opcode = mos6502_get(cpu, cpu->PC); - bool is_acc = mos6502_addr_mode(opcode) == ACC; - vm_8bit result = oper << 1; MOS_CHECK_NZ(result); @@ -42,10 +39,10 @@ DEFINE_INST(asl) cpu->P |= MOS_CARRY; } - if (!is_acc) { - mos6502_set(cpu, cpu->eff_addr, result); - } else { + if (cpu->addr_mode == ACC) { cpu->A = result; + } else { + mos6502_set(cpu, cpu->eff_addr, result); } } @@ -114,9 +111,6 @@ DEFINE_INST(eor) */ DEFINE_INST(lsr) { - vm_8bit opcode = mos6502_get(cpu, cpu->PC); - bool is_acc = mos6502_addr_mode(opcode) == ACC; - vm_8bit result = oper >> 1; // The N flag is ALWAYS cleared in LSR, because a zero is always @@ -132,10 +126,10 @@ DEFINE_INST(lsr) cpu->P |= MOS_CARRY; } - if (!is_acc) { - mos6502_set(cpu, cpu->eff_addr, result); - } else { + if (cpu->addr_mode == ACC) { cpu->A = result; + } else { + mos6502_set(cpu, cpu->eff_addr, result); } } @@ -156,9 +150,6 @@ DEFINE_INST(ora) */ DEFINE_INST(rol) { - vm_8bit opcode = mos6502_get(cpu, cpu->PC); - bool is_acc = mos6502_addr_mode(opcode) == ACC; - vm_8bit result = oper << 1; // Rotations are effectively _9-bit_. So we aren't rotating bit 7 @@ -175,10 +166,10 @@ DEFINE_INST(rol) MOS_CHECK_NZ(result); - if (!is_acc) { - mos6502_set(cpu, cpu->eff_addr, result); - } else { + if (cpu->addr_mode == ACC) { cpu->A = result; + } else { + mos6502_set(cpu, cpu->eff_addr, result); } } @@ -188,9 +179,6 @@ DEFINE_INST(rol) */ DEFINE_INST(ror) { - vm_8bit opcode = mos6502_get(cpu, cpu->PC); - bool is_acc = mos6502_addr_mode(opcode) == ACC; - vm_8bit result = oper >> 1; // See the code for ROL for my note on 9-bit rotation (vs. 8-bit). @@ -205,10 +193,10 @@ DEFINE_INST(ror) MOS_CHECK_NZ(result); - if (!is_acc) { - mos6502_set(cpu, cpu->eff_addr, result); - } else { + if (cpu->addr_mode == ACC) { cpu->A = result; + } else { + mos6502_set(cpu, cpu->eff_addr, result); } } diff --git a/src/mos6502/mos6502.c b/src/mos6502/mos6502.c index d6bca70..a3e2e9f 100644 --- a/src/mos6502/mos6502.c +++ b/src/mos6502/mos6502.c @@ -170,6 +170,7 @@ mos6502_create(vm_segment *rmem, vm_segment *wmem) mos6502_set_memory(cpu, rmem, wmem); cpu->eff_addr = 0; + cpu->addr_mode = 0; cpu->PC = 0; cpu->A = 0; cpu->X = 0; @@ -303,16 +304,17 @@ mos6502_execute(mos6502 *cpu) mos6502_instruction_handler handler; opcode = mos6502_get(cpu, cpu->PC); + cpu->addr_mode = mos6502_addr_mode(opcode); // The disassembler knows how many bytes each operand requires // (maybe this code doesn't belong in the disassembler); let's use // that to figure out the total number of bytes to skip. We add 1 // because we need to account for the opcode as well. - bytes = 1 + mos6502_dis_expected_bytes(mos6502_addr_mode(opcode)); + bytes = 1 + mos6502_dis_expected_bytes(cpu->addr_mode); // First, we need to know how to resolve our effective address and // how to execute anything. - resolver = mos6502_get_address_resolver(mos6502_addr_mode(opcode)); + resolver = mos6502_get_address_resolver(cpu->addr_mode); handler = mos6502_get_instruction_handler(opcode); // The operand is the effective operand, the value that the diff --git a/tests/mos6502/arith.c b/tests/mos6502/arith.c index 205c57e..85a076e 100644 --- a/tests/mos6502/arith.c +++ b/tests/mos6502/arith.c @@ -92,7 +92,7 @@ Test(mos6502_arith, cpy) Test(mos6502_arith, dec) { cpu->A = 5; - mos6502_set(cpu, cpu->PC, 0x3A); + cpu->addr_mode = ACC; mos6502_handle_dec(cpu, 0); cr_assert_eq(cpu->A, 4); @@ -104,7 +104,7 @@ Test(mos6502_arith, dec) cpu->eff_addr = 123; mos6502_set(cpu, 123, 44); - mos6502_set(cpu, cpu->PC, 0x00); + cpu->addr_mode = 0; mos6502_handle_dec(cpu, 44); cr_assert_eq(mos6502_get(cpu, 123), 43); } @@ -131,7 +131,7 @@ Test(mos6502_arith, inc) cpu->A = 8; cpu->eff_addr = 0; - mos6502_set(cpu, cpu->PC, 0x1A); + cpu->addr_mode = ACC; mos6502_handle_inc(cpu, 0); cr_assert_eq(cpu->A, 9); diff --git a/tests/mos6502/bits.c b/tests/mos6502/bits.c index 816e7a1..4ebb85b 100644 --- a/tests/mos6502/bits.c +++ b/tests/mos6502/bits.c @@ -23,7 +23,7 @@ Test(mos6502_bits, asl) mos6502_handle_asl(cpu, 22); cr_assert_eq(mos6502_get(cpu, 123), 44); - mos6502_set(cpu, cpu->PC, 0x0A); + cpu->addr_mode = ACC; mos6502_handle_asl(cpu, 5); cr_assert_eq(cpu->A, 10); @@ -98,7 +98,7 @@ Test(mos6502_bits, lsr) cr_assert_eq(mos6502_get(cpu, 123), 5); cr_assert_eq(cpu->P & MOS_CARRY, MOS_CARRY); - mos6502_set(cpu, cpu->PC, 0x4A); + cpu->addr_mode = ACC; mos6502_handle_lsr(cpu, 5); cr_assert_eq(cpu->A, 2); cr_assert_eq(cpu->P & MOS_CARRY, MOS_CARRY); @@ -122,7 +122,7 @@ Test(mos6502_bits, rol) mos6502_handle_rol(cpu, 128); cr_assert_eq(mos6502_get(cpu, 234), 0); - mos6502_set(cpu, cpu->PC, 0x2A); + cpu->addr_mode = ACC; cpu->P = 0; cpu->A = 0xff; mos6502_handle_rol(cpu, cpu->A); @@ -141,7 +141,7 @@ Test(mos6502_bits, ror) mos6502_handle_ror(cpu, 0); cr_assert_eq(mos6502_get(cpu, 123), 128); - mos6502_set(cpu, cpu->PC, 0x6A); + cpu->addr_mode = ACC; cpu->P = 0; cpu->A = 0xff; mos6502_handle_ror(cpu, cpu->A);