mirror of
https://github.com/zoriya/ComSquare.git
synced 2026-06-06 19:32:18 +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/Bit.cpp
|
||||||
sources/APU/Instructions/Stack.cpp
|
sources/APU/Instructions/Stack.cpp
|
||||||
sources/APU/Instructions/Subroutine.cpp
|
sources/APU/Instructions/Subroutine.cpp
|
||||||
|
sources/APU/Instructions/ProgramFlow.cpp
|
||||||
)
|
)
|
||||||
|
|
||||||
# include criterion & coverage
|
# include criterion & coverage
|
||||||
@@ -158,6 +159,7 @@ add_executable(ComSquare
|
|||||||
sources/Debugger/APUDebug.cpp
|
sources/Debugger/APUDebug.cpp
|
||||||
sources/APU/Instructions/Stack.cpp
|
sources/APU/Instructions/Stack.cpp
|
||||||
sources/APU/Instructions/Subroutine.cpp
|
sources/APU/Instructions/Subroutine.cpp
|
||||||
|
sources/APU/Instructions/ProgramFlow.cpp
|
||||||
)
|
)
|
||||||
|
|
||||||
target_compile_definitions(ComSquare PUBLIC DEBUGGER_ENABLED)
|
target_compile_definitions(ComSquare PUBLIC DEBUGGER_ENABLED)
|
||||||
|
|||||||
@@ -174,6 +174,8 @@ namespace ComSquare::APU
|
|||||||
return this->TSET1(this->_getAbsoluteAddr());
|
return this->TSET1(this->_getAbsoluteAddr());
|
||||||
case 0x0F:
|
case 0x0F:
|
||||||
return this->BRK();
|
return this->BRK();
|
||||||
|
case 0x10:
|
||||||
|
return this->BPL();
|
||||||
case 0x11:
|
case 0x11:
|
||||||
return this->TCALL(1);
|
return this->TCALL(1);
|
||||||
case 0x12:
|
case 0x12:
|
||||||
@@ -188,6 +190,10 @@ namespace ComSquare::APU
|
|||||||
return this->OR1(this->_getAbsoluteBit(), true);
|
return this->OR1(this->_getAbsoluteBit(), true);
|
||||||
case 0x2D:
|
case 0x2D:
|
||||||
return this->PUSH(this->_internalRegisters.a);
|
return this->PUSH(this->_internalRegisters.a);
|
||||||
|
case 0x2F:
|
||||||
|
return this->BRA();
|
||||||
|
case 0x30:
|
||||||
|
return this->BMI();
|
||||||
case 0x31:
|
case 0x31:
|
||||||
return this->TCALL(3);
|
return this->TCALL(3);
|
||||||
case 0x32:
|
case 0x32:
|
||||||
@@ -208,6 +214,8 @@ namespace ComSquare::APU
|
|||||||
return this->TCLR1(this->_getAbsoluteAddr());
|
return this->TCLR1(this->_getAbsoluteAddr());
|
||||||
case 0x4F:
|
case 0x4F:
|
||||||
return this->PCALL();
|
return this->PCALL();
|
||||||
|
case 0x50:
|
||||||
|
return this->BVC();
|
||||||
case 0x51:
|
case 0x51:
|
||||||
return this->TCALL(5);
|
return this->TCALL(5);
|
||||||
case 0x52:
|
case 0x52:
|
||||||
@@ -224,6 +232,8 @@ namespace ComSquare::APU
|
|||||||
return this->PUSH(this->_internalRegisters.y);
|
return this->PUSH(this->_internalRegisters.y);
|
||||||
case 0x6F:
|
case 0x6F:
|
||||||
return this->RET();
|
return this->RET();
|
||||||
|
case 0x70:
|
||||||
|
return this->BVS();
|
||||||
case 0x71:
|
case 0x71:
|
||||||
return this->TCALL(7);
|
return this->TCALL(7);
|
||||||
case 0x72:
|
case 0x72:
|
||||||
@@ -240,6 +250,8 @@ namespace ComSquare::APU
|
|||||||
return this->EOR1(this->_getAbsoluteBit());
|
return this->EOR1(this->_getAbsoluteBit());
|
||||||
case 0x8E:
|
case 0x8E:
|
||||||
return this->POP(this->_internalRegisters.psw);
|
return this->POP(this->_internalRegisters.psw);
|
||||||
|
case 0x90:
|
||||||
|
return this->BCC();
|
||||||
case 0x91:
|
case 0x91:
|
||||||
return this->TCALL(9);
|
return this->TCALL(9);
|
||||||
case 0x92:
|
case 0x92:
|
||||||
@@ -254,6 +266,8 @@ namespace ComSquare::APU
|
|||||||
return this->MOV1(this->_getAbsoluteBit(), true);
|
return this->MOV1(this->_getAbsoluteBit(), true);
|
||||||
case 0xAE:
|
case 0xAE:
|
||||||
return this->POP(this->_internalRegisters.a);
|
return this->POP(this->_internalRegisters.a);
|
||||||
|
case 0xB0:
|
||||||
|
return this->BCS();
|
||||||
case 0xB1:
|
case 0xB1:
|
||||||
return this->TCALL(11);
|
return this->TCALL(11);
|
||||||
case 0xB2:
|
case 0xB2:
|
||||||
@@ -268,6 +282,8 @@ namespace ComSquare::APU
|
|||||||
return this->MOV1(this->_getAbsoluteBit());
|
return this->MOV1(this->_getAbsoluteBit());
|
||||||
case 0xCE:
|
case 0xCE:
|
||||||
return this->POP(this->_internalRegisters.x);
|
return this->POP(this->_internalRegisters.x);
|
||||||
|
case 0xD0:
|
||||||
|
return this->BNE();
|
||||||
case 0xD1:
|
case 0xD1:
|
||||||
return this->TCALL(13);
|
return this->TCALL(13);
|
||||||
case 0xD2:
|
case 0xD2:
|
||||||
@@ -278,6 +294,8 @@ namespace ComSquare::APU
|
|||||||
return this->SET1(this->_getDirectAddr(), 7);
|
return this->SET1(this->_getDirectAddr(), 7);
|
||||||
case 0xEE:
|
case 0xEE:
|
||||||
return this->POP(this->_internalRegisters.y);
|
return this->POP(this->_internalRegisters.y);
|
||||||
|
case 0xF0:
|
||||||
|
return BEQ();
|
||||||
case 0xF1:
|
case 0xF1:
|
||||||
return this->TCALL(15);
|
return this->TCALL(15);
|
||||||
case 0xF2:
|
case 0xF2:
|
||||||
|
|||||||
@@ -232,6 +232,25 @@ namespace ComSquare::APU
|
|||||||
int RET();
|
int RET();
|
||||||
//! @brief Return from interrupt.
|
//! @brief Return from interrupt.
|
||||||
int RETI();
|
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:
|
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,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.psw, 0x12);
|
||||||
cr_assert_eq(apu->_internalRegisters.pch, 0x34);
|
cr_assert_eq(apu->_internalRegisters.pch, 0x34);
|
||||||
cr_assert_eq(apu->_internalRegisters.pcl, 0x56);
|
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