1
0
mirror of https://github.com/pevans/erc-c.git synced 2024-06-16 06:29:37 +00:00

Add addr_mode field, rely upon it vs. the opcode

This makes testing _slightly_ easier, because now the handlers require a
type of state in the cpu vs. a specific opcode state in the segment that
we execute from. (The latter being just more complex to work with and
require in testing.)
This commit is contained in:
Peter Evans 2018-04-15 00:56:34 -05:00
parent 56e9d97791
commit 8e810e724f
6 changed files with 38 additions and 51 deletions

View File

@ -104,6 +104,11 @@ typedef struct {
*/ */
vm_16bit eff_addr; 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 * These are the last opcode and last effective address that was
* used in the instruction previous to the one currently being * used in the instruction previous to the one currently being

View File

@ -154,19 +154,14 @@ DEFINE_INST(cpy)
*/ */
DEFINE_INST(dec) DEFINE_INST(dec)
{ {
vm_8bit opcode = mos6502_get(cpu, cpu->PC); if (cpu->addr_mode == ACC) {
bool is_acc = mos6502_addr_mode(opcode) == ACC; MOS_CHECK_NZ(cpu->A - 1);
cpu->A--;
if (!is_acc) {
MOS_CHECK_NZ(oper - 1);
mos6502_set(cpu, cpu->eff_addr, oper - 1);
return; return;
} }
// If we get here, then this is ACC mode, and we should work off MOS_CHECK_NZ(oper - 1);
// that. mos6502_set(cpu, cpu->eff_addr, oper - 1);
MOS_CHECK_NZ(cpu->A - 1);
cpu->A--;
} }
/* /*
@ -192,17 +187,14 @@ DEFINE_INST(dey)
*/ */
DEFINE_INST(inc) DEFINE_INST(inc)
{ {
vm_8bit opcode = mos6502_get(cpu, cpu->PC); if (cpu->addr_mode == ACC) {
bool is_acc = mos6502_addr_mode(opcode) == ACC; MOS_CHECK_NZ(cpu->A + 1);
cpu->A++;
if (!is_acc) {
MOS_CHECK_NZ(oper + 1);
mos6502_set(cpu, cpu->eff_addr, oper + 1);
return; return;
} }
MOS_CHECK_NZ(cpu->A + 1); MOS_CHECK_NZ(oper + 1);
cpu->A++; mos6502_set(cpu, cpu->eff_addr, oper + 1);
} }
/* /*

View File

@ -31,9 +31,6 @@ DEFINE_INST(and)
*/ */
DEFINE_INST(asl) DEFINE_INST(asl)
{ {
vm_8bit opcode = mos6502_get(cpu, cpu->PC);
bool is_acc = mos6502_addr_mode(opcode) == ACC;
vm_8bit result = oper << 1; vm_8bit result = oper << 1;
MOS_CHECK_NZ(result); MOS_CHECK_NZ(result);
@ -42,10 +39,10 @@ DEFINE_INST(asl)
cpu->P |= MOS_CARRY; cpu->P |= MOS_CARRY;
} }
if (!is_acc) { if (cpu->addr_mode == ACC) {
mos6502_set(cpu, cpu->eff_addr, result);
} else {
cpu->A = result; cpu->A = result;
} else {
mos6502_set(cpu, cpu->eff_addr, result);
} }
} }
@ -114,9 +111,6 @@ DEFINE_INST(eor)
*/ */
DEFINE_INST(lsr) DEFINE_INST(lsr)
{ {
vm_8bit opcode = mos6502_get(cpu, cpu->PC);
bool is_acc = mos6502_addr_mode(opcode) == ACC;
vm_8bit result = oper >> 1; vm_8bit result = oper >> 1;
// The N flag is ALWAYS cleared in LSR, because a zero is always // The N flag is ALWAYS cleared in LSR, because a zero is always
@ -132,10 +126,10 @@ DEFINE_INST(lsr)
cpu->P |= MOS_CARRY; cpu->P |= MOS_CARRY;
} }
if (!is_acc) { if (cpu->addr_mode == ACC) {
mos6502_set(cpu, cpu->eff_addr, result);
} else {
cpu->A = result; cpu->A = result;
} else {
mos6502_set(cpu, cpu->eff_addr, result);
} }
} }
@ -156,9 +150,6 @@ DEFINE_INST(ora)
*/ */
DEFINE_INST(rol) DEFINE_INST(rol)
{ {
vm_8bit opcode = mos6502_get(cpu, cpu->PC);
bool is_acc = mos6502_addr_mode(opcode) == ACC;
vm_8bit result = oper << 1; vm_8bit result = oper << 1;
// Rotations are effectively _9-bit_. So we aren't rotating bit 7 // Rotations are effectively _9-bit_. So we aren't rotating bit 7
@ -175,10 +166,10 @@ DEFINE_INST(rol)
MOS_CHECK_NZ(result); MOS_CHECK_NZ(result);
if (!is_acc) { if (cpu->addr_mode == ACC) {
mos6502_set(cpu, cpu->eff_addr, result);
} else {
cpu->A = result; cpu->A = result;
} else {
mos6502_set(cpu, cpu->eff_addr, result);
} }
} }
@ -188,9 +179,6 @@ DEFINE_INST(rol)
*/ */
DEFINE_INST(ror) DEFINE_INST(ror)
{ {
vm_8bit opcode = mos6502_get(cpu, cpu->PC);
bool is_acc = mos6502_addr_mode(opcode) == ACC;
vm_8bit result = oper >> 1; vm_8bit result = oper >> 1;
// See the code for ROL for my note on 9-bit rotation (vs. 8-bit). // 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); MOS_CHECK_NZ(result);
if (!is_acc) { if (cpu->addr_mode == ACC) {
mos6502_set(cpu, cpu->eff_addr, result);
} else {
cpu->A = result; cpu->A = result;
} else {
mos6502_set(cpu, cpu->eff_addr, result);
} }
} }

View File

@ -170,6 +170,7 @@ mos6502_create(vm_segment *rmem, vm_segment *wmem)
mos6502_set_memory(cpu, rmem, wmem); mos6502_set_memory(cpu, rmem, wmem);
cpu->eff_addr = 0; cpu->eff_addr = 0;
cpu->addr_mode = 0;
cpu->PC = 0; cpu->PC = 0;
cpu->A = 0; cpu->A = 0;
cpu->X = 0; cpu->X = 0;
@ -303,16 +304,17 @@ mos6502_execute(mos6502 *cpu)
mos6502_instruction_handler handler; mos6502_instruction_handler handler;
opcode = mos6502_get(cpu, cpu->PC); opcode = mos6502_get(cpu, cpu->PC);
cpu->addr_mode = mos6502_addr_mode(opcode);
// The disassembler knows how many bytes each operand requires // The disassembler knows how many bytes each operand requires
// (maybe this code doesn't belong in the disassembler); let's use // (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 // that to figure out the total number of bytes to skip. We add 1
// because we need to account for the opcode as well. // 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 // First, we need to know how to resolve our effective address and
// how to execute anything. // 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); handler = mos6502_get_instruction_handler(opcode);
// The operand is the effective operand, the value that the // The operand is the effective operand, the value that the

View File

@ -92,7 +92,7 @@ Test(mos6502_arith, cpy)
Test(mos6502_arith, dec) Test(mos6502_arith, dec)
{ {
cpu->A = 5; cpu->A = 5;
mos6502_set(cpu, cpu->PC, 0x3A); cpu->addr_mode = ACC;
mos6502_handle_dec(cpu, 0); mos6502_handle_dec(cpu, 0);
cr_assert_eq(cpu->A, 4); cr_assert_eq(cpu->A, 4);
@ -104,7 +104,7 @@ Test(mos6502_arith, dec)
cpu->eff_addr = 123; cpu->eff_addr = 123;
mos6502_set(cpu, 123, 44); mos6502_set(cpu, 123, 44);
mos6502_set(cpu, cpu->PC, 0x00); cpu->addr_mode = 0;
mos6502_handle_dec(cpu, 44); mos6502_handle_dec(cpu, 44);
cr_assert_eq(mos6502_get(cpu, 123), 43); cr_assert_eq(mos6502_get(cpu, 123), 43);
} }
@ -131,7 +131,7 @@ Test(mos6502_arith, inc)
cpu->A = 8; cpu->A = 8;
cpu->eff_addr = 0; cpu->eff_addr = 0;
mos6502_set(cpu, cpu->PC, 0x1A); cpu->addr_mode = ACC;
mos6502_handle_inc(cpu, 0); mos6502_handle_inc(cpu, 0);
cr_assert_eq(cpu->A, 9); cr_assert_eq(cpu->A, 9);

View File

@ -23,7 +23,7 @@ Test(mos6502_bits, asl)
mos6502_handle_asl(cpu, 22); mos6502_handle_asl(cpu, 22);
cr_assert_eq(mos6502_get(cpu, 123), 44); cr_assert_eq(mos6502_get(cpu, 123), 44);
mos6502_set(cpu, cpu->PC, 0x0A); cpu->addr_mode = ACC;
mos6502_handle_asl(cpu, 5); mos6502_handle_asl(cpu, 5);
cr_assert_eq(cpu->A, 10); 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(mos6502_get(cpu, 123), 5);
cr_assert_eq(cpu->P & MOS_CARRY, MOS_CARRY); cr_assert_eq(cpu->P & MOS_CARRY, MOS_CARRY);
mos6502_set(cpu, cpu->PC, 0x4A); cpu->addr_mode = ACC;
mos6502_handle_lsr(cpu, 5); mos6502_handle_lsr(cpu, 5);
cr_assert_eq(cpu->A, 2); cr_assert_eq(cpu->A, 2);
cr_assert_eq(cpu->P & MOS_CARRY, MOS_CARRY); cr_assert_eq(cpu->P & MOS_CARRY, MOS_CARRY);
@ -122,7 +122,7 @@ Test(mos6502_bits, rol)
mos6502_handle_rol(cpu, 128); mos6502_handle_rol(cpu, 128);
cr_assert_eq(mos6502_get(cpu, 234), 0); cr_assert_eq(mos6502_get(cpu, 234), 0);
mos6502_set(cpu, cpu->PC, 0x2A); cpu->addr_mode = ACC;
cpu->P = 0; cpu->P = 0;
cpu->A = 0xff; cpu->A = 0xff;
mos6502_handle_rol(cpu, cpu->A); mos6502_handle_rol(cpu, cpu->A);
@ -141,7 +141,7 @@ Test(mos6502_bits, ror)
mos6502_handle_ror(cpu, 0); mos6502_handle_ror(cpu, 0);
cr_assert_eq(mos6502_get(cpu, 123), 128); cr_assert_eq(mos6502_get(cpu, 123), 128);
mos6502_set(cpu, cpu->PC, 0x6A); cpu->addr_mode = ACC;
cpu->P = 0; cpu->P = 0;
cpu->A = 0xff; cpu->A = 0xff;
mos6502_handle_ror(cpu, cpu->A); mos6502_handle_ror(cpu, cpu->A);