Implementing the COP instruction

This commit is contained in:
AnonymusRaccoon
2020-02-19 18:44:45 +01:00
parent 27f755e315
commit 52b5a6ba23
5 changed files with 83 additions and 6 deletions
+2
View File
@@ -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;
+3
View File
@@ -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.
+22
View File
@@ -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();
+15 -6
View File
@@ -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";
+41
View File
@@ -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);
}