mirror of
https://github.com/tdinucci/6502-emulator.git
synced 2024-11-23 07:34:14 +00:00
Jump opcodes (minus RTI)
This commit is contained in:
parent
f407339fc3
commit
af0099caa6
44
src/opcode/handler/jump-opcode-handler-container.cpp
Normal file
44
src/opcode/handler/jump-opcode-handler-container.cpp
Normal 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);
|
||||
}
|
||||
}
|
35
src/opcode/handler/jump-opcode-handler-container.h
Normal file
35
src/opcode/handler/jump-opcode-handler-container.h
Normal 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
|
@ -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();
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
}
|
||||
|
66
test/jump-opcode-handler-test.cpp
Normal file
66
test/jump-opcode-handler-test.cpp
Normal 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());
|
||||
}
|
Loading…
Reference in New Issue
Block a user