mirror of
https://github.com/hch12907/orbum.git
synced 2024-06-01 19:08:05 -04:00
Fix clang-7 and MSVC build
- added missing includes - fixed ambiguous Bitfield extract_from - VU branch delay slot cleanup - removed unused CGif function - removed reference to removed variables
This commit is contained in:
parent
313f59a019
commit
4e62239a94
|
@ -76,9 +76,9 @@ struct Bitfield
|
|||
throw std::logic_error("Cannot extract bitfield over 64 bit boundary from a uqword [not implemented]");
|
||||
|
||||
if (start < 64)
|
||||
return Bitfield(start, length).extract_from<To>(value.lo);
|
||||
return Bitfield(start, length).extract_from<To, udword>(value.lo);
|
||||
else
|
||||
return Bitfield(start - 64, length).extract_from<To>(value.hi);
|
||||
return Bitfield(start - 64, length).extract_from<To, udword>(value.hi);
|
||||
}
|
||||
|
||||
constexpr bool operator==(const Bitfield& rhs) const
|
||||
|
|
|
@ -1,8 +1,10 @@
|
|||
#pragma once
|
||||
|
||||
#include <cereal/cereal.hpp>
|
||||
#include <array>
|
||||
#include <utility>
|
||||
|
||||
#include <cereal/cereal.hpp>
|
||||
|
||||
#include "Common/Types/Primitive.hpp"
|
||||
#include "Common/Types/Register/PcRegisters.hpp"
|
||||
|
||||
|
@ -13,13 +15,13 @@
|
|||
/// configured branch slots have been run, and then the jump/branch occurs.
|
||||
/// A default slot size of 1 is used by the EE and IOP cores.
|
||||
/// slot + 1 is used internally as this is the real amount of instruction cycles.
|
||||
template <size_t slots = 1>
|
||||
/// inst_size specifies the instruction size of the unit (4 bytes for EE & IOP, 8 for VU)
|
||||
template <size_t slots = 1, size_t inst_size = Constants::MIPS::SIZE_MIPS_INSTRUCTION>
|
||||
class BranchDelaySlot
|
||||
{
|
||||
public:
|
||||
BranchDelaySlot() :
|
||||
current_slot(0),
|
||||
branch_pc(0)
|
||||
pending_branches { std::pair(-1, 0), std::pair(-1, 0) }
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -39,6 +41,13 @@ public:
|
|||
throw std::runtime_error("BDS: More than 2 branches in queue - this should not happen");
|
||||
}
|
||||
|
||||
/// Obtains the PC of a soon-to-happen branching.
|
||||
/// This is used by the *AL* (link register) branching/jumping instructions.
|
||||
uptr get_branch_pc()
|
||||
{
|
||||
return pending_branches[0].second;
|
||||
}
|
||||
|
||||
/// Sets a pending branch to the direct address given.
|
||||
void set_branch_direct(const uptr address)
|
||||
{
|
||||
|
@ -49,14 +58,14 @@ public:
|
|||
/// the offset specified. Used for I-type instructions (imm's).
|
||||
void set_branch_itype(WordPcRegister& pc, const shword imm)
|
||||
{
|
||||
add_branch_queue((pc.read_uword() + Constants::MIPS::SIZE_MIPS_INSTRUCTION) + (imm << 2));
|
||||
add_branch_queue((pc.read_uword() + inst_size) + (imm * inst_size));
|
||||
}
|
||||
|
||||
/// Sets a pending branch which combines the current PC address with
|
||||
/// the region address. Used for J-type instructions.
|
||||
void set_branch_jtype(WordPcRegister& pc, const uptr j_region_addr)
|
||||
{
|
||||
add_branch_queue(((pc.read_uword() + Constants::MIPS::SIZE_MIPS_INSTRUCTION) & 0xF0000000) | (j_region_addr << 2));
|
||||
add_branch_queue(((pc.read_uword() + inst_size) & 0xF0000000) | (j_region_addr * inst_size));
|
||||
}
|
||||
|
||||
/// Advances the PC by either incrementing by 1 instruction,
|
||||
|
@ -88,7 +97,7 @@ public:
|
|||
}
|
||||
|
||||
// Increment by 1 instruction.
|
||||
pc.offset(Constants::MIPS::SIZE_MIPS_INSTRUCTION);
|
||||
pc.offset(inst_size);
|
||||
}
|
||||
|
||||
/// Stops the current branch in progress (used by exception handler).
|
||||
|
@ -110,7 +119,7 @@ public:
|
|||
protected:
|
||||
// sword of std::pair = cycles left before branching
|
||||
// uptr of std::pair = address to branch to
|
||||
std::array<std::pair<sword, uptr>, 2> pending_branches;
|
||||
std::array<std::pair<sword, uptr>, slots + 1> pending_branches;
|
||||
|
||||
public:
|
||||
template <class Archive>
|
||||
|
|
|
@ -33,6 +33,4 @@ public:
|
|||
int handle_data_reglist(const uqword data);
|
||||
|
||||
int handle_data_image(const uqword data);
|
||||
|
||||
std::pair<size_t, SizedDwordRegister*> get_register_descriptor() const;
|
||||
};
|
||||
|
|
|
@ -282,14 +282,14 @@ bool CVuInterpreter::check_data_hazard(VuUnit_Base* unit, const VuInstructionDec
|
|||
decoder.lower_src(1).value_or(-1)};
|
||||
|
||||
// If the instruction is WAITP, return true if EFU is running
|
||||
if ((decoder.get_lower_inst().value) & 0x7FF == 0x7BF)
|
||||
if (((decoder.get_lower_inst().value) & 0x7FF) == 0x7BF)
|
||||
{
|
||||
if (unit->efu.is_running())
|
||||
return true;
|
||||
}
|
||||
|
||||
// If the instruction is WAITQ, return true if FDIV is running
|
||||
if ((decoder.get_lower_inst().value) & 0x7FF == 0x3BF)
|
||||
if (((decoder.get_lower_inst().value) & 0x7FF) == 0x3BF)
|
||||
{
|
||||
if (unit->fdiv.is_running())
|
||||
return true;
|
||||
|
@ -309,7 +309,7 @@ bool CVuInterpreter::check_data_hazard(VuUnit_Base* unit, const VuInstructionDec
|
|||
{
|
||||
if (fmac.is_using_register(upper_read[0], inst.dest()))
|
||||
return true;
|
||||
if (fmac.is_using_register(upper_read[1], 1 << (3 - inst.bc())))
|
||||
if (fmac.is_using_register(upper_read[1], 1U << (3 - inst.bc())))
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
@ -334,7 +334,7 @@ bool CVuInterpreter::check_data_hazard(VuUnit_Base* unit, const VuInstructionDec
|
|||
return true;
|
||||
if (fmac.is_using_register(upper_read[1], inst.dest()))
|
||||
return true;
|
||||
if (fmac.is_using_register(upper_read[2], 1 << (3 - inst.bc())))
|
||||
if (fmac.is_using_register(upper_read[2], 1U << (3 - inst.bc())))
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,10 +1,7 @@
|
|||
#include "Resources/Ee/Gif/GifRegisters.hpp"
|
||||
|
||||
GifRegister_Ctrl::GifRegister_Ctrl() :
|
||||
transfer_started(false),
|
||||
tag(),
|
||||
transfer_register_count(0),
|
||||
transfer_loop_count(0),
|
||||
rgbaq_q(1.0f)
|
||||
{
|
||||
}
|
|
@ -28,11 +28,8 @@ public:
|
|||
void serialize(Archive & archive)
|
||||
{
|
||||
archive(
|
||||
cereal::base_class<SizedWordRegister>(this),
|
||||
CEREAL_NVP(transfer_started),
|
||||
CEREAL_NVP(tag),
|
||||
CEREAL_NVP(transfer_register_count),
|
||||
CEREAL_NVP(transfer_loop_count),
|
||||
cereal::base_class<SizedWordRegister>(this)
|
||||
// CEREAL_NVP(tag) // TODO
|
||||
);
|
||||
}
|
||||
};
|
||||
|
|
|
@ -1,112 +1,17 @@
|
|||
#pragma once
|
||||
|
||||
#include <cereal/cereal.hpp>
|
||||
|
||||
#include "Common/Types/Mips/BranchDelaySlot.hpp"
|
||||
#include "Common/Types/Primitive.hpp"
|
||||
#include "Common/Types/Register/PcRegisters.hpp"
|
||||
|
||||
/// BranchDelaySlot, modified slightly for the VUs.
|
||||
/// BranchDelaySlot modified slightly for the VUs.
|
||||
/// See BranchDelaySlot for more documentation.
|
||||
template <size_t slots = 1>
|
||||
class VuBranchDelaySlot : public BranchDelaySlot<slots>
|
||||
class VuBranchDelaySlot : public BranchDelaySlot<1, Constants::EE::VPU::SIZE_VU_INSTRUCTION>
|
||||
{
|
||||
public:
|
||||
VuBranchDelaySlot() :
|
||||
second_branch_pc(0),
|
||||
second_branch_pending(false),
|
||||
BranchDelaySlot<slots>()
|
||||
{
|
||||
}
|
||||
|
||||
/// is_branch_pending() in VuBranchDelaySlot has the same behaviour as the
|
||||
/// one in BranchDelaySlot.
|
||||
using BranchDelaySlot<slots>::is_branch_pending;
|
||||
|
||||
/// Obtains the PC of which the VU is branching to.
|
||||
/// This is used by the *AL* (link register) branching/jumping instructions.
|
||||
uptr get_branch_pc()
|
||||
{
|
||||
return branch_pc;
|
||||
}
|
||||
|
||||
/// Sets the offset of the PC address of the VUs, with a delay slot.
|
||||
/// See BranchDelaySlot::set_branch_itype for more documentation.
|
||||
/// The only difference is the size of the instruction - VU instructions are 8 bytes long
|
||||
/// whereas EE Core instructions are only 4.
|
||||
void set_branch_itype(WordPcRegister& pc, const shword imm)
|
||||
{
|
||||
// If we are branching in the delay slot, the original branch runs for only one cycle
|
||||
if (is_branch_pending())
|
||||
{
|
||||
second_branch_pending = true;
|
||||
second_branch_pc = (pc.read_uword() + Constants::EE::VPU::SIZE_VU_INSTRUCTION + imm * 8) & 0x3FFF;
|
||||
}
|
||||
else
|
||||
{
|
||||
current_slot = slots + 1;
|
||||
|
||||
// VU can hold 16KB of instructions only (and 4KB in VU0), so AND it with 0x3FFF
|
||||
branch_pc = (pc.read_uword() + Constants::EE::VPU::SIZE_VU_INSTRUCTION + imm * 8) & 0x3FFF;
|
||||
}
|
||||
}
|
||||
|
||||
/// Sets the PC address of the VUs, with a delay slot.
|
||||
/// The VUs' jumping range is much smaller than the EE Core's
|
||||
/// (just 16KB is sufficient for the VUs), and so this method behaves
|
||||
/// differently from the original set_branch_jtype.
|
||||
/// The VUs don't have the concept of virtual address, so just jump
|
||||
void set_branch_jtype(WordPcRegister& pc, const uptr jump_to)
|
||||
{
|
||||
if (is_branch_pending())
|
||||
{
|
||||
second_branch_pending = true;
|
||||
second_branch_pc = (jump_to * 8) & 0x3FFF;
|
||||
}
|
||||
else
|
||||
{
|
||||
current_slot = slots + 1;
|
||||
branch_pc = (jump_to * 8) & 0x3FFF;
|
||||
}
|
||||
add_branch_queue((jump_to * Constants::EE::VPU::SIZE_VU_INSTRUCTION) & 0x3FFF);
|
||||
}
|
||||
|
||||
void advance_pc(WordPcRegister& pc)
|
||||
{
|
||||
if (current_slot)
|
||||
{
|
||||
current_slot--;
|
||||
if (!current_slot)
|
||||
{
|
||||
pc.write_uword(branch_pc);
|
||||
if (second_branch_pending)
|
||||
{
|
||||
second_branch_pending = false;
|
||||
branch_pc = second_branch_pc;
|
||||
current_slot = 1;
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
pc.offset(Constants::EE::VPU::SIZE_VU_INSTRUCTION);
|
||||
}
|
||||
|
||||
private:
|
||||
// introduces the base class variables to this class
|
||||
using BranchDelaySlot<slots>::branch_pc;
|
||||
using BranchDelaySlot<slots>::current_slot;
|
||||
|
||||
uptr second_branch_pc;
|
||||
bool second_branch_pending;
|
||||
|
||||
// Serialization
|
||||
public:
|
||||
template <class Archive>
|
||||
void serialize(Archive& archive)
|
||||
{
|
||||
archive(
|
||||
CEREAL_NVP(current_slot),
|
||||
CEREAL_NVP(branch_pc),
|
||||
CEREAL_NVP(second_branch_pc),
|
||||
CEREAL_NVP(second_branch_pending));
|
||||
}
|
||||
};
|
||||
};
|
||||
|
|
|
@ -67,7 +67,7 @@ public:
|
|||
/// Also known as the TPC (termination PC), treated as the same thing.
|
||||
/// Made to be 32-bit even though only 16-bits are used (bus maps easier).
|
||||
WordPcRegister pc;
|
||||
VuBranchDelaySlot<> bdelay;
|
||||
VuBranchDelaySlot bdelay;
|
||||
|
||||
/// The CMSAR register used for micro subroutine execution.
|
||||
/// See VU Users Manual page 202.
|
||||
|
|
Loading…
Reference in a new issue