Adding 8-bit Increment & Decrement Operations

Creating a generic function to set Negative and Zero flags with a value
This commit is contained in:
Melefo
2020-02-26 13:12:42 +01:00
parent 5033b949f9
commit 2776be601e
10 changed files with 157 additions and 24 deletions
+2 -2
View File
@@ -81,7 +81,7 @@ add_executable(unit_tests
sources/APU/Instructions/16bitArithmetic.cpp sources/APU/Instructions/16bitArithmetic.cpp
sources/APU/Instructions/16bitDataTransmission.cpp sources/APU/Instructions/16bitDataTransmission.cpp
sources/APU/Instructions/8bitShiftRotation.cpp sources/APU/Instructions/8bitShiftRotation.cpp
) sources/APU/Instructions/8bitIncrementDecrement.cpp)
# include criterion & coverage # include criterion & coverage
target_link_libraries(unit_tests criterion -lgcov) target_link_libraries(unit_tests criterion -lgcov)
@@ -173,7 +173,7 @@ add_executable(ComSquare
sources/APU/Instructions/16bitArithmetic.cpp sources/APU/Instructions/16bitArithmetic.cpp
sources/APU/Instructions/16bitDataTransmission.cpp sources/APU/Instructions/16bitDataTransmission.cpp
sources/APU/Instructions/8bitShiftRotation.cpp sources/APU/Instructions/8bitShiftRotation.cpp
) sources/APU/Instructions/8bitIncrementDecrement.cpp)
target_compile_definitions(ComSquare PUBLIC DEBUGGER_ENABLED) target_compile_definitions(ComSquare PUBLIC DEBUGGER_ENABLED)
+30
View File
@@ -194,6 +194,8 @@ namespace ComSquare::APU
return this->ASL(this->_getDirectAddrByX(), 5); return this->ASL(this->_getDirectAddrByX(), 5);
case 0x1C: case 0x1C:
return this->ASL(this->_internalRegisters.a, 2, true); return this->ASL(this->_internalRegisters.a, 2, true);
case 0x1D:
return this->DECreg(this->_internalRegisters.x);
case 0x1F: case 0x1F:
return this->JMP(this->_getAbsoluteAddrByX(), true); return this->JMP(this->_getAbsoluteAddrByX(), true);
case 0x20: case 0x20:
@@ -230,6 +232,8 @@ namespace ComSquare::APU
return this->ROL(this->_getAbsoluteAddrByX(), 5); return this->ROL(this->_getAbsoluteAddrByX(), 5);
case 0x3C: case 0x3C:
return this->ROL(this->_internalRegisters.a, 2, true); return this->ROL(this->_internalRegisters.a, 2, true);
case 0x3D:
return this->INCreg(this->_internalRegisters.x);
case 0x3F: case 0x3F:
return this->CALL(this->_getAbsoluteAddr()); return this->CALL(this->_getAbsoluteAddr());
case 0x40: case 0x40:
@@ -314,6 +318,10 @@ namespace ComSquare::APU
return this->BBS(this->_getDirectAddr(), 4); return this->BBS(this->_getDirectAddr(), 4);
case 0x8A: case 0x8A:
return this->EOR1(this->_getAbsoluteBit()); return this->EOR1(this->_getAbsoluteBit());
case 0x8B:
return this->DEC(this->_getDirectAddr(), 4);
case 0x8C:
return this->DEC(this->_getAbsoluteAddr(), 5);
case 0x8E: case 0x8E:
return this->POP(this->_internalRegisters.psw); return this->POP(this->_internalRegisters.psw);
case 0x90: case 0x90:
@@ -326,6 +334,10 @@ namespace ComSquare::APU
return this->BBC(this->_getDirectAddr(), 4); return this->BBC(this->_getDirectAddr(), 4);
case 0x9A: case 0x9A:
return this->SUBW(this->_getDirectAddr()); return this->SUBW(this->_getDirectAddr());
case 0x9B:
return this->DEC(this->_getDirectAddrByX(), 5);
case 0x9C:
return this->DECreg(this->_internalRegisters.a);
case 0x9E: case 0x9E:
return this->DIV(); return this->DIV();
case 0x9F: case 0x9F:
@@ -340,6 +352,10 @@ namespace ComSquare::APU
return this->BBS(this->_getDirectAddr(), 5); return this->BBS(this->_getDirectAddr(), 5);
case 0xAA: case 0xAA:
return this->MOV1(this->_getAbsoluteBit(), true); return this->MOV1(this->_getAbsoluteBit(), true);
case 0xAB:
return this->INC(this->_getDirectAddr(), 4);
case 0xAC:
return this->INC(this->_getAbsoluteAddr(), 5);
case 0xAE: case 0xAE:
return this->POP(this->_internalRegisters.a); return this->POP(this->_internalRegisters.a);
case 0xB0: case 0xB0:
@@ -352,6 +368,10 @@ namespace ComSquare::APU
return this->BBC(this->_getDirectAddr(), 5); return this->BBC(this->_getDirectAddr(), 5);
case 0xBA: case 0xBA:
return this->MOVW(this->_getDirectAddr(), true); return this->MOVW(this->_getDirectAddr(), true);
case 0xBB:
return this->INC(this->_getDirectAddrByX(), 5);
case 0xBC:
return this->INCreg(this->_internalRegisters.a);
case 0xBE: case 0xBE:
return this->DAS(); return this->DAS();
case 0xC0: case 0xC0:
@@ -378,6 +398,8 @@ namespace ComSquare::APU
return this->BBC(this->_getDirectAddr(), 6); return this->BBC(this->_getDirectAddr(), 6);
case 0xDA: case 0xDA:
return this->MOVW(this->_getDirectAddr()); return this->MOVW(this->_getDirectAddr());
case 0xDC:
return this->DECreg(this->_internalRegisters.y);
case 0xDE: case 0xDE:
return this->CBNE(this->_getDirectAddrByX(), true); return this->CBNE(this->_getDirectAddrByX(), true);
case 0xDF: case 0xDF:
@@ -398,6 +420,8 @@ namespace ComSquare::APU
return this->CLR1(this->_getDirectAddr(), 7); return this->CLR1(this->_getDirectAddr(), 7);
case 0xF3: case 0xF3:
return this->BBC(this->_getDirectAddr(), 7); return this->BBC(this->_getDirectAddr(), 7);
case 0xFC:
return this->INCreg(this->_internalRegisters.y);
case 0xEA: case 0xEA:
return this->NOT1(this->_getAbsoluteBit()); return this->NOT1(this->_getAbsoluteBit());
case 0xED: case 0xED:
@@ -424,6 +448,12 @@ namespace ComSquare::APU
this->_paddingCycles = total - cycles; this->_paddingCycles = total - cycles;
} }
void APU::_setNZflags(uint8_t value)
{
this->_internalRegisters.n = value & 0x80u;
this->_internalRegisters.z = !value;
}
MemoryMap::MemoryMap() : MemoryMap::MemoryMap() :
Page0(0x00F0), Page0(0x00F0),
Page1(0x0100), Page1(0x0100),
+12
View File
@@ -174,6 +174,9 @@ namespace ComSquare::APU
//! @brief Get absolute offset and separate its bits //! @brief Get absolute offset and separate its bits
std::pair<uint24_t, uint24_t> _getAbsoluteBit(); std::pair<uint24_t, uint24_t> _getAbsoluteBit();
//! @brief Set Negative and Zero flags with value after an instruction
void _setNZflags(uint8_t value);
//! @brief Execute a single instruction. //! @brief Execute a single instruction.
//! @return The number of cycles that the instruction took. //! @return The number of cycles that the instruction took.
virtual int _executeInstruction(); virtual int _executeInstruction();
@@ -302,6 +305,15 @@ namespace ComSquare::APU
int ROR(uint24_t operand, int cycles, bool accumulator = false); int ROR(uint24_t operand, int cycles, bool accumulator = false);
//! @brief Exchange Nibbles. //! @brief Exchange Nibbles.
int XCN(); int XCN();
//! @brief Increment a value at an address.
int INC(uint24_t addr, int cycles);
//! @brief Increment a register.
int INCreg(uint8_t &value);
//! @brief Decrement a value at an address.
int DEC(uint24_t addr, int cycles);
//! @brief Decrement a register.
int DECreg(uint8_t &value);
public: public:
explicit APU(std::shared_ptr<MemoryMap> &map); explicit APU(std::shared_ptr<MemoryMap> &map);
APU(const APU &) = default; APU(const APU &) = default;
@@ -14,8 +14,7 @@ namespace ComSquare::APU
uint16_t value = ((this->_internalRead(addr2) << 8u) | this->_internalRead(addr)); uint16_t value = ((this->_internalRead(addr2) << 8u) | this->_internalRead(addr));
this->_internalRegisters.ya = value; this->_internalRegisters.ya = value;
this->_internalRegisters.n = value & 0x8000u; this->_setNZflags(value);
this->_internalRegisters.z = !value;
} }
else { else {
this->_internalWrite(addr, this->_internalRegisters.a); this->_internalWrite(addr, this->_internalRegisters.a);
@@ -0,0 +1,40 @@
//
// Created by Melefo on 26/02/2020.
//
#include "../APU.hpp"
namespace ComSquare::APU
{
int APU::INC(uint24_t addr, int cycles)
{
uint8_t value = this->_internalRead(addr);
this->_internalWrite(addr, ++value);
this->_setNZflags(value);
return cycles;
}
int APU::INCreg(uint8_t &value)
{
value++;
this->_setNZflags(value);
return 2;
}
int APU::DEC(uint24_t addr, int cycles)
{
uint8_t value = this->_internalRead(addr);
this->_internalWrite(addr, --value);
this->_setNZflags(value);
return cycles;
}
int APU::DECreg(uint8_t &value)
{
value--;
this->_setNZflags(value);
return 2;
}
}
@@ -16,8 +16,7 @@ namespace ComSquare::APU
this->_internalRegisters.a = value; this->_internalRegisters.a = value;
else else
this->_internalWrite(operand, value); this->_internalWrite(operand, value);
this->_internalRegisters.n = value & 0x80u; this->_setNZflags(value);
this->_internalRegisters.z = !value;
return cycles; return cycles;
} }
@@ -46,8 +45,7 @@ namespace ComSquare::APU
this->_internalRegisters.a = result; this->_internalRegisters.a = result;
else else
this->_internalWrite(operand, result); this->_internalWrite(operand, result);
this->_internalRegisters.n = result & 0x80u; this->_setNZflags(result);
this->_internalRegisters.z = !result;
return cycles; return cycles;
} }
@@ -69,8 +67,7 @@ namespace ComSquare::APU
int APU::XCN() int APU::XCN()
{ {
this->_internalRegisters.a = (this->_internalRegisters.a >> 4u) | (this->_internalRegisters.a << 4u); this->_internalRegisters.a = (this->_internalRegisters.a >> 4u) | (this->_internalRegisters.a << 4u);
this->_internalRegisters.n = this->_internalRegisters.a & 0x80u; this->_setNZflags(this->_internalRegisters.a);
this->_internalRegisters.z = !this->_internalRegisters.a;
return 5; return 5;
} }
} }
+2 -4
View File
@@ -28,8 +28,7 @@ namespace ComSquare::APU
uint8_t data = this->_internalRead(abs); uint8_t data = this->_internalRead(abs);
this->_internalWrite(abs, data | this->_internalRegisters.a); this->_internalWrite(abs, data | this->_internalRegisters.a);
this->_internalRegisters.n = data & 0x80u; this->_setNZflags(data);
this->_internalRegisters.z = !data;
return 6; return 6;
} }
@@ -38,8 +37,7 @@ namespace ComSquare::APU
uint8_t data = this->_internalRead(abs); uint8_t data = this->_internalRead(abs);
this->_internalWrite(abs, data & ~this->_internalRegisters.a); this->_internalWrite(abs, data & ~this->_internalRegisters.a);
this->_internalRegisters.n = data & 0x80u; this->_setNZflags(data);
this->_internalRegisters.z = !data;
return 6; return 6;
} }
@@ -15,8 +15,7 @@ namespace ComSquare::APU
if (this->_internalRegisters.h || (this->_internalRegisters.a & 0x0Fu) > 0x09) { if (this->_internalRegisters.h || (this->_internalRegisters.a & 0x0Fu) > 0x09) {
this->_internalRegisters.a += 0x06; this->_internalRegisters.a += 0x06;
} }
this->_internalRegisters.n = this->_internalRegisters.a & 0x80u; this->_setNZflags(this->_internalRegisters.a);
this->_internalRegisters.z = !this->_internalRegisters.a;
return 3; return 3;
} }
@@ -29,8 +28,7 @@ namespace ComSquare::APU
if (!this->_internalRegisters.h || (this->_internalRegisters.a & 0x0Fu) > 0x09) { if (!this->_internalRegisters.h || (this->_internalRegisters.a & 0x0Fu) > 0x09) {
this->_internalRegisters.a -= 0x06; this->_internalRegisters.a -= 0x06;
} }
this->_internalRegisters.n = this->_internalRegisters.a & 0x80u; this->_setNZflags(this->_internalRegisters.a);
this->_internalRegisters.z = !this->_internalRegisters.a;
return 3; return 3;
} }
} }
@@ -28,8 +28,7 @@ namespace ComSquare::APU
this->_internalRegisters.a = 0xFF - (ya - (this->_internalRegisters.x << 9u)) / (0x100 - this->_internalRegisters.x); this->_internalRegisters.a = 0xFF - (ya - (this->_internalRegisters.x << 9u)) / (0x100 - this->_internalRegisters.x);
this->_internalRegisters.y = this->_internalRegisters.x + (ya - (this->_internalRegisters.x << 9u)) % (0x100 - this->_internalRegisters.x); this->_internalRegisters.y = this->_internalRegisters.x + (ya - (this->_internalRegisters.x << 9u)) % (0x100 - this->_internalRegisters.x);
} }
this->_internalRegisters.z = !this->_internalRegisters.a; this->_setNZflags(this->_internalRegisters.a);
this->_internalRegisters.n = this->_internalRegisters.a & 0x80u;
return 12; return 12;
} }
} }
+64 -4
View File
@@ -891,7 +891,7 @@ Test(XVIbitDataTransmission, MOVW)
// // // //
////////////////////////////////////// //////////////////////////////////////
Test(VIIIShiftRotation, ASL) Test(VIIIbitShiftRotation, ASL)
{ {
auto apu = Init().second.apu; auto apu = Init().second.apu;
int result = 0; int result = 0;
@@ -913,7 +913,7 @@ Test(VIIIShiftRotation, ASL)
cr_assert_eq(apu->_internalRegisters.z, false); cr_assert_eq(apu->_internalRegisters.z, false);
} }
Test(VIIIShiftRotation, LSR) Test(VIIIbitShiftRotation, LSR)
{ {
auto apu = Init().second.apu; auto apu = Init().second.apu;
int result = 0; int result = 0;
@@ -935,7 +935,7 @@ Test(VIIIShiftRotation, LSR)
cr_assert_eq(apu->_internalRegisters.z, false); cr_assert_eq(apu->_internalRegisters.z, false);
} }
Test(VIIIShiftRotation, ROL) Test(VIIIbitShiftRotation, ROL)
{ {
auto apu = Init().second.apu; auto apu = Init().second.apu;
int result = 0; int result = 0;
@@ -957,7 +957,7 @@ Test(VIIIShiftRotation, ROL)
cr_assert_eq(apu->_internalRegisters.z, false); cr_assert_eq(apu->_internalRegisters.z, false);
} }
Test(VIIIShiftRotation, ROR) Test(VIIIbitShiftRotation, ROR)
{ {
auto apu = Init().second.apu; auto apu = Init().second.apu;
int result = 0; int result = 0;
@@ -990,4 +990,64 @@ Test(VIIIShiftRotation, XCN)
cr_assert_eq(apu->_internalRegisters.a, 0xAA); cr_assert_eq(apu->_internalRegisters.a, 0xAA);
cr_assert_eq(apu->_internalRegisters.n, true); cr_assert_eq(apu->_internalRegisters.n, true);
cr_assert_eq(apu->_internalRegisters.z, false); cr_assert_eq(apu->_internalRegisters.z, false);
}
///////////////////////////////////////////
// //
// (VIII)8-bit Increment Decrement tests //
// //
///////////////////////////////////////////
Test(VIIIbitIncrementDecrement, INC)
{
auto apu = Init().second.apu;
int result = 0;
apu->_internalWrite(apu->_internalRegisters.pc, 0x55);
apu->_internalWrite(0x55, 0xDD);
result = apu->INC(apu->_getDirectAddr(), 4);
cr_assert_eq(result, 4);
cr_assert_eq(apu->_internalRead(0x55), 0xDE);
cr_assert_eq(apu->_internalRegisters.z, false);
cr_assert_eq(apu->_internalRegisters.n, true);
}
Test(VIIIbitIncrementDecrement, INCreg)
{
auto apu = Init().second.apu;
int result = 0;
apu->_internalRegisters.a = 0x76;
result = apu->INCreg(apu->_internalRegisters.a);
cr_assert_eq(result, 2);
cr_assert_eq(apu->_internalRegisters.a, 0x77);
cr_assert_eq(apu->_internalRegisters.z, false);
cr_assert_eq(apu->_internalRegisters.n, false);
}
Test(VIIIbitIncrementDecrement, DEC)
{
auto apu = Init().second.apu;
int result = 0;
apu->_internalWrite(apu->_internalRegisters.pc, 0x55);
apu->_internalWrite(0x55, 0xDD);
result = apu->DEC(apu->_getDirectAddr(), 4);
cr_assert_eq(result, 4);
cr_assert_eq(apu->_internalRead(0x55), 0xDC);
cr_assert_eq(apu->_internalRegisters.z, false);
cr_assert_eq(apu->_internalRegisters.n, true);
}
Test(VIIIbitIncrementDecrement, DECreg)
{
auto apu = Init().second.apu;
int result = 0;
apu->_internalRegisters.a = 0x76;
result = apu->DECreg(apu->_internalRegisters.a);
cr_assert_eq(result, 2);
cr_assert_eq(apu->_internalRegisters.a, 0x75);
cr_assert_eq(apu->_internalRegisters.z, false);
cr_assert_eq(apu->_internalRegisters.n, false);
} }