Jump opcodes (minus RTI)

This commit is contained in:
Tony Di Nucci 2019-04-22 00:19:16 +01:00
parent f407339fc3
commit af0099caa6
6 changed files with 162 additions and 2 deletions

View File

@ -0,0 +1,44 @@
#include "jump-opcode-handler-container.h"
#include "../../utils.h"
namespace emu_6502 {
JumpOpcodeHandlerContainer::JumpOpcodeHandlerContainer() {
handlers.insert({Op::JMP_ABS, [this](Machine& machine) { jmp_abs(machine); }});
handlers.insert({Op::JMP_IND, [this](Machine& machine) { jmp_ind(machine); }});
handlers.insert({Op::JSR, [this](Machine& machine) { jsr(machine); }});
handlers.insert({Op::RTI, [this](Machine& machine) { rti(machine); }});
handlers.insert({Op::RTS, [this](Machine& machine) { rts(machine); }});
}
void JumpOpcodeHandlerContainer::jmp_abs(Machine& machine) {
auto addr = get_abs_address(machine);
machine.get_cpu().get_pc().set_value(addr);
}
void JumpOpcodeHandlerContainer::jmp_ind(Machine& machine) {
auto addr = get_ind_address(machine);
machine.get_cpu().get_pc().set_value(addr);
}
void JumpOpcodeHandlerContainer::jsr(Machine& machine) {
uint16_t addr = get_abs_address(machine);
uint16_t pc_value = machine.get_cpu().get_pc().get_value();
machine.get_stack().push(pc_value >> 8);
machine.get_stack().push(pc_value);
machine.get_cpu().get_pc().set_value(addr);
}
void JumpOpcodeHandlerContainer::rti(Machine& machine) {}
void JumpOpcodeHandlerContainer::rts(Machine& machine) {
auto low_byte = machine.get_stack().pop();
auto high_byte = machine.get_stack().pop();
uint16_t return_address = (high_byte << 8) + low_byte + 1;
machine.get_cpu().get_pc().set_value(return_address);
}
}

View File

@ -0,0 +1,35 @@
#ifndef INC_6502_EMULATOR_JUMP_OPCODE_HANDLER_CONTAINER_H
#define INC_6502_EMULATOR_JUMP_OPCODE_HANDLER_CONTAINER_H
#include "opcode-handler-container.h"
namespace emu_6502 {
class JumpOpcodeHandlerContainer : public OpcodeHandlerContainer {
private:
enum Op {
JMP_ABS = 0x4C,
JMP_IND = 0x6C,
JSR = 0x20,
RTI = 0x40,
RTS = 0x60
};
void jmp_abs(Machine& machine);
void jmp_ind(Machine& machine);
void jsr(Machine& machine);
void rti(Machine& machine);
void rts(Machine& machine);
public:
JumpOpcodeHandlerContainer();
JumpOpcodeHandlerContainer(const JumpOpcodeHandlerContainer&) = delete;
JumpOpcodeHandlerContainer& operator=(const JumpOpcodeHandlerContainer&) = delete;
};
}
#endif //INC_6502_EMULATOR_JUMP_OPCODE_HANDLER_CONTAINER_H

View File

@ -8,6 +8,7 @@
#include "handler/compare-opcode-handler-container.h"
#include "handler/stack-opcode-handler-container.h"
#include "handler/branch-opcode-handler-container.h"
#include "handler/jump-opcode-handler-container.h"
#include "../utils.h"
namespace emu_6502 {
@ -22,6 +23,7 @@ namespace emu_6502 {
handler_containers.push_back(make_unique<CompareOpcodeHandlerContainer>());
handler_containers.push_back(make_unique<StackOpcodeHandlerContainer>());
handler_containers.push_back(make_unique<BranchOpcodeHandlerContainer>());
handler_containers.push_back(make_unique<JumpOpcodeHandlerContainer>());
init_handlers();
}

View File

@ -48,6 +48,18 @@ namespace emu_6502 {
return address;
}
uint16_t get_ind_address(Machine& machine) {
auto low_byte = machine.read_program_byte();
auto high_byte = machine.read_program_byte();
uint16_t paddress = (high_byte << 8) + low_byte;
auto low = machine.get_memory().get_at(paddress);
auto high = machine.get_memory().get_at(paddress + 1);
uint16_t address = (high << 8) + low;
return address;
}
uint16_t get_ind_x_address(Machine& machine) {
uint8_t paddress = machine.get_cpu().get_x().get_value() + machine.read_program_byte();
auto low = machine.get_memory().get_at(paddress);

View File

@ -15,11 +15,12 @@ namespace emu_6502 {
uint8_t get_zpg_address(Machine& machine);
uint8_t get_zpg_x_address(Machine& machine);
uint8_t get_zpg_y_address(Machine& machine);
uint16_t get_abs_address(Machine& machine);
uint16_t get_abs_x_address(Machine& machine);
uint16_t get_abs_y_address(Machine& machine);
uint16_t get_abs_x_address(Machine& machine);
uint16_t get_abs_y_address(Machine& machine);
uint16_t get_ind_address(Machine& machine);
uint16_t get_ind_x_address(Machine& machine);
uint16_t get_ind_y_address(Machine& machine);
}

View File

@ -0,0 +1,66 @@
#include "gtest/gtest.h"
#include "test-utils.h"
using namespace std;
using namespace emu_6502;
const uint8_t JMP_ABS = 0x4C;
const uint8_t JMP_IND = 0x6C;
const uint8_t JSR = 0x20;
const uint8_t RTI = 0x40;
const uint8_t RTS = 0x60;
const uint8_t LDA_IMM = 0xA9;
TEST(LoadOpcodeHandlerContainer, JMP_ABS) {
auto machine = create_machine({JMP_ABS, 0x34, 0x12});
try {
machine->execute();
}
catch (exception) {
}
ASSERT_EQ(0x1234, machine->get_cpu().get_pc().get_value());
}
TEST(LoadOpcodeHandlerContainer, JMP_IND) {
auto machine = create_machine({JMP_IND, 0x34, 0x12});
machine->get_memory().set_at(0x1234, 0xF6);
machine->get_memory().set_at(0x1235, 0xAB);
try {
machine->execute();
}
catch (exception) {
}
ASSERT_EQ(0xABF6, machine->get_cpu().get_pc().get_value());
}
TEST(LoadOpcodeHandlerContainer, JSR) {
auto machine = create_machine({JSR, 0x34, 0x12});
try {
machine->execute();
}
catch (exception) {
}
ASSERT_EQ(0x1234, machine->get_cpu().get_pc().get_value());
ASSERT_EQ(3, machine->get_stack().pop());
}
TEST(LoadOpcodeHandlerContainer, RTS) {
auto machine = create_machine({JSR, 0x07, 0x06, 0x0, 0x0, 0x0, 0x0, LDA_IMM, 0x99, RTS});
try {
machine->execute();
}
catch (exception) {
}
ASSERT_EQ(0x99, machine->get_cpu().get_a().get_value());
ASSERT_EQ(0x605, machine->get_cpu().get_pc().get_value());
}