srctree

Mikael Larsson parent 205e7374 e0b71b1e 75f15daa
Merge pull request #32 from robinlinden/empty-stack

Change sp to point to the next empty position on the stack
core/src/mos6502.cpp added: 40, removed: 42, total 0
@@ -61,26 +61,33 @@ constexpr uint16_t high_byte(uint16_t word) {
 
namespace n_e_s::core {
 
Mos6502::Ram::Ram(IMmu *mmu) : mmu_(mmu) {}
Mos6502::Stack::Stack(Registers *registers, IMmu *mmu)
: registers_(registers), mmu_(mmu) {}
 
uint8_t Mos6502::Ram::read_byte(uint8_t addr) const {
return mmu_->read_byte(ram_offset_ + addr);
uint8_t Mos6502::Stack::pop_byte() {
return mmu_->read_byte(ram_offset_ + ++registers_->sp);
}
 
uint16_t Mos6502::Ram::read_word(uint8_t addr) const {
return mmu_->read_word(ram_offset_ + addr);
uint16_t Mos6502::Stack::pop_word() {
const uint16_t ret = mmu_->read_word(ram_offset_ + ++registers_->sp);
++registers_->sp;
return ret;
}
 
void Mos6502::Ram::write_byte(uint8_t addr, uint8_t byte) {
mmu_->write_byte(ram_offset_ + addr, byte);
void Mos6502::Stack::push_byte(uint8_t byte) {
mmu_->write_byte(ram_offset_ + registers_->sp--, byte);
}
 
void Mos6502::Ram::write_word(uint8_t addr, uint16_t word) {
mmu_->write_word(ram_offset_ + addr, word);
void Mos6502::Stack::push_word(uint16_t word) {
mmu_->write_word(ram_offset_ + --registers_->sp, word);
--registers_->sp;
}
 
Mos6502::Mos6502(Registers *const registers, IMmu *const mmu)
: registers_(registers), mmu_(mmu), ram_(mmu_), pipeline_() {}
: registers_(registers),
mmu_(mmu),
stack_(registers_, mmu_),
pipeline_() {}
 
// Most instruction timings are from https://robinli.eu/f/6502_cpu.txt
void Mos6502::execute() {
@@ -95,11 +102,10 @@ void Mos6502::execute() {
/* Do nothing. */
});
pipeline_.push([=]() {
registers_->sp -= 2;
ram_.write_word(registers_->sp, registers_->pc);
stack_.push_word(registers_->pc);
});
pipeline_.push([=]() {
ram_.write_byte(--registers_->sp, registers_->p | B_FLAG);
stack_.push_byte(registers_->p | B_FLAG);
});
pipeline_.push([=]() { ++registers_->pc; });
pipeline_.push(
@@ -108,7 +114,7 @@ void Mos6502::execute() {
case PHP:
pipeline_.push([=]() { ++registers_->pc; });
pipeline_.push([=]() {
ram_.write_byte(--registers_->sp, registers_->p);
stack_.push_byte(registers_->p);
});
return;
case BPL:
@@ -137,7 +143,7 @@ void Mos6502::execute() {
case PHA:
pipeline_.push([=]() { ++registers_->pc; });
pipeline_.push([=]() {
ram_.write_byte(--registers_->sp, registers_->a);
stack_.push_byte(registers_->a);
});
return;
case JMP:
 
core/src/mos6502.h added: 40, removed: 42, total 0
@@ -24,24 +24,26 @@ private:
Registers *const registers_;
IMmu *const mmu_;
 
// Exactly like the mmu except that the address is offset to be inside
// the ram bank.
class Ram {
// Wraps the mmu to provide more convenient access to the stack.
// All functions have side effects on the stack pointer, so it'll always
// point to the next available address in the mmu's stack area.
class Stack {
public:
Ram(IMmu *mmu);
Stack(Registers *registers, IMmu *mmu);
 
uint8_t read_byte(uint8_t addr) const;
uint16_t read_word(uint8_t addr) const;
uint8_t pop_byte();
uint16_t pop_word();
 
void write_byte(uint8_t addr, uint8_t byte);
void write_word(uint8_t addr, uint16_t word);
void push_byte(uint8_t byte);
void push_word(uint16_t word);
 
private:
Registers *const registers_;
IMmu *const mmu_;
const uint16_t ram_offset_{0x0100};
};
 
Ram ram_;
Stack stack_;
 
// Holds the atoms staged to be executed.
std::queue<std::function<void()>> pipeline_;
 
core/test/src/test_cpu.cpp added: 40, removed: 42, total 0
@@ -127,12 +127,10 @@ TEST_F(CpuTest, brk) {
stage_instruction(BRK);
expected.pc = 0xDEAD;
 
const uint8_t pc_size = 2;
const uint8_t expected_pc_stack_addr = expected.sp - pc_size;
const uint8_t p_size = 1;
const uint8_t expected_p_stack_addr = expected_pc_stack_addr - p_size;
const uint8_t expected_pc_stack_addr = expected.sp - 1;
const uint8_t expected_p_stack_addr = expected_pc_stack_addr - 1;
 
expected.sp -= pc_size + p_size;
expected.sp -= 2 + 1; // 1 word and 1 byte
 
ON_CALL(mmu, read_word(kBrkAddress)).WillByDefault(Return(0xDEAD));
 
@@ -156,11 +154,7 @@ TEST_F(CpuTest, php) {
expected.p = registers.p;
++expected.pc;
 
const uint8_t p_size = 1;
const uint8_t expected_stack_addr = registers.sp - p_size;
 
EXPECT_CALL(mmu,
write_byte(kStackOffset + expected_stack_addr, registers.p));
EXPECT_CALL(mmu, write_byte(kStackOffset + registers.sp, registers.p));
 
step_execution(3);
EXPECT_EQ(expected, registers);
@@ -294,11 +288,7 @@ TEST_F(CpuTest, pha) {
registers.sp = 0x05;
registers.a = 0x84;
 
const uint8_t a_size = 1;
const uint8_t expected_stack_addr = registers.sp - a_size;
 
EXPECT_CALL(mmu,
write_byte(kStackOffset + expected_stack_addr, registers.a));
EXPECT_CALL(mmu, write_byte(kStackOffset + registers.sp, registers.a));
 
step_execution(3);