mirror of
https://github.com/zoriya/ComSquare.git
synced 2026-05-25 23:48:29 +00:00
Adding some Program Flow operations
This commit is contained in:
@@ -73,6 +73,7 @@ add_executable(unit_tests
|
||||
sources/APU/Instructions/Bit.cpp
|
||||
sources/APU/Instructions/Stack.cpp
|
||||
sources/APU/Instructions/Subroutine.cpp
|
||||
sources/APU/Instructions/ProgramFlow.cpp
|
||||
)
|
||||
|
||||
# include criterion & coverage
|
||||
@@ -158,6 +159,7 @@ add_executable(ComSquare
|
||||
sources/Debugger/APUDebug.cpp
|
||||
sources/APU/Instructions/Stack.cpp
|
||||
sources/APU/Instructions/Subroutine.cpp
|
||||
sources/APU/Instructions/ProgramFlow.cpp
|
||||
)
|
||||
|
||||
target_compile_definitions(ComSquare PUBLIC DEBUGGER_ENABLED)
|
||||
|
||||
@@ -174,6 +174,8 @@ namespace ComSquare::APU
|
||||
return this->TSET1(this->_getAbsoluteAddr());
|
||||
case 0x0F:
|
||||
return this->BRK();
|
||||
case 0x10:
|
||||
return this->BPL();
|
||||
case 0x11:
|
||||
return this->TCALL(1);
|
||||
case 0x12:
|
||||
@@ -188,6 +190,10 @@ namespace ComSquare::APU
|
||||
return this->OR1(this->_getAbsoluteBit(), true);
|
||||
case 0x2D:
|
||||
return this->PUSH(this->_internalRegisters.a);
|
||||
case 0x2F:
|
||||
return this->BRA();
|
||||
case 0x30:
|
||||
return this->BMI();
|
||||
case 0x31:
|
||||
return this->TCALL(3);
|
||||
case 0x32:
|
||||
@@ -208,6 +214,8 @@ namespace ComSquare::APU
|
||||
return this->TCLR1(this->_getAbsoluteAddr());
|
||||
case 0x4F:
|
||||
return this->PCALL();
|
||||
case 0x50:
|
||||
return this->BVC();
|
||||
case 0x51:
|
||||
return this->TCALL(5);
|
||||
case 0x52:
|
||||
@@ -224,6 +232,8 @@ namespace ComSquare::APU
|
||||
return this->PUSH(this->_internalRegisters.y);
|
||||
case 0x6F:
|
||||
return this->RET();
|
||||
case 0x70:
|
||||
return this->BVS();
|
||||
case 0x71:
|
||||
return this->TCALL(7);
|
||||
case 0x72:
|
||||
@@ -240,6 +250,8 @@ namespace ComSquare::APU
|
||||
return this->EOR1(this->_getAbsoluteBit());
|
||||
case 0x8E:
|
||||
return this->POP(this->_internalRegisters.psw);
|
||||
case 0x90:
|
||||
return this->BCC();
|
||||
case 0x91:
|
||||
return this->TCALL(9);
|
||||
case 0x92:
|
||||
@@ -254,6 +266,8 @@ namespace ComSquare::APU
|
||||
return this->MOV1(this->_getAbsoluteBit(), true);
|
||||
case 0xAE:
|
||||
return this->POP(this->_internalRegisters.a);
|
||||
case 0xB0:
|
||||
return this->BCS();
|
||||
case 0xB1:
|
||||
return this->TCALL(11);
|
||||
case 0xB2:
|
||||
@@ -268,6 +282,8 @@ namespace ComSquare::APU
|
||||
return this->MOV1(this->_getAbsoluteBit());
|
||||
case 0xCE:
|
||||
return this->POP(this->_internalRegisters.x);
|
||||
case 0xD0:
|
||||
return this->BNE();
|
||||
case 0xD1:
|
||||
return this->TCALL(13);
|
||||
case 0xD2:
|
||||
@@ -278,6 +294,8 @@ namespace ComSquare::APU
|
||||
return this->SET1(this->_getDirectAddr(), 7);
|
||||
case 0xEE:
|
||||
return this->POP(this->_internalRegisters.y);
|
||||
case 0xF0:
|
||||
return BEQ();
|
||||
case 0xF1:
|
||||
return this->TCALL(15);
|
||||
case 0xF2:
|
||||
|
||||
@@ -232,6 +232,25 @@ namespace ComSquare::APU
|
||||
int RET();
|
||||
//! @brief Return from interrupt.
|
||||
int RETI();
|
||||
|
||||
//! @brief Branch Always, go to the specified location from the next instruction.
|
||||
int BRA();
|
||||
//! @brief Branch if Zero Flag is set
|
||||
int BEQ();
|
||||
//! @brief Branch if Zero Flag is clear
|
||||
int BNE();
|
||||
//! @brief Branch if Carry Flag is set
|
||||
int BCS();
|
||||
//! @brief Branch if Carry Flag is clear
|
||||
int BCC();
|
||||
//! @brief Branch if Overflow Flag is set
|
||||
int BVS();
|
||||
//! @brief Branch if Overflow Flag is set
|
||||
int BVC();
|
||||
//! @brief Branch if Negative Flag is set
|
||||
int BMI();
|
||||
//! @brief Branch if Negative Flag is clear
|
||||
int BPL();
|
||||
public:
|
||||
explicit APU(std::shared_ptr<MemoryMap> &map);
|
||||
APU(const APU &) = default;
|
||||
|
||||
@@ -0,0 +1,80 @@
|
||||
//
|
||||
// Created by Melefo on 21/02/2020.
|
||||
//
|
||||
|
||||
#include "../APU.hpp"
|
||||
|
||||
namespace ComSquare::APU
|
||||
{
|
||||
int APU::BRA()
|
||||
{
|
||||
int8_t offset = this->_internalRead(this->_internalRegisters.pc++);
|
||||
|
||||
this->_internalRegisters.pc += offset;
|
||||
return 4;
|
||||
}
|
||||
|
||||
int APU::BEQ()
|
||||
{
|
||||
if (!this->_internalRegisters.z)
|
||||
return 2;
|
||||
this->BRA();
|
||||
return 4;
|
||||
}
|
||||
|
||||
int APU::BNE()
|
||||
{
|
||||
if (this->_internalRegisters.z)
|
||||
return 2;
|
||||
this->BRA();
|
||||
return 4;
|
||||
}
|
||||
|
||||
int APU::BCS()
|
||||
{
|
||||
if (!this->_internalRegisters.c)
|
||||
return 2;
|
||||
this->BRA();
|
||||
return 4;
|
||||
}
|
||||
|
||||
int APU::BCC()
|
||||
{
|
||||
if (this->_internalRegisters.c)
|
||||
return 2;
|
||||
this->BRA();
|
||||
return 4;
|
||||
}
|
||||
|
||||
int APU::BVS()
|
||||
{
|
||||
if (!this->_internalRegisters.v)
|
||||
return 2;
|
||||
this->BRA();
|
||||
return 4;
|
||||
}
|
||||
|
||||
int APU::BVC()
|
||||
{
|
||||
if (this->_internalRegisters.v)
|
||||
return 2;
|
||||
this->BRA();
|
||||
return 4;
|
||||
}
|
||||
|
||||
int APU::BMI()
|
||||
{
|
||||
if (!this->_internalRegisters.n)
|
||||
return 2;
|
||||
this->BRA();
|
||||
return 4;
|
||||
}
|
||||
|
||||
int APU::BPL()
|
||||
{
|
||||
if (this->_internalRegisters.n)
|
||||
return 2;
|
||||
this->BRA();
|
||||
return 4;
|
||||
}
|
||||
}
|
||||
@@ -464,4 +464,146 @@ Test(Subroutine, RETI)
|
||||
cr_assert_eq(apu->_internalRegisters.psw, 0x12);
|
||||
cr_assert_eq(apu->_internalRegisters.pch, 0x34);
|
||||
cr_assert_eq(apu->_internalRegisters.pcl, 0x56);
|
||||
}
|
||||
|
||||
/////////////////////////////
|
||||
// //
|
||||
// Subroutine Program Flow //
|
||||
// //
|
||||
/////////////////////////////
|
||||
|
||||
Test(ProgramFlow, BRA)
|
||||
{
|
||||
auto apu = Init().second.apu;
|
||||
int result = 0;
|
||||
|
||||
apu->_internalWrite(apu->_internalRegisters.pc, 23);
|
||||
apu->_internalWrite(apu->_internalRegisters.pc + 24, 101);
|
||||
result = apu->BRA();
|
||||
cr_assert_eq(result, 4);
|
||||
cr_assert_eq(apu->_internalRead(apu->_internalRegisters.pc), 101);
|
||||
}
|
||||
|
||||
Test(ProgramFlow, BEQ)
|
||||
{
|
||||
auto apu = Init().second.apu;
|
||||
int result = 0;
|
||||
|
||||
apu->_internalWrite(apu->_internalRegisters.pc, 23);
|
||||
apu->_internalWrite(apu->_internalRegisters.pc + 24, 101);
|
||||
result = apu->BEQ();
|
||||
cr_assert_eq(result, 2);
|
||||
apu->_internalRegisters.z = true;
|
||||
result = apu->BEQ();
|
||||
cr_assert_eq(result, 4);
|
||||
cr_assert_eq(apu->_internalRead(apu->_internalRegisters.pc), 101);
|
||||
}
|
||||
|
||||
Test(ProgramFlow, BNE)
|
||||
{
|
||||
auto apu = Init().second.apu;
|
||||
int result = 0;
|
||||
|
||||
apu->_internalWrite(apu->_internalRegisters.pc, 23);
|
||||
apu->_internalWrite(apu->_internalRegisters.pc + 24, 101);
|
||||
apu->_internalRegisters.z = true;
|
||||
result = apu->BNE();
|
||||
cr_assert_eq(result, 2);
|
||||
apu->_internalRegisters.z = false;
|
||||
result = apu->BNE();
|
||||
cr_assert_eq(result, 4);
|
||||
cr_assert_eq(apu->_internalRead(apu->_internalRegisters.pc), 101);
|
||||
}
|
||||
|
||||
Test(ProgramFlow, BCS)
|
||||
{
|
||||
auto apu = Init().second.apu;
|
||||
int result = 0;
|
||||
|
||||
apu->_internalWrite(apu->_internalRegisters.pc, 23);
|
||||
apu->_internalWrite(apu->_internalRegisters.pc + 24, 101);
|
||||
result = apu->BCS();
|
||||
cr_assert_eq(result, 2);
|
||||
apu->_internalRegisters.c = true;
|
||||
result = apu->BCS();
|
||||
cr_assert_eq(result, 4);
|
||||
cr_assert_eq(apu->_internalRead(apu->_internalRegisters.pc), 101);
|
||||
}
|
||||
|
||||
Test(ProgramFlow, BCC)
|
||||
{
|
||||
auto apu = Init().second.apu;
|
||||
int result = 0;
|
||||
|
||||
apu->_internalWrite(apu->_internalRegisters.pc, 23);
|
||||
apu->_internalWrite(apu->_internalRegisters.pc + 24, 101);
|
||||
apu->_internalRegisters.c = true;
|
||||
result = apu->BCC();
|
||||
cr_assert_eq(result, 2);
|
||||
apu->_internalRegisters.c = false;
|
||||
result = apu->BCC();
|
||||
cr_assert_eq(result, 4);
|
||||
cr_assert_eq(apu->_internalRead(apu->_internalRegisters.pc), 101);
|
||||
}
|
||||
|
||||
Test(ProgramFlow, BVS)
|
||||
{
|
||||
auto apu = Init().second.apu;
|
||||
int result = 0;
|
||||
|
||||
apu->_internalWrite(apu->_internalRegisters.pc, 23);
|
||||
apu->_internalWrite(apu->_internalRegisters.pc + 24, 101);
|
||||
result = apu->BVS();
|
||||
cr_assert_eq(result, 2);
|
||||
apu->_internalRegisters.v = true;
|
||||
result = apu->BVS();
|
||||
cr_assert_eq(result, 4);
|
||||
cr_assert_eq(apu->_internalRead(apu->_internalRegisters.pc), 101);
|
||||
}
|
||||
|
||||
Test(ProgramFlow, BVC)
|
||||
{
|
||||
auto apu = Init().second.apu;
|
||||
int result = 0;
|
||||
|
||||
apu->_internalWrite(apu->_internalRegisters.pc, 23);
|
||||
apu->_internalWrite(apu->_internalRegisters.pc + 24, 101);
|
||||
apu->_internalRegisters.v = true;
|
||||
result = apu->BVC();
|
||||
cr_assert_eq(result, 2);
|
||||
apu->_internalRegisters.v = false;
|
||||
result = apu->BVC();
|
||||
cr_assert_eq(result, 4);
|
||||
cr_assert_eq(apu->_internalRead(apu->_internalRegisters.pc), 101);
|
||||
}
|
||||
|
||||
Test(ProgramFlow, BMI)
|
||||
{
|
||||
auto apu = Init().second.apu;
|
||||
int result = 0;
|
||||
|
||||
apu->_internalWrite(apu->_internalRegisters.pc, 23);
|
||||
apu->_internalWrite(apu->_internalRegisters.pc + 24, 101);
|
||||
result = apu->BMI();
|
||||
cr_assert_eq(result, 2);
|
||||
apu->_internalRegisters.n = true;
|
||||
result = apu->BMI();
|
||||
cr_assert_eq(result, 4);
|
||||
cr_assert_eq(apu->_internalRead(apu->_internalRegisters.pc), 101);
|
||||
}
|
||||
|
||||
Test(ProgramFlow, BPL)
|
||||
{
|
||||
auto apu = Init().second.apu;
|
||||
int result = 0;
|
||||
|
||||
apu->_internalWrite(apu->_internalRegisters.pc, 23);
|
||||
apu->_internalWrite(apu->_internalRegisters.pc + 24, 101);
|
||||
apu->_internalRegisters.n = true;
|
||||
result = apu->BPL();
|
||||
cr_assert_eq(result, 2);
|
||||
apu->_internalRegisters.n = false;
|
||||
result = apu->BPL();
|
||||
cr_assert_eq(result, 4);
|
||||
cr_assert_eq(apu->_internalRead(apu->_internalRegisters.pc), 101);
|
||||
}
|
||||
Reference in New Issue
Block a user