Merge branch 'master' into serialization

This commit is contained in:
Marco Satti 2018-08-18 14:46:40 +08:00
commit 1605c43d86
9 changed files with 1464 additions and 378 deletions

View file

@ -27,12 +27,13 @@ public:
/// Read/write floats - wrappers around read/write uword.
f32 read_float(const size_t offset)
{
return static_cast<f32>(read_uword(offset));
const uword raw = read_uword(offset);
return *reinterpret_cast<const f32*>(&raw);
}
void write_float(const size_t offset, const f32 value)
{
write_uword(offset, static_cast<uword>(value));
write_uword(offset, *reinterpret_cast<const uword*>(&value));
}
/// ByteBusMappable overrides.

View file

@ -24,12 +24,13 @@ public:
/// Read/write floats - wrappers around read/write uword.
f32 read_float()
{
return static_cast<f32>(read_uword());
const uword raw = read_uword();
return *reinterpret_cast<const f32*>(&raw);
}
void write_float(const f32 value)
{
write_uword(static_cast<uword>(value));
write_uword(*reinterpret_cast<const uword*>(&value));
}
/// Bitfield extraction/insertion.

View file

@ -122,7 +122,7 @@ void CEeCoreInterpreter::RSQRT_S(const EeCoreInstruction inst)
if (val_source2 == 0.0F)
{
csr.set_d_flag_sticky(1);
result = static_cast<f32>(Constants::EE::EECore::FPU::FMAX_POS);
result = *reinterpret_cast<const f32*>(&Constants::EE::EECore::FPU::FMAX_POS);
}
else if (val_source2 < 0.0F)
{

View file

@ -164,12 +164,13 @@ void CEeCoreInterpreter::DIV_S(const EeCoreInstruction inst)
if (reg_source1.read_float() != 0 && reg_source2.read_float() == 0)
{
csr.set_d_flag_sticky(1);
result = static_cast<f32>(Constants::EE::EECore::FPU::FMAX_POS);
result = *reinterpret_cast<const f32*>(&Constants::EE::EECore::FPU::FMAX_POS);
}
else if (reg_source1.read_float() == 0 && reg_source2.read_float() == 0)
{
csr.set_i_flag_sticky(1);
result = static_cast<f32>(Constants::EE::EECore::FPU::FMAX_POS);
result = *reinterpret_cast<const f32*>(&Constants::EE::EECore::FPU::FMAX_POS);
}
else
{

View file

@ -1,3 +1,5 @@
#include <boost/format.hpp>
#include "Controller/Ee/Vpu/Vif/CVif.hpp"
#include "Core.hpp"
@ -76,12 +78,12 @@ int CVif::time_step(const int ticks_available)
// If the I bit is set, we need to raise an interrupt after the whole VIF packet has been processed - set a context variable.
/*
if (instruction.i())
{
auto _lock = r.ee.intc.stat.scope_lock();
r.ee.intc.stat.insert_field(EeIntcRegister_Stat::VIF, 1);
}
*/
if (instruction.i())
{
auto _lock = r.ee.intc.stat.scope_lock();
r.ee.intc.stat.insert_field(EeIntcRegister_Stat::VIF, 1);
}
*/
}
}
}
@ -95,36 +97,84 @@ void CVif::INSTRUCTION_UNSUPPORTED(VifUnit_Base* unit, const VifcodeInstruction
throw std::runtime_error("VIFcode CMD field was invalid! Please fix.");
}
// Refer to EE Users Manual pg 103.
void CVif::NOP(VifUnit_Base* unit, const VifcodeInstruction inst)
{
// nothing to do
return;
}
// Refer to EE Users Manual pg 104.
void CVif::STCYCL(VifUnit_Base* unit, const VifcodeInstruction inst)
{
// Writes CODE.IMMEDIATE to CYCLE
uword immediate = inst.imm();
unit->cycle.write_uword(immediate);
}
// Refer to EE Users Manual pg 105.
void CVif::OFFSET(VifUnit_Base* unit, const VifcodeInstruction inst)
{
// VIF1 only
if (unit->core_id != 1) {
BOOST_LOG(Core::get_logger()) << str(boost::format("Warning: VIF%d called a VIF1-only instruction: OFFSET") % unit->core_id);
return;
}
// Clear STAT.DBF
unit->stat.insert_field(VifUnitRegister_Stat::DBF, 0);
// Writes the lower 10 bits of CODE.IMMEDIATE to OFST
uword immediate = inst.imm();
unit->ofst.insert_field(VifUnitRegister_Ofst::OFFSET, immediate);
// Transfer BASE to TOPS
unit->tops.write_uword(unit->base.read_uword());
}
// Refer to EE Users Manual pg 106.
void CVif::BASE(VifUnit_Base* unit, const VifcodeInstruction inst)
{
// VIF1 only
if (unit->core_id != 1) {
BOOST_LOG(Core::get_logger()) << str(boost::format("Warning: VIF%d called a VIF1-only instruction: BASE") % unit->core_id);
return;
}
// Writes the lower 10 bits of CODE.IMMEDIATE to BASE
uword immediate = inst.imm();
unit->base.insert_field(VifUnitRegister_Base::BASE, immediate);
}
// Refer to EE Users Manual pg 107.
void CVif::ITOP(VifUnit_Base* unit, const VifcodeInstruction inst)
{
uword immediate = inst.imm();
unit->itops.insert_field(VifUnitRegister_Itops::ITOPS, immediate);
}
// Refer to EE Users Manual pg 108.
void CVif::STMOD(VifUnit_Base* unit, const VifcodeInstruction inst)
{
uword immediate = inst.imm();
unit->mode.insert_field(VifUnitRegister_Mode::MOD, immediate);
}
void CVif::MSKPATH3(VifUnit_Base* unit, const VifcodeInstruction inst)
{
// VIF1 only
if (unit->core_id != 1) {
BOOST_LOG(Core::get_logger()) << str(boost::format("Warning: VIF%d called a VIF1-only instruction: MSKPATH3") % unit->core_id);
return;
}
// TODO: Implement this when GIF is implemented
}
void CVif::MARK(VifUnit_Base* unit, const VifcodeInstruction inst)
{
uword immediate = inst.imm();
unit->mark.insert_field(VifUnitRegister_Mark::MARK, immediate);
}
void CVif::FLUSHE(VifUnit_Base* unit, const VifcodeInstruction inst)
@ -133,10 +183,24 @@ void CVif::FLUSHE(VifUnit_Base* unit, const VifcodeInstruction inst)
void CVif::FLUSH(VifUnit_Base* unit, const VifcodeInstruction inst)
{
// VIF1 only
if (unit->core_id != 1) {
BOOST_LOG(Core::get_logger()) << str(boost::format("Warning: VIF%d called a VIF1-only instruction: FLUSH") % unit->core_id);
return;
}
// TODO: Implement this
}
void CVif::FLUSHA(VifUnit_Base* unit, const VifcodeInstruction inst)
{
// VIF1 only
if (unit->core_id != 1) {
BOOST_LOG(Core::get_logger()) << str(boost::format("Warning: VIF%d called a VIF1-only instruction: FLUSHA") % unit->core_id);
return;
}
// TODO: Implement this
}
void CVif::MSCAL(VifUnit_Base* unit, const VifcodeInstruction inst)
@ -149,6 +213,13 @@ void CVif::MSCNT(VifUnit_Base* unit, const VifcodeInstruction inst)
void CVif::MSCALF(VifUnit_Base* unit, const VifcodeInstruction inst)
{
// VIF1 only
if (unit->core_id != 1) {
BOOST_LOG(Core::get_logger()) << str(boost::format("Warning: VIF%d called a VIF1-only instruction: MSCALF") % unit->core_id);
return;
}
// TODO: Implement this
}
void CVif::STMASK(VifUnit_Base* unit, const VifcodeInstruction inst)
@ -169,10 +240,24 @@ void CVif::MPG(VifUnit_Base* unit, const VifcodeInstruction inst)
void CVif::DIRECT(VifUnit_Base* unit, const VifcodeInstruction inst)
{
// VIF1 only
if (unit->core_id != 1) {
BOOST_LOG(Core::get_logger()) << str(boost::format("Warning: VIF%d called a VIF1-only instruction: DIRECT") % unit->core_id);
return;
}
// TODO: Implement this
}
void CVif::DIRECTHL(VifUnit_Base* unit, const VifcodeInstruction inst)
{
// VIF1 only
if (unit->core_id != 1) {
BOOST_LOG(Core::get_logger()) << str(boost::format("Warning: VIF%d called a VIF1-only instruction: DIRECTHL") % unit->core_id);
return;
}
// TODO: Implement this
}
void CVif::UNPACK(VifUnit_Base* unit, const VifcodeInstruction inst)

View file

@ -5,80 +5,164 @@
void CVuInterpreter::FTOI0(VuUnit_Base* unit, const VuInstruction inst)
{
// TODO: Implement.
#if defined(BUILD_DEBUG)
BOOST_LOG(Core::get_logger()) << boost::format("(%s, %d) FTOI0: Not implemented.") % __FILENAME__ % __LINE__;
#else
throw std::runtime_error("FTOI0: Not implemented.");
#endif
SizedQwordRegister& ft = unit->vf[inst.ft()];
SizedQwordRegister& fs = unit->vf[inst.fs()];
ubyte dest = inst.dest();
for (auto field : VuVectorField::VECTOR_FIELDS)
{
if (inst.test_dest_field(field))
{
const f32 f = fs.read_float(field);
// No conversions needed
const uword result = static_cast<uword>(f);
ft.write_uword(field, result);
}
}
}
void CVuInterpreter::FTOI4(VuUnit_Base* unit, const VuInstruction inst)
{
// TODO: Implement.
#if defined(BUILD_DEBUG)
BOOST_LOG(Core::get_logger()) << boost::format("(%s, %d) FTOI4: Not implemented.") % __FILENAME__ % __LINE__;
#else
throw std::runtime_error("FTOI4: Not implemented.");
#endif
SizedQwordRegister& ft = unit->vf[inst.ft()];
SizedQwordRegister& fs = unit->vf[inst.fs()];
ubyte dest = inst.dest();
for (auto field : VuVectorField::VECTOR_FIELDS)
{
if (inst.test_dest_field(field))
{
// Multiply the float by (1 << n), where n is the precision of the fixed-point
// See ITOF4 for the (reversed) reason for doing so
const f32 f = fs.read_float(field) * (1 << 4);
// Cast the resultant float into an integer
const uword result = static_cast<uword>(f);
ft.write_uword(field, result);
}
}
}
void CVuInterpreter::FTOI12(VuUnit_Base* unit, const VuInstruction inst)
{
// TODO: Implement.
#if defined(BUILD_DEBUG)
BOOST_LOG(Core::get_logger()) << boost::format("(%s, %d) FTOI12: Not implemented.") % __FILENAME__ % __LINE__;
#else
throw std::runtime_error("FTOI12: Not implemented.");
#endif
// See FTOI4 for more details on how the code works.
SizedQwordRegister& ft = unit->vf[inst.ft()];
SizedQwordRegister& fs = unit->vf[inst.fs()];
ubyte dest = inst.dest();
for (auto field : VuVectorField::VECTOR_FIELDS)
{
if (inst.test_dest_field(field))
{
const f32 f = fs.read_float(field) * (1 << 12);
const uword result = static_cast<uword>(f);
ft.write_uword(field, result);
}
}
}
void CVuInterpreter::FTOI15(VuUnit_Base* unit, const VuInstruction inst)
{
// TODO: Implement.
#if defined(BUILD_DEBUG)
BOOST_LOG(Core::get_logger()) << boost::format("(%s, %d) FTOI15: Not implemented.") % __FILENAME__ % __LINE__;
#else
throw std::runtime_error("FTOI15: Not implemented.");
#endif
// See FTOI4 for more details on how the code works.
SizedQwordRegister& ft = unit->vf[inst.ft()];
SizedQwordRegister& fs = unit->vf[inst.fs()];
ubyte dest = inst.dest();
for (auto field : VuVectorField::VECTOR_FIELDS)
{
if (inst.test_dest_field(field))
{
const f32 f = fs.read_float(field) * (1 << 15);
const uword result = static_cast<uword>(f);
ft.write_uword(field, result);
}
}
}
void CVuInterpreter::ITOF0(VuUnit_Base* unit, const VuInstruction inst)
{
// TODO: Implement.
#if defined(BUILD_DEBUG)
BOOST_LOG(Core::get_logger()) << boost::format("(%s, %d) ITOF0: Not implemented.") % __FILENAME__ % __LINE__;
#else
throw std::runtime_error("ITOF0: Not implemented.");
#endif
SizedQwordRegister& ft = unit->vf[inst.ft()];
SizedQwordRegister& fs = unit->vf[inst.fs()];
ubyte dest = inst.dest();
for (auto field : VuVectorField::VECTOR_FIELDS)
{
if (inst.test_dest_field(field))
{
uword u = fs.read_uword(field);
// No fractional parts to worry about, just cast it
const f32 result = static_cast<f32>(u);
ft.write_float(field, result);
}
}
}
void CVuInterpreter::ITOF4(VuUnit_Base* unit, const VuInstruction inst)
{
// TODO: Implement.
#if defined(BUILD_DEBUG)
BOOST_LOG(Core::get_logger()) << boost::format("(%s, %d) ITOF4: Not implemented.") % __FILENAME__ % __LINE__;
#else
throw std::runtime_error("ITOF4: Not implemented.");
#endif
SizedQwordRegister& ft = unit->vf[inst.ft()];
SizedQwordRegister& fs = unit->vf[inst.fs()];
ubyte dest = inst.dest();
for (auto field : VuVectorField::VECTOR_FIELDS)
{
if (inst.test_dest_field(field))
{
const uword u = fs.read_uword(field);
// The FPU is faster multiplying than dividing, thus we let the compiler
// calculate (1 / n) for us, and we multiply that value later
// Since the values we use are representable in floats, there's no precision loss
constexpr f32 multiplier = 1 / static_cast<f32>(1 << 4);
// By dividing the input, we essentially "move" the decimal point of it
// i.e. 10010101 to 1001.0101
const f32 result = u * multiplier;
ft.write_float(field, result);
}
}
}
void CVuInterpreter::ITOF12(VuUnit_Base* unit, const VuInstruction inst)
{
// TODO: Implement.
#if defined(BUILD_DEBUG)
BOOST_LOG(Core::get_logger()) << boost::format("(%s, %d) ITOF12: Not implemented.") % __FILENAME__ % __LINE__;
#else
throw std::runtime_error("ITOF12: Not implemented.");
#endif
// See ITOF4 for more details
SizedQwordRegister& ft = unit->vf[inst.ft()];
SizedQwordRegister& fs = unit->vf[inst.fs()];
ubyte dest = inst.dest();
for (auto field : VuVectorField::VECTOR_FIELDS)
{
if (inst.test_dest_field(field))
{
const uword u = fs.read_uword(field);
constexpr f32 multiplier = 1 / static_cast<f32>(1 << 12);
const f32 result = u * multiplier;
ft.write_float(field, result);
}
}
}
void CVuInterpreter::ITOF15(VuUnit_Base* unit, const VuInstruction inst)
{
// TODO: Implement.
#if defined(BUILD_DEBUG)
BOOST_LOG(Core::get_logger()) << boost::format("(%s, %d) ITOF15: Not implemented.") % __FILENAME__ % __LINE__;
#else
throw std::runtime_error("ITOF15: Not implemented.");
#endif
// See ITOF4 for more details
SizedQwordRegister& ft = unit->vf[inst.ft()];
SizedQwordRegister& fs = unit->vf[inst.fs()];
ubyte dest = inst.dest();
for (auto field : VuVectorField::VECTOR_FIELDS)
{
if (inst.test_dest_field(field))
{
const uword u = fs.read_uword(field);
constexpr f32 multiplier = 1 / static_cast<f32>(1 << 15);
const f32 result = u * multiplier;
ft.write_float(field, result);
}
}
}

View file

@ -35,7 +35,7 @@ public:
VifUnitRegister_Ofst ofst;
VifUnitRegister_Top top;
VifUnitRegister_Tops tops;
VifUnitRegister_Mask mark;
VifUnitRegister_Mark mark;
VifUnitRegister_Num num;
VifUnitRegister_Code code;
VifUnitRegister_Stat stat;

View file

@ -113,19 +113,19 @@ f32 to_ps2_float(const f32 value, FpuFlags& flags)
{
// Set OF flag, clamp to +/- Fmax.
flags.OF = true;
return static_cast<f32>(flags.SF ? Constants::EE::EECore::FPU::FMAX_NEG : Constants::EE::EECore::FPU::FMAX_POS);
return *reinterpret_cast<const f32*>(flags.SF ? &Constants::EE::EECore::FPU::FMAX_NEG : &Constants::EE::EECore::FPU::FMAX_POS);
}
case FP_NAN:
{
// Set OF flag, clamp to +/- Fmax.
flags.OF = true;
return static_cast<f32>(flags.SF ? Constants::EE::EECore::FPU::FMAX_NEG : Constants::EE::EECore::FPU::FMAX_POS);
return *reinterpret_cast<const f32*>(flags.SF ? &Constants::EE::EECore::FPU::FMAX_NEG : &Constants::EE::EECore::FPU::FMAX_POS);
}
case FP_SUBNORMAL:
{
// Set UF flag, round to +/- 0.
flags.UF = true;
return static_cast<f32>(flags.SF ? Constants::EE::EECore::FPU::ZERO_NEG : Constants::EE::EECore::FPU::ZERO_POS);
return *reinterpret_cast<const f32*>(flags.SF ? &Constants::EE::EECore::FPU::ZERO_NEG : &Constants::EE::EECore::FPU::ZERO_POS);
}
case FP_ZERO:
{