mirror of
https://github.com/tdinucci/6502-emulator.git
synced 2024-12-03 12:49:37 +00:00
Add "transfer" instructions
This commit is contained in:
parent
d987a4849e
commit
534c5576f8
@ -13,12 +13,12 @@ namespace emu_6502 {
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
const T Register<T>::get_value() {
|
||||
T Register<T>::get_value() const {
|
||||
return value;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
const string& Register<T>::get_name() {
|
||||
const string& Register<T>::get_name() const {
|
||||
return name;
|
||||
}
|
||||
}
|
||||
|
@ -20,9 +20,9 @@ namespace emu_6502 {
|
||||
Register<T>(const Register<T>&) = delete;
|
||||
Register<T>& operator=(const Register<T>&) = delete;
|
||||
|
||||
const string& get_name();
|
||||
const string& get_name() const;
|
||||
|
||||
const T get_value();
|
||||
T get_value() const;
|
||||
void set_value(T value);
|
||||
};
|
||||
}
|
||||
|
@ -51,7 +51,8 @@ namespace emu_6502 {
|
||||
|
||||
public:
|
||||
LoadOpcodeHandlerContainer();
|
||||
LoadOpcodeHandlerContainer(const LoadOpcodeHandlerContainer& other) = delete;
|
||||
LoadOpcodeHandlerContainer(const LoadOpcodeHandlerContainer&) = delete;
|
||||
LoadOpcodeHandlerContainer& operator=(const LoadOpcodeHandlerContainer&) = delete;
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -15,6 +15,7 @@ namespace emu_6502 {
|
||||
public:
|
||||
OpcodeHandlerContainer();
|
||||
OpcodeHandlerContainer(const OpcodeHandlerContainer& other) = delete;
|
||||
OpcodeHandlerContainer operator=(const OpcodeHandlerContainer& other) = delete;
|
||||
|
||||
virtual ~OpcodeHandlerContainer() {};
|
||||
|
||||
|
@ -45,6 +45,7 @@ namespace emu_6502 {
|
||||
public:
|
||||
StoreOpcodeHandlerContainer();
|
||||
StoreOpcodeHandlerContainer(const StoreOpcodeHandlerContainer& other) = delete;
|
||||
StoreOpcodeHandlerContainer operator=(const StoreOpcodeHandlerContainer& other) = delete;
|
||||
};
|
||||
}
|
||||
|
||||
|
42
src/opcode/handler/transfer-opcode-handler-container.cpp
Normal file
42
src/opcode/handler/transfer-opcode-handler-container.cpp
Normal file
@ -0,0 +1,42 @@
|
||||
#include "transfer-opcode-handler-container.h"
|
||||
|
||||
namespace emu_6502 {
|
||||
|
||||
TransferOpcodeHandlerContainer::TransferOpcodeHandlerContainer() : OpcodeHandlerContainer() {
|
||||
handlers.insert({Op::TAX, [this](Machine& machine) {
|
||||
transfer(machine, machine.get_cpu().get_a(), machine.get_cpu().get_x());
|
||||
}});
|
||||
|
||||
handlers.insert({Op::TAY, [this](Machine& machine) {
|
||||
transfer(machine, machine.get_cpu().get_a(), machine.get_cpu().get_y());
|
||||
}});
|
||||
|
||||
handlers.insert({Op::TSX, [this](Machine& machine) {
|
||||
transfer(machine, machine.get_cpu().get_sp(), machine.get_cpu().get_x());
|
||||
}});
|
||||
|
||||
handlers.insert({Op::TXA, [this](Machine& machine) {
|
||||
transfer(machine, machine.get_cpu().get_x(), machine.get_cpu().get_a());
|
||||
}});
|
||||
|
||||
handlers.insert({Op::TXS, [this](Machine& machine) {
|
||||
transfer(machine, machine.get_cpu().get_x(), machine.get_cpu().get_sp(), true);
|
||||
}});
|
||||
|
||||
handlers.insert({Op::TYA, [this](Machine& machine) {
|
||||
transfer(machine, machine.get_cpu().get_y(), machine.get_cpu().get_a());
|
||||
}});
|
||||
}
|
||||
|
||||
void TransferOpcodeHandlerContainer::transfer(Machine& machine, const Register<uint8_t>& source,
|
||||
Register<uint8_t>& dest, bool ignoreFlags) {
|
||||
auto value = source.get_value();
|
||||
dest.set_value(value);
|
||||
|
||||
if (!ignoreFlags) {
|
||||
auto& ps = machine.get_cpu().get_ps();
|
||||
ps.set_zero(value == 0);
|
||||
ps.set_negative((value & 0x80) == 0x80);
|
||||
}
|
||||
}
|
||||
}
|
30
src/opcode/handler/transfer-opcode-handler-container.h
Normal file
30
src/opcode/handler/transfer-opcode-handler-container.h
Normal file
@ -0,0 +1,30 @@
|
||||
#ifndef INC_6502_EMULATOR_TRANSFER_OPCODE_HANDLER_CONTAINER_H
|
||||
#define INC_6502_EMULATOR_TRANSFER_OPCODE_HANDLER_CONTAINER_H
|
||||
|
||||
#include "opcode-handler-container.h"
|
||||
#include "../../machine/register.h"
|
||||
|
||||
namespace emu_6502 {
|
||||
class TransferOpcodeHandlerContainer : public OpcodeHandlerContainer {
|
||||
private:
|
||||
enum Op {
|
||||
TAX = 0xAA,
|
||||
TAY = 0xA8,
|
||||
TSX = 0xBA,
|
||||
TXA = 0x8A,
|
||||
TXS = 0x9A,
|
||||
TYA = 0x98
|
||||
};
|
||||
|
||||
void transfer(Machine& machine, const Register<uint8_t>& source, Register<uint8_t>& dest,
|
||||
bool ignoreFlags = false);
|
||||
|
||||
public:
|
||||
TransferOpcodeHandlerContainer();
|
||||
TransferOpcodeHandlerContainer(const TransferOpcodeHandlerContainer&) = delete;
|
||||
TransferOpcodeHandlerContainer operator=(const TransferOpcodeHandlerContainer&) = delete;
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
#endif //INC_6502_EMULATOR_TRANSFER_OPCODE_HANDLER_CONTAINER_H
|
@ -1,6 +1,7 @@
|
||||
#include "opcode-handler-directory.h"
|
||||
#include "handler/load-opcode-handler-container.h"
|
||||
#include "handler/store-opcode-handler-container.h"
|
||||
#include "handler/transfer-opcode-handler-container.h"
|
||||
#include "../utils.h"
|
||||
|
||||
namespace emu_6502 {
|
||||
@ -8,6 +9,7 @@ namespace emu_6502 {
|
||||
OpcodeHandlerDirectory::OpcodeHandlerDirectory() : handler_containers{}, handlers{} {
|
||||
handler_containers.push_back(make_unique<LoadOpcodeHandlerContainer>());
|
||||
handler_containers.push_back(make_unique<StoreOpcodeHandlerContainer>());
|
||||
handler_containers.push_back(make_unique<TransferOpcodeHandlerContainer>());
|
||||
|
||||
init_handlers();
|
||||
}
|
||||
|
@ -1,9 +1,6 @@
|
||||
#include "gtest/gtest.h"
|
||||
#include "test-utils.h"
|
||||
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
|
||||
using namespace std;
|
||||
using namespace emu_6502;
|
||||
|
||||
|
@ -1,9 +1,6 @@
|
||||
#include "gtest/gtest.h"
|
||||
#include "test-utils.h"
|
||||
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
|
||||
using namespace std;
|
||||
using namespace emu_6502;
|
||||
|
||||
|
207
test/transfer-opcode-handler-test.cpp
Normal file
207
test/transfer-opcode-handler-test.cpp
Normal file
@ -0,0 +1,207 @@
|
||||
#include "gtest/gtest.h"
|
||||
#include "test-utils.h"
|
||||
|
||||
using namespace std;
|
||||
using namespace emu_6502;
|
||||
|
||||
const uint8_t TAX = 0xAA;
|
||||
const uint8_t TAY = 0xA8;
|
||||
const uint8_t TSX = 0xBA;
|
||||
const uint8_t TXA = 0x8A;
|
||||
const uint8_t TXS = 0x9A;
|
||||
const uint8_t TYA = 0x98;
|
||||
|
||||
TEST(TransferOpcodeHandlerContainer, TAX) {
|
||||
auto machine = create_machine({TAX});
|
||||
machine->get_cpu().get_a().set_value(0x11);
|
||||
machine->execute();
|
||||
|
||||
ASSERT_EQ(0x11, machine->get_cpu().get_x().get_value());
|
||||
ASSERT_TRUE(are_flags_set(machine->get_cpu().get_ps(), RegisterFlagSet{}));
|
||||
}
|
||||
|
||||
TEST(TransferOpcodeHandlerContainer, TAX_ZeroFlag) {
|
||||
auto machine = create_machine({TAX});
|
||||
machine->get_cpu().get_a().set_value(0);
|
||||
machine->execute();
|
||||
|
||||
ASSERT_EQ(0, machine->get_cpu().get_x().get_value());
|
||||
|
||||
RegisterFlagSet flags{};
|
||||
flags.zero = true;
|
||||
ASSERT_TRUE(are_flags_set(machine->get_cpu().get_ps(), flags));
|
||||
}
|
||||
|
||||
TEST(TransferOpcodeHandlerContainer, TAX_NegativeFlag) {
|
||||
auto machine = create_machine({TAX});
|
||||
machine->get_cpu().get_a().set_value(0xf0);
|
||||
machine->execute();
|
||||
|
||||
ASSERT_EQ(0xf0, machine->get_cpu().get_x().get_value());
|
||||
|
||||
RegisterFlagSet flags{};
|
||||
flags.negative = true;
|
||||
ASSERT_TRUE(are_flags_set(machine->get_cpu().get_ps(), flags));
|
||||
}
|
||||
|
||||
TEST(TransferOpcodeHandlerContainer, TAY) {
|
||||
auto machine = create_machine({TAY});
|
||||
machine->get_cpu().get_a().set_value(0x11);
|
||||
machine->execute();
|
||||
|
||||
ASSERT_EQ(0x11, machine->get_cpu().get_y().get_value());
|
||||
ASSERT_TRUE(are_flags_set(machine->get_cpu().get_ps(), RegisterFlagSet{}));
|
||||
}
|
||||
|
||||
TEST(TransferOpcodeHandlerContainer, TAY_ZeroFlag) {
|
||||
auto machine = create_machine({TAY});
|
||||
machine->get_cpu().get_a().set_value(0);
|
||||
machine->execute();
|
||||
|
||||
ASSERT_EQ(0, machine->get_cpu().get_y().get_value());
|
||||
|
||||
RegisterFlagSet flags{};
|
||||
flags.zero = true;
|
||||
ASSERT_TRUE(are_flags_set(machine->get_cpu().get_ps(), flags));
|
||||
}
|
||||
|
||||
TEST(TransferOpcodeHandlerContainer, TAY_NegativeFlag) {
|
||||
auto machine = create_machine({TAY});
|
||||
machine->get_cpu().get_a().set_value(0xf0);
|
||||
machine->execute();
|
||||
|
||||
ASSERT_EQ(0xf0, machine->get_cpu().get_y().get_value());
|
||||
|
||||
RegisterFlagSet flags{};
|
||||
flags.negative = true;
|
||||
ASSERT_TRUE(are_flags_set(machine->get_cpu().get_ps(), flags));
|
||||
}
|
||||
|
||||
TEST(TransferOpcodeHandlerContainer, TSX) {
|
||||
auto machine = create_machine({TSX});
|
||||
machine->get_cpu().get_sp().set_value(0x11);
|
||||
machine->execute();
|
||||
|
||||
ASSERT_EQ(0x11, machine->get_cpu().get_x().get_value());
|
||||
ASSERT_TRUE(are_flags_set(machine->get_cpu().get_ps(), RegisterFlagSet{}));
|
||||
}
|
||||
|
||||
TEST(TransferOpcodeHandlerContainer, TSX_ZeroFlag) {
|
||||
auto machine = create_machine({TSX});
|
||||
machine->get_cpu().get_sp().set_value(0);
|
||||
machine->execute();
|
||||
|
||||
ASSERT_EQ(0, machine->get_cpu().get_x().get_value());
|
||||
|
||||
RegisterFlagSet flags{};
|
||||
flags.zero = true;
|
||||
ASSERT_TRUE(are_flags_set(machine->get_cpu().get_ps(), flags));
|
||||
}
|
||||
|
||||
TEST(TransferOpcodeHandlerContainer, TSX_NegativeFlag) {
|
||||
auto machine = create_machine({TSX});
|
||||
machine->get_cpu().get_sp().set_value(0xf0);
|
||||
machine->execute();
|
||||
|
||||
ASSERT_EQ(0xf0, machine->get_cpu().get_x().get_value());
|
||||
|
||||
RegisterFlagSet flags{};
|
||||
flags.negative = true;
|
||||
ASSERT_TRUE(are_flags_set(machine->get_cpu().get_ps(), flags));
|
||||
}
|
||||
|
||||
TEST(TransferOpcodeHandlerContainer, TXA) {
|
||||
auto machine = create_machine({TXA});
|
||||
machine->get_cpu().get_x().set_value(0x11);
|
||||
machine->execute();
|
||||
|
||||
ASSERT_EQ(0x11, machine->get_cpu().get_a().get_value());
|
||||
ASSERT_TRUE(are_flags_set(machine->get_cpu().get_ps(), RegisterFlagSet{}));
|
||||
}
|
||||
|
||||
TEST(TransferOpcodeHandlerContainer, TXA_ZeroFlag) {
|
||||
auto machine = create_machine({TXA});
|
||||
machine->get_cpu().get_x().set_value(0);
|
||||
machine->execute();
|
||||
|
||||
ASSERT_EQ(0, machine->get_cpu().get_a().get_value());
|
||||
|
||||
RegisterFlagSet flags{};
|
||||
flags.zero = true;
|
||||
ASSERT_TRUE(are_flags_set(machine->get_cpu().get_ps(), flags));
|
||||
}
|
||||
|
||||
TEST(TransferOpcodeHandlerContainer, TXA_NegativeFlag) {
|
||||
auto machine = create_machine({TXA});
|
||||
machine->get_cpu().get_x().set_value(0xf0);
|
||||
machine->execute();
|
||||
|
||||
ASSERT_EQ(0xf0, machine->get_cpu().get_a().get_value());
|
||||
|
||||
RegisterFlagSet flags{};
|
||||
flags.negative = true;
|
||||
ASSERT_TRUE(are_flags_set(machine->get_cpu().get_ps(), flags));
|
||||
}
|
||||
|
||||
TEST(TransferOpcodeHandlerContainer, TXS) {
|
||||
auto machine = create_machine({TXS});
|
||||
machine->get_cpu().get_x().set_value(0x11);
|
||||
machine->execute();
|
||||
|
||||
ASSERT_EQ(0x11, machine->get_cpu().get_sp().get_value());
|
||||
ASSERT_TRUE(are_flags_set(machine->get_cpu().get_ps(), RegisterFlagSet{}));
|
||||
}
|
||||
|
||||
TEST(TransferOpcodeHandlerContainer, TXS_ZeroFlag) {
|
||||
auto machine = create_machine({TXS});
|
||||
machine->get_cpu().get_x().set_value(0);
|
||||
machine->execute();
|
||||
|
||||
ASSERT_EQ(0, machine->get_cpu().get_sp().get_value());
|
||||
|
||||
// flags not affected with this op
|
||||
ASSERT_TRUE(are_flags_set(machine->get_cpu().get_ps(), RegisterFlagSet{}));
|
||||
}
|
||||
|
||||
TEST(TransferOpcodeHandlerContainer, TXS_NegativeFlag) {
|
||||
auto machine = create_machine({TXS});
|
||||
machine->get_cpu().get_x().set_value(0xf0);
|
||||
machine->execute();
|
||||
|
||||
ASSERT_EQ(0xf0, machine->get_cpu().get_sp().get_value());
|
||||
// flags not affected with this op
|
||||
ASSERT_TRUE(are_flags_set(machine->get_cpu().get_ps(), RegisterFlagSet{}));
|
||||
}
|
||||
|
||||
TEST(TransferOpcodeHandlerContainer, TYA) {
|
||||
auto machine = create_machine({TYA});
|
||||
machine->get_cpu().get_y().set_value(0x11);
|
||||
machine->execute();
|
||||
|
||||
ASSERT_EQ(0x11, machine->get_cpu().get_a().get_value());
|
||||
ASSERT_TRUE(are_flags_set(machine->get_cpu().get_ps(), RegisterFlagSet{}));
|
||||
}
|
||||
|
||||
TEST(TransferOpcodeHandlerContainer, TYA_ZeroFlag) {
|
||||
auto machine = create_machine({TYA});
|
||||
machine->get_cpu().get_y().set_value(0);
|
||||
machine->execute();
|
||||
|
||||
ASSERT_EQ(0, machine->get_cpu().get_a().get_value());
|
||||
|
||||
RegisterFlagSet flags{};
|
||||
flags.zero = true;
|
||||
ASSERT_TRUE(are_flags_set(machine->get_cpu().get_ps(), flags));
|
||||
}
|
||||
|
||||
TEST(TransferOpcodeHandlerContainer, TYA_NegativeFlag) {
|
||||
auto machine = create_machine({TYA});
|
||||
machine->get_cpu().get_y().set_value(0xf0);
|
||||
machine->execute();
|
||||
|
||||
ASSERT_EQ(0xf0, machine->get_cpu().get_a().get_value());
|
||||
|
||||
RegisterFlagSet flags{};
|
||||
flags.negative = true;
|
||||
ASSERT_TRUE(are_flags_set(machine->get_cpu().get_ps(), flags));
|
||||
}
|
Loading…
Reference in New Issue
Block a user