mirror of
https://github.com/tdinucci/6502-emulator.git
synced 2025-02-17 08:30:39 +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/compare-opcode-handler-container.h"
|
||||||
#include "handler/stack-opcode-handler-container.h"
|
#include "handler/stack-opcode-handler-container.h"
|
||||||
#include "handler/branch-opcode-handler-container.h"
|
#include "handler/branch-opcode-handler-container.h"
|
||||||
|
#include "handler/jump-opcode-handler-container.h"
|
||||||
#include "../utils.h"
|
#include "../utils.h"
|
||||||
|
|
||||||
namespace emu_6502 {
|
namespace emu_6502 {
|
||||||
@ -22,6 +23,7 @@ namespace emu_6502 {
|
|||||||
handler_containers.push_back(make_unique<CompareOpcodeHandlerContainer>());
|
handler_containers.push_back(make_unique<CompareOpcodeHandlerContainer>());
|
||||||
handler_containers.push_back(make_unique<StackOpcodeHandlerContainer>());
|
handler_containers.push_back(make_unique<StackOpcodeHandlerContainer>());
|
||||||
handler_containers.push_back(make_unique<BranchOpcodeHandlerContainer>());
|
handler_containers.push_back(make_unique<BranchOpcodeHandlerContainer>());
|
||||||
|
handler_containers.push_back(make_unique<JumpOpcodeHandlerContainer>());
|
||||||
|
|
||||||
init_handlers();
|
init_handlers();
|
||||||
}
|
}
|
||||||
|
@ -48,6 +48,18 @@ namespace emu_6502 {
|
|||||||
return address;
|
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) {
|
uint16_t get_ind_x_address(Machine& machine) {
|
||||||
uint8_t paddress = machine.get_cpu().get_x().get_value() + machine.read_program_byte();
|
uint8_t paddress = machine.get_cpu().get_x().get_value() + machine.read_program_byte();
|
||||||
auto low = machine.get_memory().get_at(paddress);
|
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_address(Machine& machine);
|
||||||
uint8_t get_zpg_x_address(Machine& machine);
|
uint8_t get_zpg_x_address(Machine& machine);
|
||||||
uint8_t get_zpg_y_address(Machine& machine);
|
uint8_t get_zpg_y_address(Machine& machine);
|
||||||
|
|
||||||
uint16_t get_abs_address(Machine& machine);
|
uint16_t get_abs_address(Machine& machine);
|
||||||
uint16_t get_abs_x_address(Machine& machine);
|
uint16_t get_abs_x_address(Machine& machine);
|
||||||
uint16_t get_abs_y_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_x_address(Machine& machine);
|
||||||
uint16_t get_ind_y_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…
x
Reference in New Issue
Block a user