Play-/tools/VuTest/IntBranchDelayTest.cpp

81 lines
2.4 KiB
C++
Raw Normal View History

2022-08-18 16:59:08 -04:00
#include "IntBranchDelayTest.h"
#include "VuAssembler.h"
void CIntBranchDelayTest::Execute(CTestVm& virtualMachine)
{
virtualMachine.Reset();
auto microMem = reinterpret_cast<uint32*>(virtualMachine.m_microMem);
2022-08-19 11:31:59 -04:00
//Inspired by Dawn of Mana (FMAC delay right at the moment branch is to be executed)
2022-08-18 16:59:08 -04:00
{
CVuAssembler assembler(microMem);
auto equalLabel = assembler.CreateLabel();
auto doneLabel = assembler.CreateLabel();
2022-08-31 17:46:50 -04:00
//pipeTime = 0 (LQ result available at pipeTime 4)
2022-08-18 16:59:08 -04:00
assembler.Write(
CVuAssembler::Upper::NOP(),
2022-08-19 11:31:59 -04:00
CVuAssembler::Lower::LQ(CVuAssembler::DEST_XYZ, CVuAssembler::VF2, 0, CVuAssembler::VI5));
2022-08-18 16:59:08 -04:00
2022-08-31 17:46:50 -04:00
//pipeTime = 1
2022-08-18 16:59:08 -04:00
assembler.Write(
CVuAssembler::Upper::NOP(),
2022-08-19 11:31:59 -04:00
CVuAssembler::Lower::LQ(CVuAssembler::DEST_XYZ, CVuAssembler::VF3, 1, CVuAssembler::VI5));
2022-08-18 16:59:08 -04:00
2022-08-31 17:46:50 -04:00
//pipeTime = 2
2022-08-18 16:59:08 -04:00
assembler.Write(
CVuAssembler::Upper::NOP(),
CVuAssembler::Lower::ISUBIU(CVuAssembler::VI1, CVuAssembler::VI1, 1));
2022-08-31 17:46:50 -04:00
//pipeTime = 3, 4
2022-08-19 11:31:59 -04:00
//Upper instruction stalls here waiting for result from pipeTime 0
//This gives enough time for the IBEQ instruction to pick up the result
//from the previous ISUBIU instruction
2022-08-18 16:59:08 -04:00
assembler.Write(
2022-08-19 11:31:59 -04:00
CVuAssembler::Upper::ITOF12(CVuAssembler::DEST_XYZ, CVuAssembler::VF2, CVuAssembler::VF2),
2022-08-18 16:59:08 -04:00
CVuAssembler::Lower::IBEQ(CVuAssembler::VI1, CVuAssembler::VI0, equalLabel));
assembler.Write(
2022-08-19 11:31:59 -04:00
CVuAssembler::Upper::ITOF12(CVuAssembler::DEST_XYZ, CVuAssembler::VF3, CVuAssembler::VF3),
2022-08-18 16:59:08 -04:00
CVuAssembler::Lower::NOP());
assembler.Write(
CVuAssembler::Upper::NOP(),
CVuAssembler::Lower::IADDIU(CVuAssembler::VI2, CVuAssembler::VI0, 0));
assembler.Write(
CVuAssembler::Upper::NOP(),
CVuAssembler::Lower::IBEQ(CVuAssembler::VI0, CVuAssembler::VI0, doneLabel));
assembler.Write(
CVuAssembler::Upper::NOP(),
CVuAssembler::Lower::NOP());
assembler.MarkLabel(equalLabel);
assembler.Write(
CVuAssembler::Upper::NOP(),
CVuAssembler::Lower::IADDIU(CVuAssembler::VI2, CVuAssembler::VI0, 1));
assembler.MarkLabel(doneLabel);
assembler.Write(
CVuAssembler::Upper::NOP() | CVuAssembler::Upper::E_BIT,
CVuAssembler::Lower::NOP());
assembler.Write(
CVuAssembler::Upper::NOP(),
CVuAssembler::Lower::NOP());
}
virtualMachine.m_cpu.m_State.nCOP2VI[1] = 1;
virtualMachine.ExecuteTest(0);
TEST_VERIFY(virtualMachine.m_cpu.m_State.nCOP2VI[1] == 0);
TEST_VERIFY(virtualMachine.m_cpu.m_State.nCOP2VI[2] == 1);
}