mirror of
https://github.com/pevans/erc-c.git
synced 2024-12-13 00:29:03 +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:
parent
56e9d97791
commit
8e810e724f
@ -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
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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);
|
||||
|
Loading…
Reference in New Issue
Block a user