CPU/Recompiler: Don't require fallback for GTE instructions
This commit is contained in:
parent
a6dab97928
commit
a5afb250ea
|
@ -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
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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
|
|
@ -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
|
||||||
|
|
|
@ -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
|
Loading…
Reference in New Issue