mirror of
https://github.com/zoriya/ComSquare.git
synced 2026-06-03 10:26:36 +00:00
Implementing the COP instruction
This commit is contained in:
@@ -201,6 +201,8 @@ namespace ComSquare::CPU
|
||||
switch (opcode) {
|
||||
case Instructions::BRK: this->BRK(); return 7 + !this->_isEmulationMode;
|
||||
|
||||
case Instructions::COP: this->COP(); return 7 + !this->_isEmulationMode;
|
||||
|
||||
case Instructions::RTI: this->RTI(); return 6 + !this->_isEmulationMode;
|
||||
|
||||
case Instructions::ADC_IM: this->ADC(this->_getImmediateAddr()); return 2 + !this->_registers.p.m;
|
||||
|
||||
@@ -186,6 +186,7 @@ namespace ComSquare::CPU
|
||||
enum Instructions
|
||||
{
|
||||
BRK = 0x00,
|
||||
COP = 0x02,
|
||||
RTI = 0x40,
|
||||
|
||||
ADC_DPXi = 0x61,
|
||||
@@ -365,6 +366,8 @@ namespace ComSquare::CPU
|
||||
|
||||
//! @brief Break instruction - Causes a software break. The PC is loaded from a vector table.
|
||||
void BRK();
|
||||
//! @brief Co-Processor Enable instruction - Causes a software break. The PC is loaded from a vector table.
|
||||
void COP();
|
||||
//! @brief Return from Interrupt - Used to return from a interrupt handler.
|
||||
void RTI();
|
||||
//! @brief Add with carry - Adds operand to the Accumulator; adds an additional 1 if carry is set.
|
||||
|
||||
@@ -43,6 +43,28 @@ namespace ComSquare::CPU
|
||||
}
|
||||
}
|
||||
|
||||
void CPU::COP()
|
||||
{
|
||||
if (this->_isEmulationMode) {
|
||||
this->_registers.pc += 2;
|
||||
this->_push(this->_registers.pc);
|
||||
this->_push(this->_registers.p.flags);
|
||||
this->_registers.p.i = true;
|
||||
this->_registers.p.d = false;
|
||||
this->_registers.pc = this->_cartridgeHeader.emulationInterrupts.cop;
|
||||
|
||||
} else {
|
||||
this->_push(this->_registers.pbr);
|
||||
this->_registers.pc += 2;
|
||||
this->_push(this->_registers.pc);
|
||||
this->_push(this->_registers.p.flags);
|
||||
this->_registers.p.i = true;
|
||||
this->_registers.p.d = false;
|
||||
this->_registers.pbr = 0x0;
|
||||
this->_registers.pc = this->_cartridgeHeader.nativeInterrupts.cop;
|
||||
}
|
||||
}
|
||||
|
||||
void CPU::RTI()
|
||||
{
|
||||
this->_registers.p.flags = this->_pop();
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
|
||||
#include "CPUDebug.hpp"
|
||||
#include "../Utility/Utility.hpp"
|
||||
#include "../Exceptions/InvalidOpcode.hpp"
|
||||
|
||||
using namespace ComSquare::CPU;
|
||||
|
||||
@@ -24,14 +25,20 @@ namespace ComSquare::Debugger
|
||||
|
||||
unsigned CPUDebug::update()
|
||||
{
|
||||
if (!this->isVisible()) {
|
||||
this->_snes.disableCPUDebugging();
|
||||
return 0;
|
||||
}
|
||||
try {
|
||||
if (!this->isVisible()) {
|
||||
this->_snes.disableCPUDebugging();
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (this->_isPaused)
|
||||
if (this->_isPaused)
|
||||
return 0xFF;
|
||||
return CPU::update();
|
||||
} catch (InvalidOpcode &e) {
|
||||
this->pause();
|
||||
this->_ui.logger->append(e.what());
|
||||
return 0xFF;
|
||||
return CPU::update();
|
||||
}
|
||||
}
|
||||
|
||||
unsigned CPUDebug::_executeInstruction(uint8_t opcode)
|
||||
@@ -106,6 +113,8 @@ namespace ComSquare::Debugger
|
||||
switch (opcode) {
|
||||
case Instructions::BRK: return "BRK";
|
||||
|
||||
case Instructions::COP: return "COP";
|
||||
|
||||
case Instructions::RTI: return "RTI";
|
||||
|
||||
case Instructions::ADC_IM: return "ADC";
|
||||
|
||||
@@ -49,4 +49,45 @@ Test(CPU_native, BRK)
|
||||
cr_assert_eq(data, 0x158u, "The program counter should be incremented by two and pushed on the stack but it was 0x%X (expected 0x158).", data);
|
||||
data = pair.second.cpu->_pop();
|
||||
cr_assert_eq(data, 0x15, "The program bank register should be pushed on the stack but it was 0x%X (expected 0x15).", data);
|
||||
}
|
||||
|
||||
Test(CPU_emulated, COP)
|
||||
{
|
||||
auto pair = Init();
|
||||
pair.second.cpu->_isEmulationMode = true;
|
||||
pair.second.cartridge->header.emulationInterrupts.cop = 0x123u;
|
||||
pair.second.cpu->_registers.p.flags = 0x0F;
|
||||
pair.second.cpu->_registers.pc = 0x156u;
|
||||
pair.second.cpu->_registers.pbr = 0x15;
|
||||
pair.second.cpu->COP();
|
||||
cr_assert_eq(pair.second.cpu->_registers.pc, 0x123u, "The program counter should be 0x123u but it was 0x%X", pair.second.cpu->_registers.pc);
|
||||
cr_assert_eq(pair.second.cpu->_registers.pbr, 0x15, "The PBR should be 0x15 but it was 0x%X", pair.second.cpu->_registers.pbr);
|
||||
cr_assert_eq(pair.second.cpu->_registers.p.d, false, "The decimal flag should not be set.");
|
||||
cr_assert_eq(pair.second.cpu->_registers.p.i, true, "The Interrupt disable flag should be set.");
|
||||
cr_assert_eq(pair.second.cpu->_registers.p.x_b, false, "The break flag should not be set.");
|
||||
int data = pair.second.cpu->_pop();
|
||||
cr_assert_eq(data, 0x0F, "The Status Registers should be pushed into the stack with the value 0x0F but it was 0x%X (expected 0xF1).", data);
|
||||
data = pair.second.cpu->_pop16();
|
||||
cr_assert_eq(data, 0x158u, "The program counter should be incremented by two and pushed on the stack but it was 0x%X (expected 0x158).", data);
|
||||
}
|
||||
|
||||
Test(CPU_native, COP)
|
||||
{
|
||||
auto pair = Init();
|
||||
pair.second.cpu->_isEmulationMode = false;
|
||||
pair.second.cartridge->header.nativeInterrupts.cop = 0x123u;
|
||||
pair.second.cpu->_registers.p.flags = 0xF1;
|
||||
pair.second.cpu->_registers.pc = 0x156u;
|
||||
pair.second.cpu->_registers.pbr = 0x15;
|
||||
pair.second.cpu->COP();
|
||||
cr_assert_eq(pair.second.cpu->_registers.pc, 0x123u, "The program counter should be 0x123u but it was 0x%X", pair.second.cpu->_registers.pc);
|
||||
cr_assert_eq(pair.second.cpu->_registers.pbr, 0x0, "The PBR should be 0x0 but it was 0x%X", pair.second.cpu->_registers.pbr);
|
||||
cr_assert_eq(pair.second.cpu->_registers.p.d, false, "The decimal flag should not be set.");
|
||||
cr_assert_eq(pair.second.cpu->_registers.p.i, true, "The Interrupt disable flag should be set.");
|
||||
int data = pair.second.cpu->_pop();
|
||||
cr_assert_eq(data, 0xF1, "The Status Registers should be pushed into the stack with the value 0xF1 but it was 0x%X (expected 0xF1).", data);
|
||||
data = pair.second.cpu->_pop16();
|
||||
cr_assert_eq(data, 0x158u, "The program counter should be incremented by two and pushed on the stack but it was 0x%X (expected 0x158).", data);
|
||||
data = pair.second.cpu->_pop();
|
||||
cr_assert_eq(data, 0x15, "The program bank register should be pushed on the stack but it was 0x%X (expected 0x15).", data);
|
||||
}
|
||||
Reference in New Issue
Block a user