Implement VU transfer instructions

finally finished implementing those instructions!
also added some basic comments
This commit is contained in:
hch12907 2018-08-20 00:41:46 +08:00
parent 9ead3c7cba
commit cabefebec9
7 changed files with 205 additions and 117 deletions

View file

@ -3,6 +3,14 @@
#include "Controller/Ee/Vpu/Vu/Interpreter/CVuInterpreter.hpp"
#include "Core.hpp"
// All instructions here are related to the conversion between floating-points and
// fixed-points.
//
// FTOIx are the instructions for converting a float to a fixed with (32-x) bits
// as the integer part, and (x) bits as the fractional part.
//
// ITOFx are the instructions for converting a fixed to a float.
void CVuInterpreter::FTOI0(VuUnit_Base* unit, const VuInstruction inst)
{
SizedQwordRegister& ft = unit->vf[inst.ft()];

View file

@ -4,6 +4,9 @@
#include "Controller/Ee/Vpu/Vu/Interpreter/CVuInterpreter.hpp"
#include "Core.hpp"
// All instructions here are related to the EFU (Elementary Functio Unit).
// All results produced by those instructions are stored in the P register.
void CVuInterpreter::ESADD(VuUnit_Base* unit, const VuInstruction inst)
{
// P = VF[fs](x)^2 + VF[fs](y)^2 + VF[fs](z)^2

View file

@ -3,6 +3,9 @@
#include "Controller/Ee/Vpu/Vu/Interpreter/CVuInterpreter.hpp"
#include "Core.hpp"
// All instructions here are related to the flags.
// Mostly straightforward.
void CVuInterpreter::FSAND(VuUnit_Base* unit, const VuInstruction inst)
{
const uword status = unit->status.read_uword();

View file

@ -8,6 +8,8 @@
#include "Resources/Ee/Vpu/Vu/VuUnits.hpp"
#include "Utilities/Utilities.hpp"
// All instructions here are related to float arithmetic.
//
// Explaination for the comments:
// VF[x] - the x-th register of VF
// VF[x](f) - the f field of the x-th register of VF, if not specified

View file

@ -5,6 +5,8 @@
#include "Resources/Ee/Vpu/Vu/VuUnits.hpp"
#include "Utilities/Utilities.hpp"
// All instructions here are related to integer arithmetics.
void CVuInterpreter::IADD(VuUnit_Base* unit, const VuInstruction inst)
{
// VI[id] = VI[is] + VI[it]

View file

@ -5,6 +5,13 @@
#include "Core.hpp"
#include "Resources/RResources.hpp"
// Miscellaneous VU instructions.
// Includes:-
// - random (R* instructions)
// - branching & jumps
// - GIF/VIF interaction
// - WAIT* instruciotns (synchronization between different VU execution units)
void CVuInterpreter::NOP(VuUnit_Base* unit, const VuInstruction inst)
{
return;
@ -35,7 +42,7 @@ void CVuInterpreter::RINIT(VuUnit_Base* unit, const VuInstruction inst)
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.
// Writes a float consisting 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);
@ -102,7 +109,7 @@ void CVuInterpreter::IBEQ(VuUnit_Base* unit, const VuInstruction inst)
if (reg_source_1.read_uhword() == reg_source_2.read_uhword())
{
unit->pc.offset(inst.imm11() * 8);
unit->pc.offset(inst.imm11() * NUMBER_BYTES_IN_DWORD);
}
}
@ -112,7 +119,7 @@ void CVuInterpreter::IBGEZ(VuUnit_Base* unit, const VuInstruction inst)
if (reg_source_1.read_uhword() >= 0)
{
unit->pc.offset(inst.imm11() * 8);
unit->pc.offset(inst.imm11() * NUMBER_BYTES_IN_DWORD);
}
}
@ -122,7 +129,7 @@ void CVuInterpreter::IBGTZ(VuUnit_Base* unit, const VuInstruction inst)
if (reg_source_1.read_uhword() > 0)
{
unit->pc.offset(inst.imm11() * 8);
unit->pc.offset(inst.imm11() * NUMBER_BYTES_IN_DWORD);
}
}
@ -132,7 +139,7 @@ void CVuInterpreter::IBLEZ(VuUnit_Base* unit, const VuInstruction inst)
if (reg_source_1.read_uhword() <= 0)
{
unit->pc.offset(inst.imm11() * 8);
unit->pc.offset(inst.imm11() * NUMBER_BYTES_IN_DWORD);
}
}
@ -142,7 +149,7 @@ void CVuInterpreter::IBLTZ(VuUnit_Base* unit, const VuInstruction inst)
if (reg_source_1.read_uhword() < 0)
{
unit->pc.offset(inst.imm11() * 8);
unit->pc.offset(inst.imm11() * NUMBER_BYTES_IN_DWORD);
}
}
@ -153,13 +160,13 @@ void CVuInterpreter::IBNE(VuUnit_Base* unit, const VuInstruction inst)
if (reg_source_1.read_uhword() != reg_source_2.read_uhword())
{
unit->pc.offset(inst.imm11() * 8);
unit->pc.offset(inst.imm11() * NUMBER_BYTES_IN_DWORD);
}
}
void CVuInterpreter::B(VuUnit_Base* unit, const VuInstruction inst)
{
unit->pc.offset(inst.imm11() * 8);
unit->pc.offset(inst.imm11() * NUMBER_BYTES_IN_DWORD);
}
void CVuInterpreter::BAL(VuUnit_Base* unit, const VuInstruction inst)
@ -168,7 +175,7 @@ void CVuInterpreter::BAL(VuUnit_Base* unit, const VuInstruction inst)
constexpr uword next_addr_offset = 16;
reg_dest.write_uhword(unit->pc.read_uword() + next_addr_offset);
unit->pc.offset(inst.imm11() * 8);
unit->pc.offset(inst.imm11() * NUMBER_BYTES_IN_DWORD);
}
void CVuInterpreter::JR(VuUnit_Base* unit, const VuInstruction inst)

View file

@ -4,185 +4,248 @@
#include "Core.hpp"
#include "Resources/Ee/Vpu/Vu/VuUnits.hpp"
// All instructions here are related to registers.
// Particularly load/store
void CVuInterpreter::MOVE(VuUnit_Base* unit, const VuInstruction inst)
{
// TODO: Implement.
#if defined(BUILD_DEBUG)
BOOST_LOG(Core::get_logger()) << boost::format("(%s, %d) MOVE: Not implemented.") % __FILENAME__ % __LINE__;
#else
throw std::runtime_error("MOVE: Not implemented.");
#endif
SizedQwordRegister& reg_source = unit->vf[inst.fs()];
SizedQwordRegister& reg_dest = unit->vf[inst.ft()];
for (auto field : VuVectorField::VECTOR_FIELDS)
{
if (inst.test_dest_field(field))
{
reg_dest.write_uword(reg_source.read_uword(field), field);
}
}
}
void CVuInterpreter::MFIR(VuUnit_Base* unit, const VuInstruction inst)
{
// TODO: Implement.
#if defined(BUILD_DEBUG)
BOOST_LOG(Core::get_logger()) << boost::format("(%s, %d) MFIR: Not implemented.") % __FILENAME__ % __LINE__;
#else
throw std::runtime_error("MFIR: Not implemented.");
#endif
SizedHwordRegister& reg_source = unit->vi[inst.is()];
SizedQwordRegister& reg_dest = unit->vf[inst.ft()];
for (auto field : VuVectorField::VECTOR_FIELDS)
{
if (inst.test_dest_field(field))
{
reg_dest.write_uword(reg_source.read_uhword(), field);
}
}
}
void CVuInterpreter::MTIR(VuUnit_Base* unit, const VuInstruction inst)
{
// TODO: Implement.
#if defined(BUILD_DEBUG)
BOOST_LOG(Core::get_logger()) << boost::format("(%s, %d) MTIR: Not implemented.") % __FILENAME__ % __LINE__;
#else
throw std::runtime_error("MTIR: Not implemented.");
#endif
SizedQwordRegister& reg_source = unit->vf[inst.fs()];
SizedHwordRegister& reg_dest = unit->vi[inst.it()];
reg_dest.write_uhword(reg_source.read_uword(inst.fsf()) & 0xFFFF);
}
void CVuInterpreter::MR32(VuUnit_Base* unit, const VuInstruction inst)
{
// TODO: Implement.
#if defined(BUILD_DEBUG)
BOOST_LOG(Core::get_logger()) << boost::format("(%s, %d) MR32: Not implemented.") % __FILENAME__ % __LINE__;
#else
throw std::runtime_error("MR32: Not implemented.");
#endif
SizedQwordRegister& reg_source = unit->vf[inst.fs()];
SizedQwordRegister& reg_dest = unit->vf[inst.ft()];
reg_dest.write_uword(reg_source.read_uword(VuVectorField::W), VuVectorField::X);
reg_dest.write_uword(reg_source.read_uword(VuVectorField::X), VuVectorField::Y);
reg_dest.write_uword(reg_source.read_uword(VuVectorField::Y), VuVectorField::Z);
reg_dest.write_uword(reg_source.read_uword(VuVectorField::Z), VuVectorField::W);
}
void CVuInterpreter::LQ(VuUnit_Base* unit, const VuInstruction inst)
{
// TODO: Implement.
#if defined(BUILD_DEBUG)
BOOST_LOG(Core::get_logger()) << boost::format("(%s, %d) LQ: Not implemented.") % __FILENAME__ % __LINE__;
#else
throw std::runtime_error("LQ: Not implemented.");
#endif
SizedHwordRegister& reg_source = unit->vi[inst.is()];
SizedQwordRegister& reg_dest = unit->vf[inst.ft()];
const uword address = (inst.imm11() + reg_source.read_uhword()) * NUMBER_BYTES_IN_QWORD;
const uqword source = unit->bus.read_uqword(BusContext::Vu, address);
for (auto field : VuVectorField::VECTOR_FIELDS)
{
if (inst.test_dest_field(field))
{
// Investigate?: Endianness scares me
reg_dest.write_float(source.uw[field], field);
}
}
}
void CVuInterpreter::LQD(VuUnit_Base* unit, const VuInstruction inst)
{
// TODO: Implement.
#if defined(BUILD_DEBUG)
BOOST_LOG(Core::get_logger()) << boost::format("(%s, %d) LQD: Not implemented.") % __FILENAME__ % __LINE__;
#else
throw std::runtime_error("LQD: Not implemented.");
#endif
SizedHwordRegister& reg_source = unit->vi[inst.is()];
SizedQwordRegister& reg_dest = unit->vf[inst.ft()];
// Pre-decrement VI first
reg_source.write_uhword(reg_source.read_uhword() - 1);
const uword address = reg_source.read_uhword() * NUMBER_BYTES_IN_QWORD;
const uqword source = unit->bus.read_uqword(BusContext::Vu, address);
for (auto field : VuVectorField::VECTOR_FIELDS)
{
if (inst.test_dest_field(field))
{
// Investigate?: Endianness scares me
reg_dest.write_float(source.uw[field], field);
}
}
}
void CVuInterpreter::LQI(VuUnit_Base* unit, const VuInstruction inst)
{
// TODO: Implement.
#if defined(BUILD_DEBUG)
BOOST_LOG(Core::get_logger()) << boost::format("(%s, %d) LQI: Not implemented.") % __FILENAME__ % __LINE__;
#else
throw std::runtime_error("LQI: Not implemented.");
#endif
SizedHwordRegister& reg_source = unit->vi[inst.is()];
SizedQwordRegister& reg_dest = unit->vf[inst.ft()];
const uword address = reg_source.read_uhword() * NUMBER_BYTES_IN_QWORD;
const uqword source = unit->bus.read_uqword(BusContext::Vu, address);
for (auto field : VuVectorField::VECTOR_FIELDS)
{
if (inst.test_dest_field(field))
{
// Investigate?: Endianness scares me
reg_dest.write_float(source.uw[field], field);
}
}
// Post-increment the VI
reg_source.write_uhword(reg_source.read_uhword() + 1);
}
void CVuInterpreter::SQ(VuUnit_Base* unit, const VuInstruction inst)
{
// TODO: Implement.
#if defined(BUILD_DEBUG)
BOOST_LOG(Core::get_logger()) << boost::format("(%s, %d) SQ: Not implemented.") % __FILENAME__ % __LINE__;
#else
throw std::runtime_error("SQ: Not implemented.");
#endif
SizedQwordRegister& reg_source_1 = unit->vf[inst.fs()];
SizedHwordRegister& reg_source_2 = unit->vi[inst.it()];
const uword address = (inst.imm11() + reg_source_2.read_uhword()) * NUMBER_BYTES_IN_QWORD;
for (auto field : VuVectorField::VECTOR_FIELDS)
{
if (inst.test_dest_field(field))
{
unit->bus.write_uword(BusContext::Vu, address + NUMBER_BYTES_IN_WORD * field, reg_source_1.read_uword(field));
}
}
}
void CVuInterpreter::SQD(VuUnit_Base* unit, const VuInstruction inst)
{
// TODO: Implement.
#if defined(BUILD_DEBUG)
BOOST_LOG(Core::get_logger()) << boost::format("(%s, %d) SQD: Not implemented.") % __FILENAME__ % __LINE__;
#else
throw std::runtime_error("SQD: Not implemented.");
#endif
SizedQwordRegister& reg_source_1 = unit->vf[inst.fs()];
SizedHwordRegister& reg_source_2 = unit->vi[inst.it()];
reg_source_2.write_uhword(reg_source_2.read_uhword() - 1);
const uword address = reg_source_2.read_uhword() * NUMBER_BYTES_IN_QWORD;
for (auto field : VuVectorField::VECTOR_FIELDS)
{
if (inst.test_dest_field(field))
{
unit->bus.write_uword(BusContext::Vu, address + NUMBER_BYTES_IN_WORD * field, reg_source_1.read_uword(field));
}
}
}
void CVuInterpreter::SQI(VuUnit_Base* unit, const VuInstruction inst)
{
// MEM(Ft) = Fs
auto& reg_source1 = unit->vf[inst.fs()];
auto& reg_source2 = unit->vi[inst.ft()]; // Mem Addr.
SizedQwordRegister& reg_source_1 = unit->vf[inst.fs()];
SizedHwordRegister& reg_source_2 = unit->vi[inst.ft()]; // Mem Addr.
// Real address obtained by VI * 16 (qword addressing).
uword address = reg_source2.read_uhword() * NUMBER_BYTES_IN_QWORD;
const uword address = reg_source_2.read_uhword() * NUMBER_BYTES_IN_QWORD;
// 32-bit write for each dest subfield.
if (inst.test_dest_x())
unit->bus.write_uword(BusContext::Vu, address, reg_source1.read_uword(0));
if (inst.test_dest_y())
unit->bus.write_uword(BusContext::Vu, address + 4, reg_source1.read_uword(1));
if (inst.test_dest_z())
unit->bus.write_uword(BusContext::Vu, address + 8, reg_source1.read_uword(2));
if (inst.test_dest_w())
unit->bus.write_uword(BusContext::Vu, address + 12, reg_source1.read_uword(3));
for (auto field : VuVectorField::VECTOR_FIELDS)
{
if (inst.test_dest_field(field))
{
unit->bus.write_uword(BusContext::Vu, address + NUMBER_BYTES_IN_WORD * field, reg_source_1.read_uword(field));
}
}
// Post increment.
reg_source2.write_uhword(reg_source2.read_uhword() + 1);
reg_source_2.write_uhword(reg_source_2.read_uhword() + 1);
}
void CVuInterpreter::ILW(VuUnit_Base* unit, const VuInstruction inst)
{
// TODO: Implement.
#if defined(BUILD_DEBUG)
BOOST_LOG(Core::get_logger()) << boost::format("(%s, %d) ILW: Not implemented.") % __FILENAME__ % __LINE__;
#else
throw std::runtime_error("ILW: Not implemented.");
#endif
SizedHwordRegister& reg_source = unit->vi[inst.is()];
SizedHwordRegister& reg_dest = unit->vi[inst.it()];
const uword address = (inst.imm15() + reg_source.read_uhword()) * NUMBER_BYTES_IN_QWORD;
const uword source = unit->bus.read_uqword(BusContext::Vu, address).uw[inst.dest()];
reg_dest.write_uhword(static_cast<uhword>(source));
}
void CVuInterpreter::ISW(VuUnit_Base* unit, const VuInstruction inst)
{
// TODO: Implement.
#if defined(BUILD_DEBUG)
BOOST_LOG(Core::get_logger()) << boost::format("(%s, %d) ISW: Not implemented.") % __FILENAME__ % __LINE__;
#else
throw std::runtime_error("ISW: Not implemented.");
#endif
SizedHwordRegister& reg_source_1 = unit->vi[inst.it()];
SizedHwordRegister& reg_source_2 = unit->vi[inst.is()];
const uword address = (inst.imm15() + reg_source_2.read_uhword()) * NUMBER_BYTES_IN_QWORD;
for (auto field : VuVectorField::VECTOR_FIELDS)
{
if (inst.test_dest_field(field))
{
unit->bus.write_uword(BusContext::Vu, address + NUMBER_BYTES_IN_WORD * field, reg_source_1.read_uhword());
}
}
}
void CVuInterpreter::ILWR(VuUnit_Base* unit, const VuInstruction inst)
{
// TODO: Implement.
#if defined(BUILD_DEBUG)
BOOST_LOG(Core::get_logger()) << boost::format("(%s, %d) ILWR: Not implemented.") % __FILENAME__ % __LINE__;
#else
throw std::runtime_error("ILWR: Not implemented.");
#endif
SizedHwordRegister& reg_source = unit->vi[inst.is()];
SizedHwordRegister& reg_dest = unit->vi[inst.it()];
const uword address = reg_source.read_uhword() * NUMBER_BYTES_IN_QWORD;
const uword source = unit->bus.read_uqword(BusContext::Vu, address).uw[inst.dest()];
reg_dest.write_uhword(static_cast<uhword>(source));
}
void CVuInterpreter::ISWR(VuUnit_Base* unit, const VuInstruction inst)
{
// MEM(Fs) = Ft.
auto& reg_source1 = unit->vi[inst.ft()]; // Data.
auto& reg_source2 = unit->vi[inst.fs()]; // Mem Addr.
SizedHwordRegister& reg_source_1 = unit->vi[inst.it()]; // Data.
SizedHwordRegister& reg_source_2 = unit->vi[inst.is()]; // Mem Addr.
// Real address obtained by VI * 16.
uword address = reg_source2.read_uhword() * NUMBER_BYTES_IN_QWORD;
const uword address = reg_source_2.read_uhword() * NUMBER_BYTES_IN_QWORD;
// 32-bit write for each dest subfield. Upper 16-bits of VI[Ft] value is set to 0.
if (inst.test_dest_x())
unit->bus.write_uword(BusContext::Vu, address, static_cast<uword>(reg_source1.read_uhword()));
if (inst.test_dest_y())
unit->bus.write_uword(BusContext::Vu, address + 4, static_cast<uword>(reg_source1.read_uhword()));
if (inst.test_dest_z())
unit->bus.write_uword(BusContext::Vu, address + 8, static_cast<uword>(reg_source1.read_uhword()));
if (inst.test_dest_w())
unit->bus.write_uword(BusContext::Vu, address + 12, static_cast<uword>(reg_source1.read_uhword()));
for (auto field : VuVectorField::VECTOR_FIELDS)
{
if (inst.test_dest_field(field))
{
unit->bus.write_uword(BusContext::Vu, address + NUMBER_BYTES_IN_WORD * field, reg_source_1.read_uhword());
}
}
}
void CVuInterpreter::LOI(VuUnit_Base* unit, const VuInstruction inst)
{
// TODO: Implement.
#if defined(BUILD_DEBUG)
BOOST_LOG(Core::get_logger()) << boost::format("(%s, %d) LOI: Not implemented.") % __FILENAME__ % __LINE__;
#else
throw std::runtime_error("LOI: Not implemented.");
#endif
// Call this instruction when the I bit of the upper instruction is set
// And pass the lower instruction in
unit->i.write_uword(inst.value);
// (In case you are wondering... LOI is a pseudo-instruction, it's
// not supposed to be referenced)
}
void CVuInterpreter::MFP(VuUnit_Base* unit, const VuInstruction inst)
{
// TODO: Implement.
#if defined(BUILD_DEBUG)
BOOST_LOG(Core::get_logger()) << boost::format("(%s, %d) MFP: Not implemented.") % __FILENAME__ % __LINE__;
#else
throw std::runtime_error("MFP: Not implemented.");
#endif
SizedWordRegister& reg_source = unit->p;
SizedQwordRegister& reg_dest = unit->vf[inst.ft()];
for (auto field : VuVectorField::VECTOR_FIELDS)
{
if (inst.test_dest_field(field))
{
reg_dest.write_uword(reg_source.read_uword(), field);
}
}
}