From 4da96894ae400d4c19286660f312b103f079bb6a Mon Sep 17 00:00:00 2001
From: Anonymus Raccoon
Date: Tue, 25 Feb 2020 23:05:15 +0100
Subject: [PATCH] Implementing the XCE instruction
---
sources/CPU/CPU.cpp | 2 ++
sources/CPU/CPU.hpp | 6 +++-
.../CPU/Instructions/InternalInstruction.cpp | 14 ++++++++
sources/Debugger/CPUDebug.cpp | 2 ++
tests/CPU/testInternal.cpp | 33 +++++++++++++++++++
5 files changed, 56 insertions(+), 1 deletion(-)
diff --git a/sources/CPU/CPU.cpp b/sources/CPU/CPU.cpp
index 81eb58e..718066a 100644
--- a/sources/CPU/CPU.cpp
+++ b/sources/CPU/CPU.cpp
@@ -326,6 +326,8 @@ namespace ComSquare::CPU
case Instructions::AND_SR: this->AND(this->_getStackRelativeAddr()); return 4 + !this->_registers.p.m;
case Instructions::AND_SRYi: this->AND(this->_getStackRelativeIndirectIndexedYAddr()); return 7 + !this->_registers.p.m;
+ case Instructions::XCE: this->XCE(); return 2;
+
default:
throw InvalidOpcode("CPU", opcode);
}
diff --git a/sources/CPU/CPU.hpp b/sources/CPU/CPU.hpp
index 8015292..ddd184a 100644
--- a/sources/CPU/CPU.hpp
+++ b/sources/CPU/CPU.hpp
@@ -308,7 +308,9 @@ namespace ComSquare::CPU
AND_DPYi = 0x31,
AND_DPYil = 0x37,
AND_SR = 0x23,
- AND_SRYi = 0x33
+ AND_SRYi = 0x33,
+
+ XCE = 0xFB
};
//! @brief The main CPU
@@ -455,6 +457,8 @@ namespace ComSquare::CPU
void SED();
//! @brief Set the Interrupt Disable flag.
void SEI();
+ //! @brief Exchange Carry and Emulation Flags
+ void XCE();
//! @brief And accumulator with memory.
void AND(uint24_t valueAddr);
public:
diff --git a/sources/CPU/Instructions/InternalInstruction.cpp b/sources/CPU/Instructions/InternalInstruction.cpp
index c5891c3..b1ed4bc 100644
--- a/sources/CPU/Instructions/InternalInstruction.cpp
+++ b/sources/CPU/Instructions/InternalInstruction.cpp
@@ -150,4 +150,18 @@ namespace ComSquare::CPU
this->_registers.p.z = this->_registers.y == 0;
this->_registers.p.n = this->_registers.y & 0x8000u;
}
+
+ void CPU::XCE()
+ {
+ bool oldCarry = this->_registers.p.c;
+ this->_registers.p.c = this->_isEmulationMode;
+ this->_isEmulationMode = oldCarry;
+
+ if (!this->_isEmulationMode) {
+ this->_registers.p.m = true;
+ this->_registers.p.x_b = true;
+ this->_registers.xh = 0;
+ this->_registers.yh = 0;
+ }
+ }
}
\ No newline at end of file
diff --git a/sources/Debugger/CPUDebug.cpp b/sources/Debugger/CPUDebug.cpp
index 0441109..9b4f02f 100644
--- a/sources/Debugger/CPUDebug.cpp
+++ b/sources/Debugger/CPUDebug.cpp
@@ -240,6 +240,8 @@ namespace ComSquare::Debugger
case Instructions::AND_SR: return "AND";
case Instructions::AND_SRYi: return "AND";
+ case Instructions::XCE: return "XCE";
+
default: return "Unknown";
}
}
diff --git a/tests/CPU/testInternal.cpp b/tests/CPU/testInternal.cpp
index c0b1538..87bce8e 100644
--- a/tests/CPU/testInternal.cpp
+++ b/tests/CPU/testInternal.cpp
@@ -461,4 +461,37 @@ Test(SED, set)
pair.second.cpu->_registers.p.flags = 0x00;
pair.second.cpu->SED();
cr_assert_eq(pair.second.cpu->_registers.p.d, true, "The decimal flag should be set");
+}
+
+Test(XCE, enableEmulation)
+{
+ auto pair = Init();
+ pair.second.cpu->_isEmulationMode = false;
+ pair.second.cpu->_registers.p.flags = 0;
+ pair.second.cpu->_registers.p.c = true;
+ pair.second.cpu->_registers.xh = 0xFF;
+ pair.second.cpu->_registers.yh = 0xFF;
+ pair.second.cpu->XCE();
+ cr_assert_eq(pair.second.cpu->_isEmulationMode, true, "The e flag should be set");
+ cr_assert_eq(pair.second.cpu->_registers.p.c, false, "The carry flag should not be set");
+ cr_assert_eq(pair.second.cpu->_registers.p.m, false, "The memory width flag should be untouched (unset)");
+ cr_assert_eq(pair.second.cpu->_registers.p.x_b, false, "The index width flag should be untouched (unset)");
+ cr_assert_eq(pair.second.cpu->_registers.xh, 0xFF, "The high byte of the x index flag should be untouched (0xFF)");
+ cr_assert_eq(pair.second.cpu->_registers.yh, 0xFF, "The high byte of the y index flag should be untouched (0xFF)");
+}
+
+Test(XCE, enableNative)
+{
+ auto pair = Init();
+ pair.second.cpu->_isEmulationMode = true;
+ pair.second.cpu->_registers.p.flags = 0;
+ pair.second.cpu->_registers.xh = 0xFF;
+ pair.second.cpu->_registers.yh = 0xFF;
+ pair.second.cpu->XCE();
+ cr_assert_eq(pair.second.cpu->_isEmulationMode, false, "The e flag should be not set");
+ cr_assert_eq(pair.second.cpu->_registers.p.c, true, "The carry flag should be set");
+ cr_assert_eq(pair.second.cpu->_registers.p.m, true, "The memory width flag should be set");
+ cr_assert_eq(pair.second.cpu->_registers.p.x_b, true, "The index width flag should be set");
+ cr_assert_eq(pair.second.cpu->_registers.xh, 0, "The high byte of the x index flag should be set to 0");
+ cr_assert_eq(pair.second.cpu->_registers.yh, 0, "The high byte of the y index flag should be set to 0");
}
\ No newline at end of file