CPU/Recompiler: Don't require fallback for GTE instructions

This commit is contained in:
Connor McLaughlin 2019-12-11 21:54:08 +10:00
parent a6dab97928
commit a5afb250ea
5 changed files with 82 additions and 0 deletions

View File

@ -113,6 +113,10 @@ bool CodeGenerator::CompileInstruction(const CodeBlockInstruction& cbi)
result = Compile_cop0(cbi); result = Compile_cop0(cbi);
break; break;
case InstructionOp::cop2:
result = Compile_cop2(cbi);
break;
case InstructionOp::funct: case InstructionOp::funct:
{ {
switch (cbi.instruction.r.funct) switch (cbi.instruction.r.funct)
@ -1500,4 +1504,60 @@ bool CodeGenerator::Compile_cop0(const CodeBlockInstruction& cbi)
} }
} }
bool CodeGenerator::Compile_cop2(const CodeBlockInstruction& cbi)
{
if (cbi.instruction.cop.IsCommonInstruction())
{
switch (cbi.instruction.cop.CommonOp())
{
case CopCommonInstruction::mfcn:
case CopCommonInstruction::cfcn:
{
const u32 reg = static_cast<u32>(cbi.instruction.r.rd.GetValue()) +
((cbi.instruction.cop.CommonOp() == CopCommonInstruction::cfcn) ? 32 : 0);
InstructionPrologue(cbi, 1);
Value value = m_register_cache.AllocateScratch(RegSize_32);
EmitFunctionCallPtr(&value, &Thunks::ReadGTERegister, m_register_cache.GetCPUPtr(),
Value::FromConstantU32(reg));
m_register_cache.WriteGuestRegisterDelayed(cbi.instruction.r.rt, std::move(value));
InstructionEpilogue(cbi);
return true;
}
case CopCommonInstruction::mtcn:
case CopCommonInstruction::ctcn:
{
const u32 reg = static_cast<u32>(cbi.instruction.r.rd.GetValue()) +
((cbi.instruction.cop.CommonOp() == CopCommonInstruction::ctcn) ? 32 : 0);
InstructionPrologue(cbi, 1);
Value value = m_register_cache.ReadGuestRegister(cbi.instruction.r.rt);
EmitFunctionCallPtr(nullptr, &Thunks::WriteGTERegister, m_register_cache.GetCPUPtr(),
Value::FromConstantU32(reg), value);
InstructionEpilogue(cbi);
return true;
}
default:
return Compile_Fallback(cbi);
}
}
else
{
// forward everything to the GTE.
InstructionPrologue(cbi, 1);
Value instruction_bits = Value::FromConstantU32(cbi.instruction.bits & GTE::Instruction::REQUIRED_BITS_MASK);
EmitFunctionCallPtr(nullptr, &Thunks::ExecuteGTEInstruction, m_register_cache.GetCPUPtr(), instruction_bits);
InstructionEpilogue(cbi);
return true;
}
}
} // namespace CPU::Recompiler } // namespace CPU::Recompiler

View File

@ -192,6 +192,7 @@ private:
bool Compile_Branch(const CodeBlockInstruction& cbi); bool Compile_Branch(const CodeBlockInstruction& cbi);
bool Compile_lui(const CodeBlockInstruction& cbi); bool Compile_lui(const CodeBlockInstruction& cbi);
bool Compile_cop0(const CodeBlockInstruction& cbi); bool Compile_cop0(const CodeBlockInstruction& cbi);
bool Compile_cop2(const CodeBlockInstruction& cbi);
Core* m_cpu; Core* m_cpu;
JitCodeBuffer* m_code_buffer; JitCodeBuffer* m_code_buffer;

View File

@ -92,4 +92,19 @@ void Thunks::RaiseAddressException(Core* cpu, u32 address, bool store, bool bran
cpu->RaiseException(store ? Exception::AdES : Exception::AdEL); cpu->RaiseException(store ? Exception::AdES : Exception::AdEL);
} }
void Thunks::ExecuteGTEInstruction(Core* cpu, u32 instruction_bits)
{
cpu->m_cop2.ExecuteInstruction(GTE::Instruction{instruction_bits});
}
u32 Thunks::ReadGTERegister(Core* cpu, u32 reg)
{
return cpu->m_cop2.ReadRegister(reg);
}
void Thunks::WriteGTERegister(Core* cpu, u32 reg, u32 value)
{
cpu->m_cop2.WriteRegister(reg, value);
}
} // namespace CPU::Recompiler } // namespace CPU::Recompiler

View File

@ -23,6 +23,9 @@ public:
static void UpdateLoadDelay(Core* cpu); static void UpdateLoadDelay(Core* cpu);
static void RaiseException(Core* cpu, u8 excode); static void RaiseException(Core* cpu, u8 excode);
static void RaiseAddressException(Core* cpu, u32 address, bool store, bool branch); static void RaiseAddressException(Core* cpu, u32 address, bool store, bool branch);
static void ExecuteGTEInstruction(Core* cpu, u32 instruction_bits);
static u32 ReadGTERegister(Core* cpu, u32 reg);
static void WriteGTERegister(Core* cpu, u32 reg, u32 value);
}; };
class ASMFunctions class ASMFunctions

View File

@ -133,6 +133,9 @@ union Instruction
BitField<u32, u8, 0, 6> command; BitField<u32, u8, 0, 6> command;
ALWAYS_INLINE u8 GetShift() const { return sf ? 12 : 0; } ALWAYS_INLINE u8 GetShift() const { return sf ? 12 : 0; }
// only the first 20 bits are needed to execute
static constexpr u32 REQUIRED_BITS_MASK = ((1 << 20) - 1);
}; };
} // namespace GTE } // namespace GTE