From c9a40be3e2677efbc49ac8d8ed7c76f08e2de9ca Mon Sep 17 00:00:00 2001 From: Anonymus Raccoon Date: Thu, 26 Mar 2020 23:54:10 +0100 Subject: [PATCH] Fixed a missunderstanding of the pbr use --- sources/CPU/AddressingModes.cpp | 72 ++++++++++--------- sources/CPU/CPU.cpp | 13 +++- sources/CPU/CPU.hpp | 2 + .../CPU/Instructions/InternalInstruction.cpp | 20 +++--- sources/Debugger/CPUDebug.cpp | 38 +++++++--- sources/Debugger/CPUDebug.hpp | 10 +-- tests/CPU/testAddressingMode.cpp | 2 +- 7 files changed, 95 insertions(+), 62 deletions(-) diff --git a/sources/CPU/AddressingModes.cpp b/sources/CPU/AddressingModes.cpp index 9b78aa2..0d39b18 100644 --- a/sources/CPU/AddressingModes.cpp +++ b/sources/CPU/AddressingModes.cpp @@ -9,50 +9,54 @@ namespace ComSquare::CPU { uint24_t CPU::_getImmediateAddr8Bits() { - return this->_registers.pac++; + uint24_t ret = this->_registers.pac; + this->_registers.pc++; + return ret; } uint24_t CPU::_getImmediateAddrForA() { - uint24_t effective = this->_registers.pac++; + uint24_t effective = this->_registers.pac; + this->_registers.pc++; if (!this->_registers.p.m) - this->_registers.pac++; + this->_registers.pc++; return effective; } uint24_t CPU::_getImmediateAddrForX() { - uint24_t effective = this->_registers.pac++; + uint24_t effective = this->_registers.pac; + this->_registers.pc++; if (!this->_registers.p.x_b) - this->_registers.pac++; + this->_registers.pc++; return effective; } uint24_t CPU::_getDirectAddr() { - uint8_t addr = this->_bus->read(this->_registers.pac++); + uint8_t addr = this->readPC(); return this->_registers.d + addr; } uint24_t CPU::_getAbsoluteAddr() { uint24_t addr = this->_registers.dbr << 16u; - addr += this->_bus->read(this->_registers.pac++); - addr += this->_bus->read(this->_registers.pac++) << 8u; + addr += this->readPC(); + addr += this->readPC() << 8u; return addr; } uint24_t CPU::_getAbsoluteLongAddr() { - uint24_t addr = this->_bus->read(this->_registers.pac++); - addr += this->_bus->read(this->_registers.pac++) << 8u; - addr += this->_bus->read(this->_registers.pac++) << 16u; + uint24_t addr = this->readPC(); + addr += this->readPC() << 8u; + addr += this->readPC() << 16u; return addr; } uint24_t CPU::_getDirectIndirectIndexedYAddr() { - uint16_t dp = this->_bus->read(this->_registers.pac++) + this->_registers.d; + uint16_t dp = this->readPC() + this->_registers.d; uint24_t base = this->_bus->read(dp); base += this->_bus->read(dp + 1) << 8u; base += this->_registers.dbr << 16u; @@ -63,7 +67,7 @@ namespace ComSquare::CPU uint24_t CPU::_getDirectIndirectIndexedYLongAddr() { - uint16_t dp = this->_bus->read(this->_registers.pac++) + this->_registers.d; + uint16_t dp = this->readPC() + this->_registers.d; uint24_t base = this->_bus->read(dp); base += this->_bus->read(dp + 1) << 8u; base += this->_bus->read(dp + 2) << 16u; @@ -72,7 +76,7 @@ namespace ComSquare::CPU uint24_t CPU::_getDirectIndirectIndexedXAddr() { - uint16_t dp = this->_bus->read(this->_registers.pac++) + this->_registers.d; + uint16_t dp = this->readPC() + this->_registers.d; dp += this->_registers.x; uint24_t base = this->_bus->read(dp); base += this->_bus->read(dp + 1) << 8u; @@ -82,22 +86,22 @@ namespace ComSquare::CPU uint24_t CPU::_getDirectIndexedByXAddr() { - uint16_t dp = this->_bus->read(this->_registers.pac++) + this->_registers.d; + uint16_t dp = this->readPC() + this->_registers.d; dp += this->_registers.x; return dp; } uint24_t CPU::_getDirectIndexedByYAddr() { - uint16_t dp = this->_bus->read(this->_registers.pac++) + this->_registers.d; + uint16_t dp = this->readPC() + this->_registers.d; dp += this->_registers.y; return dp; } uint24_t CPU::_getAbsoluteIndexedByXAddr() { - uint16_t abs = this->_bus->read(this->_registers.pac++); - abs += this->_bus->read(this->_registers.pac++) << 8u; + uint16_t abs = this->readPC(); + abs += this->readPC() << 8u; uint24_t effective = abs + (this->_registers.dbr << 16u); if ((effective & 0x80000000u) == (((effective + this->_registers.x) & 0x80000000u))) this->_hasIndexCrossedPageBoundary = true; @@ -106,8 +110,8 @@ namespace ComSquare::CPU uint24_t CPU::_getAbsoluteIndexedByYAddr() { - uint16_t abs = this->_bus->read(this->_registers.pac++); - abs += this->_bus->read(this->_registers.pac++) << 8u; + uint16_t abs = this->readPC(); + abs += this->readPC() << 8u; uint24_t effective = abs + (this->_registers.dbr << 16u); if ((effective & 0x80000000u) == (((effective + this->_registers.y) & 0x80000000u))) this->_hasIndexCrossedPageBoundary = true; @@ -116,32 +120,32 @@ namespace ComSquare::CPU uint24_t CPU::_getAbsoluteIndexedByXLongAddr() { - uint24_t lng = this->_bus->read(this->_registers.pac++); - lng += this->_bus->read(this->_registers.pac++) << 8u; - lng += this->_bus->read(this->_registers.pac++) << 16u; + uint24_t lng = this->readPC(); + lng += this->readPC() << 8u; + lng += this->readPC() << 16u; return lng + this->_registers.x; } uint24_t CPU::_getProgramCounterRelativeAddr() { uint24_t pc = this->_registers.pac; - int8_t mod = this->_bus->read(this->_registers.pac++); + int8_t mod = this->readPC(); return pc + mod; } uint24_t CPU::_getProgramCounterRelativeLongAddr() { uint24_t pc = this->_registers.pac; - uint8_t val1 = this->_bus->read(this->_registers.pac++); - uint8_t val2 = this->_bus->read(this->_registers.pac++); + uint8_t val1 = this->readPC(); + uint8_t val2 = this->readPC(); int16_t mod = val2 > 0x7F ? (static_cast(val2) * 256 - val1) : (val1 | val2 << 8u); return pc + mod; } uint24_t CPU::_getAbsoluteIndirectAddr() { - uint16_t abs = this->_bus->read(this->_registers.pac++); - abs += this->_bus->read(this->_registers.pac++) << 8u; + uint16_t abs = this->readPC(); + abs += this->readPC() << 8u; uint24_t effective = this->_bus->read(abs); effective += this->_bus->read(abs + 1) << 8u; return effective; @@ -149,8 +153,8 @@ namespace ComSquare::CPU uint24_t CPU::_getAbsoluteIndirectIndexedByXAddr() { - uint24_t abs = this->_bus->read(this->_registers.pac++); - abs += this->_bus->read(this->_registers.pac++) << 8u; + uint24_t abs = this->readPC(); + abs += this->readPC() << 8u; abs += this->_registers.x; uint24_t effective = this->_bus->read(abs); effective += this->_bus->read(abs + 1) << 8u; @@ -159,7 +163,7 @@ namespace ComSquare::CPU uint24_t CPU::_getDirectIndirectAddr() { - uint16_t dp = this->_bus->read(this->_registers.pac++) + this->_registers.d; + uint16_t dp = this->readPC() + this->_registers.d; uint24_t effective = this->_bus->read(dp); effective += this->_bus->read(dp + 1) << 8u; effective += this->_registers.dbr << 16u; @@ -168,7 +172,7 @@ namespace ComSquare::CPU uint24_t CPU::_getDirectIndirectLongAddr() { - uint16_t dp = this->_bus->read(this->_registers.pac++) + this->_registers.d; + uint16_t dp = this->readPC() + this->_registers.d; uint24_t effective = this->_bus->read(dp); effective += this->_bus->read(++dp) << 8u; effective += this->_bus->read(++dp) << 16u; @@ -177,12 +181,12 @@ namespace ComSquare::CPU uint24_t CPU::_getStackRelativeAddr() { - return this->_bus->read(this->_registers.pac++) + this->_registers.s; + return this->readPC() + this->_registers.s; } uint24_t CPU::_getStackRelativeIndirectIndexedYAddr() { - uint24_t base = this->_bus->read(this->_registers.pac++) + this->_registers.s; + uint24_t base = this->readPC() + this->_registers.s; base += this->_registers.dbr << 16u; return base + this->_registers.y; } diff --git a/sources/CPU/CPU.cpp b/sources/CPU/CPU.cpp index 92f3474..879ed39 100644 --- a/sources/CPU/CPU.cpp +++ b/sources/CPU/CPU.cpp @@ -195,12 +195,21 @@ namespace ComSquare::CPU } } + uint8_t CPU::readPC() + { + uint8_t ret = this->_bus->read(this->_registers.pac); + this->_registers.pc++; + return ret; + } + unsigned CPU::update() { unsigned cycles = 0; - for (int i = 0; i < 0xFF; i++) - cycles += this->_executeInstruction(this->_bus->read(this->_registers.pac++)); + for (int i = 0; i < 0xFF; i++) { + cycles += this->_executeInstruction(this->readPC()); + this->_registers.pc++; + } return cycles; } diff --git a/sources/CPU/CPU.hpp b/sources/CPU/CPU.hpp index 8fab4cb..9c32d6c 100644 --- a/sources/CPU/CPU.hpp +++ b/sources/CPU/CPU.hpp @@ -253,6 +253,8 @@ namespace ComSquare::CPU //! @brief Pop 16 bits of data from the stack. uint16_t _pop16(); + //! @brief Return the data at the program bank concatenated with the program counter. It also increment the program counter (the program bank is not incremented on overflows). + uint8_t readPC(); //! @brief Execute a single instruction. //! @return The number of CPU cycles that the instruction took. diff --git a/sources/CPU/Instructions/InternalInstruction.cpp b/sources/CPU/Instructions/InternalInstruction.cpp index c83b690..77112ec 100644 --- a/sources/CPU/Instructions/InternalInstruction.cpp +++ b/sources/CPU/Instructions/InternalInstruction.cpp @@ -259,48 +259,48 @@ namespace ComSquare::CPU int CPU::BCC(uint24_t valueAddr) { if (!this->_registers.p.c) - this->_registers.pac += static_cast(this->_bus->read(valueAddr)); + this->_registers.pc += static_cast(this->_bus->read(valueAddr)); return !this->_registers.p.c; } int CPU::BCS(uint24_t valueAddr) { if (this->_registers.p.c) - this->_registers.pac += static_cast(this->_bus->read(valueAddr)); + this->_registers.pc += static_cast(this->_bus->read(valueAddr)); return this->_registers.p.c; } int CPU::BEQ(uint24_t valueAddr) { if (this->_registers.p.z) - this->_registers.pac += static_cast(this->_bus->read(valueAddr)); + this->_registers.pc += static_cast(this->_bus->read(valueAddr)); return this->_registers.p.z; } int CPU::BNE(uint24_t valueAddr) { if (!this->_registers.p.z) - this->_registers.pac += static_cast(this->_bus->read(valueAddr)); + this->_registers.pc += static_cast(this->_bus->read(valueAddr)); return !this->_registers.p.z; } int CPU::BMI(uint24_t valueAddr) { if (this->_registers.p.n) - this->_registers.pac += static_cast(this->_bus->read(valueAddr)); + this->_registers.pc += static_cast(this->_bus->read(valueAddr)); return this->_registers.p.n; } int CPU::BPL(uint24_t valueAddr) { if (!this->_registers.p.n) - this->_registers.pac += static_cast(this->_bus->read(valueAddr)); + this->_registers.pc += static_cast(this->_bus->read(valueAddr)); return !this->_registers.p.n; } int CPU::BRA(uint24_t valueAddr) { - this->_registers.pac += static_cast(this->_bus->read(valueAddr)); + this->_registers.pc += static_cast(this->_bus->read(valueAddr)); return true; } @@ -309,21 +309,21 @@ namespace ComSquare::CPU unsigned value = this->_bus->read(valueAddr); value += this->_bus->read(valueAddr + 1) << 8u; - this->_registers.pac += static_cast(value); + this->_registers.pc += static_cast(value); return true; } int CPU::BVC(uint24_t valueAddr) { if (!this->_registers.p.v) - this->_registers.pac += static_cast(this->_bus->read(valueAddr)); + this->_registers.pc += static_cast(this->_bus->read(valueAddr)); return !this->_registers.p.v; } int CPU::BVS(uint24_t valueAddr) { if (this->_registers.p.v) - this->_registers.pac += static_cast(this->_bus->read(valueAddr)); + this->_registers.pc += static_cast(this->_bus->read(valueAddr)); return this->_registers.p.v; } diff --git a/sources/Debugger/CPUDebug.cpp b/sources/Debugger/CPUDebug.cpp index 63424da..d362008 100644 --- a/sources/Debugger/CPUDebug.cpp +++ b/sources/Debugger/CPUDebug.cpp @@ -31,10 +31,7 @@ namespace ComSquare::Debugger this->_ui.disasembly->verticalHeader()->hide(); this->_ui.disasembly->horizontalHeader()->hide(); this->_ui.disasembly->horizontalHeader()->setStretchLastSection(true); - -// uint24_t pc = 0x80800; // The first byte of the ROM //TODO make this work for other rom mapping. -// while (pc < 0x80800 + this->_cartridgeHeader.romSize) -// this->_disassembledInstructions.insert(pc, this->_parseInstruction(pc)); + this->disassembledInstructions = this->_disassemble(0x808000, this->_cartridgeHeader.romSize); QMainWindow::connect(this->_ui.actionPause, &QAction::triggered, this, &CPUDebug::pause); QMainWindow::connect(this->_ui.actionStep, &QAction::triggered, this, &CPUDebug::step); @@ -59,7 +56,7 @@ namespace ComSquare::Debugger if (this->_isPaused) return 0xFF; if (this->_isStepping) - return this->_executeInstruction(this->_bus->read(this->_registers.pac++)); + return this->_executeInstruction(this->readPC()); return CPU::update(); } catch (InvalidOpcode &e) { if (!this->_isPaused) @@ -77,7 +74,8 @@ namespace ComSquare::Debugger this->_isStepping = false; this->_isPaused = true; } - this->_ui.logger->append((this->_parseInstruction(this->_registers.pac - 1).toString() + " - " + Utility::to_hex(opcode)).c_str()); + uint24_t pc = (this->_registers.pbr << 16u) | (this->_registers.pc - 1u); + this->_ui.logger->append((this->_parseInstruction(pc).toString() + " - " + Utility::to_hex(opcode)).c_str()); unsigned ret = CPU::_executeInstruction(opcode); this->_updateRegistersPanel(); return ret; @@ -137,6 +135,19 @@ namespace ComSquare::Debugger return str; } + std::vector CPUDebug::_disassemble(uint24_t pc, uint24_t length) + { + std::vector map; + uint24_t endAddr = pc + length; + + while (pc < endAddr) { + DisassembledInstruction instruction = this->_parseInstruction(pc); + map.push_back(instruction); + pc += instruction.size; + } + return map; + } + void CPUDebug::clearHistory() { this->_ui.logger->clear(); @@ -220,7 +231,7 @@ namespace ComSquare::Debugger uint24_t opcode = this->_bus->read(pc++, true); Instruction instruction = this->_instructions[opcode]; std::string argument = this->_getInstructionParameter(instruction, pc); - return DisassembledInstruction(instruction, argument, opcode); + return DisassembledInstruction(instruction, pc, argument, opcode); } std::string CPUDebug::_getInstructionParameter(Instruction &instruction, uint24_t pc) @@ -260,8 +271,8 @@ namespace ComSquare::Debugger this->_window->activateWindow(); } - DisassembledInstruction::DisassembledInstruction(const CPU::Instruction &instruction, std::string arg, uint8_t op) - : CPU::Instruction(instruction), argument(std::move(arg)), opcode(op) {} + DisassembledInstruction::DisassembledInstruction(const CPU::Instruction &instruction, uint24_t addr, std::string arg, uint8_t op) + : CPU::Instruction(instruction), address(addr), argument(std::move(arg)), opcode(op) {} std::string DisassembledInstruction::toString() { @@ -278,12 +289,17 @@ int DisassemblyModel::columnCount(const QModelIndex &) const int DisassemblyModel::rowCount(const QModelIndex &) const { - return 5; + return this->_cpu.disassembledInstructions.size(); } -QVariant DisassemblyModel::data(const QModelIndex &, int role) const +QVariant DisassemblyModel::data(const QModelIndex &index, int role) const { if (role != Qt::DisplayRole) return QVariant(); + ComSquare::Debugger::DisassembledInstruction instruction = this->_cpu.disassembledInstructions[index.row()]; + switch (index.column()) { + case 0: + return QString(ComSquare::Utility::to_hex(instruction.address).c_str()); + } return QString(); } \ No newline at end of file diff --git a/sources/Debugger/CPUDebug.hpp b/sources/Debugger/CPUDebug.hpp index 3137fa8..b9474ad 100644 --- a/sources/Debugger/CPUDebug.hpp +++ b/sources/Debugger/CPUDebug.hpp @@ -39,10 +39,11 @@ public: namespace ComSquare::Debugger { struct DisassembledInstruction : public CPU::Instruction { + uint24_t address; std::string argument; uint8_t opcode; - DisassembledInstruction(const CPU::Instruction &instruction, std::string argument, uint8_t opcode); + DisassembledInstruction(const CPU::Instruction &instruction, uint24_t address, std::string argument, uint8_t opcode); DisassembledInstruction(const DisassembledInstruction &) = default; DisassembledInstruction &operator=(const DisassembledInstruction &) = default; ~DisassembledInstruction() = default; @@ -59,8 +60,6 @@ namespace ComSquare::Debugger Ui::CPUView _ui; //! @brief The disassembly viewer's model. DisassemblyModel _model; - //! @brief The list of disassembled instructions to show on the debugger. - std::map _disassembledInstructions; //! @brief If this is set to true, the execution of the CPU will be paused. bool _isPaused = true; //! @brief If this is set to true, the CPU will execute one instruction and pause itself. @@ -75,6 +74,8 @@ namespace ComSquare::Debugger std::string _getInstructionParameter(ComSquare::CPU::Instruction &instruction, uint24_t pc); //! @brief Get a printable string representing the flags. std::string _getFlagsString(); + //! @brief Disassemble part of the memory (using the bus) and parse it to a map of address and disassembled instruction. + std::vector _disassemble(uint24_t startAddr, uint24_t size); //! @brief Update the register's panel (accumulator, stack pointer...) void _updateRegistersPanel(); @@ -104,7 +105,8 @@ namespace ComSquare::Debugger void clearHistory(); //! @brief Called when the window is closed. Turn off the debugger and revert to a basic CPU. void disableDebugger(); - public: + //! @brief The list of disassembled instructions to show on the debugger. + std::vector disassembledInstructions; //! @brief Update the UI when reseting the CPU. int RESB(uint24_t) override; //! @brief Convert a basic CPU to a debugging CPU. diff --git a/tests/CPU/testAddressingMode.cpp b/tests/CPU/testAddressingMode.cpp index 0ae047f..485366e 100644 --- a/tests/CPU/testAddressingMode.cpp +++ b/tests/CPU/testAddressingMode.cpp @@ -42,7 +42,7 @@ Test(AddrMode, ImmediateBankChange) snes.cpu->_registers.pac = 0x00FFFF; snes.cpu->_registers.p.m = true; cr_assert_eq(snes.cpu->_getImmediateAddrForA(), 0x00FFFF); - cr_assert_eq(snes.cpu->_registers.pac, 0x010000); + cr_assert_eq(snes.cpu->_registers.pac, 0x000000); } Test(AddrMode, Direct)