Rest of maths opcodes

This commit is contained in:
Tony Di Nucci 2019-04-20 12:47:57 +01:00
parent 90e33ad6cb
commit e6abdd2dd8
3 changed files with 217 additions and 43 deletions

View File

@ -12,6 +12,15 @@ namespace emu_6502 {
handlers.insert({Op::ADC_IND_X, [this](Machine& machine) { adc_ind_x(machine); }});
handlers.insert({Op::ADC_IND_Y, [this](Machine& machine) { adc_ind_y(machine); }});
handlers.insert({Op::SBC_IMM, [this](Machine& machine) { sbc_imm(machine); }});
handlers.insert({Op::SBC_ZPG, [this](Machine& machine) { sbc_zpg(machine); }});
handlers.insert({Op::SBC_ZPG_X, [this](Machine& machine) { sbc_zpg_x(machine); }});
handlers.insert({Op::SBC_ABS, [this](Machine& machine) { sbc_abs(machine); }});
handlers.insert({Op::SBC_ABS_X, [this](Machine& machine) { sbc_abs_x(machine); }});
handlers.insert({Op::SBC_ABS_Y, [this](Machine& machine) { sbc_abs_y(machine); }});
handlers.insert({Op::SBC_IND_X, [this](Machine& machine) { sbc_ind_x(machine); }});
handlers.insert({Op::SBC_IND_Y, [this](Machine& machine) { sbc_ind_y(machine); }});
handlers.insert({Op::DEC_ZPG, [this](Machine& machine) { dec_zpg(machine); }});
handlers.insert({Op::DEC_ZPG_X, [this](Machine& machine) { dec_zpg_x(machine); }});
handlers.insert({Op::DEC_ABS, [this](Machine& machine) { dec_abs(machine); }});
@ -85,6 +94,43 @@ namespace emu_6502 {
adc(machine, machine.get_memory().get_at(get_ind_y_address(machine)));
}
void MathsOpcodeHandlerContainer::sbc(Machine& machine, uint8_t value) {
// subtract is same as add negative value (i.e. add accumulator to the twos compliment of 'value')
adc(machine, (0xFF ^ value) + 1);
}
void MathsOpcodeHandlerContainer::sbc_imm(Machine& machine) {
sbc(machine, machine.read_program_byte());
}
void MathsOpcodeHandlerContainer::sbc_zpg(Machine& machine) {
sbc(machine, machine.get_memory().get_at(get_zpg_address(machine)));
}
void MathsOpcodeHandlerContainer::sbc_zpg_x(Machine& machine) {
sbc(machine, machine.get_memory().get_at(get_zpg_x_address(machine)));
}
void MathsOpcodeHandlerContainer::sbc_abs(Machine& machine) {
sbc(machine, machine.get_memory().get_at(get_abs_address(machine)));
}
void MathsOpcodeHandlerContainer::sbc_abs_x(Machine& machine) {
sbc(machine, machine.get_memory().get_at(get_abs_x_address(machine)));
}
void MathsOpcodeHandlerContainer::sbc_abs_y(Machine& machine) {
sbc(machine, machine.get_memory().get_at(get_abs_y_address(machine)));
}
void MathsOpcodeHandlerContainer::sbc_ind_x(Machine& machine) {
sbc(machine, machine.get_memory().get_at(get_ind_x_address(machine)));
}
void MathsOpcodeHandlerContainer::sbc_ind_y(Machine& machine) {
sbc(machine, machine.get_memory().get_at(get_ind_y_address(machine)));
}
void MathsOpcodeHandlerContainer::dec(Machine& machine, uint16_t address) {
uint8_t value = machine.get_memory().get_at(address) - 1;
machine.get_memory().set_at(address, value);
@ -160,28 +206,4 @@ namespace emu_6502 {
void MathsOpcodeHandlerContainer::iny(Machine& machine) {
in(machine, machine.get_cpu().get_y());
}
void MathsOpcodeHandlerContainer::sbc_imm(Machine& machine) {
}
void MathsOpcodeHandlerContainer::sbc_zpg(Machine& machine) {
}
void MathsOpcodeHandlerContainer::sbc_zpg_x(Machine& machine) {
}
void MathsOpcodeHandlerContainer::sbc_abs(Machine& machine) {
}
void MathsOpcodeHandlerContainer::sbc_abs_x(Machine& machine) {
}
void MathsOpcodeHandlerContainer::sbc_abs_y(Machine& machine) {
}
void MathsOpcodeHandlerContainer::sbc_ind_x(Machine& machine) {
}
void MathsOpcodeHandlerContainer::sbc_ind_y(Machine& machine) {
}
}

View File

@ -16,6 +16,15 @@ namespace emu_6502 {
ADC_IND_X = 0x61,
ADC_IND_Y = 0x71,
SBC_IMM = 0xE9,
SBC_ZPG = 0xE5,
SBC_ZPG_X = 0xF5,
SBC_ABS = 0xED,
SBC_ABS_X = 0xFD,
SBC_ABS_Y = 0xF9,
SBC_IND_X = 0xE1,
SBC_IND_Y = 0xF1,
DEC_ZPG = 0xC6,
DEC_ZPG_X = 0xD6,
DEC_ABS = 0xCE,
@ -29,16 +38,7 @@ namespace emu_6502 {
DEX = 0xCA,
DEY = 0x88,
INX = 0xE8,
INY = 0xC8,
SBC_IMM = 0x0,
SBC_ZPG = 0x0,
SBC_ZPG_X = 0x0,
SBC_ABS = 0x0,
SBC_ABS_X = 0x0,
SBC_ABS_Y = 0x0,
SBC_IND_X = 0x0,
SBC_IND_Y = 0x0
INY = 0xC8
};
void set_zero_neg(StatusRegister& ps, uint8_t value);
@ -53,6 +53,16 @@ namespace emu_6502 {
void adc_ind_x(Machine& machine);
void adc_ind_y(Machine& machine);
void sbc(Machine& machine, uint8_t value);
void sbc_imm(Machine& machine);
void sbc_zpg(Machine& machine);
void sbc_zpg_x(Machine& machine);
void sbc_abs(Machine& machine);
void sbc_abs_x(Machine& machine);
void sbc_abs_y(Machine& machine);
void sbc_ind_x(Machine& machine);
void sbc_ind_y(Machine& machine);
void dec(Machine& machine, uint16_t address);
void dec_zpg(Machine& machine);
void dec_zpg_x(Machine& machine);
@ -73,15 +83,6 @@ namespace emu_6502 {
void inx(Machine& machine);
void iny(Machine& machine);
void sbc_imm(Machine& machine);
void sbc_zpg(Machine& machine);
void sbc_zpg_x(Machine& machine);
void sbc_abs(Machine& machine);
void sbc_abs_x(Machine& machine);
void sbc_abs_y(Machine& machine);
void sbc_ind_x(Machine& machine);
void sbc_ind_y(Machine& machine);
public:
MathsOpcodeHandlerContainer();
MathsOpcodeHandlerContainer(const MathsOpcodeHandlerContainer&) = delete;

View File

@ -13,6 +13,15 @@ const uint8_t ADC_ABS_Y = 0x79;
const uint8_t ADC_IND_X = 0x61;
const uint8_t ADC_IND_Y = 0x71;
const uint8_t SBC_IMM = 0xE9;
const uint8_t SBC_ZPG = 0xE5;
const uint8_t SBC_ZPG_X = 0xF5;
const uint8_t SBC_ABS = 0xED;
const uint8_t SBC_ABS_X = 0xFD;
const uint8_t SBC_ABS_Y = 0xF9;
const uint8_t SBC_IND_X = 0xE1;
const uint8_t SBC_IND_Y = 0xF1;
const uint8_t DEC_ZPG = 0xC6;
const uint8_t DEC_ZPG_X = 0xD6;
const uint8_t DEC_ABS = 0xCE;
@ -191,6 +200,148 @@ TEST(MathsOpcodeHandlerContainer, ADC_IND_Y) {
ASSERT_TRUE(are_flags_set(machine->get_cpu().get_ps(), RegisterFlagSet{}));
}
TEST(MathsOpcodeHandlerContainer, SBC_IMM) {
auto machine = create_machine({SBC_IMM, 0x20});
machine->get_cpu().get_a().set_value(0x50);
machine->execute();
ASSERT_EQ(0x30, machine->get_cpu().get_a().get_value());
RegisterFlagSet flags{};
flags.carry = true; // indicates no borrow
ASSERT_TRUE(are_flags_set(machine->get_cpu().get_ps(), flags));
}
TEST(MathsOpcodeHandlerContainer, SBC_IMM_WithBorrow) {
auto machine = create_machine({SBC_IMM, 0xf0});
machine->get_cpu().get_a().set_value(0xd0);
machine->execute();
ASSERT_EQ(0xe0, machine->get_cpu().get_a().get_value());
RegisterFlagSet flags{};
flags.carry = false; // indicates there was a borrow
flags.negative = true;
ASSERT_TRUE(are_flags_set(machine->get_cpu().get_ps(), flags));
}
TEST(MathsOpcodeHandlerContainer, SBC_IMM_WithOverflow) {
auto machine = create_machine({SBC_IMM, 0xb0});
machine->get_cpu().get_a().set_value(0x50);
machine->execute();
ASSERT_EQ(0xa0, machine->get_cpu().get_a().get_value());
RegisterFlagSet flags{};
flags.carry = false; // was a borrow
flags.negative = true;
flags.overflow = true;
ASSERT_TRUE(are_flags_set(machine->get_cpu().get_ps(), flags));
}
TEST(MathsOpcodeHandlerContainer, SBC_IMM_ZeroFlag) {
auto machine = create_machine({SBC_IMM, 50});
machine->get_cpu().get_a().set_value(50);
machine->execute();
ASSERT_EQ(0, machine->get_cpu().get_a().get_value());
RegisterFlagSet flags{};
flags.zero = true;
flags.carry = true; // no borrow
ASSERT_TRUE(are_flags_set(machine->get_cpu().get_ps(), flags));
}
TEST(MathsOpcodeHandlerContainer, SBC_ZPG) {
auto machine = create_machine({SBC_ZPG, 0xf1});
machine->get_cpu().get_a().set_value(36);
machine->get_memory().set_at(0xf1, 20);
machine->execute();
ASSERT_EQ(16, machine->get_cpu().get_a().get_value());
RegisterFlagSet flags{};
flags.carry = true; // no borrow
ASSERT_TRUE(are_flags_set(machine->get_cpu().get_ps(), flags));
}
TEST(MathsOpcodeHandlerContainer, SBC_ZPG_X) {
auto machine = create_machine({SBC_ZPG_X, 0xf1});
machine->get_cpu().get_a().set_value(36);
machine->get_cpu().get_x().set_value(5);
machine->get_memory().set_at(0xf6, 20);
machine->execute();
ASSERT_EQ(16, machine->get_cpu().get_a().get_value());
RegisterFlagSet flags{};
flags.carry = true; // no borrow
ASSERT_TRUE(are_flags_set(machine->get_cpu().get_ps(), flags));
}
TEST(MathsOpcodeHandlerContainer, SBC_ABS) {
auto machine = create_machine({SBC_ABS, 0xf1, 0x36});
machine->get_cpu().get_a().set_value(36);
machine->get_memory().set_at(0x36f1, 20);
machine->execute();
ASSERT_EQ(16, machine->get_cpu().get_a().get_value());
RegisterFlagSet flags{};
flags.carry = true; // no borrow
ASSERT_TRUE(are_flags_set(machine->get_cpu().get_ps(), flags));
}
TEST(MathsOpcodeHandlerContainer, SBC_ABS_X) {
auto machine = create_machine({SBC_ABS_X, 0xf1, 0x36});
machine->get_cpu().get_a().set_value(36);
machine->get_cpu().get_x().set_value(8);
machine->get_memory().set_at(0x36f9, 20);
machine->execute();
ASSERT_EQ(16, machine->get_cpu().get_a().get_value());
RegisterFlagSet flags{};
flags.carry = true; // no borrow
ASSERT_TRUE(are_flags_set(machine->get_cpu().get_ps(), flags));
}
TEST(MathsOpcodeHandlerContainer, SBC_ABS_Y) {
auto machine = create_machine({SBC_ABS_Y, 0xf1, 0x36});
machine->get_cpu().get_a().set_value(36);
machine->get_cpu().get_y().set_value(8);
machine->get_memory().set_at(0x36f9, 20);
machine->execute();
ASSERT_EQ(16, machine->get_cpu().get_a().get_value());
RegisterFlagSet flags{};
flags.carry = true; // no borrow
ASSERT_TRUE(are_flags_set(machine->get_cpu().get_ps(), flags));
}
TEST(MathsOpcodeHandlerContainer, SBC_IND_X) {
auto machine = create_machine({SBC_IND_X, 0x41});
machine->get_cpu().get_x().set_value(0x22);
machine->get_cpu().get_a().set_value(36);
machine->get_memory().set_at(0x63, 0x34);
machine->get_memory().set_at(0x64, 0x12);
machine->get_memory().set_at(0x1234, 20);
machine->execute();
ASSERT_EQ(16, machine->get_cpu().get_a().get_value());
RegisterFlagSet flags{};
flags.carry = true; // no borrow
ASSERT_TRUE(are_flags_set(machine->get_cpu().get_ps(), flags));
}
TEST(MathsOpcodeHandlerContainer, SBC_IND_Y) {
auto machine = create_machine({SBC_IND_Y, 0x41});
machine->get_cpu().get_y().set_value(0x22);
machine->get_cpu().get_a().set_value(36);
machine->get_memory().set_at(0x41, 0x34);
machine->get_memory().set_at(0x42, 0x12);
machine->get_memory().set_at(0x1256, 20);
machine->execute();
ASSERT_EQ(16, machine->get_cpu().get_a().get_value());
RegisterFlagSet flags{};
flags.carry = true; // no borrow
ASSERT_TRUE(are_flags_set(machine->get_cpu().get_ps(), flags));
}
TEST(MathsOpcodeHandlerContainer, DEC_ZPG) {
auto machine = create_machine({DEC_ZPG, 0xf1});
machine->get_memory().set_at(0xf1, 20);