From cabefebec98f372747534e345c7e81feb40c3c9a Mon Sep 17 00:00:00 2001 From: hch12907 Date: Mon, 20 Aug 2018 00:41:46 +0800 Subject: [PATCH] Implement VU transfer instructions finally finished implementing those instructions! also added some basic comments --- .../Vu/Interpreter/CVuInterpreter_CONVERT.cpp | 8 + .../Vpu/Vu/Interpreter/CVuInterpreter_EFU.cpp | 3 + .../Vu/Interpreter/CVuInterpreter_FLAG.cpp | 3 + .../Vu/Interpreter/CVuInterpreter_FLOAT.cpp | 2 + .../Vu/Interpreter/CVuInterpreter_INTEGER.cpp | 2 + .../Vu/Interpreter/CVuInterpreter_OTHER.cpp | 25 +- .../Interpreter/CVuInterpreter_TRANSFER.cpp | 279 +++++++++++------- 7 files changed, 205 insertions(+), 117 deletions(-) diff --git a/liborbum/src/Controller/Ee/Vpu/Vu/Interpreter/CVuInterpreter_CONVERT.cpp b/liborbum/src/Controller/Ee/Vpu/Vu/Interpreter/CVuInterpreter_CONVERT.cpp index 19ac1006..1059efc8 100644 --- a/liborbum/src/Controller/Ee/Vpu/Vu/Interpreter/CVuInterpreter_CONVERT.cpp +++ b/liborbum/src/Controller/Ee/Vpu/Vu/Interpreter/CVuInterpreter_CONVERT.cpp @@ -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()]; diff --git a/liborbum/src/Controller/Ee/Vpu/Vu/Interpreter/CVuInterpreter_EFU.cpp b/liborbum/src/Controller/Ee/Vpu/Vu/Interpreter/CVuInterpreter_EFU.cpp index 090ef611..d101728f 100644 --- a/liborbum/src/Controller/Ee/Vpu/Vu/Interpreter/CVuInterpreter_EFU.cpp +++ b/liborbum/src/Controller/Ee/Vpu/Vu/Interpreter/CVuInterpreter_EFU.cpp @@ -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 diff --git a/liborbum/src/Controller/Ee/Vpu/Vu/Interpreter/CVuInterpreter_FLAG.cpp b/liborbum/src/Controller/Ee/Vpu/Vu/Interpreter/CVuInterpreter_FLAG.cpp index 883dc64d..f69679a0 100644 --- a/liborbum/src/Controller/Ee/Vpu/Vu/Interpreter/CVuInterpreter_FLAG.cpp +++ b/liborbum/src/Controller/Ee/Vpu/Vu/Interpreter/CVuInterpreter_FLAG.cpp @@ -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(); diff --git a/liborbum/src/Controller/Ee/Vpu/Vu/Interpreter/CVuInterpreter_FLOAT.cpp b/liborbum/src/Controller/Ee/Vpu/Vu/Interpreter/CVuInterpreter_FLOAT.cpp index b33b6589..71f50a09 100644 --- a/liborbum/src/Controller/Ee/Vpu/Vu/Interpreter/CVuInterpreter_FLOAT.cpp +++ b/liborbum/src/Controller/Ee/Vpu/Vu/Interpreter/CVuInterpreter_FLOAT.cpp @@ -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 diff --git a/liborbum/src/Controller/Ee/Vpu/Vu/Interpreter/CVuInterpreter_INTEGER.cpp b/liborbum/src/Controller/Ee/Vpu/Vu/Interpreter/CVuInterpreter_INTEGER.cpp index a22b72b4..93fa2df1 100644 --- a/liborbum/src/Controller/Ee/Vpu/Vu/Interpreter/CVuInterpreter_INTEGER.cpp +++ b/liborbum/src/Controller/Ee/Vpu/Vu/Interpreter/CVuInterpreter_INTEGER.cpp @@ -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] diff --git a/liborbum/src/Controller/Ee/Vpu/Vu/Interpreter/CVuInterpreter_OTHER.cpp b/liborbum/src/Controller/Ee/Vpu/Vu/Interpreter/CVuInterpreter_OTHER.cpp index 4482a900..80db8464 100644 --- a/liborbum/src/Controller/Ee/Vpu/Vu/Interpreter/CVuInterpreter_OTHER.cpp +++ b/liborbum/src/Controller/Ee/Vpu/Vu/Interpreter/CVuInterpreter_OTHER.cpp @@ -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) diff --git a/liborbum/src/Controller/Ee/Vpu/Vu/Interpreter/CVuInterpreter_TRANSFER.cpp b/liborbum/src/Controller/Ee/Vpu/Vu/Interpreter/CVuInterpreter_TRANSFER.cpp index 2f64d6ad..3435d7c0 100644 --- a/liborbum/src/Controller/Ee/Vpu/Vu/Interpreter/CVuInterpreter_TRANSFER.cpp +++ b/liborbum/src/Controller/Ee/Vpu/Vu/Interpreter/CVuInterpreter_TRANSFER.cpp @@ -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(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(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(reg_source1.read_uhword())); - if (inst.test_dest_y()) - unit->bus.write_uword(BusContext::Vu, address + 4, static_cast(reg_source1.read_uhword())); - if (inst.test_dest_z()) - unit->bus.write_uword(BusContext::Vu, address + 8, static_cast(reg_source1.read_uhword())); - if (inst.test_dest_w()) - unit->bus.write_uword(BusContext::Vu, address + 12, static_cast(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); + } + } }