mirror of
https://github.com/hch12907/orbum.git
synced 2024-06-02 19:38:16 -04:00
Merge branch 'master' into serialization
This commit is contained in:
commit
1605c43d86
|
@ -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.
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -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
|
||||
{
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
File diff suppressed because it is too large
Load diff
|
@ -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;
|
||||
|
|
|
@ -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:
|
||||
{
|
||||
|
|
Loading…
Reference in a new issue