Implement VU_OTHER instructions

This commit is contained in:
hch12907 2018-08-19 20:28:20 +08:00
parent fe1cf18572
commit 9ead3c7cba

View file

@ -1,208 +1,233 @@
#include <boost/format.hpp>
#include <cmath>
#include "Controller/Ee/Vpu/Vu/Interpreter/CVuInterpreter.hpp"
#include "Core.hpp"
#include "Resources/RResources.hpp"
void CVuInterpreter::NOP(VuUnit_Base* unit, const VuInstruction inst)
{
return;
}
void CVuInterpreter::CLIP(VuUnit_Base* unit, const VuInstruction inst)
{
// TODO: Implement.
#if defined(BUILD_DEBUG)
BOOST_LOG(Core::get_logger()) << boost::format("(%s, %d) CLIP: Not implemented.") % __FILENAME__ % __LINE__;
#else
throw std::runtime_error("CLIP: Not implemented.");
#endif
// Left-shifts CLIP by 6 bits, compares the fields of FS with w field of FT,
// and sets the corresponding flags
SizedQwordRegister& reg_source_1 = unit->vf[inst.fs()];
SizedQwordRegister& reg_source_2 = unit->vf[inst.ft()];
VuUnitRegister_Clipping& clip = unit->clipping;
const f32 ft = std::abs(reg_source_2.read_float(VuVectorField::W));
clip.shift_judgement();
clip.insert_field(VuUnitRegister_Clipping::POSX_0, reg_source_1.read_float(VuVectorField::X) > ft);
clip.insert_field(VuUnitRegister_Clipping::NEGX_0, reg_source_1.read_float(VuVectorField::X) < -ft);
clip.insert_field(VuUnitRegister_Clipping::POSY_0, reg_source_1.read_float(VuVectorField::Y) > ft);
clip.insert_field(VuUnitRegister_Clipping::NEGY_0, reg_source_1.read_float(VuVectorField::Y) < -ft);
clip.insert_field(VuUnitRegister_Clipping::POSZ_0, reg_source_1.read_float(VuVectorField::Z) > ft);
clip.insert_field(VuUnitRegister_Clipping::NEGZ_0, reg_source_1.read_float(VuVectorField::Z) < -ft);
}
void CVuInterpreter::RINIT(VuUnit_Base* unit, const VuInstruction inst)
{
// TODO: Implement.
#if defined(BUILD_DEBUG)
BOOST_LOG(Core::get_logger()) << boost::format("(%s, %d) RINIT: Not implemented.") % __FILENAME__ % __LINE__;
#else
throw std::runtime_error("RINIT: Not implemented.");
#endif
SizedQwordRegister& reg_source = unit->vf[inst.fs()];
SizedWordRegister& reg_dest = unit->r;
// Writes a float consisting of 23 bits of R as mantissa and 001111111 as exp+sign.
constexpr uword append = 0b001111111 << 23;
const f32 fsf = (reg_source.read_uword(inst.fsf()) & 0x7FFFFF) | append;
reg_dest.write_uword(fsf);
}
void CVuInterpreter::RGET(VuUnit_Base* unit, const VuInstruction inst)
{
// TODO: Implement.
#if defined(BUILD_DEBUG)
BOOST_LOG(Core::get_logger()) << boost::format("(%s, %d) RGET: Not implemented.") % __FILENAME__ % __LINE__;
#else
throw std::runtime_error("RGET: Not implemented.");
#endif
SizedWordRegister& reg_source = unit->r;
SizedQwordRegister& reg_dest = unit->vf[inst.ft()];
for (auto field : VuVectorField::VECTOR_FIELDS)
{
if (inst.test_dest_field(field))
{
reg_dest.write_uword(field, reg_source.read_uword());
}
}
}
void CVuInterpreter::RNEXT(VuUnit_Base* unit, const VuInstruction inst)
{
// TODO: Implement.
#if defined(BUILD_DEBUG)
BOOST_LOG(Core::get_logger()) << boost::format("(%s, %d) RNEXT: Not implemented.") % __FILENAME__ % __LINE__;
#else
throw std::runtime_error("RNEXT: Not implemented.");
#endif
SizedWordRegister& reg_R = unit->r;
SizedQwordRegister& reg_dest = unit->vf[inst.ft()];
// A Galois form M-series LFSR adapted from PCSX2 (advance_r() in pcsx2/vu.cpp)
const int x = (reg_R.read_uword() >> 4) & 1;
const int y = (reg_R.read_uword() >> 22) & 1;
reg_R.write_uword(((reg_R.read_uword() << 1) ^ (x ^ y)) & 0x7FFFFF);
// Append the exp+sign to R
reg_R.write_uword(reg_R.read_uword() | 0b001111111 << 23);
}
void CVuInterpreter::RXOR(VuUnit_Base* unit, const VuInstruction inst)
{
// TODO: Implement.
#if defined(BUILD_DEBUG)
BOOST_LOG(Core::get_logger()) << boost::format("(%s, %d) RXOR: Not implemented.") % __FILENAME__ % __LINE__;
#else
throw std::runtime_error("RXOR: Not implemented.");
#endif
SizedWordRegister& reg_source_1 = unit->r;
SizedQwordRegister& reg_source_2 = unit->vf[inst.ft()];
SizedWordRegister& reg_dest = unit->r;
const uword a = reg_source_1.read_uword();
const uword b = reg_source_2.read_uword(inst.fsf()) & 0x7FFFFF;
const uword result = a ^ b;
reg_dest.write_uword(result);
}
void CVuInterpreter::WAITQ(VuUnit_Base* unit, const VuInstruction inst)
{
// TODO: Implement.
// TODO:
// Actual synchronization.
// The VU Interpreter is synchronous, I imagine, so synchronization is actually unneeded.
#if defined(BUILD_DEBUG)
BOOST_LOG(Core::get_logger()) << boost::format("(%s, %d) WAITQ: Not implemented.") % __FILENAME__ % __LINE__;
#else
throw std::runtime_error("WAITQ: Not implemented.");
BOOST_LOG(Core::get_logger()) << boost::format("(%s, %d) WAITQ is called!") % __FILENAME__ % __LINE__;
#endif
return;
}
void CVuInterpreter::IBEQ(VuUnit_Base* unit, const VuInstruction inst)
{
// TODO: Implement.
#if defined(BUILD_DEBUG)
BOOST_LOG(Core::get_logger()) << boost::format("(%s, %d) IBEQ: Not implemented.") % __FILENAME__ % __LINE__;
#else
throw std::runtime_error("IBEQ: Not implemented.");
#endif
SizedHwordRegister& reg_source_1 = unit->vi[inst.is()];
SizedHwordRegister& reg_source_2 = unit->vi[inst.it()];
if (reg_source_1.read_uhword() == reg_source_2.read_uhword())
{
unit->pc.offset(inst.imm11() * 8);
}
}
void CVuInterpreter::IBGEZ(VuUnit_Base* unit, const VuInstruction inst)
{
// TODO: Implement.
#if defined(BUILD_DEBUG)
BOOST_LOG(Core::get_logger()) << boost::format("(%s, %d) IBGEZ: Not implemented.") % __FILENAME__ % __LINE__;
#else
throw std::runtime_error("IBGEZ: Not implemented.");
#endif
SizedHwordRegister& reg_source_1 = unit->vi[inst.is()];
if (reg_source_1.read_uhword() >= 0)
{
unit->pc.offset(inst.imm11() * 8);
}
}
void CVuInterpreter::IBGTZ(VuUnit_Base* unit, const VuInstruction inst)
{
// TODO: Implement.
#if defined(BUILD_DEBUG)
BOOST_LOG(Core::get_logger()) << boost::format("(%s, %d) IBGTZ: Not implemented.") % __FILENAME__ % __LINE__;
#else
throw std::runtime_error("IBGTZ: Not implemented.");
#endif
SizedHwordRegister& reg_source_1 = unit->vi[inst.is()];
if (reg_source_1.read_uhword() > 0)
{
unit->pc.offset(inst.imm11() * 8);
}
}
void CVuInterpreter::IBLEZ(VuUnit_Base* unit, const VuInstruction inst)
{
// TODO: Implement.
#if defined(BUILD_DEBUG)
BOOST_LOG(Core::get_logger()) << boost::format("(%s, %d) IBLEZ: Not implemented.") % __FILENAME__ % __LINE__;
#else
throw std::runtime_error("IBLEZ: Not implemented.");
#endif
SizedHwordRegister& reg_source_1 = unit->vi[inst.is()];
if (reg_source_1.read_uhword() <= 0)
{
unit->pc.offset(inst.imm11() * 8);
}
}
void CVuInterpreter::IBLTZ(VuUnit_Base* unit, const VuInstruction inst)
{
// TODO: Implement.
#if defined(BUILD_DEBUG)
BOOST_LOG(Core::get_logger()) << boost::format("(%s, %d) IBLTZ: Not implemented.") % __FILENAME__ % __LINE__;
#else
throw std::runtime_error("IBLTZ: Not implemented.");
#endif
SizedHwordRegister& reg_source_1 = unit->vi[inst.is()];
if (reg_source_1.read_uhword() < 0)
{
unit->pc.offset(inst.imm11() * 8);
}
}
void CVuInterpreter::IBNE(VuUnit_Base* unit, const VuInstruction inst)
{
// TODO: Implement.
#if defined(BUILD_DEBUG)
BOOST_LOG(Core::get_logger()) << boost::format("(%s, %d) IBNE: Not implemented.") % __FILENAME__ % __LINE__;
#else
throw std::runtime_error("IBNE: Not implemented.");
#endif
SizedHwordRegister& reg_source_1 = unit->vi[inst.is()];
SizedHwordRegister& reg_source_2 = unit->vi[inst.it()];
if (reg_source_1.read_uhword() != reg_source_2.read_uhword())
{
unit->pc.offset(inst.imm11() * 8);
}
}
void CVuInterpreter::B(VuUnit_Base* unit, const VuInstruction inst)
{
// TODO: Implement.
#if defined(BUILD_DEBUG)
BOOST_LOG(Core::get_logger()) << boost::format("(%s, %d) B: Not implemented.") % __FILENAME__ % __LINE__;
#else
throw std::runtime_error("B: Not implemented.");
#endif
unit->pc.offset(inst.imm11() * 8);
}
void CVuInterpreter::BAL(VuUnit_Base* unit, const VuInstruction inst)
{
// TODO: Implement.
#if defined(BUILD_DEBUG)
BOOST_LOG(Core::get_logger()) << boost::format("(%s, %d) BAL: Not implemented.") % __FILENAME__ % __LINE__;
#else
throw std::runtime_error("BAL: Not implemented.");
#endif
SizedHwordRegister& reg_dest = unit->vi[inst.it()];
constexpr uword next_addr_offset = 16;
reg_dest.write_uhword(unit->pc.read_uword() + next_addr_offset);
unit->pc.offset(inst.imm11() * 8);
}
void CVuInterpreter::JR(VuUnit_Base* unit, const VuInstruction inst)
{
// TODO: Implement.
#if defined(BUILD_DEBUG)
BOOST_LOG(Core::get_logger()) << boost::format("(%s, %d) JR: Not implemented.") % __FILENAME__ % __LINE__;
#else
throw std::runtime_error("JR: Not implemented.");
#endif
SizedHwordRegister& reg_source_1 = unit->vi[inst.is()];
unit->pc.write_uword(reg_source_1.read_uhword());
}
void CVuInterpreter::JALR(VuUnit_Base* unit, const VuInstruction inst)
{
// TODO: Implement.
#if defined(BUILD_DEBUG)
BOOST_LOG(Core::get_logger()) << boost::format("(%s, %d) JALR: Not implemented.") % __FILENAME__ % __LINE__;
#else
throw std::runtime_error("JALR: Not implemented.");
#endif
SizedHwordRegister& reg_source_1 = unit->vi[inst.is()];
SizedHwordRegister& reg_dest = unit->vi[inst.it()];
constexpr uword next_addr_offset = 16;
reg_dest.write_uhword(unit->pc.read_uword() + next_addr_offset);
unit->pc.write_uword(reg_source_1.read_uhword());
}
void CVuInterpreter::WAITP(VuUnit_Base* unit, const VuInstruction inst)
{
// TODO: Implement.
// TODO:
// Actual synchronization.
// The VU Interpreter is synchronous, I imagine, so synchronization is actually unneeded.
#if defined(BUILD_DEBUG)
BOOST_LOG(Core::get_logger()) << boost::format("(%s, %d) WAITP: Not implemented.") % __FILENAME__ % __LINE__;
#else
throw std::runtime_error("WAITP: Not implemented.");
BOOST_LOG(Core::get_logger()) << boost::format("(%s, %d) WAITP is called!") % __FILENAME__ % __LINE__;
#endif
return;
}
void CVuInterpreter::XGKICK(VuUnit_Base* unit, const VuInstruction inst)
{
// TODO: Implement.
// TODO: Wait for GIF to be implemented
#if defined(BUILD_DEBUG)
BOOST_LOG(Core::get_logger()) << boost::format("(%s, %d) XGKICK: Not implemented.") % __FILENAME__ % __LINE__;
BOOST_LOG(Core::get_logger()) << boost::format("(%s, %d) XGKICK: Not implemented. (GIF not implemented)") % __FILENAME__ % __LINE__;
#else
throw std::runtime_error("XGKICK: Not implemented.");
throw std::runtime_error("XGKICK: Not implemented. (GIF not implemented)");
#endif
}
void CVuInterpreter::XTOP(VuUnit_Base* unit, const VuInstruction inst)
{
// TODO: Implement.
#if defined(BUILD_DEBUG)
BOOST_LOG(Core::get_logger()) << boost::format("(%s, %d) XTOP: Not implemented.") % __FILENAME__ % __LINE__;
#else
throw std::runtime_error("XTOP: Not implemented.");
#endif
SizedHwordRegister& reg_dest = unit->vi[inst.it()];
const RResources& r = core->get_resources();
VifUnit_Base* vif = r.ee.vpu.vif.units[unit->core_id];
reg_dest.write_uhword(vif->top.read_uword());
}
void CVuInterpreter::XITOP(VuUnit_Base* unit, const VuInstruction inst)
{
// TODO: Implement.
#if defined(BUILD_DEBUG)
BOOST_LOG(Core::get_logger()) << boost::format("(%s, %d) XITOP: Not implemented.") % __FILENAME__ % __LINE__;
#else
throw std::runtime_error("XITOP: Not implemented.");
#endif
SizedHwordRegister& reg_dest = unit->vi[inst.it()];
const RResources& r = core->get_resources();
VifUnit_Base* vif = r.ee.vpu.vif.units[unit->core_id];
reg_dest.write_uhword(vif->itop.read_uword());
}