From 519f0320acfd168144871b95bdfc8ed08cba2dec Mon Sep 17 00:00:00 2001 From: scawful Date: Sun, 10 Dec 2023 02:14:30 -0500 Subject: [PATCH] Add WriteLong to Memory, CPU --- src/app/emu/cpu/cpu.cc | 57 ++++++++++++++++++++++-- src/app/emu/cpu/cpu.h | 8 +++- src/app/emu/cpu/internal/addressing.cc | 2 +- src/app/emu/cpu/internal/instructions.cc | 6 ++- src/app/emu/memory/memory.h | 13 ++++-- src/app/emu/memory/mock_memory.h | 6 ++- 6 files changed, 78 insertions(+), 14 deletions(-) diff --git a/src/app/emu/cpu/cpu.cc b/src/app/emu/cpu/cpu.cc index 62afea58..78ea134e 100644 --- a/src/app/emu/cpu/cpu.cc +++ b/src/app/emu/cpu/cpu.cc @@ -806,6 +806,7 @@ void CPU::ExecuteInstruction(uint8_t opcode) { case 0x20: // JSR Absolute { operand = Absolute(AccessType::Control); + PB = (operand >> 16); JSR(operand); break; } @@ -904,7 +905,7 @@ void CPU::ExecuteInstruction(uint8_t opcode) { case 0xBD: // LDA Absolute Indexed, X { operand = AbsoluteIndexedX(); - LDA(operand); + LDA(operand, false, false, true); break; } case 0xBF: // LDA Absolute Long Indexed, X @@ -1321,9 +1322,11 @@ void CPU::ExecuteInstruction(uint8_t opcode) { STA(operand); break; case 0x97: // STA DP Indirect Long Indexed, Y + { operand = DirectPageIndirectLongIndexedY(); STA(operand); break; + } case 0x99: // STA Absolute Indexed, Y operand = AbsoluteIndexedY(); STA(operand); @@ -1510,7 +1513,8 @@ void CPU::LogInstructions(uint16_t PC, uint8_t opcode, uint16_t operand, << "$" << std::uppercase << std::setw(2) << std::setfill('0') << static_cast(PB) << ":" << std::hex << PC; std::cout << " \033[1;32m" - << ": 0x" << std::hex << static_cast(opcode) << " "; + << ": 0x" << std::hex << std::uppercase << std::setw(2) + << std::setfill('0') << static_cast(opcode) << " "; std::cout << " \033[1;35m" << opcode_to_mnemonic.at(opcode) << " " << "\033[0m"; @@ -1526,7 +1530,53 @@ void CPU::LogInstructions(uint16_t PC, uint8_t opcode, uint16_t operand, std::cout << std::hex << std::setw(4) << std::setfill('0') << static_cast(operand); } + + bool x_indexing, y_indexing; + auto x_indexed_instruction_opcodes = {0x15, 0x16, 0x17, 0x55, 0x56, + 0x57, 0xD5, 0xD6, 0xD7, 0xF5, + 0xF6, 0xF7, 0xBD}; + auto y_indexed_instruction_opcodes = {0x19, 0x97, 0x1D, 0x59, 0x5D, 0x99, + 0x9D, 0xB9, 0xD9, 0xDD, 0xF9, 0xFD}; + if (std::find(x_indexed_instruction_opcodes.begin(), + x_indexed_instruction_opcodes.end(), + opcode) != x_indexed_instruction_opcodes.end()) { + x_indexing = true; + } else { + x_indexing = false; + } + if (std::find(y_indexed_instruction_opcodes.begin(), + y_indexed_instruction_opcodes.end(), + opcode) != y_indexed_instruction_opcodes.end()) { + y_indexing = true; + } else { + y_indexing = false; + } + + if (x_indexing) { + std::cout << ", X"; + } + + if (y_indexing) { + std::cout << ", Y"; + } } + + // Log the registers and flags. + std::cout << std::right; + std::cout << "\033[1;33m" + << " A:" << std::hex << std::setw(2) << std::setfill('0') + << static_cast(A); + std::cout << " X:" << std::hex << std::setw(2) << std::setfill('0') + << static_cast(X); + std::cout << " Y:" << std::hex << std::setw(2) << std::setfill('0') + << static_cast(Y); + std::cout << " S:" << std::hex << std::setw(2) << std::setfill('0') + << static_cast(status); + std::cout << " DB:" << std::hex << std::setw(2) << std::setfill('0') + << static_cast(DB); + std::cout << " D:" << std::hex << std::setw(2) << std::setfill('0') + << static_cast(D); + std::cout << std::endl; } } @@ -1548,7 +1598,6 @@ uint8_t CPU::GetInstructionLength(uint8_t opcode) { case 0xFC: // JSR Absolute Indexed Indirect case 0xDC: // JMP Absolute Indirect Long case 0x6B: // RTL - case 0x82: // BRL Relative Long PC = next_pc_; return 0; @@ -1559,7 +1608,7 @@ uint8_t CPU::GetInstructionLength(uint8_t opcode) { case 0x60: // RTS PC = last_call_frame_; - return 0; + return 3; // Branch Instructions (BCC, BCS, BNE, BEQ, etc.) case 0x90: // BCC near diff --git a/src/app/emu/cpu/cpu.h b/src/app/emu/cpu/cpu.h index d6019512..3c410de2 100644 --- a/src/app/emu/cpu/cpu.h +++ b/src/app/emu/cpu/cpu.h @@ -160,7 +160,7 @@ class CPU : public Memory, public Loggable, public core::ExperimentFlags { // Low: First operand byte // // LDA addr - uint16_t Absolute(AccessType access_type = AccessType::Data); + uint32_t Absolute(AccessType access_type = AccessType::Data); // Effective Address: // The Data Bank Register is concatened with the 16-bit operand @@ -342,6 +342,9 @@ class CPU : public Memory, public Loggable, public core::ExperimentFlags { void WriteWord(uint32_t address, uint16_t value) override { memory.WriteWord(address, value); } + void WriteLong(uint32_t address, uint32_t value) { + memory.WriteLong(address, value); + } uint8_t FetchByte() { uint32_t address = (PB << 16) | PC + 1; @@ -498,7 +501,8 @@ class CPU : public Memory, public Loggable, public core::ExperimentFlags { void JSL(uint32_t address); // LDA: Load accumulator - void LDA(uint16_t address, bool immediate = false, bool direct_page = false); + void LDA(uint16_t address, bool immediate = false, bool direct_page = false, + bool data_bank = false); // LDX: Load X register void LDX(uint16_t address, bool immediate = false); diff --git a/src/app/emu/cpu/internal/addressing.cc b/src/app/emu/cpu/internal/addressing.cc index b8e2fa51..685246ed 100644 --- a/src/app/emu/cpu/internal/addressing.cc +++ b/src/app/emu/cpu/internal/addressing.cc @@ -4,7 +4,7 @@ namespace yaze { namespace app { namespace emu { -uint16_t CPU::Absolute(CPU::AccessType access_type) { +uint32_t CPU::Absolute(CPU::AccessType access_type) { auto operand = FetchWord(); uint32_t bank = (access_type == CPU::AccessType::Data) ? (DB << 16) : (PB << 16); diff --git a/src/app/emu/cpu/internal/instructions.cc b/src/app/emu/cpu/internal/instructions.cc index ee41748d..a06ff7bd 100644 --- a/src/app/emu/cpu/internal/instructions.cc +++ b/src/app/emu/cpu/internal/instructions.cc @@ -361,7 +361,7 @@ void CPU::JSL(uint32_t address) { next_pc_ = address; // Set program counter to the new address } -void CPU::LDA(uint16_t address, bool isImmediate, bool direct_page) { +void CPU::LDA(uint16_t address, bool isImmediate, bool direct_page, bool data_bank) { uint8_t bank = PB; if (direct_page) { bank = 0; @@ -628,7 +628,9 @@ void CPU::RTL() { PB = memory.PopByte(); } -void CPU::RTS() { last_call_frame_ = memory.PopWord(); } +void CPU::RTS() { + last_call_frame_ = memory.PopWord(); +} void CPU::SBC(uint32_t value, bool isImmediate) { uint16_t operand; diff --git a/src/app/emu/memory/memory.h b/src/app/emu/memory/memory.h index dc0a7ba8..ed91a36f 100644 --- a/src/app/emu/memory/memory.h +++ b/src/app/emu/memory/memory.h @@ -117,6 +117,7 @@ class Memory { virtual void WriteByte(uint32_t address, uint8_t value) = 0; virtual void WriteWord(uint32_t address, uint16_t value) = 0; + virtual void WriteLong(uint32_t address, uint32_t value) = 0; virtual void PushByte(uint8_t value) = 0; virtual uint8_t PopByte() = 0; @@ -263,6 +264,12 @@ class MemoryImpl : public Memory, public Loggable { memory_.at(mapped_address) = value & 0xFF; memory_.at(mapped_address + 1) = (value >> 8) & 0xFF; } + void WriteLong(uint32_t address, uint32_t value) override { + uint32_t mapped_address = GetMappedAddress(address); + memory_.at(mapped_address) = value & 0xFF; + memory_.at(mapped_address + 1) = (value >> 8) & 0xFF; + memory_.at(mapped_address + 2) = (value >> 16) & 0xFF; + } // Stack operations void PushByte(uint8_t value) override { @@ -347,11 +354,11 @@ class MemoryImpl : public Memory, public Loggable { } if (bank <= 0x3F) { - if (offset <= 0x1FFF) { + if (address <= 0x1FFF) { return (0x7E << 16) + offset; // Shadow RAM - } else if (offset <= 0x5FFF) { + } else if (address <= 0x5FFF) { return (bank << 16) + (offset - 0x2000) + 0x2000; // Hardware Registers - } else if (offset <= 0x7FFF) { + } else if (address <= 0x7FFF) { return offset - 0x6000 + 0x6000; // Expansion RAM } else { // Return lorom mapping diff --git a/src/app/emu/memory/mock_memory.h b/src/app/emu/memory/mock_memory.h index 30b1feb1..e1a43d69 100644 --- a/src/app/emu/memory/mock_memory.h +++ b/src/app/emu/memory/mock_memory.h @@ -34,6 +34,7 @@ class MockMemory : public Memory { MOCK_METHOD2(WriteByte, void(uint32_t address, uint8_t value)); MOCK_METHOD2(WriteWord, void(uint32_t address, uint16_t value)); + MOCK_METHOD2(WriteLong, void(uint32_t address, uint32_t value)); MOCK_METHOD1(PushByte, void(uint8_t value)); MOCK_METHOD0(PopByte, uint8_t()); @@ -173,8 +174,9 @@ class MockMemory : public Memory { return value; }); ON_CALL(*this, SP()).WillByDefault([this]() { return SP_; }); - ON_CALL(*this, SetSP(::testing::_)) - .WillByDefault([this](uint16_t value) { SP_ = value; }); + ON_CALL(*this, SetSP(::testing::_)).WillByDefault([this](uint16_t value) { + SP_ = value; + }); ON_CALL(*this, ClearMemory()).WillByDefault([this]() { memory_.resize(64000, 0x00); });