Adding 16-bit Arithmetic Operations

This commit is contained in:
Melefo
2020-02-25 19:00:02 +01:00
parent a0f53ebd70
commit ebc3df354b
5 changed files with 188 additions and 2 deletions
+2 -2
View File
@@ -77,7 +77,7 @@ add_executable(unit_tests
sources/APU/Instructions/ProgramFlow.cpp sources/APU/Instructions/ProgramFlow.cpp
sources/APU/Operand.cpp sources/APU/Operand.cpp
sources/APU/Instructions/DecimalCompensation.cpp; sources/APU/Instructions/DecimalCompensation.cpp;
sources/APU/Instructions/MultiplicationDivision.cpp) sources/APU/Instructions/MultiplicationDivision.cpp sources/APU/Instructions/16bitArithmetic.cpp)
# include criterion & coverage # include criterion & coverage
target_link_libraries(unit_tests criterion -lgcov) target_link_libraries(unit_tests criterion -lgcov)
@@ -165,7 +165,7 @@ add_executable(ComSquare
sources/APU/Instructions/ProgramFlow.cpp sources/APU/Instructions/ProgramFlow.cpp
sources/APU/Operand.cpp sources/APU/Operand.cpp
sources/APU/Instructions/DecimalCompensation.cpp sources/APU/Instructions/DecimalCompensation.cpp
sources/APU/Instructions/MultiplicationDivision.cpp) sources/APU/Instructions/MultiplicationDivision.cpp sources/APU/Instructions/16bitArithmetic.cpp)
target_compile_definitions(ComSquare PUBLIC DEBUGGER_ENABLED) target_compile_definitions(ComSquare PUBLIC DEBUGGER_ENABLED)
+10
View File
@@ -184,6 +184,8 @@ namespace ComSquare::APU
return this->CLR1(this->_getDirectAddr(), 0); return this->CLR1(this->_getDirectAddr(), 0);
case 0x13: case 0x13:
return this->BBC(this->_getDirectAddr(), 0); return this->BBC(this->_getDirectAddr(), 0);
case 0x1A:
return this->DECW(this->_getDirectAddr());
case 0x1F: case 0x1F:
return this->JMP(this->_getAbsoluteAddrByX(), true); return this->JMP(this->_getAbsoluteAddrByX(), true);
case 0x20: case 0x20:
@@ -210,6 +212,8 @@ namespace ComSquare::APU
return this->CLR1(this->_getDirectAddr(), 1); return this->CLR1(this->_getDirectAddr(), 1);
case 0x33: case 0x33:
return this->BBC(this->_getDirectAddr(), 1); return this->BBC(this->_getDirectAddr(), 1);
case 0x3A:
return this->INCW(this->_getDirectAddr());
case 0x3F: case 0x3F:
return this->CALL(this->_getAbsoluteAddr()); return this->CALL(this->_getAbsoluteAddr());
case 0x40: case 0x40:
@@ -236,6 +240,8 @@ namespace ComSquare::APU
return this->CLR1(this->_getDirectAddr(), 2); return this->CLR1(this->_getDirectAddr(), 2);
case 0x53: case 0x53:
return this->BBC(this->_getDirectAddr(), 2); return this->BBC(this->_getDirectAddr(), 2);
case 0x5A:
return this->CMPW(this->_getDirectAddr());
case 0x5F: case 0x5F:
return this->JMP(this->_getAbsoluteAddr()); return this->JMP(this->_getAbsoluteAddr());
case 0x60: case 0x60:
@@ -262,6 +268,8 @@ namespace ComSquare::APU
return this->CLR1(this->_getDirectAddr(), 3); return this->CLR1(this->_getDirectAddr(), 3);
case 0x73: case 0x73:
return this->BBC(this->_getDirectAddr(), 3); return this->BBC(this->_getDirectAddr(), 3);
case 0x7A:
return this->ADDW(this->_getDirectAddr());
case 0x7F: case 0x7F:
return this->RETI(); return this->RETI();
case 0x80: case 0x80:
@@ -284,6 +292,8 @@ namespace ComSquare::APU
return this->CLR1(this->_getDirectAddr(), 4); return this->CLR1(this->_getDirectAddr(), 4);
case 0x93: case 0x93:
return this->BBC(this->_getDirectAddr(), 4); return this->BBC(this->_getDirectAddr(), 4);
case 0x9A:
return this->SUBW(this->_getDirectAddr());
case 0x9E: case 0x9E:
return this->DIV(); return this->DIV();
case 0xA0: case 0xA0:
+11
View File
@@ -277,6 +277,17 @@ namespace ComSquare::APU
int MUL(); int MUL();
//! @brief Divide the 16-bit value YA by X, storing the quotient in A and the remainder in Y. //! @brief Divide the 16-bit value YA by X, storing the quotient in A and the remainder in Y.
int DIV(); int DIV();
//! @brief Increment a word value.
int INCW(uint24_t addr);
//! @brief Decrement a word value.
int DECW(uint24_t addr);
//! @brief Add YA with a word value.
int ADDW(uint24_t addr);
//! @brief Subtract YA with a word value.
int SUBW(uint24_t addr);
//! @brief Compare YA with a word value.
int CMPW(uint24_t addr);
public: public:
explicit APU(std::shared_ptr<MemoryMap> &map); explicit APU(std::shared_ptr<MemoryMap> &map);
APU(const APU &) = default; APU(const APU &) = default;
@@ -0,0 +1,77 @@
//
// Created by Melefo on 25/02/2020.
//
#include "../APU.hpp"
namespace ComSquare::APU
{
int APU::INCW(uint24_t addr)
{
uint24_t addr2 = addr + 1 + (this->_internalRegisters.p ? 0x0100 : 0);
uint16_t value = ((this->_internalRead(addr2) << 8u) | this->_internalRead(addr)) + 1u;
this->_internalWrite(addr, value);
this->_internalWrite(addr2, value >> 8u);
this->_internalRegisters.n = value & 0x8000u;
this->_internalRegisters.z = !value;
return 6;
}
int APU::DECW(uint24_t addr)
{
uint24_t addr2 = addr + 1 + (this->_internalRegisters.p ? 0x0100 : 0);
uint16_t value = ((this->_internalRead(addr2) << 8u) | this->_internalRead(addr)) - 1u;
this->_internalWrite(addr, value);
this->_internalWrite(addr2, value >> 8u);
this->_internalRegisters.n = value & 0x8000u;
this->_internalRegisters.z = !value;
return 6;
}
int APU::ADDW(uint24_t addr)
{
uint24_t addr2 = addr + 1 + (this->_internalRegisters.p ? 0x0100 : 0);
uint16_t value = ((this->_internalRead(addr2) << 8u) | this->_internalRead(addr));
uint24_t result = this->_internalRegisters.ya + value;
this->_internalRegisters.v = (~(this->_internalRegisters.ya ^ value) & (this->_internalRegisters.ya ^ result)) & 0x8000u;
this->_internalRegisters.c = result > 0xFFFFu;
this->_internalRegisters.h = ((this->_internalRegisters.ya & 0x0FFFu) + (value & 0x0FFFu)) > 0x0FFFu;
this->_internalRegisters.z = !result;
this->_internalRegisters.n = result & 0x8000u;
this->_internalRegisters.ya = result;
return 5;
}
int APU::SUBW(uint24_t addr)
{
uint24_t addr2 = addr + 1 + (this->_internalRegisters.p ? 0x0100 : 0);
uint16_t value = ((this->_internalRead(addr2) << 8u) | this->_internalRead(addr));
uint24_t result = this->_internalRegisters.ya - value;
uint16_t tmp = ((this->_internalRegisters.ya & 0x0F00u) - (value & 0x0F00u)) >> 8u;
if ((this->_internalRegisters.ya & 0x00FFu) < (value & 0x00FFu))
tmp--;
this->_internalRegisters.v = ((this->_internalRegisters.ya ^ value) & (this->_internalRegisters.ya ^ result)) & 0x8000u;
this->_internalRegisters.c = result <= 0xFFFFu;
this->_internalRegisters.h = tmp <= 0x000F;
this->_internalRegisters.z = !result;
this->_internalRegisters.n = result & 0x8000u;
this->_internalRegisters.ya = result;
return 5;
}
int APU::CMPW(uint24_t addr)
{
uint24_t addr2 = addr + 1 + (this->_internalRegisters.p ? 0x0100 : 0);
uint16_t value = ((this->_internalRead(addr2) << 8u) | this->_internalRead(addr));
uint24_t result = this->_internalRegisters.ya - value;
this->_internalRegisters.z = !result;
this->_internalRegisters.n = result & 0x8000u;
this->_internalRegisters.c = this->_internalRegisters.ya >= value;
return 4;
}
}
+88
View File
@@ -768,4 +768,92 @@ Test(MultiplicationDivision, DIV)
result = apu->DIV(); result = apu->DIV();
cr_assert_eq(apu->_internalRegisters.y, 147); cr_assert_eq(apu->_internalRegisters.y, 147);
cr_assert_eq(apu->_internalRegisters.a, 211); cr_assert_eq(apu->_internalRegisters.a, 211);
}
//////////////////////////////////
// //
// (XVI)16-bit Arithmetic tests //
// //
//////////////////////////////////
Test(XVIbitArithmetic, INCW)
{
auto apu = Init().second.apu;
int result = 0;
apu->_internalWrite(apu->_internalRegisters.pc, 0x55);
apu->_internalWrite(0x55, 0xFF);
apu->_internalWrite(0x55 + 1, 0x22);
result = apu->INCW(apu->_getDirectAddr());
cr_assert_eq(result, 6);
cr_assert_eq(apu->_internalRead(0x55), 0x00);
cr_assert_eq(apu->_internalRead(0x55 + 1), 0x23);
}
Test(XVIbitArithmetic, DECW)
{
auto apu = Init().second.apu;
int result = 0;
apu->_internalWrite(apu->_internalRegisters.pc, 0x55);
apu->_internalWrite(0x55, 0x00);
apu->_internalWrite(0x55 + 1, 0x23);
result = apu->DECW(apu->_getDirectAddr());
cr_assert_eq(result, 6);
cr_assert_eq(apu->_internalRead(0x55), 0xFF);
cr_assert_eq(apu->_internalRead(0x55 + 1), 0x22);
}
Test(XVIbitArithmetic, ADDW)
{
auto apu = Init().second.apu;
int result = 0;
apu->_internalRegisters.ya = 0x4321;
apu->_internalWrite(apu->_internalRegisters.pc, 0x55);
apu->_internalWrite(0x55, 0x11);
apu->_internalWrite(0x55 + 1, 0x22);
result = apu->ADDW(apu->_getDirectAddr());
cr_assert_eq(result, 5);
cr_assert_eq(apu->_internalRegisters.ya, 0x6532);
cr_assert_eq(apu->_internalRegisters.n, false);
cr_assert_eq(apu->_internalRegisters.v, false);
cr_assert_eq(apu->_internalRegisters.h, false);
cr_assert_eq(apu->_internalRegisters.z, false);
cr_assert_eq(apu->_internalRegisters.c, false);
}
Test(XVIbitArithmetic, SUBW)
{
auto apu = Init().second.apu;
int result = 0;
apu->_internalRegisters.ya = 0x4321;
apu->_internalWrite(apu->_internalRegisters.pc, 0x55);
apu->_internalWrite(0x55, 0x11);
apu->_internalWrite(0x55 + 1, 0x22);
result = apu->SUBW(apu->_getDirectAddr());
cr_assert_eq(result, 5);
cr_assert_eq(apu->_internalRegisters.ya, 0x2110);
cr_assert_eq(apu->_internalRegisters.n, false);
cr_assert_eq(apu->_internalRegisters.v, false);
cr_assert_eq(apu->_internalRegisters.h, true);
cr_assert_eq(apu->_internalRegisters.z, false);
cr_assert_eq(apu->_internalRegisters.c, true);
}
Test(XVIbitArithmetic, CMPW)
{
auto apu = Init().second.apu;
int result = 0;
apu->_internalRegisters.ya = 0x2211;
apu->_internalWrite(apu->_internalRegisters.pc, 0x55);
apu->_internalWrite(0x55, 0x11);
apu->_internalWrite(0x55 + 1, 0x22);
result = apu->CMPW(apu->_getDirectAddr());
cr_assert_eq(result, 4);
cr_assert_eq(apu->_internalRegisters.z, true);
cr_assert_eq(apu->_internalRegisters.c, true);
cr_assert_eq(apu->_internalRegisters.n, false);
} }